Классификация изображений с несколькими метками с несбалансированными данными, как ее разделить?

#python #machine-learning #scikit-learn #data-analysis #imbalanced-data

#python #машинное обучение #scikit-learn #анализ данных #несбалансированные данные

Вопрос:

Я работаю над классификацией изображений с несколькими метками. Это мой фрейм данных:

[ОБНОВЛЕНО] введите описание изображения здесь

Как вы можете видеть изображения, помеченные 26 функциями. «1» означает, что существует, «0» означает, что не существует.

Моя проблема во многих ярлыках имеет несбалансированные данные. Например:

 [1] train_df.value_counts('Eyeglasses')

Output:

Eyeglasses
0    54735
1     1265
dtype: int64

[2] train_df.value_counts('Double_Chin')

Output:
Double_Chin
0    55464
1      536
dtype: int64
  

Как я могу разделить его как для обучения, так и для проверки данных как сбалансированный?

[ОБНОВЛЕНИЕ]

Я пытался

 from imblearn.over_sampling import SMOTE
smote = SMOTE()
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, 
                                                        random_state=42)

X_train_smote, y_train_smote = smote.fit_sample(X_train, y_train)
  

Ошибка ValueError: несбалансированный -learn в настоящее время поддерживает двоичные, многоклассовые и
двоично закодированные цели мультиклассов. Цели с несколькими метками и несколькими
выводами не поддерживаются.

Ответ №1:

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

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

Пример стратифицированной выборки. Источник: Википедия

Для этого я рекомендую skmultilearn IterativeStratification метод. Он поддерживает наборы данных с несколькими метками.

     from skmultilearn.model_selection.iterative_stratification import IterativeStratification

    stratifier = IterativeStratification(
        n_splits=2, order=2, sample_distribution_per_fold=[1.0 - train_fraction, train_fraction],
    )
    # this class is a generator that produces k-folds. we just want to iterate it once to make a single static split
    # NOTE: needs to be computed on hard labels.
    train_indexes, everything_else_indexes = next(stratifier.split(X=img_urls, y=labels))

    # s3url array shape (N_samp,)
    x_train, x_else = img_urls[train_indexes], img_urls[everything_else_indexes]
    # labels array shape (N_samp, n_classes)
    Y_train, Y_else = labels[train_indexes, :], labels[everything_else_indexes, :]
  

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

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

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

1. Я пытался использовать ваш код, но это приводит к нехватке оперативной памяти, даже с формой everything_else_indexes (500,26) и img_urls (500,). Я обновил свой вопрос, который заключается в том, что вы можете видеть мой фрейм данных. Также ваше визуальное объяснение не имеет смысла, потому что я не могу разделить значения, например, если метка x несбалансирована, а метка y сбалансирована, я не могу их стратифицировать, потому что они влияют на другие метки. Если я ошибаюсь, пожалуйста, поправьте меня.

2. @claymorehack Я не уверен, что значит иметь сбалансированные метки x, но несбалансированные метки y.

3. У меня всего 26 функций. Как вы можете видеть в df.png, где идет речь, каждое изображение обладает этими функциями, и у меня всего 15000 изображений. В целом, большинство функций несбалансированы, например, функция «Big_Nose» имеет {0: 14234, 1: 766}, а функция «Doubly_Chin» имеет {0: 7800, 1: 7200}. Проблема в том, что каждая функция связана друг с другом, поэтому не имеет смысла их стратифицировать. Если я попытаюсь стратифицировать положительные функции «Big_Nose», возможно, теперь я смогу столкнуться с несбалансированным «Doubly_Chin». Если я ошибаюсь, пожалуйста, поправьте меня.

4. Итак, ваши x изображения — это сами изображения, а y остальные столбцы (ваши функции). Проблема, которую вы описываете со связанными функциями, является распространенной ситуацией в наборах данных с несколькими метками, и при использовании IterativeStratification with order=2 при стратификации будет учитываться несколько меток. В документах есть более подробная информация и видеоролики с лекциями skmultilearn : scikit.ml/api /…

5. Хорошо, теперь я понимаю, но сложная сторона — моей оперативной памяти (16 ГБ) недостаточно, даже если небольшие данные.