Сквозной проект машинного обучения — это проект, который включает в себя все шаги, необходимые для разработки системы машинного обучения, от сбора и предварительной обработки данных до развертывания и обслуживания модели. Этот тип проекта включает в себя комплексный подход, который охватывает все аспекты разработки системы машинного обучения, включая подготовку данных, разработку функций, выбор модели, обучение, оценку, развертывание и мониторинг.
Конечной целью сквозного проекта машинного обучения является разработка полного и работающего решения, которое может решить конкретную проблему или задачу. Такие проекты часто используются в реальных приложениях, таких как профилактическое обслуживание, распознавание изображений, обнаружение мошенничества и многие другие, и требуют сочетания науки о данных, разработки программного обеспечения и знаний в предметной области.
В этой статье будет создан комплексный проект машинного обучения для обнаружения мошенничества с кредитными картами.
Сбор данных
Это первый шаг в каждом проекте машинного обучения, который включает сбор данных из различных источников или создание данных с помощью моделирования. Для этого проекта будет получен набор данных транзакций по кредитным картам от Kaggle https://www.kaggle.com/datasets/mlg-ulb/creditcardfraud.
Предварительная обработка данных
Этот шаг включает в себя очистку, преобразование или форматирование собранных данных, чтобы сделать их пригодными для алгоритмов машинного обучения. Давайте начнем с чтения нашего набора данных с помощью пакета Pandas.
import numpy as np import pandas as pd df = pd.read_csv('./data/creditcard.csv') # display and describe the dataset display(df.head(), df.describe())
Затем мы разделили наш набор данных на наборы для обучения и тестирования, отложив тестовые данные в качестве реальных данных для оценки производительности модели.
from sklearn.model_selection import train_test_split train_set, test_set = train_test_split(df, test_size=0.2, random_state=42) display('Train Set', train_set.head(), 'Test Set', test_set.head())
Имея помеченный набор данных, нам нужно разделить переменную предикторов (X) и целевые переменные (y) как из тестов, так и из набора поездов.
Переменная предикторов (X) — это входная или независимая переменная, используемая для прогнозирования выходной или целевой переменной. Целевая переменная (y) — это выходная или зависимая переменная, которую мы пытаемся предсказать на основе входных переменных.
X = train_set.drop(columns=['Time', 'Class']) y = train_set['Class'] X_test = test_set.drop(columns=['Time', 'Class']) y_test = test_set['Class'] print(f'X shape {X.shape}, y shape {y.shape} fraud cases {y.sum()} \ X test shape {X_test.shape}, y test shape {y_test.shape} fraud on test cases {y_test.sum()} ')
Теперь мы можем начать процесс масштабирования функций, который может помочь повысить производительность алгоритмов машинного обучения, чувствительных к различиям в масштабе между функциями. Использование функции StandardScaler() нормализует и стандартизирует функции (входные данные) нашего набора данных. Это преобразование приведет к набору данных, в котором все функции имеют одинаковый масштаб и диапазон.
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaler.fit(X) X = scaler.transform(X) X_test = scaler.transform(X_test)
Исследование и анализ данных
Изучение и анализ данных может помочь нам выявить закономерности, взаимосвязи и аномалии, которые могут помочь в выборе подходящих алгоритмов машинного обучения. Мы начнем с изучения наших целевых ярлыков.
import seaborn as sn import matplotlib.pyplot as plt sn.countplot(x=y, palette=['blue', 'red'])
Наш анализ показывает, что у нас есть несбалансированный набор данных, который может привести к предсказыванию смещения в большинстве случаев non_fraud (0). Чтобы исправить это, мы собираемся использовать методы избыточной выборки в нашем наборе данных, чтобы сохранить большую часть информации.
from imblearn.over_sampling import RandomOverSampler ros = RandomOverSampler(random_state=42) X, y = ros.fit_resample(X, y) sn.countplot(x=y, palette=['blue', 'red'])
Выбор модели
Доступны различные алгоритмы машинного обучения, и выбор подходящего зависит от решаемой проблемы, доступных данных и желаемых показателей производительности.
Мы будем использовать функцию cross_val_score для выбора кандидатов в нашу модель на основе их оценки F1.
from sklearn.neural_network import MLPClassifier from sklearn.model_selection import StratifiedKFold, RandomizedSearchCV, cross_val_score from sklearn.ensemble import HistGradientBoostingClassifier, RandomForestClassifier, VotingClassifier, IsolationForest def model_selection(model, X, y): scores = cross_val_score(model, X, y, scoring=make_scorer(f1_score), cv=8) # Print the scores for each fold and the mean score print("Cross-validation scores:", scores) print("Mean score:", scores.mean())
Кандидаты в модели
# HistGradientBoostingClasifier Model gbc=HistGradientBoostingClassifier(random_state=42) model_selection(gbc, X, y) # RandomForestClassifier Model rfc = RandomForestClassifier(random_state=42) model_selection(rfc, X, y) # MLPClassifier Model mlpc = MLPClassifier(random_state=42) model_selection(mlpc, X, y)
Обучение и оценка модели
Этот шаг включает в себя обучение и оценку производительности выбранных моделей-кандидатов с помощью подготовленных данных и построение графика их производительности по набору показателей для определения их эффективности.
from sklearn.base import clone from tqdm import tqdm from sklearn.metrics import confusion_matrix, mean_squared_error, make_scorer, precision_score, f1_score, precision_recall_curve skfold = StratifiedKFold(n_splits=8, shuffle=True, random_state=42) def heatmap(y_test, y_preds): cm = confusion_matrix(y_test, y_preds) sn.heatmap(cm, annot=True, linewidths=.5, cmap='Blues_r', square=True, fmt='.3f') plt.title(f'F1_score {f1_score(y_test, y_preds)}') plt.ylabel('Predicted Values') plt.xlabel('Actual Values') def learning_curve(train_score, test_score): # This function takes an array of the mean squard error of train and test scores plt.plot(np.sqrt(train_score), "r-.", linewidth=2, label="train") plt.plot(np.sqrt(test_score), "b-", linewidth=2, label="test") plt.title(f'Learning Curve') plt.ylabel('Mean Squared Error') plt.xlabel('Training Fold | Size') plt.legend() plt.show() def trade_of_curve(y_test, y_preds): precision, recall, thresholds = precision_recall_curve(y_test, y_preds) plt.plot(recall, precision, color='blue', label='Precision-Recall Curve') plt.xlabel('Recall') plt.ylabel('Precision') plt.title('Precision-Recall Curve') plt.legend() plt.show() return thresholds def train_evaluate(model, X, y): # train and plot learning curve model = clone(model) train_score , test_score =[], [] train_f1score , test_f1score =[], [] for train_fold, test_fold in tqdm(skfold.split(X, y), desc='Training folds 🤓'): X_train_fold, y_train_fold = X[train_fold], y[train_fold] X_test_fold, y_test_fold = X[test_fold], y[test_fold] model.fit(X_train_fold, y_train_fold) train_pred = model.predict(X_train_fold) test_pred = model.predict(X_test_fold) train_score.append(mean_squared_error(y_train_fold, train_pred)) test_score.append(mean_squared_error(y_test_fold, test_pred)) train_f1score.append(f1_score(y_train_fold, train_pred)) test_f1score.append(f1_score(y_test_fold, test_pred)) print('Training completed...🥲') print(f'Train F1_score: {np.mean(train_f1score)}') print(f'Test F1_score: {np.mean(test_f1score)}') print(f'Train MSE: {np.mean(train_score)}') print(f'Test MSE: {np.mean(test_score)}') learning_curve(train_score, test_score) return model # HistGradientBoostingClasifier Model gbc=HistGradientBoostingClassifier(random_state=42) gbc = train_evaluate(gbc, X, y) prediction = gbc.predict(X_test) heatmap(y_test, prediction)
# RandomForestClassifier Model rfc = RandomForestClassifier(random_state=42) rfc = train_evaluate(rfc, X, y) prediction = rfc.predict(X_test) heatmap(y_test, prediction)
# MLPClassifier Model mlpc = MLPClassifier(random_state=42) mlpc = train_evaluate(mlpc, X, y) prediction = mlpc.predict(X_test) heatmap(y_test, prediction)
Повышение производительности модели
На этапе оценки/обучения наша кривая обучения показала, что у нас большая разница между оценками обучения и перекрестной проверки, это означает, что наши модели переоснащаются данными обучения и плохо обобщаются на новые данные. В этом случае добавление дополнительных обучающих данных вряд ли поможет и может даже усугубить проблему переобучения.
Есть несколько способов улучшить производительность модели:
- Настройка параметров
- Регуляризация
- Ансамблевые техники
- Оценка модели
- Итерация (это повторение одного и того же шага, пока мы не получим лучшую модель)
Регуляризация
Регуляризация — это метод, используемый в машинном обучении для предотвращения переобучения модели путем попытки ограничить наши модели: чем меньше у них степеней свободы, тем сложнее им будет подгонять данные.
Разные модели имеют разные гиперпараметры регуляризации, поэтому найти лучшие гиперпараметры для регуляризации модели может быть сложно. Будем использовать RandomizedSearchCV, чтобы получить лучшие гиперпараметры регуляризации для улучшения нашей модели.
rfc_params = { "n_estimators": [int(x) for x in np.linspace(start = 10, stop = 1000, num = 10)], "max_depth": np.linspace(start = 2, stop = 10, num = 10) } histgradient_params = { 'max_iter': [int(x) for x in np.linspace(start = 100, stop = 1000, num = 10)], 'learning_rate': np.linspace(0.01, 1, num=10), 'max_depth': np.linspace(start = 2, stop = 10, num = 10), 'l2_regularization': np.linspace(0.01, 1, num=10) } mlpc_params = { 'max_iter': [int(x) for x in np.linspace(start = 10, stop = 200, num = 10)], 'alpha': np.linspace(0.0001, 0.1, num=10), 'solver': ['lbfgs', 'adam', 'sgd'] }
Настройка гиперпараметров
Это процесс выбора оптимальных гиперпараметров для алгоритма машинного обучения. Гиперпараметры — это параметры, которые не изучаются в процессе обучения, а задаются перед началом обучения. то есть скорость обучения, количество скрытых слоев, количество узлов в каждом скрытом слое, функции активации и параметры регуляризации.
Цель настройки гиперпараметров — найти набор гиперпараметров, который обеспечит наилучшую производительность модели на проверочном или тестовом наборе.
Использование RandomizeSearchCV для автоматизации поиска гиперпараметров.
scoring = { 'F1': make_scorer(f1_score, greater_is_better=True), 'precision': make_scorer(precision_score, greater_is_better=True) # 'my_scorer': my_scorer } def best_estimator(model, params, X_train, y_train): random_search = RandomizedSearchCV( model, param_distributions=params, n_iter=10, cv=5, scoring=scoring, refit='F1', n_jobs=-1, random_state=42 ) # Fit the random search algorithm to the data random_search.fit(X_train, y_train) # Print the best hyperparameters and score print("Best hyperparameters:", random_search.best_params_) print("Validation score:", random_search.best_score_) best_estimator = random_search.best_estimator_ return best_estimator
Ранняя остановка
Мы определяем гиперпараметры ранней остановки в наших моделях для решения проблемы переобучения.
# adding early stopping with warm_start hyperparameters rfc = RandomForestClassifier(warm_start=True) rfc = best_estimator(rfc, rfc_params, X, y) prediction = rfc.predict(X_test) heatmap(y_test, prediction) # adding earlying stopping defining the early_stopping hyperparameter to True mlpc = MLPClassifier(early_stopping=True, n_iter_no_change=10, max_iter=200) mlpc = best_estimator(mlpc, mlpc_params, X, y) prediction = mlpc.predict(X_test) heatmap(y_test, prediction)
Техники ансамбля
Мы уже использовали некоторые методы/модели ансамбля, например, RandomForestClassifier и HistGradientBoostingClassifier. теперь мы добавим классификатор голосования, чтобы попытаться улучшить производительность нашей модели, объединив несколько моделей для прогнозирования. Он работает путем агрегирования прогнозов нескольких моделей и выбора наиболее частого класса в качестве окончательного прогноза, что может уменьшить переоснащение.
gbc = HistGradientBoostingClassifier( max_iter=100, max_depth=10.0, learning_rate=0.34, l2_regularization=0.56 ) rfc = RandomForestClassifier(n_estimators=340, max_depth=9.11111111111111) mlpc = MLPClassifier(solver='lbfgs', max_iter=73, alpha=0.0001) vc = VotingClassifier(estimators=[('gbc', gbc), ('mlpc', mlpc), ('rfc', rfc)], voting='hard')
Оценка модели
мы снова оцениваем производительность нашей модели, прежде чем внедрять ее в производство.
vc = train_evaluate(vc, X, y) prediction = vc.predict(X_test) heatmap(y_test, prediction)
Итерация
Наша модель еще нуждается в улучшении. На этом этапе мы пытаемся повторить одни и те же шаги с разными гиперпараметрами, архитектурами моделей (TensorFlow) или методами обучения, чтобы улучшить оценку модели.
Сохранить лучшую модель
Теперь мы сохраняем нашу лучшую модель для развертывания.
import pickle pickle.dump(vc, open('./pretrained/model.pkl', 'wb')) pickle.dump(scaler, open('./pretrained/scaler.pkl', 'wb'))
Запуск производства
import pickle import pandas as pd from flask import Flask, request model = pickle.load(open('pretrained/model.pkl')) scaler = pickle.load(open('pretrained/scaler.pkl')) app = Flask(__name__) @app.route('/') def process(): try: csv = request.files['csv'] features = pd.read_csv(csv), scaled_features = scaler.transform(features) preds = model.predict(scaled_features) return {'predictions': preds} except Exception as e: print(f"Could not process {str(e)}") return {"message" : "Could not process"} if __name__ == '__main__': app.run()
Заключение
В этой статье мы рассмотрели пошаговый проект сквозного машинного обучения. Найдите его на GitHub https://github.com/MuokaPWambua/CredictCardFraudDetectionMode