これは興味深い問題です。次の2つの理由により、特に困難が伴います。
- 2つのポイントセットをどのように比較すればよいですか?機械学習の古典的な問題には、固定された数の属性があり、これらの属性を交換することはできません。たとえば、属性(
age
およびheight
センチメートル)を持つさまざまな人物に関するデータがあるかもしれません。すべてのサンプルは、それぞれに1つのエントリを持ち、そしてもちろん(age, height) = (22, 180)
同じではありません(age, height) = (180, 22)
。あなたの問題ではどちらも正しくありません。ポイントセットには3〜10のポイントがあり、ポイントを入力する順序は、2つのポイントセットを比較するときに違いが生じないようにする必要があります。
- どのように予測を行うのですか?上記のポイントセットと同様のトレーニングセットからポイントセットを選択する方法を見つけたとします。私たちの予測はあなたの写真の7つのポイントの1つでなければならないという問題に直面しています。ただし、これらのポイントはいずれも、類似のポイントセットに含まれていない可能性があります。
両方の課題に対処するアルゴリズムの概要を説明します。予測精度はあまり良くありません。しかし、たぶん、あなたはそれがどのように改善されることができる方法を見るでしょう。そして、少なくともそれは何かを予測しますよね?
1.サンプルのシミュレーション
アルゴリズムをテストできるように、サンプルとラベルを生成する関数を作成しました。
サンプルの生成:
各サンプルには3〜10個のポイントが含まれます。ポイントの数はランダムで、均一な分布から描かれます。各ポイントはの形式(x_coordinate, y_coordinate)
です。座標も正規分布から描かれたランダムなものです。
import numpy as np
from random import randint
def create_samples(number_samples, min_points, max_points):
def create_single_sample(min_points, max_points):
n = randint(min_points, max_points)
return np.array([np.random.normal(size=2) for _ in range(n)])
return np.array([create_single_sample(min_points, max_points) for _ in range(number_samples)])
ラベルの生成:おもちゃの例として、ポイントを選択するためのルールは次のとおりであると仮定します。常にに最も近いポイントを選択します(0, 0)
。ここで、「最も近い」はユークリッドノルムの観点から理解する必要があります。
def decision_function_minnorm(sample):
norms = np.apply_along_axis(np.linalg.norm, axis=1, arr=sample)
return sample[norms.argmin()]
def create_labels(samples, decision_function):
return np.array([decision_function(sample) for sample in samples])
これで、トレーニングセットとテストセットを作成できます。
n_train, n_test = 1000, 100
dec_fun = decision_function_minnorm
X_train = create_samples(number_samples=n_train, min_points=3, max_points=10)
X_test = create_samples(number_samples=n_test, min_points=3, max_points=10)
y_train = create_labels(X_train, dec_fun)
y_test = create_labels(X_test, dec_fun)
2.ハウスドルフ距離によるポイントセットの比較
最初の問題に取り組みましょう:異なるポイントセットをどのように比較する必要がありますか?ポイントセットのポイント数が異なります。また、ポイントを書き留める順序は重要ではないことに[(0,0), (1,1), (2,2)]
注意してください。ポイントセットと比較すると、ポイントセットと比較した場合と同じ結果になり[(2,2), (0,0), (1,1)]
ます。私のアプローチは、ハウスドルフ距離を介してポイントセットを比較することです。
def hausdorff(A, B):
def dist_point_to_set(x, A):
return min(np.linalg.norm(x - a) for a in A)
def dist_set_to_set(A, B):
return max(dist_point_set(a, B) for a in A)
return max(dist_set_to_set(A, B), dist_set_to_set(B, A))
3. k最近傍を介した予測と平均化
これで、ポイントセット間の距離の概念がわかりました。これにより、k最近傍分類の使用が可能になります。テストポイントセットが与えられると、k
トレーニングサンプルで、テストポイントセットに対してハウスドルフ距離が最小となるポイントセットを見つけ、そのラベルを取得します。ここで2番目の問題が発生します。これらのk
ラベルをテストポイントセットの予測にどのように変換しますか?私は最も単純なアプローチを採用しました。ラベルを平均化し、平均に最も近いテストポイントセット内のポイントを予測しました。
def predict(x, num_neighbors):
# Find num_neighbors closest points in X_train.
distances_to_train = np.array([hausdorff(x, x_train) for x_train in X_train])
neighbors_idx = np.argpartition(distances_to_train, -num_neighbors)[-num_neighbors:]
# Get labels of the neighbors and calculate the average.
targets_neighbors = y_train[neighbors_idx]
targets_mean = sum(targets_neighbors) / num_neighbors
# Find point in x that is closest to targets_mean and use it as prediction.
distances_to_mean = np.array([np.linalg.norm(p - targets_mean) for p in x])
closest_point = x[distances_to_mean.argmin()]
return closest_point
4.テスト
アルゴリズムのパフォーマンスをテストするためのすべてが整っています。
num_neighbors = 70
successes = 0
for i, x in enumerate(X_test):
print('%d/%d' % (i+1, n_test))
prediction = predict(x, num_neighbors)
successes += np.array_equal(prediction, y_test[i])
与えられた決定関数とに対して、num_neighbors = 70
84%の予測精度が得られます。これはひどく良くありません、そしてもちろんそれは私たちの決定機能に特有です、それは予測するのがかなり簡単に思えます。
これを確認するには、別の決定関数を定義します。
decision_function_maxaverage(sample):
avgs = (sample[:, 0] + sample[:, 1]) / 2
return sample[norms.argmin()]
この関数を介して使用dec_fun = decision_function_maxaverage
すると、予測精度が45%に低下します。これは、ラベルを生成する決定ルールについて考えることがいかに重要であるかを示しています。あなたのアイデアがある場合は、なぜ人々は、特定のポイントを選択し、これはあなたが最良のアルゴリズムを見つけましょう。
このアルゴリズムを改善するいくつかの方法:(1)ハウスドルフ距離の代わりに異なる距離関数を使用する、(2)k最近傍よりも洗練されたものを使用する、(3)選択したトレーニングラベルを予測に変換する方法を改善する。