Bu büyüleyici bir problem! İki şey onu özellikle zorlaştırıyor:
- İki nokta kümesini nasıl karşılaştırmalıyız? Makine Öğrenimi'ndeki klasik problemlerin sabit sayıda niteliği vardır ve bu nitelikler birbirinin yerine kullanılamaz: Örneğin, nitelikleri
age
ve height
(santimetre cinsinden) farklı kişiler hakkında verilerim olabilir . Her numunenin her biri için bir girişi vardır ve elbette (age, height) = (22, 180)
aynı değildir (age, height) = (180, 22)
. Sorununuzda da doğru değil. Bir nokta kümesinin 3 ila 10 nokta vardır ve noktalara girme sırası iki nokta kümesini karşılaştırırken bir fark yaratmamalıdır.
- Nasıl tahmin yapabiliriz? Diyelim ki, eğitim setimizden, yukarıda belirlediğiniz noktaya benzer nokta setleri seçmenin bir yolunu bulduk. Tahminimizin resminizdeki 7 noktadan biri olması gerektiği sorunuyla karşı karşıyayız; ancak bu noktaların hiçbiri benzer nokta kümelerinde bulunmayabilir.
Her iki zorluğu da ele alan bir algoritma çizeyim. Tahmin doğruluğu çok iyi değil; ama belki de bunun nasıl iyileştirilebileceğini görüyorsunuz. Ve en azından tahmin şey doğru?
1. örnekleri simüle
Algoritmayı test edebilmek için örnekler ve etiketler üreten fonksiyonlar yazdım.
Örnek oluşturma: Her örnek 3 ila 10 puan içerir. Nokta sayısı rastgele, düzgün bir dağılımdan alınmıştır. Her nokta biçimdedir (x_coordinate, y_coordinate)
. Koordinatlar tekrar rastgele, normal bir dağılımdan çizilir.
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)])
Etiket oluşturma: Oyuncak örneği olarak, bir nokta seçme kuralının aşağıdaki gibi olduğunu varsayalım: Her zaman en yakın noktayı seçin, (0, 0)
'en yakın' Öklid normuna göre anlaşılmalıdır.
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])
Şimdi tren ve test setlerimizi oluşturabiliriz:
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. Hausdorff mesafesi ile nokta kümelerinin karşılaştırılması
İlk sorunu ele alalım: Farklı nokta kümelerini nasıl karşılaştırmalıyız? Nokta kümelerindeki nokta sayısı farklıdır. Ayrıca, noktaları yazdığımız sıranın önemli olmadığını unutmayın: Belirlenen noktaya kıyasla, belirlenen noktaya kıyasla [(0,0), (1,1), (2,2)]
aynı sonucu vermelidir [(2,2), (0,0), (1,1)]
. Benim yaklaşımım nokta kümelerini Hausdorff mesafeleriyle karşılaştırmak :
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. En yakın k komşuları ile tahmin ve ortalama
Artık nokta kümeleri arasında mesafe kavramımız var. Bu, en yakın komşu sınıflandırmasını kullanmayı mümkün kılar: Bir test noktası seti verildiğinde, k
eğitim örneğimizde, test noktası setine göre en küçük Hausdorff mesafesine sahip nokta setlerini bulur ve etiketlerini alırız. Şimdi ikinci sorun geliyor: Bu k
etiketleri, test noktası seti için bir öngörüye nasıl dönüştürürüz? En basit yaklaşımı kullandım: etiketlerin ortalamasını alın ve test noktası kümesinde ortalamanın en yakın noktasını tahmin edin.
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. Test
Algoritmamızın performansını test etmek için her şey hazır.
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])
Verilen karar fonksiyonu için ve num_neighbors = 70
% 84 tahmin doğruluğu elde ediyoruz. Bu çok iyi değil ve elbette tahmin edilmesi oldukça kolay görünen karar fonksiyonumuza özgü.
Bunu görmek için farklı bir karar fonksiyonu tanımlayın:
decision_function_maxaverage(sample):
avgs = (sample[:, 0] + sample[:, 1]) / 2
return sample[norms.argmin()]
Bu işlevi kullanarak dec_fun = decision_function_maxaverage
tahmin doğruluğunu% 45'e düşürür. Bu, etiketlerinizi oluşturan karar kurallarını düşünmenin ne kadar önemli olduğunu gösterir. İnsanların neden belirli noktaları seçtiği hakkında bir fikriniz varsa , bu en iyi algoritmayı bulmanıza yardımcı olacaktır.
Bu algoritmayı geliştirmenin bazı yolları: (1) Hausdorff mesafesi yerine farklı bir mesafe fonksiyonu kullanın, (2) k-en yakın komşularından daha karmaşık bir şey kullanın, (3) seçilen eğitim etiketlerinin nasıl bir tahmine dönüştürüldüğünü geliştirin.