Найти в Дзене
ChinovnickBox

Шпаргалка по машинному обучению.

Оглавление

Небольшое предисловие

Многие студенты колледжей в России в этом году будут обязаны сдать демо-экзамен по дисцеплине, посвящённой изучению темы машинного обучения, но качество обучения в учебном заведении может страдать в силу малого количества опыта в вопросе проведения подобного рода тестирования. В силу данного обстоятельства студенты в поисках материала для подготовки обращаются к помощи интернет ресурсов, но с ужасом обнаруживают, что информация не структуризированна, так как было бы удобно экзаменуемым.

Меня тоже коснулась эта проблема, поэтому я решил написать статью, объясняющую принципы работы с необходимыми инструментами для сдачи демонстративного экзамена.

Чем эта статья отличается от любых других, посвящённых основам работы с pandas, seaborn и sklearn.

Именно данная работа обладает необходимой комплексностью повествования, описовающего специфику использования перечисленных ранее инструментов в контексте сдачи демо-экзамена. В данной статье собрано описание использования минимального набора инструментов, доступных к применению при выполнении поставленных комиссией задач.

Ход работы

Мы разбираем непосредственно один из демонстрационных вариантов прошлых лет, но в подробностях описывая каждый шаг, имея расчёт на то, что читатель сможет обратиться к шагам решения и описанным в них инструментам.

Скачать готовый ipynb файл и разбираемую таблицу можно по ссылке:

0 - Начало работы.

В первую очередь нам необходима зайти в среду разработки, которая будет предоставлена на экзамене. Как правило это Anaconda Jupyter или Google Colab, однако экзаменационная комиссия вряд-ли будет против, если вы будете использовать что-то другое.

0.1 Заходим в Jupyter любым удобным способом:

0.2 Включаем подсказки. Для этого нам нужно перейти во вкладку Nbextensions, снять галочку с пункта " disable configuration ... " и поставить галочку напротив пункта "Hinterland".

-2

0.3 Создаём новый файл

-3

1 - Выполнение примера первой части экзамена

1.1 - Импортируем необходимые для выполнения первой части библиотек

import pandas as pd
#Для манипуляции данными
import numpy as np
#Позволяет использовать новые математические инструменты, например читать NaN'ы
import matplotlib.pyplot as plt
#Для рисования графиков

1.2 - Читаем необходимых нам файл

data = pd.read_csv('Адрес файла')
data

-4

1.3 - Посмотрим информацию о созданном нами dataset'е

data.shape #Выводим размерность dataframe'a

-5

data.info() #Вывадим информацие о df'e.
#Нам это нужно, что-бы узнать типы данных столбцов

-6

Благодаря этой команде мы узнали типы данных столбцов. Так-же можно заметить, что столбец furnished (мебельный) полностью заполнен пропусками данных (NaN) .

Давайте проверим количество пустых значений во всех столбцах.

data.isna().sum() #isna - ищет пустые значения(NaN'ы), а sum() выводить их сумму

1.4 - Удалим не информативные столбцы

data.drop("furnished", axis = 1, inplace = True) # Удаляем, т.к слишком много NaN
# axis = 1 обозначет то, что мы удаляем столбец, а не строку
# inplace = True обозначет то, что df изменён
data.drop(["end_date", "start_date"], axis = 1, inplace = True) #Удяляем даты из за их неинформативности

1.5 - Теперь нам для каждого столбца(признака) таблицы повторить этот процесс, если нужно. Заменяем строковые переменные на числовые и NaN'ы на средние значения

1.5.1 - Выполним действия над столбцом "total_floor_count"

Чтобы заменить найти строковые значения столбца нам нужно сначала их найти. Для этого воспользуемся методом value_counts()

data["total_floor_count"].value_counts()

-7

Строковые значения могут вызывать проблемы с обучение модели, так что заменим их на числовые.

data["total_floor_count"].replace("10-20 arası", 15, inplace = True)
#Заменяем элемнет "10-20 arası" на 15
data["total_floor_count"].replace("20 ve üzeri", 20, inplace = True)
#Заменяем элемент "20 ve üzeri" на 20

Теперь нам нужно заменить пустые значения на медиану столбца

data["total_floor_count"].fillna(data["total_floor_count"].median(), inplace = True)
#При помощи fillna заменяем NaN'ы на медиану столбца
data["total_floor_count"] = data["total_floor_count"].astype("int64")
#Приобразуем столбец в тип данных int64

1.5.2 - Теперь выполним действия над столбцом "building_age"

data["building_age"].value_counts()

Этот столбец содержит много строковых и много числовых значений, что делает обработку данных невозможной. Для того, что-бы обеспечить дальнейшую работоспособность программы нам необходимо декодировать этот столбец, т.е заменить все строковые значения на их уникальные номера.

Для этого импортируем LabelEncoder

from sklearn.preprocessing import LabelEncoder #Импортируем LabelEncoder
le = LabelEncoder() #Создаём экземпляр LabelEncoder

Заменяем столбец "building_age" на его декодированную версию

data["building_age"] = le.fit_transform(data["building_age"].astype(str))

Проверим результат декодирования столбца

data["building_age"].value_counts()

"!Узнай что это или удали!"

le.classes_

-8

1.5.3 - Теперь подготовим столбец "floor_no"

Посмотрим уникальные значения столбца

data["floor_no"].value_counts()

В столбце 'floor_no' мы считаем не информативным, так как он может зашумить нашу модель. Удалим его.

data.drop("floor_no", axis =1, inplace = True)

1.5.4 - Перейдём к столбцу "size"

data["size"].value_counts()

Столбец полностью состоит из числовых значений, следовательно его квантиль(Значение, которое заданная случайная величина не превышает с фиксированной вероятностью) может иметь выбросы(значения сильно больше или сильно меньше среднего). Это может негативно повлиять на качество модели. Чтобы этого избежать нам нужно посчитать максимальный и минимальный квантиль, чтобы затем удалить их выбросы.

quant = data["size"].quantile(0.9)# считаем квантиль 90 %
quant_low = data["size"].quantile(0.1)# считаем квантиль 10 %

df_new = data[data["size"] < quant] # убираем выбросы по квантилю
df_new = df_new[df_new["size"] > quant_low] # убираем выбросы по квантилю

В демонстративных целях мы можем построить график, называемый 'ящиком с усами', чтобы проверить верность нашего решения.

-9

Для дальнейшего преобразования столбца нам нужно посчитать его максимум

df_new[df_new["size"] < quant]["size"].max() # считаем максимум

Теперь проверим есть ли в столбце пустые значения

df_new.isna().sum() # пустых значений нет

-10

1.5.5 - Разберём столбец "heating_type"

Посмотрим его уникальные значения

df_new["heating_type"].value_counts()

-11

Заменим строки на самое популярное значение столбца и закодируем переменную

df_new["heating_type"].fillna("Kombi (Doğalgaz)", inplace = True) # заменяем пропуски на часто встречаемое
df_new["heating_type"] = le.fit_transform(df_new["heating_type"]) # кодируем переменную

Столбец 'price' содержит огромное количество выбросов, поэтому мы не сможем взять его для обучения нашей модели, однако удалять его мы не будем. И просто заменим пропуски медианой значения

df_new["price"].fillna(df_new["price"].median(), inplace = True)

Посмотрим на уникальные значения ячеек столбца

df_new["price_currency"].value_counts()

-12

Заменим пустые значения самыми популярными значениями и закодируем весь столбец

df_new["price_currency"].fillna("TRY", inplace = True)
df_new["price_currency"] = le.fit_transform(df_new["price_currency"])

1.5.7 - В столбце 'type' всего одно уникальное значение, так-что мы можем удалить его из базы данных.

df_new["type"].value_counts() # В столбце всего одно уникальное значение

df_new.drop("type", axis = 1, inplace = True)

1.5.8 - Перейдём к столбцу 'sub_type'

df_new["sub_type"].value_counts()

В данном столбце отсутствуют пустые элементы, так - что мы можем просто закодировать его.

df_new["sub_type"] = le.fit_transform(df_new["sub_type"]) # кодируем переменные

1.5.9 - Проверим столбец 'listing_type'

df_new["listing_type"].value_counts()

Так как он имеет всего 3 уникальных числовых значения, то мы можем просто оставить этот столбец без изменений.

1.5.10 - В столбце 'tom' так-же есть определённое количество (181) уникальных значений и мы можем оставить и этот столбец без изменений.

df_new["tom"].value_counts()

-13

1.5.11 - Признак 'room_count' представляет собой столбец, состоящий из строковых значений. Из этого следует то, что нам нужно их декодировать.

df_new["room_count"] = le.fit_transform(df_new["room_count"])

1.5.12 - Столбец id мы можем просто удалить, так как он не поможет нам обучить модель

df_new.drop("id", axis = 1, inplace = True)

1.5.13 - Посмотрим на столбец 'address'

df_new["address"].value_counts()

-14

В столбце слишком много уникальных значений, что без сомнений внесёт шум в нашу модель. Удалим этот столбец.

df_new.drop("address", axis = 1, inplace = True)

1.6 - Оценим нашу очищенную и улучшенную модель

df_new

-15

2 - Выполнение примера второй части экзамена

Задания в второй части состоит из нескольких пунктов.

2.1 - Отбора признаков. Нам необходимо определить, какие признаки имеют наибольшее влияние на классификацию объектов по возрасту недвижимости (building_age) и оставить только их для обучения. Могут остаться и все исходные признаки. Необходимо обосновать выбор признаков, оставленных для обучения.

Однако в нашем случае признаки были отобраны уже на предыдущем этапе, но в можете просто еще раз продублировать всю последовательность действий в отчёте. Также можно обучить алгоритм и построить график важности признаков и показать, что все отобранные признаки влияют на конечный результат классификации. К сожалению мы не можем выполнить задание полностью без использования обучающей и тестовой выборки, так что вернёмся к этому пункту после выполнения 2.2.

2.2 - Разбиения данных на обучающую и тестовую выборку. Необходимо определить принцип разделения данных на обучающую и тестовую выборки. Даже если вы выбираете случайное разделение данных, необходимо обосновать выбор данного принципа.

Чтобы разбить разбить данные на обучающую и тестовую выборку нам нужно сначала создать выборку ответов(матрицу ответов)

x = df_new.drop("building_age", axis = 1) #Выборка обучающая
y = df_new["building_age"] #Выборка ответеная

Импортируем библиотеки для создания нужных нам выборок

from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

Создаём обучающую и тестовою выборку

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 42)

2.1 - Продолжение отбора признаков

Инструменты для машинного обучения градиентным бустингом мы возьмём из библиотеки xgboost, но вы можете использовать любую другую, например 'sklearn'.

from xgboost import XGBClassifier, plot_importance, plot_tree
#Импортируем классификатор

Создаём экземпляр классификатора, обучающего модель по модели случайного леса

xgb_cls = XGBClassifier(n_estimators = 100, learning_rate = 0.3, n_jobs = -1, random_state = 1)
xgb_cls.fit(x_train, y_train)
#Непосредственно тренеруем модель(метод для способов тренеровки моделей одинаков)

-16

Сохраняем predict(предсказание) в переменную

y_pred = xgb_cls.predict(x_test)

Смотрим текстовый отчёт по показателям классификации

print(classification_report(y_test, y_pred))

-17

Так-же мы можем воспользоваться accuracy_score для отображения точности модели, но для начала нам нужно импортировать его из библиотеки metrix

from sklearn.metrics import accuracy_score print(accuracy_score(y_pred, y_test))

Отберём признаки с помощью алгоритма и нарисуем график важности, чтобы определить силу влияния признаков(столбцов) на классификацию

plot_importance(xgb_cls)

-18

По графику важности признаков можно заметить, что признаки price_currency и listing_type не оказывают большого влияния на классификацию, значит, их можно удалить.

df_n = df_new.drop(["price_currency", "listing_type"], axis = 1)
X = df_n.drop("building_age", axis = 1)
y = df_n["building_age"]

Разбиваем новые данные на тестовою и тренировочную выборку

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 42)

2.3 - Классификации объектов. Необходимо выбрать модель классификации недвижимости по возрасту недвижимости (building_age), обосновать выбор модели. Необходимо обучить модель на обучающей выборке и протестировать. Необходимо предоставить показатели точности работы выбранной модели и всех рассматриваемых.

Импортируем необходимые для задачи классификации инструменты

from xgboost import XGBClassifier, plot_importance, plot_tree

2.3 - Классификации объектов. Необходимо выбрать модель классификации недвижимости по возрасту недвижимости (building_age), обосновать выбор модели. Необходимо обучить модель на обучающей выборке и протестировать. Необходимо предоставить показатели точности работы выбранной модели и всех рассматриваемых.

Импортируем необходимые для задачи классификации инструменты

from xgboost import XGBClassifier, plot_importance, plot_tree

Создаём экземпляр класса

xgb_cls = XGBClassifier(n_estimators = 100, learning_rate = 0.3, n_jobs = -1, random_state = 1)

Тренируем данные градиентным бустингом

xgb_cls.fit(x_train, y_train)

-19

Сохраняем предсказание в переменную

y_pred = xgb_cls.predict(x_test)

Смотрим текстовый отчёт по задачам классификации

print(classification_report(y_test, y_pred))

-20

Отбираем признаки с помощью алгоритма

plot_importance(xgb_cls)

-21

3.1 - Отбор признаков

Необходимо определить, какие признаки имеют наибольшее влияние цены на недвижимость (price) и оставить только их для обучения. Могут остаться и все исходные признаки. Необходимо обосновать выбор признаков, оставленных для обучения.

3.2 Разбиение данных на обучающую и тестирующую выборки

Необходимо определить принцип разделения данных на обучающую и тестирующую выборки. Даже если вы выбираете случайное разделение данных, необходимо обосновать выбор данного принципа.

Нарисуем ящик с усами

sns.boxplot(df_new.price)

-22

Посчитаем квантили и очистим datafram'ы от выбросов по квантилю

quant = df_new["price"].quantile(0.6)# считаем квантиль 90 % quant_low = df_new["price"].quantile(0.01)# считаем квантиль 10 % df2 = df_new[df_new["price"] < quant] # убираем выбросы по квантилю df2 = df2[df2["price"] > quant_low] # убираем выбросы по квантилю

Нарисуем ещё один ящик с усами

sns.boxplot(df2.price)

-23

Создадим выборку ответов

X = df2.drop("price", axis = 1) #Удаляем столбец с выборкой ответо из основного df y = df2["price"] #Создаём выборку ответов

Создаём новые обучающие и тестовые выборки

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 42)

Создаём новые обучающие и тестовые выборки

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 42)

3.3 - Прогнозирование

Импортируем из библиотеки xgboost метод градиентной регрессии

from xgboost import XGBRegressor

Создадим модель обучения градиентной регрессии

xgb_regr = XGBRegressor(n_estimators = 1000, learning_rate = 0.1, n_jobs = -1, random_state = 1)

Тренируем модель градиентной регрессии

xgb_regr.fit(x_train, y_train)

-24

Сохраняем финальную модель предсказания в переменную

y_pred = xgb_regr.predict(x_test)

Вычисляем квадратных корень из оценки незаметного количества

np.sqrt(mean_squared_error(y_test, y_pred))

Выводим коэффициент детерминации

r2_score(y_test, y_pred)

Спасибо за внимание)