# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.15.2
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import numpy as np

import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split


# В данном ноутбуке вам нужно оформить метод kNN (k - блжайших соседей)
#
# Для этого желательно просмотреть лекцию https://github.com/andriygav/School/blob/master/2018/Анализ%20данных/Lecture/Lecture2.pdf
#
#

class kNN:
    def __init__(self, X_train, y_train, k = 9, M = 2):
#             arguments: X_train is a matrix of shape [n, d],
#                        y_train is a matrix of shape [d],
#                        k is a number of neighbors which we wanna use
#                        M is a number of classes
#             returns: nothing
#             This function should save all data which users give in init
# your code here
        pass
    def predict(self, X):
#             arguments: X is a matrix of shape [n, d], 
#                     where n is a number of data for which I wanna get result
#                           d is a number of dimensions of data (in this task it's 2)
#             returns: Y is a matrix of shape [d]
#             This function should return prediction for inoput data X
# your code here

        return


# +
# Это данные на которым будем тестить
np.random.seed(0)

Number_of_data_for_one_classes = 100

X_0 = np.random.multivariate_normal(mean = [-1,-1], cov = np.eye(2), size = Number_of_data_for_one_classes)
X_1 = np.random.multivariate_normal(mean = [1,1], cov = np.eye(2), size = Number_of_data_for_one_classes)
Y_0 = np.zeros(Number_of_data_for_one_classes, dtype=np.int64)
Y_1 = np.ones(Number_of_data_for_one_classes, dtype=np.int64)

X = np.vstack([X_0, X_1])
Y = np.hstack([Y_0, Y_1])
# -

X_train, X_test, y_train, y_test = train_test_split(X, Y)

# +
# Покажем размерности данных для тренировочного сэта

print(X_train.shape, y_train.shape)

# +
# Покажем размерности данных для тестового сэта

print(X_test.shape, y_test.shape)

# +
# Изобразим данные, чтобы понимать что мы вообще хотим классифицировать

plt.plot(X_train[np.where(y_train == 0)[0],0], X_train[np.where(y_train == 0)[0],1], 'bo', label = 'class 0')
plt.plot(X_train[np.where(y_train == 1)[0],0], X_train[np.where(y_train == 1)[0],1], 'ro', label = 'class 1')

plt.legend(loc = 'best')
plt.show()

# +
# Создадим объект для метода kNN 
# в который дадим тренировочный сэт, 
# количество классов, и количество учитываемых соседей

model = kNN(X_train, y_train, M=2, k=9)

# +
# Получим ответы на тесте

y_test_predicter = model.predict(X_test)

# +
# Выведем ответы нашей модели

print(y_test_predicter)

# +
# Выведем истинные ответы

print(y_test)

# +
# Посчитаем точность

print(("Accuracy = %f%c")%(100*np.sum(y_test_predicter == y_test)/y_test.shape[0], '%'))
