Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

AdaBoost condinua gerando resultado distinto a cada execução do código

Realizei a mudança no código, ajustando o random_state do AdaBoostClassifier Contudo, rodei o código algumas vezes e em algumas delas o valor do AdaBoost foi alterado e depois voltou ao valor anterior como podemos ver abaixo:

Tentativa 1

A Taxa de acerto do AdaBoostClassifier é: 0.43999999999999995

Tentativa 2:

A Taxa de acerto do AdaBoostClassifier é: 0.39

Tentativa 3:

A Taxa de acerto do AdaBoostClassifier é: 0.4733333333333333

Esse é meu código:

from collections import Counter
from sklearn.model_selection import cross_val_score
import pandas as pd
import numpy as np

classificacoes = pd.read_csv('emails.csv')

texto_puro = classificacoes['email']
texto_quebrado = texto_puro.str.lower().str.split(' ')

# set são conjuntos que IMPEDEM elementos repetidos, odemos fazer INTERSECÇÃO, UNIÃO, ETC
dicionario = set()

for lista in texto_quebrado:
    dicionario.update(lista)

total_palavras = len(dicionario)
tuplas = zip(dicionario, range(total_palavras))

tradutor = {palavra: indice for palavra, indice in tuplas}


def vetorizar_texto(texto, tradutor):
    vetor = [0] * len(tradutor)
    for palavra in texto:
        if palavra in tradutor:
            posicao = tradutor[palavra]
            vetor[posicao] += 1

    return vetor


vetoresDeTexto = [vetorizar_texto(texto, tradutor) for texto in texto_quebrado]
marcacoes = classificacoes['classificacao']

X = vetoresDeTexto
Y = marcacoes

porcentagem_de_treino = 0.8

tamanho_do_treino = int(porcentagem_de_treino * len(Y))
tamanho_da_validacao = len(Y) - tamanho_do_treino

treino_dados = X[0:tamanho_do_treino]
treino_marcacoes = Y[0:tamanho_do_treino]

validacao_dados = X[tamanho_do_treino:]
validacao_marcacoes = Y[tamanho_do_treino:]


def fit_and_predict(modelo, treino_dados, treino_marcacoes, algoritmo):
    k = 10
    scores = cross_val_score(modelo, treino_dados, treino_marcacoes, cv=k)
    taxa_de_acerto = np.mean(scores)

    msg = "A Taxa de acerto do {0} é: {1}".format(algoritmo, taxa_de_acerto)
    print(msg)
    return taxa_de_acerto

def teste_real(modelo, validacao_dados, validacao_marcacoes):
    resultado = modelo.predict(validacao_dados)
    acertos = resultado == validacao_marcacoes

    total_acertos = sum(acertos)
    total_elementos = len(validacao_dados)
    taxa_acerto = 100.0 * total_acertos / total_elementos

    msg = "Taxa de acertos do algoritmo vencedor no mundo real é: {0}".format(taxa_acerto)
    print(msg)

resultados = {}

from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import LinearSVC

modelo_oneVsRest = OneVsRestClassifier(LinearSVC(random_state=0))
resultado_oneVsRest = fit_and_predict(modelo_oneVsRest, treino_dados, treino_marcacoes, "OneVsRest")
resultados[resultado_oneVsRest] = modelo_oneVsRest

from sklearn.multiclass import OneVsOneClassifier
from sklearn.svm import LinearSVC

modelo_oneVsOne = OneVsOneClassifier(LinearSVC(random_state=0))
resultado_oneVsOne = fit_and_predict(modelo_oneVsOne, treino_dados, treino_marcacoes, "OneVsOne")
resultados[resultado_oneVsOne] = modelo_oneVsOne

from sklearn.naive_bayes import MultinomialNB

modelo_MultinomialNB = MultinomialNB()
resultado_Multinomial = fit_and_predict(modelo_MultinomialNB, treino_dados, treino_marcacoes, "MultinomialNB")
resultados[resultado_Multinomial] = modelo_MultinomialNB

from sklearn.ensemble import AdaBoostClassifier

modelo_AdaBoostClassifier = AdaBoostClassifier(random_state=0)
resultado_AdaBoostClassifier = fit_and_predict(modelo_AdaBoostClassifier, treino_dados, treino_marcacoes, "AdaBoostClassifier")
resultados[resultado_AdaBoostClassifier] = modelo_AdaBoostClassifier

# teste BÁSICO
acerto_base = max(Counter(validacao_marcacoes).values())  # ele pega o valor do maior ocorrencia de zeros ou uns
taxa_de_acerto_base = 100.0 * acerto_base / len(validacao_marcacoes)
print("A Taxa de acerto base: %f" % taxa_de_acerto_base)

print(resultados)
maximo = max(resultados)
vencedor = resultados[maximo]
print("VENCEDOR:", vencedor)

# precisa fazer o FIT pois o FIT foi excluido pois não fazemos mais o treino
vencedor.fit(treino_dados, treino_marcacoes)

teste_real(vencedor, validacao_dados, validacao_marcacoes)

print("Elementos testados: %d " % len(validacao_dados))

Assim pergunto, há algum erro no meu código ou o AdaBoost continua com o random?

2 respostas

Oi José,

para te dar certeza sobre isso e vermos o que precisamos investigar, eu queria te fazer algumas perguntas.

Queria saber se além da mudança de resultado com o Adaboost você está tendo algum warning ou error no terminal/prompt?

E também se todas as outras taxas estão funcionando?

solução!

Oi novamente José, :p

eu decidi testar o código que colocou aqui e vi que estava tudo ok, mas ainda havia essa divergência nos valores do Adaboost com o random_state valendo 0, o que não era esperado acontecer.

Observando isso, primeiro eu alterei o random_state para nenhum ouNone (que já é o padrão), ou random_state=None, e o problema não se resolveu. Continuei tendo os mesmos três resultados distintos.

Para solucionar isso, usei outra coisa, um método que muda quanto é o valor incial, ou seed que está na própria classe RandomState.

Fazendo isso, pelo algoritmo receber sempre o mesmo valor inicial, ele terá sempre o mesmo conjunto de números cada vez que é chamado, o que vai produzir o mesmo resultado.

Para fazer isso, basta adicionar está linha em algum lugar do seu código:

np.random.seed(0)

Sobre essa solução, ela vai resolver o valor dos resultados, mas é legal lembrar que o fator que muda, ou que é estocástico, é algo importante dentro do Machine Learning. Afinal, queremos observar e coletar as diferentes probabilidades para tomar uma decisão informada, é isso que está no coração do que fazemos.

Repare também em um outro aspecto, os valores do Adaboost estão mudando, mas eles estão fazendo isso dentro de um intervalo. Então você já sabe que o Adaboost fica geralmente entre 0.39 e 0.47, e pode usar esse intervalo para tomar a decisão de qual modelo usar.

Sobre o porquê desta mudança mesmo usando o random_state fixado em um número, eu pesquisei, inclusive, mas não consegui encontrar uma boa explicação.

Não consigo te dar certeza, mas pelo o que eu conheço do algoritmo, arrisco que isso pode se originar de como ele está lidando com a separação entre treino e teste dos dados. O que eu imagino, é que mesmo sem valores randômicos, ele está sempre pegandos as mesmas três (ou mais) partes do conjunto de dados e então avaliando, por isso esses números.

Me diga se a solução funcionou.

Eu espero ter ajudado, e qualquer outra dúvida do curso, pode postar aqui o/.