Dati squilibrati che causano una classificazione errata nel set di dati multiclasse


9

Sto lavorando alla classificazione del testo in cui ho 39 categorie / classi e 8,5 milioni di record. (In futuro aumenteranno i dati e le categorie).

La struttura o il formato dei miei dati è il seguente.

----------------------------------------------------------------------------------------
| 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 distribuzione dei dati non è normale; è fortemente squilibrato:

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

Come puoi vedere sono altamente squilibrati e portano a classificazioni errate.

Passi che ho eseguito fino ad ora

1) Unisci la colonna product_title e key_value_pairs e rimuovi le parole di arresto e i caratteri speciali ed esegui il stemming.

2) Ho usato la pipeline per TFIDFvectorizer (), LinearSVC ()

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

Dopo questo ho adattato la pipeline e memorizzato il classificatore in pickle

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

Sul lato test ho ripetuto il passaggio 1 come indicato sopra, quindi carico il sottaceto e utilizzo la funzione di previsione

pd = cl.predict([testData])

Problemi che sto affrontando

  1. Molti prodotti vengono classificati in modo errato in alcune altre categorie

    Esempio: Ultimate Nutrition Prostar 100% Whey Protein dovrebbe essere classificato nella categoria 311 ma il mio classificatore lo sta classificando come 222, che è completamente sbagliato.

  2. Non sono sicuro se usare TFidfVectorizer () o Hashingvectorizer (), potete aiutarmi nella scelta di uno di questi insieme ai loro parametri?

  3. L'algoritmo che sto usando è LinearSVC, è una buona scelta per problemi di classificazione multi-classe con una grande quantità di dati? O dovrei usare algoritmi diversi?

  4. Dato che i miei dati sono fortemente squilibrati, ho provato un sottocampionamento casuale. I risultati sono stati migliorati ma non erano ancora all'altezza. Inoltre non sono sicuro che questo sia l'approccio giusto per eseguire il sottocampionamento casuale:

    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. Sono nuovo nell'apprendimento automatico, quindi ho usato questo approccio per la classificazione del testo. Se il mio approccio è sbagliato, per favore correggimi con quello giusto.

(Sarebbe bello se fornissi suggerimenti o soluzioni con esempi in quanto mi aiuterà a capire meglio).

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

Ho appena visto che hai provato un sottocampionamento. In breve, la convalida incrociata con piegatura a K Starificata in Sci-Kit Learn tiene conto anche della distribuzione delle classi.
Kasra Manshaei,

Risposte:


6

Bella domanda!

Alcune osservazioni

Per i dati sbilanciati hai approcci diversi. Il più consolidato è il ricampionamento (sovracampionamento di piccole classi / sottocampionamento di grandi classi). L'altro è quello di rendere gerarchica la tua classificazione, ovvero classificare le grandi classi rispetto a tutte le altre e quindi classificare le piccole classi nel secondo passaggio (i classificatori non dovrebbero essere gli stessi. Prova le strategie di selezione dei modelli per trovare il migliore).

Risposta pratica

Ho ottenuto risultati accettabili senza ricampionare i dati! Quindi provalo ma in seguito miglioralo usando i metodi di ricampionamento (statisticamente sono una specie di DEVE).

TFIDF è buono per un tale problema. I classificatori dovrebbero essere selezionati attraverso la selezione del modello, ma la mia esperienza dimostra che la regressione logistica e la foresta casuale funzionano bene su questo problema specifico (tuttavia è solo un'esperienza pratica).

Puoi seguire il codice qui sotto poiché ha funzionato semplicemente bene quindi potresti provare a modificarlo per migliorare i tuoi risultati:

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]

Si noti che il codice è astratto, pertanto TianX, TrainY, TestX, ecc. Devono essere definiti correttamente dall'utente.

suggerimenti

Fai attenzione a cos'è StopWord. Praticamente molte persone (incluso me stesso!) Hanno fatto questo errore per rimuovere le parole di arresto in base a elenchi predefiniti. Non è giusto!

Le parole d'ordine sono sensibili al corpus, quindi è necessario rimuovere le parole d'ordine in base ai concetti teorici delle informazioni (per semplicità, è necessario conoscere il tipo di TFIDF che ignora le parole d'ordine specifiche del corpo. Se hai bisogno di ulteriori spiegazioni, fammi sapere per aggiornare la mia risposta) .

VotingClassifier è una strategia di meta-apprendimento nella famiglia dei metodi Ensemble . Traggono vantaggio da diversi classificatori. Provali mentre funzionano abbastanza bene in pratica.

Lo schema di voto prende semplicemente i risultati di diversi classificatori e restituisce l'output di quello che ha la più alta probabilità di avere ragione. Quindi un tipo di approccio democratico contro la dittatura;)

Spero che sia d'aiuto!


Benvenuto! Per un ricampionamento intuitivo puoi fare riferimento al link che ho inserito per il ricampionamento. C'è un'istruzione passo-passo.
Kasra Manshaei,

Sto provando la tua soluzione, se mi sono bloccato da qualche parte o in caso di dubbi, posterò nella sezione commenti. spero che andrà bene per te!
anomalo il

certo amico mio ... buona fortuna!
Kasra Manshaei,

1
se ha funzionato, allora puoi accettare la risposta :)
Kasra Manshaei,

@outlier poiché la risposta ha risolto il tuo problema, accetta gentilmente (e possibilmente votalo); le risposte richiedono tempo prezioso per gli intervistati (volontari)
desertnaut,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.