Dados desequilibrados, causando má classificação no conjunto de dados de várias classes

9

Estou trabalhando na classificação de texto, onde tenho 39 categorias / classes e 8,5 milhões de registros. (No futuro, dados e categorias aumentarão).

Estrutura ou formato dos meus dados é o seguinte.

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

A distribuição de dados não é normal; é altamente desequilibrado:

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

Como você pode ver, eles são altamente desequilibrados e levam a erros de classificação.

Etapas que eu executei até agora

1) Mescle a coluna product_title e key_value_pairs e remova palavras de parada e caracteres especiais e execute a derivação.

2) Eu usei pipeline para TFIDFvectorizer (), LinearSVC ()

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

Depois disso, ajustei o pipeline e guardei o classificador em picles

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

No lado do teste, repeti a etapa 1, conforme mencionado acima, e carregue o pickle e use a função de previsão

pd = cl.predict([testData])

Problemas que estou enfrentando

  1. Muitos produtos estão sendo classificados incorretamente em algumas outras categorias

    Exemplo: Ultimate Nutrition Prostar 100% Whey Protein deve ser classificado na categoria 311, mas meu classificador está classificando-o como 222, o que está completamente errado.

  2. Não tenho certeza se devo usar o TFidfVectorizer () ou o Hashingvectorizer (), vocês podem me ajudar a selecionar uma dessas opções juntamente com os parâmetros?

  3. O algoritmo que estou usando é o LinearSVC, é uma boa opção para problemas de classificação de várias classes com grande quantidade de dados? Ou devo usar algoritmos diferentes?

  4. Como meus dados estão altamente desequilibrados, tentei uma subamostragem aleatória. Os resultados foram aprimorados, mas ainda não estavam à altura. Também não tenho certeza se esta é a abordagem correta para executar uma subamostragem aleatória:

    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. Eu sou novo em aprendizado de máquina, então usei essa abordagem para classificação de texto. Se minha abordagem estiver errada, corrija-me com a correta.

(Seria ótimo se você der sugestões ou soluções com exemplos, pois isso me ajudará a entender melhor).

*** 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)
ponto fora da curva
fonte
Acabei de ver que você tentou sub-amostrar. Apenas, a validação cruzada com dobra K iniciada no Sci-Kit Learn também leva em consideração a distribuição de classes.
Kasra Manshaei

Respostas:

6

Boa pergunta!

Algumas observações

Para dados desequilibrados, você tem abordagens diferentes. O mais bem estabelecido é a reamostragem (sobreamostragem de pequenas classes / subamostragem de grandes classes). O outro é tornar sua classificação hierárquica, ou seja, classificar grandes classes contra todas as outras e depois classificar pequenas classes na segunda etapa (os classificadores não devem ser os mesmos. Tente estratégias de seleção de modelos para encontrar o melhor).

Resposta Prática

Eu tenho resultados aceitáveis ​​sem reamostrar os dados! Portanto, tente, mas depois aprimore-o usando métodos de reamostragem (estatisticamente, eles são uma espécie de DEVE).

TFIDF é bom para esse problema. Os classificadores devem ser selecionados por meio da seleção de modelos, mas minha experiência mostra que a Regressão Logística e a Floresta Aleatória funcionam bem nesse problema específico (no entanto, é apenas uma experiência prática).

Você pode seguir o código abaixo, pois ele funcionou muito bem e tentar modificá-lo para melhorar seus resultados:

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]

Observe que o código é abstrato, portanto, TianX, TrainY, TestX etc. devem ser adequadamente definidos por você.

Dicas

Tenha cuidado com o que é o StopWord. Praticamente muitas pessoas (inclusive eu!) Cometeram esse erro ao remover palavras de parada de acordo com listas predefinidas. Isso não está certo!

As palavras de parada são sensíveis ao corpus, portanto, você precisa remover as palavras de parada de acordo com os conceitos teóricos da informação (para simplificar, você precisa saber que o TFIDF ignora suas palavras de parada específicas do corpus. Se precisar de mais explicações, informe-me para atualizar minha resposta) .

VotingClassifier é uma estratégia de meta-aprendizado na família de Métodos de Conjunto . Eles se beneficiam de diferentes classificadores. Experimente-os, pois eles funcionam muito bem na prática.

O esquema de votação simplesmente pega os resultados de diferentes classificadores e retorna a saída daquele que tem a maior probabilidade de estar certo. Então, tipo de abordagem democrática contra a ditadura;)

Espero que ajude!

Kasra Manshaei
fonte
Bem-vinda! Para reamostragem intuitiva, consulte o link que eu coloquei para reamostragem. Há uma instrução passo a passo.
Kasra Manshaei
Estou tentando a sua solução, se eu ficar preso em qualquer lugar ou em caso de dúvida eu vou postar na seção de comentários. espero que seja bom para você!
outlier
com certeza meu amigo ... boa sorte!
Kasra Manshaei
11
se funcionou, então você pode aceitar a resposta :)
Kasra Manshaei
@outlier desde que a resposta abordou seu problema, aceite-o (e possivelmente vote-o); respostas ocupar o tempo valioso para (voluntário) dos entrevistados
desertnaut