Время прочтения: 3 мин.

Digital audit всё в большей мере становится не модным новшеством в работе аудиторов, а скорее стандартом.

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

Однако, достигнутая точность по тем или иным причинам может нас не устраивать. Например, при необходимости классификации нескольких сотен тысяч объектов 1%, представленный 1000 неверно классифицируемых образцов, может быть существенным. Всё зависит от ситуации.

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

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

В качестве метрики мы использовали взвешенную F1-score, а по различным классам анализировали метрики precision и recall.

Стандартными изученными способами мы смогли добиться значения f1-score на уровне 0,81. Но необходимо было значение 0,85.

Мы сделали следующее. Разделили первоначальную обучающую выборку для исходной модели ещё на 2 части. По первой части мы обучили три модели. Например, так:

In [ ]:
calibrated_cv = CalibratedClassifierCV(
					LinearSVC(
						   C = 3, 
						   intercept_scaling = 1, 
						   class_weight = 'balanced', 
						   random_state = 412
						 ), 
					method = 'sigmoid', 
					cv = 5
					)
text_clf_fl_first = Pipeline(
			      [
			       ('tfidfV', 
				TfidfVectorizer(

						 lowercase=True, 
						 sublinear_tf=True, 
						 min_df=10, 
						 norm='l2', 
						 encoding='utf8', 
						 ngram_range=(1, 4), 
						 stop_words=stop_wordus)
						),
                             ('clf', calibrated_cv)
                           ])

_ = text_clf_fl_first.fit(
			   df_tempr_fl_aos1['Answer'], 
			   df_tempr_fl_aos1['NewClassification']
			  )

Использовались модели из модуля scikit-learn. Вторая модель строилась на основе SGDClassifier, третья – LogisticRegression. CalibratedClassifierCV использовался для возможности получения вероятности предсказания (по тем моделям, в которых эта функция отсутсвует), Pipeline соответственно помогал конвейерной обработке входных данных и их предсказанию. Предсказательная мощность каждой модели около 0,81 по f1.

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

Теперь самое интересное. Все предсказанные результаты мы будем рассматривать в качестве признаков и подадим их на вход четвёртой модели.

Для этого мы добавим в датасеты предсказанные столбцы и с помощью функции get_dummies() сформируем категориальные признаки по сделанным предсказаниям.

In [ ]:
df3['Pred1'] = y_pred1
df3['Pred2'] = y_pred2
df3['Pred3'] = y_pred3 
df4['Pred1'] = y_pred4
df4['Pred2'] = y_pred5
df4['Pred3'] = y_pred6
df4 = pd.concat([df3, df4])
df4 = pd.get_dummies(df4, columns = ['Pred1', 'Pred2', 'Pred3'])

В качестве 4-ой модели также используем LinearSVC.

In [ ]:
_ = final_model.fit(df4.loc[df4.index.isin(df_pred_fl_aos1.index)].drop(['id', 'NewClassification', 'id_num_bp2'], axis = 'columns'), df4.loc[df4.index.isin(df_pred_fl_aos1.index)]['id_num_bp2'])
y_pred_final = final_model.predict(df4.loc[df4.index.isin(df_predict4_fl_aos.index)].drop(['id', 'NewClassification', 'id_num_bp2'], axis = 'columns'))
y_prob = text_clf_fl_first.predict_proba(x_t2)

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

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