# импортируем необходимые нам библиотеки для работы с данными
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import re
# импорт моделей
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.dummy import DummyClassifier
# импорт метрик
from sklearn.metrics import f1_score, recall_score, precision_score, roc_curve
from sklearn.metrics import precision_recall_curve, accuracy_score, roc_auc_score
# импорт утилит
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.utils import shuffle
# импорт классов и пайплайнов
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn import set_config
# установим общие параметры для тетради
# оформление графиков
sns.set()
# вывод pipeline
set_config(display='diagram')
# читаем файл и сохраняем в переменные дальнейшей работы, в том числе изменений
# используем оператор обработки исключений, чтобы избежать ошибки, при открытии данных,
# расположенных по другому адресу
try:
df = pd.read_csv('/datasets/Churn.csv')
except:
df = pd.read_csv('datasets/Churn.csv')
try:
df_control = pd.read_csv('/datasets/Churn.csv')
except:
df_control = pd.read_csv('datasets/Churn.csv')
# проверим результат, а также ознакомимся с данными
# используем метод sample() для случайной выборки
# с параметром random_state=1, для сохранения результата
# при повторных запусках алгоритма
data_list = [df, df_control]
for data in data_list:
display(data.sample(5, random_state=1))
print('=' * 45)
# изучим данные более внимательно
df.info()
for inx, name in enumerate(df.columns):
df.rename(
columns=
{df.columns[inx]:
'_'.join(re.findall('[A-Z][^A-Z]*',
df.columns[inx]))
.lower()}, inplace=True)
# проверим результат
df.columns
# изучим содержание датасета на предмет явных проблем
print('\033[1m' + 'Количество явных дубликатов: ' + '\033[0m', df.duplicated().sum())
print('=' * 45)
n=0
for column in df:
print('\033[1m' + f'Количество пропусков в столбце {df.columns[n]}:' + '\033[0m',
df[column].isna().sum())
print('=' * 45)
print()
n += 1
# изучим содержание датасета на предмет явных проблем
print('\033[1m' + 'Количество явных дубликатов без учета RowNumber и CustomerId: ' + '\033[0m', df.drop(
['row_number', 'customer_id'], axis=1).duplicated().sum())
print('=' * 45)
print(
'\033[1m' + 'Количество явных дубликатов исключительно по признакам Surname, Gender, Age: ' + '\033[0m',
df[['surname', 'gender', 'age']].duplicated().sum())
print('=' * 45)
dupe_filter = df[['surname', 'gender', 'age']].duplicated(keep=False)
df[dupe_filter].sort_values('surname').head(15)
df = df.drop(['row_number', 'customer_id', 'surname'], axis=1)
df.describe()
df.hist(bins=50, figsize=(20,15), color='r', edgecolor='black', linewidth=1)
plt.show()
# подготовим датасет
df_cleaned = df.copy()
def boxplot_slave(data, name, xlim = None, ylim = None):
'''
boxplot_slave принимает данные в параметр data и возвращает боксплот;
name используется для разметки и принимает название исследуемого признака.
xlim и ylim используются для масштабирования графика, ограничивая его оси
и принимают кортеж (tuple) из двух цифр (начало и конец ограничения)
'''
# выведем описание данных
print('\033[1m' + f'Описание признака {name}:' + '\033[0m')
print(data.describe())
print('=' * 45)
# построим боксплот
box = plt.boxplot(
x=data, vert=False,
patch_artist=True, notch=True
)
fig = plt.gcf()
fig.set_size_inches(15, 8)
if xlim is not None:
plt.xlim(xlim)
if ylim is not None:
plt.ylim(ylim)
plt.title(
f'Боксплот признака {name}',
fontsize=14
)
plt.show()
# выведем его минимальные и максимальные значения
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1
lower_fence = Q1 - (1.5 * IQR)
upper_fence = Q3 + (1.5 * IQR)
print('\033[1m' + f'Пороговые значения боксплота {name}:' + '\033[0m')
print('Нижняя граница значений:', lower_fence)
print('Верхняя граница значений:', upper_fence)
print()
print()
def loss_estimator(feature_name, data=df_cleaned, lower_fence = None, upper_fence = None):
'''
loss_estimator принимает в параметры:
feature_name - наименование признака;
data - наименование датасета, в котором производится обработка (df_cleaned по умолчанию);
lower_fence - нижний порог значения признака,
после которого все значения отбрасываются (None по умолчанию);
upper_fence - верхний порог значения признака,
после которого все значения отбрасываются (None по умолчанию),
после чего отфильтровывает переданный датасет (data), по указанным значениям,
возвращает его и статистику изменения значений.
'''
before = len(df_cleaned)
if lower_fence is not None:
data = data[data[feature_name] >= lower_fence]
elif upper_fence is not None:
data = data[data[feature_name] <= upper_fence]
else:
print('Выбросы не очищались')
after = len(data)
print(f'Исходное количество наблюдений {before}')
print(f'Количество наблюдений уменьшилось на {1-after/before:.2%} по сравнению с предыдущей версией df_cleaned.')
print(f'Количество наблюдений уменьшилось на {1-after/len(df):.2%} по сравнению с df.')
print(f'Итоговое количество наблюдений {after}')
return data
df_cleaned['exited'].value_counts()
part = df_cleaned['exited'].value_counts()[1] / df_cleaned['exited'].value_counts()[0]
print(f'Доля положительного целевого признака в выборке {part:.2%}')
num_att = ['credit_score', 'age', 'tenure', 'balance', 'estimated_salary']
boxplot_slave(df_cleaned['credit_score'], df_cleaned['credit_score'].name)
df[df['credit_score'] < 383.0]
df_cleaned = loss_estimator(feature_name = 'credit_score', lower_fence=383.0)
# проверим результат
assert df_cleaned['credit_score'].min() == 383, 'Есть одинаковые пользователи в разных группах!'
plt.hist(df_cleaned['credit_score'], color ='r', edgecolor='black', linewidth=1, bins=50)
plt.title('Гистограмма credit_score', fontsize=14)
plt.show()
boxplot_slave(df_cleaned['age'], df_cleaned['age'].name)
df_cleaned = loss_estimator(feature_name = 'age', upper_fence = 62.0)
# проверим результат
assert df_cleaned['age'].max() == 62.0, 'Есть одинаковые пользователи в разных группах!'
plt.hist(df_cleaned['tenure'], color ='r', edgecolor='black', linewidth=1, bins=11)
plt.title('Гистограмма tenure', fontsize=14)
plt.show()
df_cleaned['tenure'].describe()
df[['tenure', 'exited']].corr()
boxplot_slave(df_cleaned['balance'], df_cleaned['balance'].name)
df_cleaned[df_cleaned['balance'] < 97157.960000][['balance', 'exited']].corr()
df_cleaned[['balance', 'exited']].corr()
boxplot_slave(df_cleaned['estimated_salary'], df_cleaned['estimated_salary'].name)
cat_att = df_cleaned.columns.drop(num_att)[:-1]
cat_att
for feature in cat_att:
print('\033[1m' + f'Значения признака {df_cleaned[feature].name}:' + '\033[0m')
print(df_cleaned[feature].value_counts())
print('=' * 45)
print()
df_cleaned[['num_of_products', 'has_cr_card', 'exited']].corr()
# разделим датасет на признаки и целевой признак
# сформируем фильтры
features = df_cleaned.columns.drop('exited')
target = ['exited']
# подготовим массивы
X = df_cleaned[features]
y = np.ravel(df_cleaned[target])
# подготовим массивы на данных с выбросами
X_raw = df[features]
y_raw = np.ravel(df[target])
print(num_att)
print(cat_att)
num_pipeline = Pipeline([
# для обработки пропусков
('imputer', SimpleImputer(strategy='mean')),
# для стандартизации
('std_caler', StandardScaler())
])
num_pipeline
full_pipeline = ColumnTransformer([
# встроим числовой пайплайн
('num', num_pipeline, num_att),
# для обработки категорий
('cat', OneHotEncoder(), cat_att)
])
full_pipeline
# lr_pipe
lr_pipeline = Pipeline([
('full', full_pipeline),
('lr', LogisticRegression(random_state=42))
])
# dtc_pipe
dtc_pipeline = Pipeline([
('full', full_pipeline),
('dtc', DecisionTreeClassifier(random_state=42) )
])
# rfc_pipe
rfc_pipeline = Pipeline([
('full', full_pipeline),
('rfc', RandomForestClassifier(random_state=42))
])
# сформируем лист пайплайнов
model_pipe_list = [lr_pipeline, dtc_pipeline, rfc_pipeline]
# подготовим тестовый набор без выбросов
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# подготовим обучающий и валидационный набор без выбросов
X_train, X_val, y_train, y_val = train_test_split(
X_train, y_train, test_size=0.25, random_state=42
)
# подготовим тестовый набор с выбросами
X_train_raw, X_test_raw, y_train_raw, y_test_raw = train_test_split(
X_raw, y_raw, test_size=0.2, random_state=42
)
# подготовим обучающий и валидационный набор с выбросами
X_train_raw, X_val_raw, y_train_raw, y_val_raw = train_test_split(
X_train_raw, y_train_raw, test_size=0.25, random_state=42
)
# подготовим объединенный набор без выбросов
X_train_max = pd.concat((X_train, X_val))
y_train_max = np.concatenate((y_train, y_val))
# подготовим объединенный набор с выбросами
X_train_max_raw = pd.concat((X_train_raw, X_val_raw))
y_train_max_raw = np.concatenate((y_train_raw, y_val_raw))
# определим функцию проверки
def ml_slave(mod, data_list, score_list, name_list=None, best_params = None):
'''
Функция принимает разные модели в параметры, чтобы вывести их accuracy и сравнить с целевым.
mod - вид модели;
data_list - список, содержащий датасеты для обучения модели [X, y, test];
score_list - список, собирающий оценки модели;
name_list - параметр для вывода названия модели вместе с оценкой (по умолчанию None),
'''
model = mod.fit(data_list[0], data_list[1])
predictions = model.predict(data_list[2])
result = f1_score(data_list[3], predictions)
if name_list is not None:
print(f'F1-score модели {name_list}: {result:.4}')
else:
print(f'F1-score модели: {result:.4}')
if best_params is not None:
best_params.append(model.best_params_)
print(f'Оценка достигнута при параметрах: {best_params[0]}')
score_list.append(result)
print('=' * 45)
print()
# сформируем списки для работы функций
# наборы
pipe_data_list = [X_train, y_train, X_val, y_val]
raw_pipe_data_list = [X_train_raw, y_train_raw, X_val_raw, y_val_raw]
# общий лист
total_data_list = [pipe_data_list, raw_pipe_data_list]
# оценки
pipe_score = []
raw_pipe_score = []
total_pipe_score = [pipe_score, raw_pipe_score]
# названия
model_names = ['LogisticRegression', 'DecisionTreeClassifier', 'RandomForestClassifier']
%%time
for i in range(0,2):
if i == 0:
print('\033[1m' + 'I. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ОЧИЩЕННОЙ ДАТЕ БЕЗ ВЫБРОСОВ' + '\033[0m')
else:
print('\033[1m' + 'II. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ГРЯЗНОЙ ДАТЕ С ВЫБРОСАМИ' + '\033[0m')
for inx, pipe in enumerate(model_pipe_list):
ml_slave(pipe, total_data_list[i], total_pipe_score[i], model_names[inx])
def downsample(features, target):
'''
downsample принимает наборы (features, target), после чего разделяет их на положительные и отрицательные,
уменьшает доминирующий признак, формирует новые наборы и возвращает измененные выборки.
'''
features_zeros = features[target == 0]
features_ones = features[target == 1]
target_zeros = target[target == 0]
target_ones = target[target == 1]
value = len(features_ones)
fraction = round((len(features_ones) / len(features_zeros)), 4)
features_downsampled = pd.concat(
[features_zeros.sample(frac=fraction, random_state=12345)] + [features_ones])
target_downsampled = np.concatenate(
(target_zeros[np.random.choice(
len(target_zeros), size=value)], target_ones)
)
features_downsampled, target_downsampled = shuffle(
features_downsampled, target_downsampled, random_state=12345)
return features_downsampled, target_downsampled
# подготовка списка данных для функции
features_downsampled, target_downsampled = downsample(
X_train, y_train
)
pure_downsampled_list = [features_downsampled, target_downsampled, X_val, y_val]
# подготовка списка данных для функции
features_downsampled_raw, target_downsampled_raw = downsample(
X_train_raw, y_train_raw
)
raw_downsampled_list = [features_downsampled_raw, target_downsampled_raw, X_val_raw, y_val_raw]
# сформируем списки для работы функций
# наборы
total_downsample_list = [pure_downsampled_list, raw_downsampled_list]
# подготовка списка для оценок
pure_downsample_score = []
raw_downsample_score = []
downasmpled_pipe_score = [pure_downsample_score, raw_downsample_score]
%%time
for i in range(0,2):
if i == 0:
print('\033[1m' + 'I. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ОЧИЩЕННОЙ DOWNSAMPLED-ДАТЕ БЕЗ ВЫБРОСОВ' + '\033[0m')
else:
print('\033[1m' + 'II. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ГРЯЗНОЙ DOWNSAMPLED-ДАТЕ С ВЫБРОСАМИ' + '\033[0m')
for inx, pipe in enumerate(model_pipe_list):
ml_slave(pipe, total_downsample_list[i], downasmpled_pipe_score[i], model_names[inx])
# определим функцию проверки
def ml_threshold_slave(mod, data_list, score_list, auc_roc_score, name_list = None, threshold_list = None):
'''
Функция принимает разные модели в параметры, чтобы вывести их accuracy и сравнить с целевым.
mod - вид модели;
data_list - список, содержащий датасеты для обучения модели [X, y, test];
score_list - список, куда будут сохранены оценки (f1);
auc_roc_score - список, куда будут сохранены оценки roc-кривой;
name_list - параметр для разметки, передающий название модели;
threshold_list - список, сохраняющий лучшее значение порога.
'''
# основная часть функции, оценка по разным порогам
mod.fit(data_list[0], data_list[1])
predictions = mod.predict_proba(data_list[2])
probabilities_one_valid = predictions[:, 1]
best_score = 0
best_threshold = 0
# цикл на перебор порога и вывод результатов на экран
if name_list is not None:
print('\033[1m' + f'Статистика модели {name_list}' + '\033[0m')
else:
print('\033[1m' + 'Статистика модели' + '\033[0m')
for threshold in np.arange(0, 0.95, 0.05):
predicted_valid = probabilities_one_valid > threshold
precision = precision_score(data_list[3], predicted_valid)
recall = recall_score(data_list[3], predicted_valid)
result = f1_score(data_list[3], predicted_valid)
print('Порог = {:.2f} | Точность = {:.3f}, Полнота = {:.3f} | F1-мера = {:.3f}'.format(
threshold, precision, recall, result))
if best_score < result:
best_score = result
best_threshold = threshold
# вывод оценок
print()
if name_list is not None:
print('\033[1m' + f'Оценки модели {name_list}' + '\033[0m')
else:
print('\033[1m' + 'Оценки модели' + '\033[0m')
print(f'F1: {best_score:.4}')
auc_roc = roc_auc_score(data_list[3], predictions[:, 1])
print('AUC:', auc_roc)
print('Лучшее значение порога:', round(best_threshold, 2))
print('=' * 45)
print()
print()
# дополнение списка оценок
score_list.append(round(best_score, 4))
auc_roc_score.append(auc_roc)
if threshold_list is not None:
threshold_list.append(round(best_threshold, 4))
# построим PR-кривую
precision, recall, thresholds = precision_recall_curve(
data_list[3], predictions[:, 1]
)
plt.figure(figsize=(10, 10))
plt.step(recall, precision, where='post')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.ylim([0.0, 1.05])
plt.xlim([0.0, 1.0])
plt.title('PR-кривая')
# построим ROC-кривую
fpr, tpr, thresholds = roc_curve(data_list[3], predictions[:, 1])
plt.figure(figsize=(10, 10))
plt.plot(fpr, tpr, linestyle='-')
plt.plot([0, 1], [0, 1], linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC-кривая')
plt.show()
# подготовка списка для оценок f1
pure_threshold_score = []
raw_threshold_score = []
total_threshold_score = [pure_threshold_score, raw_threshold_score]
# подготовка списка для оценок ROC-кривых
pure_auc_roc = []
raw_auc_roc = []
total_auc_roc = [pure_auc_roc, raw_auc_roc]
%%time
for i in range(0,2):
if i == 0:
print('\033[1m' + 'I. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ОЧИЩЕННОЙ THRESHOLDED-ДАТЕ БЕЗ ВЫБРОСОВ' + '\033[0m')
else:
print('\033[1m' + 'II. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ГРЯЗНОЙ THRESHOLDED-ДАТЕ С ВЫБРОСАМИ' + '\033[0m')
for inx, pipe in enumerate(model_pipe_list):
ml_threshold_slave(
pipe, total_data_list[i],
total_threshold_score[i],
total_auc_roc[i],
model_names[inx]
)
# сформируем сводную таблицу
score_table = pd.DataFrame(
{'model': model_names,
'pure_f1': total_pipe_score[0], 'raw_f1': total_pipe_score[1],
'pure_downsampled_score': downasmpled_pipe_score[0],
'raw_downsampled_score': downasmpled_pipe_score[1],
'pure_threshold_score': total_threshold_score[0],
'raw_threshold_score': total_threshold_score[1],
'pure_auc_roc': total_auc_roc[0],
'raw_auc_roc': total_auc_roc[1]
}
)
pd.set_option('max_colwidth', 400)
score_table
score_table.max()
# сетка параметров для LogisticRegression
lr_param_grid = [
{'lr__class_weight': [None, 'balanced'],
'lr__C': [0.5, 1.0, 1.5, 2.0]}
]
# сетка параметров для DecisionTreeClassifier
dtc_param_grid = [
{'dtc__max_depth': range(1, 10),
'dtc__criterion': ['gini', 'entropy'],
'dtc__splitter': ['random', 'best'],
'dtc__min_samples_leaf': range(1, 10),
'dtc__class_weight': [None, 'balanced']}
]
# сетка параметров для RandomForestClassifier
rfc_param_grid = [
{'rfc__n_estimators': range(50, 200, 50),
'rfc__criterion': ['gini', 'entropy'],
'rfc__min_samples_split': range(2, 10),
'rfc__min_samples_leaf': range(1, 10, 3),
'rfc__class_weight': [None, 'balanced']}
]
# список сеток
param_grid_list = [lr_param_grid, dtc_param_grid, rfc_param_grid]
tune_pure_score = []
tune_raw_score = []
total_tune_score = [tune_pure_score, tune_raw_score]
lr_params = []
dtc_params = []
rfc_params = []
raw_lr_params = {}
raw_dtc_params = {}
raw_rfc_params = {}
best_params_list = [lr_params, dtc_params, rfc_params]
raw_best_params_list = [raw_lr_params, raw_dtc_params, raw_rfc_params]
total_params_list = [best_params_list, raw_best_params_list]
%%time
for i in range(0,2):
if i == 0:
print('\033[1m' + 'I. ПОКАЗАТЕЛИ НАСТРОЕННЫХ МОДЕЛЕЙ ПО ОЧИЩЕННОЙ ДАТЕ БЕЗ ВЫБРОСОВ' + '\033[0m')
else:
print('\033[1m' + 'II. ПОКАЗАТЕЛИ НАСТРОЕННЫХ МОДЕЛЕЙ ПО ГРЯЗНОЙ ДАТЕ С ВЫБРОСАМИ' + '\033[0m')
for inx in range(0, 3):
grid_pipeline = GridSearchCV(
model_pipe_list[inx],
param_grid_list[inx],
cv=5, scoring='f1',
return_train_score=True,
verbose=1)
ml_slave(
grid_pipeline, total_data_list[i],
total_tune_score[i], model_names[inx], best_params_list[inx]
)
# определим модели с лучшими параметрами
lr_model = lr_pipeline.set_params(**best_params_list[0][0])
dtc_model = dtc_pipeline.set_params(**best_params_list[1][0])
rfc_model = rfc_pipeline.set_params(**best_params_list[2][0])
tune_model_list = [lr_model, dtc_model, rfc_model]
tune_pure_score_thresh = []
tune_raw_score_thresh = []
total_threshold_score = [tune_pure_score_thresh, tune_raw_score_thresh]
pure_threshold_number = []
raw_threshold_number = []
threshold_number = [pure_threshold_number, raw_threshold_number]
%%time
for i in range(0,2):
if i == 0:
print('\033[1m' + 'I. ПОКАЗАТЕЛИ НАСТРОЕННЫХ МОДЕЛЕЙ ПО ОЧИЩЕННОЙ THRESHOLDED-ДАТЕ БЕЗ ВЫБРОСОВ' + '\033[0m')
else:
print('\033[1m' + 'II. ПОКАЗАТЕЛИ НАСТРОЕННЫХ МОДЕЛЕЙ ПО ГРЯЗНОЙ THRESHOLDED-ДАТЕ С ВЫБРОСАМИ' + '\033[0m')
for inx, pipe in enumerate(tune_model_list):
ml_threshold_slave(
pipe,
total_data_list[i],
total_threshold_score[i],
total_auc_roc[i],
model_names[inx],
threshold_number[i]
)
# сформируем сводную таблицу
tune_score_table = pd.DataFrame(
{'model': model_names,
'pure_threshold_number': threshold_number[0],
'raw_threshold_number': threshold_number[1],
'pure_f1': total_pipe_score[0],
'raw_f1': total_pipe_score[1],
'pure_f1_tune_thresh': total_threshold_score[0],
'raw_f1_tune_thresh': total_threshold_score[1]
}
)
pd.set_option('max_colwidth', 400)
tune_score_table
# подготовим объединенный набор без выбросов
X_train_max = pd.concat((X_train, X_val))
y_train_max = np.concatenate((y_train, y_val))
# подготовим объединенный набор с выбросами
X_train_max_raw = pd.concat((X_train_raw, X_val_raw))
y_train_max_raw = np.concatenate((y_train_raw, y_val_raw))
# определим списки для функции
pure_data_max_list = [X_train_max, y_train_max, X_test, y_test]
raw_data_max_list = [X_train_max_raw, y_train_max_raw, X_test_raw, y_test_raw]
pure_raw_max_data = [pure_data_max_list, raw_data_max_list]
# подготовка списка для оценок f1
test_pure_threshold_score = []
test_raw_threshold_score = []
test_total_threshold_score = [test_pure_threshold_score, test_raw_threshold_score]
# подготовка списка для оценок ROC-кривых
test_pure_auc_roc = []
test_raw_auc_roc = []
test_total_auc_roc = [test_pure_auc_roc, test_raw_auc_roc]
test_pure_threshold_number = []
test_raw_threshold_number = []
test_threshold_number = [test_pure_threshold_number, test_raw_threshold_number]
%%time
for i in range(0,2):
if i == 0:
print('\033[1m' + 'I. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ОЧИЩЕННОЙ THRESHOLDED-ДАТЕ БЕЗ ВЫБРОСОВ' + '\033[0m')
else:
print('\033[1m' + 'II. ПОКАЗАТЕЛИ ЧИСТЫХ МОДЕЛЕЙ ПО ГРЯЗНОЙ THRESHOLDED-ДАТЕ С ВЫБРОСАМИ' + '\033[0m')
for inx, pipe in enumerate(tune_model_list):
ml_threshold_slave(
pipe,
pure_raw_max_data[i],
test_total_threshold_score[i],
test_total_auc_roc[i],
model_names[inx],
test_threshold_number[i]
)
# сформируем сводную таблицу
test_score_table = pd.DataFrame(
{'model': model_names,
'test_pure_f1': test_total_threshold_score[0],
'test_raw_f1': test_total_threshold_score[1],
'test_pure_auc_roc': test_total_auc_roc[0],
'test_raw_auc_roc': test_total_auc_roc[1],
'pure_threshold_number': test_threshold_number[0],
'raw_threshold_number': test_threshold_number[1]
}
)
pd.set_option('max_colwidth', 400)
test_score_table
display(score_table.style.set_caption('Оценки чистых моделей'))
display(tune_score_table.style.set_caption('Оценки настроенных моделей'))
test_score_table.style.set_caption('Оценки моделей на тестовой дате')
sns.set(rc={'figure.figsize':(11.7,8.27)})
feature_importance = tune_model_list[2].named_steps['rfc'].feature_importances_
feature_imp = pd.DataFrame(sorted(zip(feature_importance, features)), columns=['Value','Feature'])
sns.barplot(x="Value", y="Feature", data=feature_imp.sort_values(by="Value", ascending=False))
plt.title('Feature importance')
plt.tight_layout()
plt.show();