<jupyter_start><jupyter_text>Домашнее задание №1: Классификация.  Логистическая регрессия и kNN. Форма для сдачи будет опубликована позднее.  Пожалуйста, не производите никаких манипуляций с  переменной `_dict_for_submission` и с ячейками, в которых она используется. На ее основе будет сгенерирован итоговый файл для сдачи задания.<jupyter_code># Do not change me, just run
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
_dict_for_submission = dict()


def transform_list(list_of_ints):
    return [str(x) for x in list_of_ints]
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<jupyter_output><empty_output><jupyter_text>Часть 1. Небольшой numpy-разогрев. (10%)<jupyter_code>import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
# Создайте матрицу A размерами 10 на 10 из упорядоченных целых чисел от 0 до 100
# hint: np.arange(100).reshape((10, 10))

A = np.arange(100).reshape((10, 10))
A
# Посчитайте средние значения в матрице по столбцам

# Ваш код здесь
np.mean(A, axis=0)
# Транспонируйте матрицу A

# Ваш код здесь
A_t = A.T
A_t
# Перемножьте поэлементно матрицу A и транспонированную матрицу A 

# Ваш код здесь
A_t * A
# Посчитайте matrix product (результат матричного умножения) матрицы A на саму себя и запишите в матрицу B
# https://en.wikipedia.org/wiki/Matrix_multiplication
# or https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html

B = A @ A<jupyter_output><empty_output><jupyter_text>Не меняйте следующую ячейку. Просто запустите ее.<jupyter_code># Do not change me, just run
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
_dict_for_submission['B'] = transform_list(list(B.flatten()))
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<jupyter_output><empty_output><jupyter_text>Часть 2. Логистическая регрессия и kNN. Будем работать с подвыборкой из [данных о типе лесного покрытия из репозитория UCI](http://archive.ics.uci.edu/ml/datasets/Covertype). Доступно 7 различных классов. Каждый объект описывается 54 признаками, 40 из которых являются бинарными. Описание данных доступно по ссылке, а так же в файле `covtype.info.txt`.<jupyter_code>import pandas as pd
# If on colab, uncomment the following lines

# !wget "https://downloader.disk.yandex.com/disk/cd3ead013809a9da37434c792796d4b063dfc89571c68c273ca3788013b82bf8/5d865a2d/8bfV6Unxao6CYWcER5-G5fza25GZaFjE_xFvc0-ExCwlqmFjBf2bynRfBnL6ubJC8XhsoYHi7h9Nu6gfvS8wxg%3D%3D?uid=76549735&filename=forest_dataset.csv&disposition=attachment&hash=&limit=0&content_type=application%2Fvnd.ms-excel&owner_uid=76549735&fsize=1293856&hid=9b439c18e67923b45c3b3d8891bdf9ab&media_type=spreadsheet&tknv=v2&etag=45e530aa3c9796cb705d4e27be7a6e9c" -O forest_dataset.csv
all_data = pd.read_csv('forest_dataset.csv')<jupyter_output><empty_output><jupyter_text>Выделим 20% данных в `delayed_data` в качестве выборки, на которой будет производиться финальное сравнение моделей (до конца ноутбука она более не используется), в `all_data` поместим оставшиеся 80%. Не будем перемешивать данные сознательно (для удобства проверки).<jupyter_code>delayed_data = all_data[int(0.8 * len(all_data)):]
all_data = all_data[:int(0.8 * len(all_data))]<jupyter_output><empty_output><jupyter_text>Выделим значения метки класса в переменную `labels`, признаковые описания в переменную `feature_matrix`. Так как данные числовые и не имеют пропусков, переведем их в `numpy`-формат с помощью метода `.values`.<jupyter_code>labels = all_data[all_data.columns[-1]].values
feature_matrix = all_data[all_data.columns[:-1]].values

delayed_labels = delayed_data[delayed_data.columns[-1]].values
delayed_feature_matrix = delayed_data[delayed_data.columns[:-1]].values<jupyter_output><empty_output><jupyter_text>2.1 Двуклассовая классификация (10%) Для начала будем работать только с двумя типами лесного покрытия. Обучите линейный классификатор для разделения двух классов. Данные разделите на train и test с помощью `train_test_split`.<jupyter_code>from sklearn.model_selection import train_test_split

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import f1_score, accuracy_score
two_class_labels_indices = (labels == 1) + (labels == 2)

two_class_feature_matrix = feature_matrix[two_class_labels_indices]
two_class_labels = labels[two_class_labels_indices]
train_feature_matrix, test_feature_matrix, train_labels, test_labels = train_test_split(two_class_feature_matrix, two_class_labels)<jupyter_output><empty_output><jupyter_text>Обучите логистическую регрессию. Оцените качество классификации на отложенной выборке с помощью `accuracy` и `f1_score` ([Wikipedia](https://en.wikipedia.org/wiki/F1_score)).<jupyter_code>lr_clf = LogisticRegression(max_iter=3000)
# Ваш код здесь
# from sklearn.preprocessing import StandardScaler

# scaler = StandardScaler()
# train_feature_matrix_scaled = scaler.fit_transform(train_feature_matrix)
# test_feature_matrix_scaled = scaler.transform(test_feature_matrix)
lr_clf.fit(train_feature_matrix, train_labels)
preds_1 = lr_clf.predict(test_feature_matrix)
print('f1-score = {}'.format(f1_score(test_labels, preds_1)))
print('accuracy = {}'.format(accuracy_score(test_labels, preds_1)))<jupyter_output>f1-score = 0.7143879742304938
accuracy = 0.7672112018669778<jupyter_text>2.2 Многоклассовая классификация: логистическая регрессия (40%) **Комментарий:***Логистическая регрессия позволяет решать и задачу многоклассовой классификации. Класс ``LogisticRegression`` позвляет это делать двумя способами:* - *1. Стандартный One vs Rest (т.е. каждый класс отделяется от всех других). Параметр `multi_class='ovr'`.*- *2. Используюя кросс-энтропию (оценивается сразу вектор вероятностей принадлежности классам). Параметр `multi_class='multinomial'`.**По умолчанию будем использовать второй способ.* Теперь будем работать со всеми 7 типами покрытия (данные уже находятся в переменных `feature_matrix` и `labels`, если Вы их не переопределили). Разделите выборку на обучающую и тестовую с помощью метода `train_test_split`, используйте значения параметров `test_size=0.2`, `random_state=42`. Обучите логистическую регрессию  на данном датасете.<jupyter_code>lr_clf = LogisticRegression(max_iter=3000, multi_class='multinomial')

# Ваш код здесь
#multi_scaler = StandardScaler()

feature_matrix_train, feature_matrix_test, labels_train, labels_test = train_test_split(feature_matrix,
                                                                                          labels,
                                                                                          test_size=0.2,
                                                                                          random_state=42)
# feature_matrix_train_scaled = multi_scaler.fit_transform(feature_matrix_train)
# feature_matrix_test_scaled = multi_scaler.transform(feauture_matrix_test)
lr_clf.fit(feature_matrix_train, labels_train)<jupyter_output><empty_output><jupyter_text>С помощью 5-кратной кросс-валидации (`GridSearchCV`) подберите оптимальное значение параметров `С` и `penalty`. Для параметра `C` используйте набор значений `np.linspace(0.01, 1, 10)`, а для `penalty` - `['l1', 'l2']`. Критерий качества `scoring = 'accuracy'`.<jupyter_code># Ваш код здесь
from sklearn.model_selection import GridSearchCV

parameters = {'C':np.linspace(0.01, 1, 10), 'penalty': ['l2']}
grid = GridSearchCV(estimator=LogisticRegression(multi_class='multinomial', max_iter=1000), 
                    param_grid=parameters, 
                    scoring='accuracy',
                    cv=5)
grid.fit(feature_matrix_train, labels_train)<jupyter_output><empty_output><jupyter_text>Постройте графики средних значений критерия качества `accuracy` для типов регуляризации `l1` и `l2` в зависимости от коэффициента регуляризации `C`.<jupyter_code># Ваш код здесь
y_plot_grid_logreg = grid.cv_results_['mean_test_score']
x_plot_grid_logreg = np.linspace(0.01, 1, 10)
plt.plot(x_plot_grid_logreg, y_plot_grid_logreg);<jupyter_output><empty_output><jupyter_text>Проанализируйте полученные графики. Чему равны найденные оптимальные значения параметров `C` и `penalty`?<jupyter_code># Ваш код здесь
grid.best_params_<jupyter_output><empty_output><jupyter_text>Используя найденные оптимальные значения `C` и `penalty`, обучите логистическую регрессию на обучающей выборке (train) и вычислите вероятности принадлежности к классам для тестовой (test)  выборки (`best_lr_clf.predict_proba`).<jupyter_code>best_lr_clf = LogisticRegression(C=0.12, max_iter=1000)

# Ваш код здесь
best_lr_clf.fit(feature_matrix_train, labels_train)
preds = best_lr_clf.predict_proba(feature_matrix_test)<jupyter_output><empty_output><jupyter_text>Для полученной матрицы вычислите усредненные по всем объектам из тестовой выборки значения вероятностей принадлежности к классам. Сравните ее оценкой вероятности принадлежности к классу на основе частот меток классов в обучающей выборке.<jupyter_code># Ваш код здесь
preds_proba_mean = np.mean(preds, axis=0)
x_plt = [i for i in range(1, 8)]
plt.plot(x_plt, preds_proba_mean);
train_quantity = [(labels_train == i).sum() / labels_train.shape[0] for i in set(labels_train)]
plt.plot(x_plt, train_quantity, c='r');<jupyter_output><empty_output><jupyter_text>2.3 Многоклассовая классификация: kNN (30%). Вспомним первое занятие. Обучите на том же датасете `KNeighborsClassifier` из `sklearn`.<jupyter_code>from sklearn.neighbors import KNeighborsClassifier

# Ваш код здесь
from sklearn.model_selection import cross_val_score


knc_model = KNeighborsClassifier()
knc_model.fit(feature_matrix_train, labels_train)
print('unform mean cv score: {}'.format(cross_val_score(estimator=KNeighborsClassifier(weights='uniform'),
                                                                                       X=feature_matrix_train,
                                                                                       y=labels_train)
                                        .mean()))
print('distance mean cv score: {}'.format(cross_val_score(estimator=KNeighborsClassifier(weights='distance'),
                                                                                         X=feature_matrix_train,
                                                                                         y=labels_train)
                                          .mean()))<jupyter_output>unform mean cv score: 0.71171875
distance mean cv score: 0.740625<jupyter_text>Попробуйте использовать различные стратегии вычисления весов: `[‘uniform’, ‘distance’]`. Выберите одно из них самостоятельно. Чем обоснован Ваш выбор? Переберите по сетке от `1` до `10` параметр числа соседей. Покажите на графике, как менялись значения критерия качества `accuracy` при изменении числа соседей.<jupyter_code># Ваш код здесь
params_knn = {'n_neighbors': [i for i in range(1, 11)]}
grid_knn = GridSearchCV(estimator=KNeighborsClassifier(weights='distance'),
                        param_grid=params_knn, cv=5, scoring='accuracy')
grid_knn.fit(feature_matrix_train, labels_train)
y_plot_scores = grid_knn.cv_results_['mean_test_score']
x_plot_neighbors = np.array([i for i in range(1, 11)])
plt.plot(x_plot_neighbors, y_plot_scores);<jupyter_output><empty_output><jupyter_text>Используя найденное оптимальное число соседей, вычислите вероятности принадлежности к классам для тестовой выборки (`.predict_proba`).<jupyter_code># Ваш код здесь
grid_knn.predict_proba(feature_matrix_test)<jupyter_output><empty_output><jupyter_text>Создайте объект `best_knn_clf`, который представляет собой лучший классификатор.<jupyter_code># Hint: для этого достаточно указать стратегию вычисления весов и число соседей в конструкторе

best_knn_clf = KNeighborsClassifier(n_neighbors=6, weights='distance')<jupyter_output><empty_output><jupyter_text>2.4 Сравнение результатов логистической регрессии и kNN (10%).В реальной жизни новые данные становятся доступны с течением времени. Сравните качество Вашей лучшей модели логистической регресии `best_lr_clf` и лучшего kNN `best_knn_clf` на отложенной выборке `delayed_data`. Какая из моделей показала лучший результат?<jupyter_code># Ваш код здесь
best_lr_clf.fit(feature_matrix_train, labels_train)
best_knn_clf.fit(feature_matrix_train, labels_train)
print(accuracy_score(delayed_labels, best_lr_clf.predict(delayed_feature_matrix)))
print(accuracy_score(delayed_labels, best_knn_clf.predict(delayed_feature_matrix)))<jupyter_output>0.6855
0.7525<jupyter_text>Не меняйте следующую ячейку. Запустите ее для генерации `submission` файла.<jupyter_code># Do not change me, just run
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
_dict_for_submission['best_lr_clf_delayed'] = transform_list(list(best_lr_clf.predict(delayed_feature_matrix)))
_dict_for_submission['best_knn_clf_delayed'] = transform_list(list(best_knn_clf.predict(delayed_feature_matrix)))

import json
with open('submission_hw1_basic.json', 'w') as iofile:
    json.dump(_dict_for_submission, iofile)
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1084818684695759, 'fraction_numerical': 0.025583896742470805, 'mean_word_length': 5.312803103782735, 'pattern_counts': {'":': 0, '<': 78, '<?xml version=': 0, '>': 78, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 33, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '20', 'dir': 'jupyter-structured-clean-dedup', 'id': '291488', 'license': 'MIT', 'n_tokens_mistral': 5031, 'n_tokens_neox': 5248, 'n_words': 935, 'path': 'homeworks_basic/homework1_Linclass_kNN/HW1_kNN_and_Logistic_regression.ipynb', 'repo_name': 'ivangoldov/ml-mipt', 'size': '13016'}