Работы по машинному обучению 3ИСиП-19-1

—

от автора

Предобработка данных

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

import pandas as pd import numpy as np

Импортируем данные из файла в переменную и просматриваем содержимое

data_frame = pd.read_csv('bank.csv') data_frame
data_frame.info()

Начинаю с самого простого — бинарные признаки default, housing, loan.

data_frame['default'] = np.where(data_frame['default'] == 'yes', 1, 0) data_frame['housing'] = np.where(data_frame['housing'] == 'yes', 1, 0) data_frame['loan'] = np.where(data_frame['loan'] == 'yes', 1, 0)

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

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

В последствии, когда анализ будет выполнен без них, можно будет провести эксперимент с возвращением их в исходный набор данных

data_frame.drop(['day', 'month', 'contact'], axis = 1, inplace = True)

Для удобства в дальнейшей работе разделю исходный набор данных — на числовой и объектовый

object_df = data_frame.select_dtypes(include=['object']).copy() value_df = data_frame.select_dtypes(include=[int]).copy() value_df
object_df

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

object_df['job'].value_counts()

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

target = value_df['y'] value_df.drop('y', axis = 1, inplace = True)

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

object_df_encoded = pd.get_dummies(object_df) object_df_encoded

Выделить наиболее влияющие признаки на ‘подпишется ли клиент на срочный депозит’ и в дальнейшем использовать только их.

from sklearn.ensemble import RandomForestClassifier from sklearn.feature_selection import SelectFromModel
randomforest = RandomForestClassifier(random_state = 0, n_jobs = -1) selector = SelectFromModel(randomforest, threshold = 0.1) val_important = selector.fit_transform(value_df, target) val_important

Так, уже какие-то зависимости найдены, а что если попробовать обработать числовые данные? Например прошкалировать или нормализовать?

from sklearn.preprocessing import StandardScaler, Normalizer  scaler = StandardScaler() value_df_scaled = scaler.fit_transform(value_df)   normalizer = Normalizer() value_df_normalized = normalizer.fit_transform(value_df)  val_important_sc = selector.fit_transform(value_df_scaled, target) val_important_sc

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

val_important_nr = selector.fit_transform(value_df_normalized, target) val_important_nr

Признаков стало больше. Но хорошо ли это? Проверю в конечном анализе.
С помощью модели случайного леса можно так же посмотреть на коэффициенты важности признаков и на их основе построить диаграмму.

import matplotlib.pyplot as plt rf_model = randomforest.fit(value_df, target) names = value_df.columns.values ticks = [i for i in range(len(rf_model.feature_importances_))]  plt.figure() plt.title('Важность признаков') plt.bar(names, rf_model.feature_importances_) plt.xticks(ticks, names, rotation = 90) plt.show()

Ну вот, и на диаграмме сразу стало видно, какие столбцы выводит SelectFromModel с порогом 0.1. А что покажет нормализация?

rf_model = randomforest.fit(value_df_normalized, target) names = value_df.columns.values ticks = [i for i in range(len(rf_model.feature_importances_))]  plt.figure() plt.title('Важность признаков') plt.bar(names, rf_model.feature_importances_) plt.xticks(ticks, names, rotation = 90) plt.show()

Как-то не однозначно, не стоит сразу этому доверять, проверим это на обучении.

Так же не забываем найти и значимые признаки среди закодированных категорий.

obj_important = selector.fit_transform(object_df_encoded, target) obj_important

Не густо, надо вывести диаграмму.

rf_model = randomforest.fit(object_df_encoded, target) names = object_df_encoded.columns.values ticks = [i for i in range(len(rf_model.feature_importances_))]  plt.figure() plt.title('Важность признаков') plt.bar(names, rf_model.feature_importances_) plt.xticks(ticks, names, rotation = 90) plt.show()
Важность признаков
Важность признаков

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

Необходимо разделить данные на обучающую и тестовую выборки в соотношении 80%, 20%.

from sklearn.model_selection import train_test_split

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

features = np.array(pd.DataFrame(val_important).join(pd.DataFrame(obj_important), rsuffix='_obj')) features_train, features_test, target_train, target_test = train_test_split(features, target, test_size = 0.20, random_state = 0)

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

# импортируем модели, с помощью которых будеи проводить анализ from sklearn.neighbors import KNeighborsClassifier  from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier from sklearn.naive_bayes import GaussianNB  # этот медот понадобится для оценки точности обченной модели from sklearn.metrics import accuracy_score 

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

kn_model = KNeighborsClassifier(n_neighbors = 20) rfc_model = RandomForestClassifier(random_state = 0) ada_model = AdaBoostClassifier(random_state = 0) gnb_model = GaussianNB()

Обучаем все выбранные модельки на тренировочных выборках.

kn_model.fit(features_train, target_train) rfc_model.fit(features_train, target_train) ada_model.fit(features_train, target_train) gnb_model.fit(features_train, target_train)

Теперь необходимо выполнить предсказания на каждой из моделей на тестовой выборке.

kn_predict = kn_model.predict(features_test) rfc_predict = rfc_model.predict(features_test) ada_predict = ada_model.predict(features_test) gnb_predict = gnb_model.predict(features_test)

И на основе этих предсказаний проверяем точность моделей по ответам из тестовой выборки.

print('KNeighbors', accuracy_score(kn_predict, target_test)) print('RandomForest', accuracy_score(rfc_predict, target_test)) print('AdaBoost', accuracy_score(ada_predict, target_test)) print('GaussianNB', accuracy_score(gnb_predict, target_test))

Теперь для наглядности построим диаграмму точности каждой из моделей(хоть и значения отличаются на сотые).

names = ['KNeighbors', 'RandomForest', 'AdaBoost', 'GaussianNB'] ticks = [i for i in range(len(names))] values = [accuracy_score(kn_predict, target_test), accuracy_score(rfc_predict, target_test),          accuracy_score(ada_predict, target_test), accuracy_score(gnb_predict, target_test)]  plt.figure() plt.title('Важность признаков') plt.barh(names, values) plt.yticks(ticks, names, rotation = 0) plt.show()

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

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


ссылка на оригинал статьи https://habr.com/ru/articles/595429/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *