이것은 매혹적인 문제입니다! 두 가지로 인해 특히 어려움이 있습니다.
- 두 점 세트를 어떻게 비교해야합니까? 기계 학습에서 고전 문제는 속성의 고정 된 수 있고, 이러한 특성은 서로 호환되지 않습니다 : 예를 들어, 내가 속성과 다른 사람에 대한 데이터를 가질 수
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) Hausdorff 거리 대신 다른 거리 함수를 사용하십시오. (2) k- 최근 접 이웃보다 더 정교한 것을 사용하십시오. (3) 선택한 교육 레이블이 예측으로 바뀌는 방법을 개선하십시오.