Meu conjunto de treinamento contém cerca de 50 mil entradas com as quais faço um aprendizado inicial. Semanalmente, ~ 5k entradas são adicionadas; mas a mesma quantidade "desaparece" (pois são os dados do usuário que precisam ser excluídos após algum tempo).
Portanto, uso o aprendizado on-line porque não tenho acesso ao conjunto de dados completo posteriormente. Atualmente estou usando um SGDClassifier
que funciona, mas meu grande problema: novas categorias estão aparecendo e agora não posso mais usar meu modelo, pois elas não estavam na inicial fit
.
Existe uma maneira SGDClassifier
ou outro modelo? Aprendizagem profunda?
Não importa se eu tenho que começar do zero AGORA (ou seja, usar algo diferente SGDClassifier
), mas preciso de algo que permita o aprendizado on-line com novos rótulos.
Respostas:
Parece que você não deseja começar a treinar novamente o modelo toda vez que uma nova categoria de etiqueta aparecer. A maneira mais fácil de reter informações máximas de dados passados seria treinar um classificador por categoria.
Dessa forma, você pode continuar treinando cada classificador de forma incremental ("online") com algo parecido
SGDClassifier
sem precisar treiná-los novamente. Sempre que uma nova categoria aparece, você adiciona um novo classificador binário apenas para essa categoria. Em seguida, você seleciona a classe com a maior probabilidade / pontuação entre o conjunto de classificadores.Isso também não é muito diferente do que você está fazendo hoje, porque
scikit's SDGClassifier
já lida com o cenário de várias classes, encaixando vários classificadores "Um vs Todos" sob o capô.Se muitas novas categorias continuarem surgindo, é claro, essa abordagem pode se tornar um pouco complicada de gerenciar.
fonte
warm_start
opçãoSe novas categorias chegarem muito raramente, prefiro a solução "um contra todos" fornecida por @oW_ . Para cada nova categoria, você treina um novo modelo no número X de amostras da nova categoria (classe 1) e no número X de amostras do restante das categorias (classe 0).
No entanto, se novas categorias chegam frequentemente e você deseja usar um único modelo compartilhado , existe uma maneira de fazer isso usando redes neurais.
Em resumo, após a chegada de uma nova categoria, adicionamos um novo nó correspondente à camada softmax com pesos zero (ou aleatórios) e mantemos os pesos antigos intactos, depois treinamos o modelo estendido com os novos dados. Aqui está um esboço visual para a ideia (desenhada por mim):
Aqui está uma implementação para o cenário completo:
O modelo é treinado em duas categorias,
Chega uma nova categoria,
Os formatos de modelo e destino são atualizados de acordo,
O modelo é treinado em novos dados.
Código:
quais saídas:
Eu devo explicar dois pontos em relação a esta saída:
O desempenho do modelo é reduzido de
0.9275
para0.8925
apenas adicionando um novo nó. Isso ocorre porque a saída do novo nó também é incluída para a seleção de categoria. Na prática, a saída do novo nó deve ser incluída somente após o modelo ser treinado em uma amostra considerável. Por exemplo, devemos atingir o pico da maior das duas primeiras entradas[0.15, 0.30, 0.55]
, ou seja, da 2ª classe, nesta fase.O desempenho do modelo estendido em duas categorias (antigas)
0.88
é menor que o modelo antigo0.9275
. Isso é normal, porque agora o modelo estendido deseja atribuir uma entrada a uma das três categorias em vez de duas. Essa diminuição também é esperada quando selecionamos entre três classificadores binários em comparação com dois classificadores binários na abordagem "um contra todos".fonte
Devo dizer que não encontrei nenhuma literatura sobre esse tópico. Até onde eu sei, o que você pergunta é impossível. Você deve estar ciente disso e o proprietário do produto também. O motivo é que qualquer função de perda depende de rótulos conhecidos; portanto, não há como prever um rótulo que não esteja nos dados de treinamento. Além disso, é ficção científica que um algoritmo de aprendizado de máquina pode prever algo para o qual não foi treinado
Dito isto, acho que pode haver uma solução alternativa (deixe-me salientar que essa é uma opinião não baseada na literatura formal). Se o classificador for probabilístico, a saída é a probabilidade de cada classe ser verdadeira e a decisão é o maior prob. Talvez você possa definir um limite para essa probabilidade, de modo que o modelo preveja "desconhecido" se todas as probabilidades estiverem abaixo desse limite. Deixe-me lhe dar um exemplo.
O que você faz com os desconhecidos depende da lógica dos negócios. Se eles são importantes, você pode criar um pool deles e treinar novamente o modelo usando os dados disponíveis. Eu acho que você pode "transferir o aprendizado" do modelo treinado, alterando a dimensão do resultado. Mas isso é algo que eu não enfrentei, então estou apenas dizendo
Assumir a contagem que
SGDClassifier
usaSVM
embaixo, o que não é um algoritmo probabilístico. Após aSGDClassifier
documentação, você pode modificar oloss
argumento paramodified_huber
oulog
para obter resultados probabilísticos.fonte
Existem duas opções:
Preveja a chance de um ponto de dados pertencer a um desconhecido ou
unk
categoria. Quaisquer novas categorias que aparecem no fluxo devem ser previstas comounk
. Isso é comum no NLP (Processamento de linguagem natural) porque sempre existem novos tokens de palavras aparecendo nos fluxos de palavras.Treine novamente o modelo sempre que uma nova categoria for exibida.
Desde que você mencionou
SGDClassifier
, presumo que você use o scikit-learn. O Scikit-learn não suporta muito bem o aprendizado on-line. Seria melhor mudar uma estrutura que suporte melhor o streaming e o aprendizado on-line, como o Spark .fonte