import numpy as np
import pandas as pd
import scipy as sp
import matplotlib.pyplot as plt
%matplotlib inline
from scipy import special
from scipy import spatial
from sklearn.neighbors import KNeighborsClassifier
def knn_classifier(x_train, y_train, x_test, k=1, distance='euclid',
weight=True):
"""
x_train is np.array with shape (l, d) (matrix with l rows, d columns)
y_train is np.array with shape (l, ) (1-dimensional array with l elements)
x_test is np.array with shape (n, d) (matrix with n rows, d columns)
k is int (if weight is True, then the argument is ignored, else - number of neighbours)
distance is int (order p of Minkowski distance) or str: 'euclidian', 'cityblock' (you can implement more options)
weight is boolean, whether to use the weighted method or not
return y_test, np.array with shape (n, ) (1-dimensional array with n elements)
"""
### SOLUTION BEGIN
distances_sq = sp.spatial.distance.cdist(x_train, x_test, metric = 'minkowski', p = 2)
weights = sp.special.softmax(distances_sq, axis = 1)
print(weights)
y_test = sp.stats.mode(weights * y_train)
return y_test
### SOLUTION END
if name == "main":
knn_classifier(x_train = np.array([[12, 3],
[4, 5],
[1, 5]]),
y_train = np.array([10, 20, 30]).transpose(),
x_test = np.array([[20, 4],
[15, 0],
[1, 4],
[-2, 5]]),
k = 2)