Como parte da implementação da grande tarefa da Análise de Sentimentos (análise de revisões), decidi dedicar algum tempo ao estudo adicional de seu elemento separado - usando o VotingClassifier do módulo sklearn.ensemble como uma ferramenta para construir um conjunto de modelos de classificação e melhorar a qualidade final das previsões. Por que isso é importante e quais são as nuances?

Muitas vezes acontece que, durante a solução do problema aplicado da análise de dados, não é imediatamente óbvio (ou nem um pouco óbvio) qual modelo de treinamento é mais adequado. Uma solução pode ser selecionar o modelo mais popular e / ou intuitivamente apropriado, com base na natureza dos dados disponíveis. Nesse caso, os parâmetros do modelo selecionado são otimizados (por exemplo, por meio do GridSearchCV) e são usados no trabalho. Outra abordagem pode ser usar um conjunto de modelos quando os resultados de vários deles estiverem envolvidos simultaneamente na formação do resultado final. Eu direi imediatamente que o objetivo do artigo não é descrever as vantagens de usar um conjunto de modelos ou os princípios de sua construção (isso pode ser lido
aqui ), mas sim em uma abordagem aplicada separadamente para resolver o problema usando um exemplo específico e analisar as nuances que surgem durante essa solução.
A declaração do problema global é a seguinte : apenas
100 análises foram feitas em telefones celulares como amostra de teste e precisamos de um modelo pré-treinado que mostre o melhor resultado nessas 100 análises - ou seja, ele determinará se a análise é positiva ou negativa. Uma dificuldade adicional, como segue a partir das condições do problema, é a falta de uma amostra de treinamento. Para superar essa dificuldade com a ajuda da biblioteca Beautiful Soup, 10.000 análises sobre telefones celulares e classificações de um dos sites russos foram analisadas com sucesso.
Ignorando as etapas de análise, pré-processamento de dados e estudo de sua estrutura inicial , passamos ao momento em que existem:
- Na amostra de treinamento, composta por 10.000 avaliações por telefone, cada avaliação é marcada como binária (positiva ou negativa). Marcação para a definição de comentários com classificações 1-3 como negativas e classificações 4-5 como positivas.
- usando o Count Vectorizer, os dados são apresentados em um formato adequado para o treinamento de modelos de classificadores
Como decidir qual modelo é melhor para você? Não temos a capacidade de iterar manualmente sobre modelos, porque uma amostra de teste de apenas 100 revisões representa um risco enorme de que algum modelo seja mais adequado a essa amostra de teste, mas se você o usar em uma amostra adicional escondida de nós ou em uma "batalha", o resultado será abaixo da média.
Para resolver esse problema
, a biblioteca Scikit-learn possui um módulo VotingClassifier , que é uma excelente ferramenta para usar vários modelos de aprendizado de máquina, diferentes entre si, e combiná-los em um classificador. Isso reduz o risco de reciclagem, bem como a interpretação incorreta dos resultados de qualquer modelo em particular.
O módulo VotingClassifier é importado com o seguinte comando :
from sklearn.ensemble import VotingClassifier
Detalhes práticos ao trabalhar com este módulo:
1) A primeira e mais importante é como obter uma única previsão do classificador combinado depois de receber previsões de cada um dos modelos incluídos nele. Entre os parâmetros VotingClassifier, há um parâmetro de
votação com dois valores possíveis: 'hard' e 'soft'.
1.1) No primeiro caso, a resposta final do classificador conjunto corresponderá à “opinião” da maioria de seus membros. Por exemplo, seu classificador combinado usa dados de três modelos diferentes. Dois deles em uma observação específica prevêem a resposta "feedback positivo", o terceiro - "feedback negativo". Assim, para esta observação, a previsão final será “feedback positivo”, pois temos 2 - “a favor” e 1 “contra”.
1.2) No segundo caso, ou seja, ao usar o valor 'flexível' do parâmetro de
votação , há uma “votação” e ponderação completas das previsões do modelo para
cada classe; portanto, a resposta final do classificador combinado é argmax da soma das probabilidades previstas.
IMPORTANTE! Para poder usar esse método de "votação",
cada classificador dentre os incluídos no seu conjunto deve suportar o método
predict_proba () para obter uma estimativa quantitativa da probabilidade de ocorrência em cada uma das classes. Observe que nem todos os modelos de classificadores suportam esse método e, portanto, podem ser usados na estrutura do VotingClassifier ao usar o método de probabilidades ponderadas (votação suave).
Vejamos um exemplo : existem três classificadores e duas classes de críticas: positiva e negativa. Cada classificador, através do método predict_proba, fornecerá um certo valor de probabilidade (p), com o qual uma observação específica é atribuída à classe 1 e, consequentemente, com probabilidade (1-p) à classe dois. O classificador combinado, após receber uma resposta de cada um dos modelos, realiza a ponderação das estimativas obtidas e fornece o resultado final obtido como
$$ display $$ max (w1 * p1 + w2 * p1 + w3 * p1, w1 * p2 + w2 * p2 + w3 * p3) $$ display $$
, em que w1, w2, w3 são os pesos dos seus classificadores incluídos no conjunto, por padrão tendo pesos iguais e p1, p2 é a avaliação de pertencer à classe 1 ou classe 2 de cada um deles. Observe também que os pesos dos classificadores ao usar o Soft Vote podem ser alterados usando o parâmetro weights, portanto, a chamada do módulo deve ser assim:
... = VotingClassifier(estimators=[('..', clf1), ('..', clf2), ('...', clf3)], voting='soft', weights=[*,*,*])
, onde os asteriscos podem indicar os pesos necessários para cada modelo.
2) A capacidade de usar
simultaneamente o módulo VotingClassifier e GridSearch para otimizar os hiperparâmetros de cada um dos classificadores incluídos no conjunto.
Quando você planeja usar um conjunto e deseja que os modelos incluídos sejam otimizados, você pode usar o GridSearch já no classificador unificado. E o código abaixo mostra como você pode trabalhar com os modelos incluídos (regressão logística, Bayes ingênuo, descida gradiente estocástica) enquanto permanece na estrutura do classificador 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
Portanto, o dicionário de parâmetros deve ser definido para que, ao acessá-lo por meio do GridSearch, você possa determinar qual parâmetro no conjunto de modelos se refere a um parâmetro cujo valor você deseja otimizar.
É tudo o que você precisa saber para usar totalmente a ferramenta VotingClassifier como uma maneira de criar um conjunto de modelos e otimizá-lo. Vejamos os resultados:
print grid.best_params_ {'lr__class_weight': 'balanced', 'sgd__penalty': 'l1', 'nb__alpha': 1, 'lr__C': 1, 'sgd__alpha': 0.001}
Os valores ótimos dos parâmetros são encontrados, resta comparar os resultados do trabalho para o conjunto de classificadores (VotingClassifier) com os parâmetros ótimos, realizaremos a validação cruzada na amostra de treinamento e comparar os modelos com os parâmetros ótimos e o conjunto constituído por eles:
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))
O resultado final:
Precisão: 0,75 (± 0,02) [Regressão logística]
Precisão: 0,79 (± 0,02) [Naive Bayes]
Precisão: 0,79 (± 0,02) [SGD]
Precisão: 0,79 (± 0,02) [Ensemble_HardVoting]
Como você pode ver, os modelos se mostraram um pouco diferentes na amostra de treinamento (com parâmetros padrão, essa diferença foi mais perceptível). Além disso, o valor total (de acordo com a métrica de precisão) do conjunto não precisa exceder o melhor valor dos modelos incluídos nele, porque o conjunto é um modelo mais estável, capaz de mostrar ± um resultado semelhante no conjunto de testes e na “batalha”, o que significa reduzir o risco de reciclagem, adequação ao conjunto de treinamento e outros problemas classificadores relacionados ao treinamento. Boa sorte na solução de problemas aplicados e muito obrigado pela atenção!
PS Dadas as especificidades e regras de publicação na sandbox, não posso fornecer um link para o github e o código-fonte para a análise fornecida neste artigo, bem como links para o Kaggle, no âmbito da competição InClass, que forneceu um conjunto de testes e ferramentas para verificar modelos nele. Só posso dizer que esse conjunto superou significativamente a linha de base e ocupou seu devido lugar na tabela de classificação após a verificação de um conjunto de testes. Espero que nas seguintes publicações eu possa compartilhar.