Datos desequilibrados que causan una clasificación errónea en el conjunto de datos multiclase


9

Estoy trabajando en la clasificación de texto donde tengo 39 categorías / clases y 8,5 millones de registros. (En el futuro, los datos y las categorías aumentarán).

La estructura o el formato de mis datos es el siguiente.

----------------------------------------------------------------------------------------
| 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 distribución de datos no es normal; Está 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 puede ver, están altamente desequilibrados y conducen a clasificaciones erróneas.

Pasos que he realizado hasta ahora

1) Combine la columna product_title y key_value_pairs y elimine las palabras de detención y los caracteres especiales y realice la derivación.

2) He usado tubería para TFIDFvectorizer (), LinearSVC ()

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

Después de esto, encajé la tubería y almacené el clasificador en pickle

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

En el lado de prueba, he repetido el paso 1 como se mencionó anteriormente y luego cargo el pepinillo y uso la función de predicción

pd = cl.predict([testData])

Problemas que estoy enfrentando

  1. Muchos productos se clasifican erróneamente en otras categorías

    Ejemplo: Ultimate Nutrition Prostar 100% Whey Protein debería clasificarse en la categoría 311, pero mi clasificador lo clasifica como 222, lo cual es completamente incorrecto.

  2. No estoy seguro de si usar TFidfVectorizer () o Hashingvectorizer (), ¿pueden ayudarme a seleccionar uno de estos junto con sus parámetros?

  3. Algoritmo que estoy usando es LinearSVC, ¿es una buena opción para problemas de clasificación de varias clases con gran cantidad de datos? ¿O debería usar diferentes algoritmos?

  4. Como mis datos están altamente desequilibrados, probé un muestreo aleatorio. Los resultados fueron mejorados pero todavía no estaban a la altura. Además, no estoy seguro de si este es el enfoque correcto para realizar un muestreo aleatorio:

    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. Soy nuevo en el aprendizaje automático, así que he usado este enfoque para la clasificación de texto. Si mi enfoque es incorrecto, corríjame con el correcto.

(Sería genial si da una sugerencia o solución con ejemplos, ya que me ayudará a entender mejor)

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

Acabo de ver que intentaste un muestreo insuficiente. Solo para su información, la validación cruzada de K-fold Startified en Sci-Kit Learn también tiene en cuenta la distribución de clases.
Kasra Manshaei

Respuestas:


6

¡Buena pregunta!

Algunas observaciones

Para los datos desequilibrados tiene diferentes enfoques. El más establecido es el remuestreo (sobremuestreo de clases pequeñas / submuestreo de clases grandes). El otro es hacer que su clasificación sea jerárquica, es decir, clasificar las clases grandes contra todas las demás y luego clasificar las clases pequeñas en el segundo paso (no se supone que los clasificadores sean iguales. Intente estrategias de selección de modelos para encontrar la mejor).

Respuesta práctica

¡Obtuve resultados aceptables sin volver a muestrear los datos! Por lo tanto, pruébelo, pero luego mejórelo utilizando métodos de remuestreo (estadísticamente son una especie de DEBE).

TFIDF es bueno para tal problema. Los clasificadores deben seleccionarse a través de la selección del modelo, pero mi experiencia muestra que la Regresión logística y el Bosque aleatorio funcionan bien en este problema específico (sin embargo, es solo una experiencia práctica).

Puede seguir el siguiente código, ya que funcionó simplemente bien, entonces puede intentar modificarlo para mejorar sus 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]

Tenga en cuenta que el código es abstracto, por lo que debe definir TianX, TrainY, TestX, etc.

Consejos

Tenga cuidado con lo que es StopWord. Prácticamente muchas personas (¡incluyéndome a mí!) Cometieron este error al eliminar palabras de detención de acuerdo con listas predefinidas. ¡Eso no está bien!

Las palabras de detención son sensibles al corpus, por lo que debe eliminar las palabras vacías de acuerdo con los conceptos teóricos de la información (para simplificar, debe saber que TFIDF ignora sus palabras vacías específicas del corpus. Si necesita más explicaciones, avíseme para actualizar mi respuesta) .

VotingClassifier es una estrategia de metaaprendizaje en la familia de métodos de conjunto . Se aprovechan de diferentes clasificadores. Pruébalos ya que funcionan bastante bien en la práctica.

El esquema de votación simplemente toma los resultados de diferentes clasificadores y devuelve el resultado del que tiene la mayor probabilidad de ser correcto. Tan amable de enfoque democrático contra la dictadura;)

¡Espero eso ayude!


¡Bienvenidos! Para un remuestreo intuitivo, puede consultar el enlace que puse para remuestrear. Hay una instrucción paso a paso.
Kasra Manshaei

Estoy probando su solución, si me atasco en algún lugar o en caso de dudas, publicaré en la sección de comentarios. ¡Espero que eso esté bien para ti!
atípico

claro mi amigo ... buena suerte!
Kasra Manshaei

1
si funcionó, entonces puede aceptar la respuesta :)
Kasra Manshaei

@outlier ya que la respuesta ha abordado su problema, por favor, acéptelo (y posiblemente vote); las respuestas toman un tiempo valioso para los encuestados (voluntarios)
desertnaut
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.