И как с ними бороться

Примечание. Это третья часть серии статей Основные проблемы наборов данных машинного обучения. Вы можете прочитать часть 1 здесь и часть 2 здесь.

Несбалансированные данные

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

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

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

Давайте посмотрим на этот пример набора данных о мошенничестве с кредитными картами и построим модель на этих несбалансированных данных. Наша цель — правильно идентифицировать мошеннические транзакции:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
df = pd.read_csv("creditcard.csv")
# checking class distribution of column `Class`
sns.countplot(data= df, x = "Class")

Здесь у нас явный классовый дисбаланс. Посмотрим, насколько это повлияет на производительность модели:

#  Splitting Data Into Training and Test Sets
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,
                                                    y,
                                                    test_size=0.2,
                                                    random_state=42)
print(X_train.shape, vX_test.shape)
------------
(227845, 30) (56962, 30)

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

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(solver='liblinear')
lr.fit(X_train, y_train)

Теперь мы оцениваем производительность модели с помощью отчета о классификации и матрицы путаницы:

from sklearn.metrics import (plot_confusion_matrix,
                             classification_report)
def gen_report(model):
  preds = model.predict(X_test)
  print(classification_report(preds, y_test))
  plot_confusion_matrix(model, X_test, y_test)
print("---LOGISTIC REGRESSION MODEL---")
gen_report(model=lr)

Беглый взгляд на эти метрики, и кажется, что наша модель работает потрясающе — 100% точность, 100% точность и 100% полнота! Но если мы копнем немного глубже, мы увидим, что наша точность падает до 53% на мошеннических данных (класс меньшинства), а полнота падает до 83%.

Как работать с несбалансированными данными

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

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

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

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

imblearn от Scikit-learn — это библиотека Python с открытым исходным кодом, лицензированная MIT, которая предоставляет инструменты для работы с несбалансированными классами. У него есть класс с именем SMOTETomek, который сочетает в себе концепции методов недостаточной и избыточной выборки, теоретически обеспечивая хороший компромисс между плюсами и минусами каждого из них (хотя на практике это не всегда так; для вашего набора данных вам может потребоваться поэкспериментировать) с каждым методом выборки, чтобы увидеть, какой из них лучше всего подходит для вашего набора данных).

from imblearn.combine import SMOTETomek
smt = SMOTETomek()
X_res, y_res= smt.fit_resample(X, y)

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

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_res,
                                                    y_res,
                                                    test_size=0.2,
                                                    stratify=y,
                                                    random_state=42
                                                    )
from sklearn.linear_model import LogisticRegression
re_lrm = LogisticRegression(solver='liblinear')
re_lrm.fit(X_train, y_train)

print("---LOGISTIC REGRESSION MODEL (RESAMPLED)---")
gen_report(model= re_lrm)

Как видите, мы значительно улучшили производительность модели!

Многомерные данные

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

По мере увеличения количества функций в наборе данных время, необходимое для обучения модели, также будет увеличиваться. Но это не все. Многомерные наборы данных чрезвычайно сложно (если не невозможно) визуализировать (представьте себе 6-мерный график... я тоже не могу!). Чем сложнее визуализировать набор данных, тем сложнее его объяснить, что усугубляет проблему «черного ящика» в машинном обучении. Кроме того, объем данных, необходимых для обучения модели, обычно растет экспоненциально с увеличением количества функций (или измерений) в наборе данных. Это часто называют проклятием размерности и может привести к множеству статистических явлений, которые не происходят в низкоразмерных условиях. Чтобы избавить нашу модель от этой проблемы, мы можем выполнить уменьшение размерности.

Хотите увидеть эволюцию художественных проектов, созданных искусственным интеллектом? Посетите наш публичный проект, чтобы увидеть таймлапсы, эксперименты с эволюцией и многое другое!

Как бороться с высокой размерностью

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

Существует два основных метода уменьшения размерности: мы можем либо удалить наименее важную функцию, либо попытаться объединить исходные функции в новые, с меньшим количеством функций. Одним из самых популярных методов уменьшения линейной размерности является PCA (анализ основных компонентов).

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

Sci-kit Learn предоставляет встроенный инструмент для этого процесса с помощью sklearn.decomposition.PCA.

Давайте сначала масштабируем данные с помощью Standard Scaler:

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X)
X_scaled = scaler.transform(X)

А теперь применим PCA:

from sklearn.decomposition import PCA
pca_10 = PCA(n_components = 10, random_state = 42)
X_pca_10 = pca_10.fit_transform(X_scaled)
# comparing before and after PCA shape
print(X.shape, X_pca_10.shape)
------------
((284807, 30), (284807, 10))

Ненормальное распределение данных

Нормальное распределение – это тип распределения данных, при котором точки данных распределяются симметрично вокруг среднего значения данных. Это похоже на кривую в форме колокола.

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

В этом блоге мы обсудим два наиболее распространенных типа ненормального распределения: левостороннее и правостороннее распределение.

Распределение с асимметрией влево имеет длинный хвост с данными с отрицательной асимметрией, в то время как асимметрия справа имеет длинный хвост с правой стороны распределения.

Как бороться с ненормальным распределением данных

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

  1. Журнал нормального преобразования. В этом методе мы берем журнал значений определенной функции.
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# sample data generation
np.random.seed(42)
data = sorted(stats.lognorm.rvs(s=0.5, 
                                loc=1, 
                                scale=1000, 
                                size=1000))
# fit lognormal distribution
shape, loc, scale = stats.lognorm.fit(data, loc=0)
pdf_lognorm = stats.lognorm.pdf(data, shape, loc, scale)

2. Преобразование Бокса-Кокса: Преобразование Бокса-Кокса является частью семейства силовых трансформаторов. Он использует показатель степени лямбда (λ), который находится в диапазоне от -5 до 5, для преобразования ненормального распределения зависимых переменных в нормальное распределение.

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
# sample data generation
np.random.seed(42)
data = sorted(stats.lognorm.rvs(s=0.7, loc=3, scale=1000, size=1000))
pdf_boxcox = stats.boxcox(data)

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

Независимая от редакции, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по данным и командам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим нашим авторам и не продаем рекламу.

Если вы хотите внести свой вклад, перейдите к нашему призыву к участию. Вы также можете подписаться на получение наших еженедельных информационных бюллетеней (Еженедельник глубокого обучения и Информационный бюллетень Comet), присоединиться к нам в Slack и следить за Comet в Twitter и LinkedIn, чтобы получать ресурсы, события и многое другое, что поможет вам быстрее создавать лучшие модели машинного обучения.