вторник, 22 марта 2022 г.

Машинное обучение с Python в розничной торговле : метрики качества в задачах классификации

Рассмотрим основные метрики качества в задачах классификации : доля правильных ответов, точность, полнота, F-мера и матрица ошибок. А также четыре различных комбинации фактических и прогнозируемых значений: истинно отрицательные (TN), ложноотрицательные (FN), истинно положительные (TP) и ложноположительные (FP). 

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

True Positive (TP) — это общее количество предсказанных положительных результатов, которые на самом деле являются положительными.

True Negative (TN) — это общее количество предсказанных отрицательных результатов, которые на самом деле являются отрицательными.

Ложное срабатывание (FP), ошибка 1 рода, — это общее количество предсказанных положительных результатов, которые на самом деле являются отрицательными.

Ложноотрицательный (FN), ошибка 2 рода — это общее количество предсказанных отрицательных результатов, которые на самом деле являются положительными.

Матрица ошибок (Сonfusion matrix)



#### Доля правильных ответов (Accuracy Score)

$$Accuracy Score = \frac{Correct Predictions}{All Predictions} = \frac{TP + TN}{TP + TN + FP + FN}$$


#### Точность (Precision)

$$Positive Precision = \frac{True Positive}{Predicted Positive} = \frac{TP}{TP + FP}$$

$$Negative Precision = \frac{True Negative}{Predicted Negative} = \frac{TN}{TN + FN}$$

#### Полнота (Recall)

$$Positive Recall = \frac{True Positive}{Actual Positive} = \frac{TP}{TP + FN}$$

$$Negative Recall = \frac{True Negative}{Actual Negative} = \frac{TN}{TN + FP}$$

### F-мера (f1-score) 

$$\frac{2*Precision*Recall}{Precision+Recall}$$

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


Загружаем наши данные и смотрим первые и последние пять строк :

df = pd.read_excel("data\shop_quit.xlsx")
pd.concat([df.head(), df.tail()])

sexexperiencewdsalaryquit
0female184.539.037380
1female34.547.030790
2female79.442.528870
3male4.747.527420
4female56.364.034830
116male28.126.026510
117female19.063.031770
118female18.949.022390
119male46.64.047310
120female21.517.521630

Расшифруем показатели :
  • sex - пол
  • experience - стаж работы в месяцах
  • wd - количество отработанных смен
  • salary - среднесменная заработная плата
  • quit - метка 0-работает, 1 - уволился
 Перекодируем пол

from sklearn.preprocessing import LabelEncoder
class_le = LabelEncoder ()

df.sex=class_le.fit_transform(df.sex.values)
df.sample(5)

sexexperiencewdsalaryquit
98193.840.560920
3800.919.037340
34020.623.035260
104013.244.036870
115018.533.534940

Присвоим показатели матрице data , а метки увольнения - вектору label

label_col = "quit"
data = df.drop(label_col, axis=1)
label = df[label_col]

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

d_train, d_test, l_train, l_test = train_test_split(data, label, test_size=0.4, random_state=23, stratify=label)

Через stratify = label используем  встроенную поддержку стратификации. Это означает,
что метод train_test_split возвращает обучающий и испытательный
поднаборы, имеющие такие же количественные соотношения меток классов ,
как у входного набора данных. Мы можем проверить , так ли это , с применением функции bincount из NumPy, которая подсчитывает количество вхождений каждого значения в массиве:

print('Labels counts in label:', np.bincount(label))
print('Labels counts in l_train:', np.bincount(l_train))
print('Labels counts in l_test:', np.bincount(l_test))
print('Labels % in label:', round(label.mean(),2))
print('Labels % in l_train:', round(l_train.mean(),2))
print('Labels % in l_test:', round(l_test.mean(),2))


Labels counts in y: [103  18]
Labels counts in y_train: [61 11]
Labels counts in y_test: [42  7]
Labels % in y: 0.15
Labels % in y_train: 0.15
Labels % in y_test: 0.14

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

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

from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics
from sklearn.metrics import plot_confusion_matrix
rfr_model = RandomForestClassifier(n_estimators=10, random_state=0)
rfr_model.fit(d_train, l_train)
predicted = rfr_model.predict(d_test)
score = metrics.accuracy_score(l_test, predicted)
print(f'Decision Tree Classification  Score = {score:.1%}\n')
print(f'Classification Report:\n {metrics.classification_report(l_test, predicted)}\n')
plot_confusion_matrix(rfr_model, d_test, l_test, cmap='Greys')
Decision Tree Classification  Score = 89.8%

Classification Report:
               precision    recall  f1-score   support

           0       0.93      0.95      0.94        42
           1       0.67      0.57      0.62         7

    accuracy                           0.90        49
   macro avg       0.80      0.76      0.78        49
weighted avg       0.89      0.90      0.89        49



Как видим, результат неплохой, доля правильных ответов 89.8%

Из реализация случайных лесов в scikit-leam можно вывести показатели важности признаков, через атрибут feature importances после подгонки классификатора RandomForestClassifier.

features_response = d_test.columns.tolist()
feat_imp_df = pd.DataFrame({
'Importance':rfr_model.feature_importances_},
index=features_response)
feat_imp_df.sort_values('Importance', ascending=True).plot.barh()


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

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



Комментариев нет:

Отправить комментарий