Збалансовані дані, що спричиняють неправильну класифікацію на множині набору даних


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% сироватковий протеїн слід класифікувати до категорії 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)

Я щойно бачив, що ви намагалися брати вибірку. Так само, підтверджена перехресна перевірка K-кратного в Sci-Kit Learn також враховує розподіл класів.
Касра Маншаї

Відповіді:


6

Приємне запитання!

Деякі зауваження

Для незбалансованих даних у вас різні підходи. Найбільш усталеним є перекомпонування (перенастроювання малих класів / недостатнє розміщення великих класів). Другий - зробити класифікацію ієрархічною, тобто класифікувати великі класи проти всіх інших, а потім класифікувати малі класи на другому кроці (класифікатори не повинні бути однаковими. Спробуйте стратегії вибору моделей, щоб знайти найкращі).

Практична відповідь

Я отримав прийнятні результати без перекомпонування даних! Тому спробуйте це, але пізніше вдосконаліть його за допомогою методів перекомпонування (статистично вони НЕОБХІДНО).

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 - це стратегія метанавчання в сім'ї методів Ensemble . Вони отримують вигоду від різних класифікаторів. Спробуйте їх, оскільки вони досить добре працюють на практиці.

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

Сподіваюся, це допомагає!


Ласкаво просимо! Для інтуїтивного перекомпонування ви можете звернутися за посиланням, яке я поклав для переупорядкування. Існує покрокова інструкція.
Касра Маншаї

Я намагаюся вирішити ваше рішення, якщо я застряг де-небудь або у випадку будь-яких сумнівів, опублікую у розділі коментарів. сподіваюся, що для вас це буде добре!
outlier

впевнений мій друг ... удачі!
Kasra Manshaei

1
якщо це спрацювало, то ви можете прийняти відповідь :)
Kasra Manshaei

@outlier, оскільки відповідь стосується Вашого питання, будь ласка, прийміть (і, можливо, підтвердіть) його; відповіді займають цінний час для (добровольців) респондентів
пустеля
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.