<jupyter_start><jupyter_text>Семинар 6 - Введение в простые модели ML Дополнительно понадобятся следующие библиотеки. Раскомментируйте код, чтобы установить их.<jupyter_code># !pip install -U scikit-learn
# !pip install pandas<jupyter_output><empty_output><jupyter_text>Метрики<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML

from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, mean_squared_error
from sklearn.datasets import load_digits
from sklearn.linear_model import LinearRegression

import warnings
warnings.simplefilter('ignore')
plt.style.use('seaborn')

%matplotlib inline<jupyter_output><empty_output><jupyter_text>Зададим истинные и "предсказанные" метки для того, чтобы посмотреть на точность предсказаний.<jupyter_code>y_pred = [0, 1, 1, 0, 0, 1, 0, 3]
y_true = [0, 1, 2, 0, 1, 2, 3, 4]<jupyter_output><empty_output><jupyter_text>Accuracy<jupyter_code>accuracy_score(y_true, y_pred)<jupyter_output><empty_output><jupyter_text>Precision<jupyter_code>precision_score(y_true, y_pred, average=None)<jupyter_output><empty_output><jupyter_text>Recall<jupyter_code>recall_score(y_true, y_pred, average=None)<jupyter_output><empty_output><jupyter_text>F1_score<jupyter_code>f1_score(y_true, y_pred, average=None)<jupyter_output><empty_output><jupyter_text>KNN  Загрузим данные<jupyter_code>data = load_digits()
print(data['DESCR'])
img = data.data[56].reshape(8, 8)
print(data.target[56])

plt.imshow(img)
plt.show()
X, y = data.data, data.target
print('В датасете {} объектов и {} признака'.format(X.shape[0], X.shape[1]))<jupyter_output>В датасете 1797 объектов и 64 признака<jupyter_text>Посмотрим на объекты:<jupyter_code>i = np.random.randint(0, X.shape[0])
print('Class name: {}'.format(y[i]))
print(X[i].reshape(8,8))

X[i]
plt.imshow(X[i].reshape(8,8), cmap='gray_r')
plt.show()<jupyter_output>Class name: 5
[[ 0.  0. 15. 13. 13. 13.  0.  0.]
 [ 0.  0. 16. 16. 11.  3.  0.  0.]
 [ 0.  0. 12. 13.  0.  0.  0.  0.]
 [ 0.  0.  5. 16.  3.  0.  0.  0.]
 [ 0.  0.  0. 11. 10.  0.  0.  0.]
 [ 0.  0.  0. 10. 14.  0.  0.  0.]
 [ 0.  0.  9. 16. 10.  0.  0.  0.]
 [ 0.  0. 11. 15.  1.  0.  0.  0.]]<jupyter_text>Посмотрим на баланс классов:<jupyter_code>counts = np.unique(y, return_counts=True)
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.bar(counts[0], counts[1])
plt.show()<jupyter_output><empty_output><jupyter_text>Разделим выборку на две части: обучающую и тестовую<jupyter_code>X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    train_size=0.5,
                                                    test_size=0.5, 
                                                    shuffle=True,
                                                   random_state=18)
X_train.shape, X_test.shape, y_train.shape, y_test.shape<jupyter_output><empty_output><jupyter_text>Метод ближайших соседей Зададим классификатор:<jupyter_code>knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
knn_predictons = knn.predict(X_test)
preds = pd.DataFrame(y_test, columns=['True'])
preds['knn_pred'] = knn_predictons
preds.head(200).T<jupyter_output><empty_output><jupyter_text>Посмотрим долю правильных ответов:<jupyter_code>accuracy_score(y_test, knn_predictons)<jupyter_output><empty_output><jupyter_text>Поиск оптимальных параметров<jupyter_code>from sklearn.model_selection import GridSearchCV
n = np.linspace(1, 21, 21, dtype=int)
n
kNN_cv = KNeighborsClassifier(n_neighbors=5)
params = {
    'metric':['minkowski', 'manhattan'],
    'n_neighbors': n,
         }

gcv = GridSearchCV(kNN_cv, param_grid=params, cv=5, scoring='accuracy')
gcv.fit(X_train, y_train)
gcv.get_params()
def print_cv_results(a, len_gs, params, param_r, param_sep): 
    d = len(params['param_grid'][param_sep])
    ar = np.array(a).reshape(d, len_gs).T
    df = pd.DataFrame(ar)

    pen_par = params['param_grid'][param_sep]
    c_par = params['param_grid'][param_r]
    if type(c_par) != list: 
        c_par = c_par.tolist()
        
    columns_mapper = dict(zip(range(0, len(pen_par)), pen_par))
    row_mapper = dict(zip(range(0, len(c_par)), c_par))

    df.rename(columns=columns_mapper, index=row_mapper, inplace=True)

    plot = df.plot(title='Mean accuracy rating', grid=True)
    plot.set_xlabel(param_r, fontsize=13)
    plot.set_ylabel('acc', rotation=0, fontsize=13, labelpad=15)
    
    plt.show()
gcv.get_params()
print_cv_results(gcv.cv_results_['mean_test_score'],
                 21, gcv.get_params(), 'n_neighbors','metric')
gcv.best_params_
print('Лучший скор %.4f' % gcv.best_score_)
print('при метрике %(metric)s и %(n_neighbors)s соседей' % gcv.best_params_)<jupyter_output>Лучший скор 0.9833
при метрике minkowski и 1 соседей<jupyter_text>Что получится на тесте?<jupyter_code>accuracy_score(y_test, gcv.predict(X_test))
gcv_preds = pd.DataFrame(gcv.predict(X_test), columns=['kNN'])
gcv_preds['True'] = y_test
gcv_preds<jupyter_output><empty_output><jupyter_text>Посмотрим на те цифры, которые "путает" наш классификатор<jupyter_code>gcv_preds[gcv_preds['True'] != gcv_preds['kNN']]<jupyter_output><empty_output><jupyter_text>Линейные модели  Постановка задачи ![picture](https://drive.google.com/uc?export=view&id=1pNRo9-N2Udjv3AK0uTJ0qCWkk9Ko_9TA) Где линейная модель - это: $$ \hat{y} = f(x) = \theta_0*1 + \theta_1*x_1 + ... + \theta_n*x_n = \theta^T*X$$ Сгенерируем исскуственные данные, на основе функции:$$f(x) = 4x+5$$<jupyter_code>def lin_function(x):
    return 4 * x + 5
x_true = np.array([-2, 2])
y_true = lin_function(x_true)

plt.plot(x_true, y_true, linewidth=1)
plt.show()
n = 100
x = np.random.rand(n, 1) * 4 - 2
e = np.random.rand(n, 1) * 4 - 2
y = lin_function(x) + e
plt.scatter(x, y, color='g')
plt.plot(x_true, y_true, linewidth=1)
plt.show()<jupyter_output><empty_output><jupyter_text>Метрики Mean Absoulte Error:$$MAE = \frac1N \sum_{i = 1}^N|f(x_i) - y_i| = \frac1N \sum_{i = 1}^N|\hat y_i - y_i| = \frac1N || \hat Y - Y||_1$$Mean Sqared Error:$$MSE = \frac1N \sum_{i = 1}^N(f(x_i) - y_i)^2 = \frac1N \sum_{i = 1}^N(\hat y_i - y_i)^2 = \frac1N ||\hat Y - Y||_2$$  Аналитический метод поиска минимума по MSE$$MSE -> min $$$$MSE = \frac1N \sum_{i = 1}^N(\hat y_i - y_i)^2 = \frac1N \sum_{i = 1}^N(\theta_i * x_i - y_i)^2 = \frac1N ||X \theta - Y||_2 = \frac1N (X\theta - Y)^T*(X\theta - Y) $$$$ \frac{d}{d\theta}[\frac1N (X\theta - Y)^T*(X\theta - Y)] =  \frac1N \frac{d}{d\theta}[Y^TY - 2Y^TX\theta+\theta^TX^TX\theta]  $$$$\hat \theta = \bigl(X^T \cdot X  \bigr)^{-1} \cdot X^T \cdot y $$<jupyter_code>x_matrix = np.hstack([np.ones((n, 1)), x])
%%time

# найдем аналитическое решение
thetha_matrix = np.linalg.inv(x_matrix.T.dot(x_matrix)).dot(x_matrix.T).dot(y)<jupyter_output>CPU times: user 100 µs, sys: 38 µs, total: 138 µs
Wall time: 105 µs<jupyter_text>Обратите внимание на время работы<jupyter_code>thetha_matrix.T[0].tolist()
print("Свободный член: {[0][0]:.7}".format(thetha_matrix.T))
print("Коэфициент: {[0][1]:.7}".format(thetha_matrix.T))
%%time
lr = LinearRegression()
lr.fit(x,y);
print("Свободный член: {:.7}".format(lr.intercept_[0]))
print("Коэфициент: {:.7}".format(lr.coef_[0][0]))
plt.scatter(x, y, color='g')
plt.scatter(x, lr.predict(x), color='r')
plt.plot(x_true, y_true, linewidth=1)
plt.show()<jupyter_output><empty_output><jupyter_text>Градиентный спуск$$\theta^{(t+1)} = \theta^{(t)} - lr\cdot \nabla MSE(\theta^{(t)}),$$где $lr$ — длина шага градиентного спуска (learning rate).$$\nabla MSE(\theta)= \frac{2}{N} X^T \cdot \bigl(X \cdot \theta - Y \bigr) $$<jupyter_code>def animate_solutions(iter_solutions):

    fig, ax = plt.subplots(figsize=(6.4 * 1, 4.8 * 1))

    def update(idx):
        _theta = iter_solutions[idx]
        
        ax.clear()       
        
        ax.scatter(x, y, color='g', label='Выборка')
        ax.plot(x_true, y_true, linewidth=1, label='Исходная зависимость')
        ax.plot(x_true, x_true * _theta[1] + _theta[0], linewidth=1, color='r', label='Предсказанная зависимость')
        
        ax.legend(loc='upper left', fontsize=13)

    fps = 3
    ani = animation.FuncAnimation(fig, update, len(iter_solutions), interval=100 / fps)
    
    return ani
%%time
lr = 0.1  # шаг обучения
n_iterations = 150  # количество итераций

theta = np.random.randn(2,1)  # начальная инициализация
iter_solutions = [theta]

for iteration in range(n_iterations):       
    gradients = 2 / n * x_matrix.T @ (x_matrix @ theta - y) 
    theta = theta - lr * gradients
    
    iter_solutions.append(theta)
# изобразим результаты численного решения

plt.figure(figsize=(6.4 * 1, 4.8 * 1))

plt.scatter(x, y, color='g', label='Выборка')
plt.plot(x_true, y_true, linewidth=1, label='Исходная зависимость')
plt.plot(x_true, x_true * theta[1] + theta[0], linewidth=1, color='r', label='Предсказанная зависимость')

plt.legend(loc='upper left', fontsize=13)
plt.show()
ani = animate_solutions(iter_solutions)
HTML(ani.to_html5_video())<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15930461403892412, 'fraction_numerical': 0.031051825934834902, 'mean_word_length': 4.5168878166465625, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 78, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '20', 'dir': 'jupyter-structured-clean-dedup', 'id': '30120', 'license': 'MIT', 'n_tokens_mistral': 4089, 'n_tokens_neox': 4009, 'n_words': 687, 'path': 'week_06_ml_intro/seminar_06.ipynb', 'repo_name': 'rualvi/cv_mipt_minor', 'size': '9146'}