Quão bem R é escalável para tarefas de classificação de texto? [fechadas]

30

Estou tentando acelerar a resposta com R. Eu finalmente quero usar as bibliotecas R para fazer a classificação de texto. Fiquei me perguntando quais são as experiências das pessoas com relação à escalabilidade de R quando se trata de fazer a classificação de texto.

É provável que eu ocorra com dados de alta dimensão (~ 300k dimensões). Eu estou olhando para usar SVM e floresta aleatória em particular como algoritmos de classificação.

As bibliotecas R seriam dimensionadas para o tamanho do meu problema?

Obrigado.

EDIÇÃO 1: Apenas para esclarecer, é provável que meu conjunto de dados tenha de 1000 a 3000 linhas (talvez um pouco mais) e 10 classes.

EDIÇÃO 2: Como sou muito novo em R, solicitarei que os pôsteres sejam mais específicos sempre que possível. Por exemplo, se você estiver sugerindo um fluxo de trabalho / pipeline, mencione as bibliotecas R envolvidas em cada etapa, se possível. Alguns indicadores adicionais (para exemplos, código de exemplo etc.) estariam no topo do bolo.

EDIÇÃO 3: Em primeiro lugar, obrigado a todos por seus comentários. E, em segundo lugar, peço desculpas, talvez eu devesse ter dado mais contexto para o problema. Eu sou novo no R, mas não muito na classificação de texto. Eu já fiz o pré-processamento (stemming, remoção de palavras irrelevantes, conversão tf-idf etc.) em algumas partes dos meus dados usando pacote tm , apenas para ter uma ideia das coisas. O tm era tão lento, mesmo em cerca de 200docs, que fiquei preocupado com a escalabilidade. Então comecei a jogar com o FSelector e até isso foi muito lento. E foi nesse ponto que fiz o meu OP.

EDIÇÃO 4: Ocorreu-me que eu tenho 10 aulas e cerca de ~ 300 documentos de treinamento por turma e, na verdade, estou construindo a matriz termXdoc de todo o conjunto de treinamento, resultando em uma dimensionalidade muito alta. Mas e quanto a reduzir todos os problemas de classificação 1 em 1 para uma série de problemas de classificação binária? Isso reduziria drasticamente o número de documentos de treinamento (e, portanto, a dimensionalidade) em cada uma das etapas do k-1, não seria? Então, essa abordagem é boa? Como ele se compara em termos de precisão à implementação comum de várias classes?

Andy
fonte
11
300k de dimensões com quantas linhas? Infelizmente, os objetos R devem estar na memória (pelo menos, a menos que você considere grandes ajustes, basicamente exigindo que você reescreva esses algoritmos). Isso significa que, com, digamos, 8 GB de RAM, acho que você não pode armazenar mais do que algumas centenas de linhas com 300 mil colunas.
Crayola
@crayola: o número de linhas pode variar de 1000 a 3000.
21411 Andy
2
Objetos R não precisam estar na memória. O mapeamento de memória é muito fácil. 300k dimensões não é um problema. Também presumo que seus dados sejam escassos, como é o caso de quase todos os problemas de texto.
Iterator
Acabei de notar o comentário acima: apenas 1000-3000 linhas? Isso é muito pequeno. Você pode explicar qual é o seu corpus? Um lote de e-mails? Descrições de pacotes no CRAN? Você pode ter mais problemas estatísticos com P >> N do que com qualquer problema de armazenamento.
Iterator
11
@Iterator: Nós temos alguns recursos educacionais (papers, ensaios, etc.) que queremos classificar.
Andy

Respostas:

17

Conforme solicitado em um comentário, aqui estão alguns indicadores para as etapas de processamento. Diversas ferramentas podem ser encontradas na exibição de tarefas CRAN para processamento de linguagem natural . Você também pode querer olhar para este artigo sobre o tmpacote (mineração de texto) para R .

  1. Antes do processamento, considere a normalização dos tokens de palavras. openNLP(para o qual existe um pacote R) é uma rota.
  2. Para o processamento de texto, uma etapa comum de pré-processamento é normalizar os dados através de tf.idf- frequência de termo * frequência inversa de documento - consulte a entrada da Wikipedia para obter mais detalhes. Existem outras normalizações mais recentes, mas esse é um método de pão com manteiga, por isso é importante conhecê-lo. Você pode implementá-lo facilmente em R: apenas armazene (docID, wordID, freq1, freq2) em que freq1 é a contagem de vezes que a palavra indexada por wordID apareceu no documento fornecido e freq2 é o número de documentos em que aparece. Não é necessário armazenar esse vetor para palavras que não aparecem em um determinado documento. Então, basta pegar freq1 / freq2 e você terá seu valor tf.idf.
  3. Depois de calcular os valores tf.idf, você pode trabalhar com toda a dimensionalidade dos seus dados ou filtrar as palavras que são essencialmente não informativas. Por exemplo, qualquer palavra que apareça em apenas 1 documento não dará muitas informações. Isso pode reduzir substancialmente sua dimensionalidade. Dado o pequeno número de documentos que estão sendo examinados, você pode achar que reduzir para apenas 1 mil dimensões é apropriado.
  4. Eu não atualizaria os dados (por exemplo, para PCA), mas você pode armazenar os dados agora em uma matriz de termos (onde as entradas agora são valores tf.idf) com facilidade, usando as matrizes esparsas, conforme suportado pelo Matrixpacote.

Neste ponto, você tem um conjunto de dados bem pré-processado. Eu recomendaria continuar com as ferramentas citadas na exibição de tarefas CRAN ou no pacote de mineração de texto. Agrupar os dados, por exemplo, projetando nos primeiros 4 ou 6 componentes principais, pode ser muito interessante para o seu grupo quando os dados são plotados.

Outra coisa: você pode achar que a redução da dimensionalidade ao longo das linhas do PCA (*) pode ser útil ao usar vários métodos de classificação, pois você está basicamente agregando as palavras relacionadas. Os primeiros 10-50 componentes principais podem ser tudo o que você precisa para a classificação do documento, considerando o tamanho da amostra.

(*) Nota: PCA é apenas um primeiro passo. Pode ser muito interessante para alguém que está começando com a mineração de texto e o PCA, mas você pode acabar descobrindo que isso é um incômodo para conjuntos de dados esparsos. Como primeiro passo, porém, dê uma olhada, especialmente através das funções prcompe princomp.

Update: Eu não especificou uma preferência nesta resposta - Eu recomendo prcompao invés de princomp.

Iterador
fonte
+1 boa resposta; Só estou curioso por que você diz que um pequeno número de docas implica em um número menor de variáveis ​​importantes - não parece um pouco super adequado?
Não sei se entendi o que você quer dizer. Mantê-los é super adaptável, certamente, então essas variáveis ​​seriam eliminadas em qualquer regularização razoável. Além disso, o vocabulário (P) cresce com o número de documentos ou amostras (N), portanto, a primeira vez que um termo aparece não indica muito. Continue adicionando documentos e a recorrência de um termo entre documentos se tornará informativa.
Iterator
@ Iterator: Obrigado pela sua resposta. Então, prcompe / ou princompserá dimensionado para esse tipo de dados que você considera? Também acabei de editar minha pergunta e adicionei algumas informações adicionais.
21411 Andy
Não, eles provavelmente não serão dimensionados quando você atingir 300K colunas. :) (Apenas para salientar: o X'X nesse caso terá entradas 90B - um problema de armazenamento.) Em vez disso, filtre primeiro pelo tf.idf. Se houver apenas, digamos, 10 classes distintas, um múltiplo pequeno de 10 deve ser adequado para uma dimensionalidade maior para separar as classes. Portanto, 1000 dimensões devem ser mais que suficientes. Ambos os métodos PCA (btw, eu recomendo prcomp) ficarão bem.
Iterator
Depois de limitar a 1000 dimensões ou talvez mais algumas (por exemplo, 2K) e executar o PCA, você pode levar as projeções para, digamos, 100 dimensões (que podem ser um exagero, mas há pouco dano nisso) e depois classificar. Neste ponto, não há nada muito emocionante acontecendo.
Iterator
5

Primeiro seja bem vindo! O processamento de texto é muito divertido, e fazê-lo no R está ficando mais fácil o tempo todo.

A resposta curta: sim - as ferramentas em R agora são muito boas para lidar com esse tipo de dados. De fato, não há nada de especial em R, C ++, Groovy, Scala ou qualquer outro idioma quando se trata de armazenamento de dados na RAM: todo idioma armazena um flutuador duplo de 8 bytes ... aguarde ... aguarde. .. 8 bytes!

Os algoritmos e sua implementação são importantes, especialmente se implementados muito pouco em relação às estruturas de dados e à complexidade computacional. Se você estiver implementando seus próprios algoritmos, apenas tome cuidado. Se estiver usando outro código, a advertência será aplicada, como em qualquer ambiente.

Para R, você precisará considerar:

  1. Sua representação de dados (veja matrizes esparsas, especialmente no Matrixpacote)
  2. Armazenamento de dados (talvez memória mapeada, usando bigmemoryou ff; ou distribuída, usando Hadoop)
  3. Seu particionamento de dados (quanto você pode caber na RAM depende de quanta RAM você possui)

O último ponto está realmente sob seu controle.

Quando se trata dessa dimensionalidade, não é mais tão grande. O número de observações terá mais impacto, mas você pode particionar seus dados para ajustar o uso da RAM, para que não haja muito com o que se preocupar.

Iterador
fonte
3

Concordo com o lápis de cera que o número de linhas é crucial aqui. Para RF, você precisará de pelo menos 3x mais RAM do que o peso de seu conjunto de dados e provavelmente muito tempo (esse número de atributos geralmente requer muitas árvores na floresta - e observe que não há implementação paralela de RF em R).

Sobre o SVM, duvido que seja uma boa idéia lutar com dimensões de 300k enquanto você provavelmente pode desenvolver uma função do kernel que será equivalente aos seus descritores de texto.

EDIT: matriz de 3k x 30k (real) ocuparia algo como 7Gb, então tudo o que você precisa fazer de RF (usando o randomForest) nesses dados é um computador com 16 GB de RAM, um pouco de sorte e bastante tempo ou apenas um computador com 24 GB RAM e bastante tempo.


fonte
Bem, eu certamente faria a seleção de recursos (chi ao quadrado, com base em entropia), mas também não consegui encontrar nenhuma biblioteca R que pudesse ser dimensionada para essa tarefa. Levando tudo isso em consideração, é correto dizer que talvez eu devesse começar a procurar soluções não-R?
21411 Andy
11
"note que não há implementação paralela de RF em R". Isso é apenas parcialmente correto, pois o foreachpacote funciona bem com o randomForestpacote. Eu acho que existe um exemplo na vinheta para foreach. (Ou talvez doMC).
crayola
@ Andy O problema é que, além de reescrever os algoritmos em uma linguagem de programação de baixo nível, não sei ao certo qual software será capaz de aplicar esses algoritmos aos seus dados. Se eu estivesse na sua situação, acho que seguiria R e reescreveria partes de randomForesttal forma que ele consultaria as colunas escolhidas aleatoriamente, por exemplo, um banco de dados SQL a cada iteração (de modo que as dimensões de 300k nunca teriam estar em carneiro). Mas isso é provavelmente principalmente porque eu sei mais sobre R do que sobre as outras opções possíveis.
Crayola
O que você quer dizer com afirmação de que não conseguiu encontrar uma biblioteca escalável para isso? Filtros como este são álgebra básica e devem funcionar sem problemas (desde que você tenha RAM suficiente).
@crayola É verdade, mas a parte de fusão é horrível. Além disso, não é um paralelismo entre membros, portanto provavelmente seria doloroso (se não impossível) nesse cenário.