Como parte de la implementación de la gran tarea del Análisis de Sentimientos (análisis de revisiones), decidí dedicar algo de tiempo al estudio adicional de su elemento separado, utilizando el VotingClassifier del módulo sklearn.ensemble como una herramienta para construir un conjunto de modelos de clasificación y mejorar la calidad final de las predicciones. ¿Por qué es esto importante y cuáles son los matices?

A menudo sucede que, en el curso de la resolución del problema aplicado del análisis de datos, no es inmediatamente obvio (o nada obvio) qué modelo de capacitación es el más adecuado. Una solución puede ser seleccionar el modelo más popular y / o intuitivamente apropiado en función de la naturaleza de los datos disponibles. En este caso, los parámetros del modelo seleccionado se optimizan (por ejemplo, a través de GridSearchCV) y se utilizan en el trabajo. Otro enfoque puede ser utilizar un conjunto de modelos cuando los resultados de varios de ellos están involucrados simultáneamente en la formación del resultado final. Diré de inmediato que el propósito del artículo no es describir las ventajas de usar un conjunto de modelos o los principios de su construcción (esto se puede encontrar
aquí ), sino más bien en un enfoque aplicado por separado para resolver el problema usando un ejemplo específico y analizando los matices que surgen durante tal solución.
El enunciado del problema global es el siguiente : solo se dieron
100 revisiones en teléfonos móviles como muestra de prueba, y necesitamos un modelo previamente entrenado que muestre el mejor resultado en estas 100 revisiones, es decir, determinará si la revisión es positiva o negativa. Una dificultad adicional, como se deduce de las condiciones del problema, es la falta de una muestra de entrenamiento. Para superar esta dificultad con la ayuda de la biblioteca Beautiful Soup, se analizaron con éxito 10,000 reseñas sobre teléfonos móviles y calificaciones para ellos de uno de los sitios rusos.
Saltando los pasos de análisis, preprocesamiento de datos y estudio de su estructura inicial , pasamos al momento en que hay:
- muestra de capacitación, que consta de 10,000 revisiones telefónicas, cada revisión está marcada como binaria (positiva o negativa). Marcado para la definición de revisiones con calificaciones 1-3 como negativas y calificaciones 4-5 como positivas.
- usando Count Vectorizer, los datos se presentan en una forma adecuada para entrenar modelos clasificadores
¿Cómo decidir qué modelo es mejor para ti? No tenemos la capacidad de enumerar modelos manualmente, porque una muestra de prueba de solo 100 revisiones plantea un gran riesgo de que algún modelo simplemente se adapte mejor a esta muestra de prueba, pero si lo usa en una muestra adicional oculta a nosotros o en una "batalla", el resultado será inferior al promedio.
Para resolver este problema
, la biblioteca Scikit-learn tiene un módulo VotingClassifier , que es una herramienta excelente para usar varios modelos de aprendizaje automático diferentes y combinarlos en un solo clasificador. Esto reduce el riesgo de reentrenamiento, así como la interpretación incorrecta de los resultados de cualquier modelo en particular.
El módulo VotingClassifier se importa con el siguiente comando :
from sklearn.ensemble import VotingClassifier
Detalles prácticos al trabajar con este módulo:
1) Lo primero y más importante es cómo obtener una sola predicción tomada del clasificador combinado después de recibir predicciones de cada uno de los modelos incluidos en él. Entre los parámetros de VotingClassifier hay un parámetro de
votación con dos valores posibles: 'hard' y 'soft'.
1.1) En el primer caso, la respuesta final del clasificador conjunto corresponderá a la "opinión" de la mayoría de sus miembros. Por ejemplo, su clasificador combinado usa datos de tres modelos diferentes. Dos de ellos en una observación específica predicen la respuesta "retroalimentación positiva", el tercero - "retroalimentación negativa". Por lo tanto, para esta observación, la predicción final será "retroalimentación positiva", ya que tenemos 2 - "a favor" y 1 "en contra".
1.2) En el segundo caso, es decir cuando se usa el valor "suave" del parámetro de
votación , hay una "votación" completa y una ponderación de las predicciones del modelo para
cada clase, por lo que la respuesta final del clasificador combinado es la argmax de la suma de las probabilidades predichas.
¡IMPORTANTE! Para poder utilizar dicho método de "votación",
cada clasificador de los incluidos en su conjunto debe admitir el método
predict_proba () para obtener una estimación cuantitativa de la probabilidad de ocurrencia en cada una de las clases. Tenga en cuenta que no todos los modelos de clasificadores admiten este método y, en consecuencia, se pueden usar dentro del marco de VotingClassifier cuando se usa el método de probabilidades ponderadas (votación suave).
Veamos un ejemplo : hay tres clasificadores y dos clases de revisiones: positivas y negativas. Cada clasificador, a través del método predict_proba, dará un cierto valor de probabilidad (p), con el que asigna una observación particular a la clase 1 y, en consecuencia, con probabilidad (1-p) a la clase dos. El clasificador combinado, después de recibir una respuesta de cada uno de los modelos, lleva a cabo la ponderación de las estimaciones obtenidas y da el resultado final obtenido como
$$ display $$ max (w1 * p1 + w2 * p1 + w3 * p1, w1 * p2 + w2 * p2 + w3 * p3) $$ display $$
, donde w1, w2, w3 son los pesos de sus clasificadores incluidos en el conjunto, por defecto tienen pesos iguales, y p1, p2 es la evaluación de pertenecer a la clase 1 o clase 2 de cada uno de ellos. Tenga en cuenta también que los pesos de los clasificadores cuando se usa Soft Vote se pueden cambiar usando el parámetro de pesos, por lo que la llamada al módulo debería verse así:
... = VotingClassifier(estimators=[('..', clf1), ('..', clf2), ('...', clf3)], voting='soft', weights=[*,*,*])
, donde los asteriscos pueden indicar los pesos requeridos para cada modelo.
2) La capacidad de usar
simultáneamente el módulo VotingClassifier y GridSearch para optimizar los hiperparámetros de cada uno de los clasificadores incluidos en el conjunto.
Cuando planea usar un conjunto y desea que los modelos incluidos en él sean optimizados, puede usar GridSearch ya en el clasificador unificado. Y el siguiente código muestra cómo puede trabajar con los modelos incluidos en él (regresión logística, ingenuo Bayes, descenso de gradiente estocástico) mientras permanece dentro del marco del clasificador unificado (VotingClassifier):
clf1 = LogisticRegression() clf2 = MultinomialNB() clf3 = SGDClassifier(max_iter=1000, loss='log') eclf = VotingClassifier(estimators=[ ('lr', clf1), ('nb', clf2),('sgd', clf3)], voting='hard') # (hard voting), . . 1.1 <b>params = {'lr__C' : [0.5,1,1.5], 'lr__class_weight': [None,'balanced'], 'nb__alpha' : [0.1,1,2], 'sgd__penalty' : ['l2', 'l1'], 'sgd__alpha': [0.0001,0.001,0.01]} </b> # , , grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5, scoring='accuracy', n_jobs=-1) grid = grid.fit(data_messages_vectorized, df_texts['Binary_Rate']) # , 5
Por lo tanto, el diccionario de parámetros debe establecerse de modo que, al acceder a él a través de GridSearch, pueda determinar qué parámetro del conjunto de modelos se refiere a un parámetro cuyo valor desea optimizar.
Eso es todo lo que necesita saber para usar completamente la herramienta VotingClassifier como una forma de construir un conjunto de modelos y optimizarlo. Veamos los resultados:
print grid.best_params_ {'lr__class_weight': 'balanced', 'sgd__penalty': 'l1', 'nb__alpha': 1, 'lr__C': 1, 'sgd__alpha': 0.001}
Se encuentran los valores óptimos de los parámetros, queda por comparar los resultados del trabajo para el conjunto de clasificadores (VotingClassifier) con los parámetros óptimos, realizaremos una validación cruzada en la muestra de entrenamiento y compararemos los modelos con los parámetros óptimos y el conjunto que consiste en ellos:
for clf, label in zip([clf1, clf2, clf3, eclf], ['Logistic Regression', 'Naive Bayes', 'SGD', 'Ensemble_HardVoting']): scores = cross_val_score(clf, data_messages_vectorized, df_texts['Binary_Rate'], cv=3, scoring='accuracy') print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
El resultado final:
Precisión: 0,75 (± 0,02) [Regresión logística]
Precisión: 0,79 (± 0,02) [Naive Bayes]
Precisión: 0,79 (± 0,02) [SGD]
Precisión: 0,79 (± 0,02) [Ensemble_HardVoting]
Como puede ver, los modelos se mostraron algo diferentes en la muestra de entrenamiento (con parámetros estándar, esta diferencia fue más notable). Además, el valor total (según la métrica de precisión) del conjunto no tiene que exceder el mejor valor de los modelos incluidos en él, porque el conjunto es más bien un modelo más estable, capaz de mostrar un resultado similar en el conjunto de prueba y en la "batalla", lo que significa reducir el riesgo de reentrenamiento, ajuste al conjunto de entrenamiento y otros clasificadores de problemas relacionados con el entrenamiento. ¡Buena suerte en la resolución de problemas aplicados y gracias por su atención!
PD Dadas las especificaciones y reglas de publicación en el sandbox, no puedo proporcionar un enlace a github y el código fuente para el análisis dado en este artículo, así como enlaces a Kaggle, en el marco de la competencia InClass que proporcionó un conjunto de pruebas y herramientas para verificar modelos en él. Solo puedo decir que este conjunto superó significativamente la línea de base y ocupó el lugar que le corresponde en la tabla de clasificación después de verificar un conjunto de prueba. Espero en las siguientes publicaciones que pueda compartir.