Des données déséquilibrées provoquent une mauvaise classification sur l'ensemble de données multiclasses

9

Je travaille sur la classification des textes où j'ai 39 catégories / classes et 8,5 millions d'enregistrements. (À l'avenir, les données et les catégories augmenteront).

La structure ou le format de mes données est le suivant.

----------------------------------------------------------------------------------------
| 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  

La distribution des données n'est pas normale; il est très déséquilibré:

-------------------------
| 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       

Comme vous pouvez le voir, ils sont très déséquilibrés et conduisent à des erreurs de classification.

Étapes que j'ai effectuées jusqu'à présent

1) Fusionnez la colonne product_title et key_value_pairs et supprimez les mots vides et les caractères spéciaux et effectuez le stemming.

2) J'ai utilisé le pipeline pour TFIDFvectorizer (), LinearSVC ()

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

Après cela, j'ai ajusté le pipeline et stocké le classificateur dans des cornichons

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

Côté test, j'ai répété l'étape 1 comme mentionné ci-dessus, puis je charge le cornichon et j'utilise la fonction de prédiction

pd = cl.predict([testData])

Problèmes auxquels je suis confronté

  1. De nombreux produits sont mal classés dans d'autres catégories

    Exemple: Ultimate Nutrition Prostar 100% Whey Protein devrait être classé dans la catégorie 311 mais mon classificateur la classe comme 222, ce qui est complètement faux.

  2. Je ne sais pas s'il faut utiliser TFidfVectorizer () ou Hashingvectorizer (), pouvez-vous m'aider à sélectionner l'un de ces paramètres avec leurs paramètres?

  3. L'algorithme que j'utilise est LinearSVC, est-ce un bon choix pour les problèmes de classification multi-classes avec une grande quantité de données? Ou dois-je utiliser différents algorithmes?

  4. Comme mes données sont très déséquilibrées, j'ai essayé un sous-échantillonnage aléatoire. Les résultats ont été améliorés mais ils n'étaient toujours pas à la hauteur. Je ne sais pas non plus si c'est la bonne approche pour effectuer un sous-échantillonnage aléatoire:

    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. Je suis nouveau dans l'apprentissage automatique, j'ai donc utilisé cette approche pour la classification de texte. Si mon approche est fausse, veuillez me corriger avec la bonne.

(Ce serait formidable si vous donnez une suggestion ou une solution avec des exemples car cela m'aidera à mieux comprendre).

*** 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)
valeur aberrante
la source
Je viens de voir que vous avez essayé de sous-échantillonner. Juste pour info, la validation croisée du pli K initié dans Sci-Kit Learn prend également en compte la distribution des classes.
Kasra Manshaei

Réponses:

6

Bonne question!

Quelques remarques

Pour les données déséquilibrées, vous avez différentes approches. Le plus bien établi est le rééchantillonnage (suréchantillonnage de petites classes / sous-échantillonnage de grandes classes). L'autre consiste à rendre votre classification hiérarchique, c'est-à-dire à classer les grandes classes par rapport à toutes les autres, puis à classer les petites classes dans la deuxième étape (les classificateurs ne sont pas censés être les mêmes. Essayez des stratégies de sélection de modèle pour trouver le meilleur).

Réponse pratique

J'ai obtenu des résultats acceptables sans rééchantillonner les données! Alors essayez-le mais améliorez-le plus tard en utilisant des méthodes de rééchantillonnage (statistiquement, elles sont en quelque sorte un MUST).

TFIDF est bon pour un tel problème. Les classificateurs doivent être sélectionnés via la sélection de modèles, mais mon expérience montre que la régression logistique et la forêt aléatoire fonctionnent bien sur ce problème spécifique (mais ce n'est qu'une expérience pratique).

Vous pouvez suivre le code ci-dessous car il fonctionnait tout simplement bien, alors vous pouvez essayer de le modifier pour améliorer vos résultats:

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]

Veuillez noter que le code est abstrait, donc TianX, TrainY, TestX, etc. doivent être correctement définis par vous.

Conseils

Faites attention à ce qu'est StopWord. Pratiquement de nombreuses personnes (moi y compris!) Ont fait cette erreur en supprimant les mots vides en fonction de listes prédéfinies. Ce n'est pas correct!

Les mots vides sont sensibles au corpus, vous devez donc supprimer les mots vides en fonction des concepts théoriques de l'information (pour rester simple, vous devez savoir que TFIDF ignore en quelque sorte vos mots vars spécifiques au corpus. Si vous avez besoin de plus d'explications, faites-le moi savoir pour mettre à jour ma réponse) .

VotingClassifier est une stratégie de méta-apprentissage dans la famille des méthodes d'ensemble . Ils bénéficient de différents classificateurs. Essayez-les car ils fonctionnent assez bien dans la pratique.

Le schéma de vote prend simplement les résultats de différents classificateurs et renvoie la sortie de celui qui a la plus forte probabilité d'avoir raison. Une sorte d'approche démocratique contre la dictature;)

J'espère que cela aide!

Kasra Manshaei
la source
Bienvenue! Pour un rééchantillonnage intuitif, vous pouvez vous référer au lien que j'ai mis pour le rééchantillonnage. Il y a une instruction étape par étape.
Kasra Manshaei
J'essaie votre solution, si je suis coincé n'importe où ou en cas de doute, je posterai dans la section des commentaires. j'espère que ce sera bien pour vous!
valeur aberrante
bien sûr mon ami ... bonne chance!
Kasra Manshaei
1
si cela a fonctionné, vous pouvez accepter la réponse :)
Kasra Manshaei
@outlier puisque la réponse a résolu votre problème, veuillez l'accepter (et éventuellement le voter); les réponses prennent un temps précieux pour les répondants (bénévoles)
desertnaut