Несбалансированные данные, приводящие к неправильной классификации в мультиклассовом наборе данных

9

Я работаю над классификацией текста, где у меня 39 категорий / классов и 8,5 миллионов записей. (В дальнейшем данные и категории будут увеличиваться).

Структура или формат моих данных выглядит следующим образом.

----------------------------------------------------------------------------------------
| product_title          | Key_value_pairs                               | taxonomy_id |
----------------------------------------------------------------------------------------
  Samsung S7 Edge        | Color:black,Display Size:5.5 inch,Internal    | 211 
                          Storage:128 GB, RAM:4 GB,Primary Camera:12 MP  

  Case cover Honor 8     | Color:transparent,Height:15 mm,width:22 mm    | 212 

  Ruggers Men's T-Shirt  | Size:L,ideal for:men,fit:regular,             | 111
                          sleeve:half sleeve

  Optimum Nutrition Gold | Flavor:chocolate,form:powder,size:34 gm       | 311
  Standard Whey Protein  

Распределение данных не нормально; это очень несбалансировано:

-------------------------
| taxonomy_id |   count |
-------------------------
          111 |  851750 
          112 |  355592
          113 |  379433
          114 |   23138
          115 |  117735
          116 |  145757
          117 | 1339471
          121 |  394026
          122 |  193433
          123 |   78299
          124 |  111962
          131 |    1776
          132 |    4425
          133 |     908
          134 |   23062
          141 |   22713
          142 |   42073
          211 |    7892
          212 | 1574744
          221 |    1047
          222 |  397515
          223 |   53009
          231 |    1227
          232 |    7683
          251 |     739
          252 |     327
          253 |   38974
          254 |      25
          311 |    2901
          321 |    7126
          412 |     856
          421 |  697802
          422 |  414855
          423 |   17750
          425 |    1240
          427 |     658
          429 |    1058
          431 |   20760
          441 |     257       

Как вы можете видеть, они сильно несбалансированы и ведут к неправильной классификации.

Шаги, которые я выполнил до сих пор

1) Объедините столбцы product_title и key_value_pairs, удалите стоп-слова и специальные символы и выполните определение.

2) Я использовал конвейер для TFIDFvectorizer (), LinearSVC ()

vectorizerPipe = Pipeline([
                 ('tfidf', TfidfVectorizer(lowercase=True, stop_words='english')),
                 ('classification', OneVsRestClassifier(LinearSVC(penalty='l2', loss='hinge'))),
                 ])

После этого я установил конвейер и сохранил классификатор в рассоле

prd = vectorizerPipe.fit(df.loc[:, 'description'], df.loc[:, 'taxonomy_id'])

На стороне тестирования я повторил шаг 1, как упомянуто выше, а затем загрузил маринад и использовал функцию прогнозирования.

pd = cl.predict([testData])

Проблемы, с которыми я сталкиваюсь

  1. Многие продукты неправильно классифицированы по некоторым другим категориям.

    Пример: Ultimate Nutrition Prostar 100% Whey Protein должен быть классифицирован как категория 311, но мой классификатор классифицирует его как 222, что совершенно неверно.

  2. Я не уверен, использовать ли TFidfVectorizer () или Hashingvectorizer (). Можете ли вы, ребята, помочь мне выбрать один из них вместе с их параметрами?

  3. Алгоритм, который я использую, - LinearSVC, это хороший выбор для многоклассовых задач классификации с большим объемом данных? Или я должен использовать разные алгоритмы?

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

    pipe = make_pipeline_imb(
        HashingVectorizer(lowercase=True),
        RandomUnderSampler(ratio={111: 405805, 112: 170431, 113: 241709, 114: 8341, 115: 50328, 116: 89445, 117: 650020, 121: 320803, 122: 162557, 123: 66156, 124: 36276, 131: 1196, 132: 3365, 133: 818, 134: 15001, 141: 6145, 142: 31783, 211: 24728, 212: 100000, 221: 791, 222: 8000, 223: 35406, 231: 785, 232: 3000, 251: 477, 252: 127, 253: 29563, 254: 33, 311: 2072, 321: 5370, 412: 652, 421: 520973, 422: 99171, 423: 16786, 425: 730, 427: 198, 429: 1249, 431: 13793, 441: 160},random_state=1), 
        OneVsRestClassifier(LinearSVC(penalty='l2', loss='hinge')))
    
  5. Я новичок в машинном обучении, поэтому я использовал этот подход для классификации текста. Если мой подход неправильный, пожалуйста, поправьте меня с правильным.

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

*** EDIT-1 ****

RndmFrst = RandomForestClassifier(n_estimators=100, max_depth=20, max_features=5000,n_jobs=-1)
LogReg = LogisticRegression()
voting = VotingClassifier(estimators=[('LogReg ', LogReg), ('RndmFrst', RndmFrst)], voting='soft', n_jobs=-1)

pipe = Pipeline([('tfidf', TfidfVectorizer(ngram_range=(1,4), max_features=50000)), ('clf', voting)])

pipe = pipe.fit(df.loc[:,'description'], df.loc[:,'taxonomy_id'])
Preds = pipe.predict(test_data)
останец
источник
Я только что видел, что вы пробовали занижение выборки Кстати, в Sci-Kit Learn начальная перекрестная проверка в K-кратном порядке также учитывает распределение классов.
Kasra Manshaei

Ответы:

6

Хороший вопрос!

Некоторые замечания

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

Практический ответ

Я получил приемлемые результаты без пересчета данных! Так что попробуйте, но позже улучшите его, используя методы передискретизации (статистически они вроде ДОЛЖНЫ).

TFIDF хорош для такой проблемы. Классификаторы следует выбирать с помощью выбора модели, но мой опыт показывает, что Логистическая регрессия и Случайный лес хорошо работают над этой конкретной проблемой (однако это просто практический опыт).

Вы можете следовать приведенному ниже коду, поскольку он работал просто хорошо, тогда вы можете попробовать изменить его, чтобы улучшить свои результаты:

train = pd.read_csv(...)
test = pd.read_csv(...)    

# TFIDF Bag Of Words Model For Text Curpos. Up to 4-grams and 50k Features
vec = TfidfVectorizer(ngram_range=(1,4), max_features=50000)
TrainX = vec.fit_transform(train)
TestX = vec.transform(test)


# Initializing Base Estimators
clf1 = LogisticRegression()
clf2 = RandomForestClassifier(n_estimators=100, max_depth=20, max_features=5000,n_jobs=-1)

# Soft Voting Classifier For Each Column
clf = VotingClassifier(estimators=[('lr', clf1), ('rf', clf2)], voting='soft', n_jobs=-1)
clf = clf.fit(TrainX, TrainY)
preds = clf.predict_proba(TestX)[:,1]

Обратите внимание, что код является абстрактным, поэтому вы должны правильно определить TianX, TrainY, TestX и т. Д.

Советы

Будьте осторожны с тем, что такое StopWord. Практически многие люди (в том числе и я!) Допустили эту ошибку, чтобы удалить стоп-слова в соответствии с заранее определенными списками. Это неправильно!

Стоп-слова чувствительны к корпусу, поэтому вам нужно удалить стоп-слова в соответствии с теориями теории информации (для простоты вам нужно знать, что TFIDF не учитывает ваши стоп-слова, характерные для корпуса. Если вам нужно больше объяснений, дайте мне знать, чтобы обновить мой ответ) ,

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

Схема голосования просто берет результаты разных классификаторов и возвращает результат того, который имеет наибольшую вероятность быть правым. Так что вроде демократический подход против диктатуры;)

Надеюсь, поможет!

Касра Маншаи
источник
Добро пожаловать! Для интуитивной повторной выборки вы можете обратиться к ссылке, которую я указал для повторной выборки. Есть пошаговая инструкция.
Kasra Manshaei
Я пробую ваше решение, если я застряну где-нибудь или в случае каких-либо сомнений я опубликую в разделе комментариев. надеюсь, что это будет хорошо для вас!
выброс
уверен, мой друг ... удачи!
Kasra Manshaei
1
если это сработало, вы можете принять ответ :)
Kasra Manshaei
@outlier, так как ответ обратился к вашей проблеме, любезно примите (и возможно upvote) это; ответы занимают ценное время (доброволец) респондентов
desertnaut