นี่เป็นปัญหาที่น่าทึ่ง! สองสิ่งที่ทำให้มันท้าทายเป็นพิเศษ:
- เราควรเปรียบเทียบชุดสองจุดอย่างไร ปัญหาคลาสสิกในการเรียนรู้ของเครื่องมีจำนวนคุณลักษณะคงที่และคุณลักษณะเหล่านี้ไม่สามารถใช้แทนกันได้ตัวอย่างเช่นฉันอาจมีข้อมูลเกี่ยวกับบุคคลที่มีคุณลักษณะแตกต่างกัน
age
และheight
(เป็นเซนติเมตร) ตัวอย่างทุกคนมีหนึ่งรายการสำหรับแต่ละและแน่นอนไม่ได้เช่นเดียวกับ(age, height) = (22, 180)
(age, height) = (180, 22)
ไม่เป็นความจริงสำหรับปัญหาของคุณ ชุดจุดมีระหว่าง 3 ถึง 10 คะแนนและลำดับที่เราป้อนคะแนนไม่ควรสร้างความแตกต่างเมื่อเปรียบเทียบชุดจุดสองจุด
- เราจะทำนายได้อย่างไร สมมติว่าเราพบวิธีการเลือกชุดคะแนนจากชุดการฝึกอบรมของเราที่คล้ายกับชุดคะแนนของคุณด้านบน เราประสบปัญหาว่าการทำนายของเราจะต้องเป็นหนึ่งใน 7 คะแนนในภาพของคุณ แต่ไม่มีจุดใดที่อาจอยู่ในชุดจุดที่คล้ายกัน
ผมขอสรุปอัลกอริทึมที่เกี่ยวข้องกับความท้าทายทั้งสอง ความแม่นยำในการทำนายไม่ดีมาก แต่บางทีคุณอาจเห็นวิธีปรับปรุงได้ และอย่างน้อยก็ทำนายบางอย่างใช่มั้ย
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. การเปรียบเทียบชุดจุดผ่านระยะทาง Hausdorff
ให้เราแก้ไขปัญหาแรก: เราจะเปรียบเทียบชุดจุดที่แตกต่างกันอย่างไร จำนวนคะแนนในชุดคะแนนนั้นแตกต่างกัน ยังจำได้ว่าคำสั่งที่เราเขียนลงจุดที่ไม่ควรเรื่อง: เมื่อเปรียบเทียบกับชุดจุดควรจะเกิดผลเช่นเดียวกับเมื่อเทียบกับชุดจุด[(0,0), (1,1), (2,2)]
[(2,2), (0,0), (1,1)]
แนวทางของฉันคือการเปรียบเทียบชุดจุดผ่านระยะทางของHausdorff :
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
ชุดจุดในตัวอย่างการฝึกอบรมของเราที่มีระยะห่าง Hausdorff ที่เล็กที่สุดเทียบกับชุดจุดทดสอบและรับฉลากของพวกเขา ปัญหาที่สองมาถึงแล้ว: เราจะเปลี่ยน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) ปรับปรุงวิธีการฝึกอบรมฉลากที่เลือกจะกลายเป็นคำทำนาย