Estou convertendo um corpus de documentos de texto em vetores de palavras para cada documento. Eu tentei isso usando um TfidfVectorizer e um HashingVectorizer
Entendo que um HashingVectorizer
não leva em consideração as IDF
pontuações como um TfidfVectorizer
faz. A razão pela qual ainda estou trabalhando com a HashingVectorizer
é a flexibilidade que ela oferece ao lidar com grandes conjuntos de dados, conforme explicado aqui e aqui . (Meu conjunto de dados original possui 30 milhões de documentos)
Atualmente, estou trabalhando com uma amostra de 45339 documentos, portanto, tenho a capacidade de trabalhar com uma TfidfVectorizer
também. Quando uso esses dois vetorizadores nos mesmos documentos 45339, as matrizes que recebo são diferentes.
hashing = HashingVectorizer() with LSM('corpus.db')) as corpus: hashing_matrix = hashing.fit_transform(corpus) print(hashing_matrix.shape)
forma da matriz de hash (45339, 1048576)
tfidf = TfidfVectorizer() with LSM('corpus.db')) as corpus: tfidf_matrix = tfidf.fit_transform(corpus) print(tfidf_matrix.shape)
forma da matriz tfidf (45339, 663307)
Quero entender melhor as diferenças entre a HashingVectorizer
e a TfidfVectorizer
, e a razão pela qual essas matrizes têm tamanhos diferentes - particularmente no número de palavras / termos.
fonte
Respostas:
A principal diferença é que
HashingVectorizer
aplica uma função de hash às contagens de frequência de termo em cada documento, ondeTfidfVectorizer
dimensiona essas contagens de frequência de termo em cada documento penalizando termos que aparecem mais amplamente no corpus. Há um ótimo resumo aqui: https://spark.apache.org/docs/latest/mllib-feature-extraction.htmlAs funções de hash são uma maneira eficiente de mapear termos para recursos; ele não precisa necessariamente ser aplicado apenas a frequências a termo, mas é assim que
HashingVectorizer
é empregado aqui. Junto com os documentos 45339, suspeito que o vetor de recurso tenha o comprimento 1048576 porque é o padrão 2 ^ 20n_features
; você pode reduzir isso e tornar o processo mais barato, mas com um risco maior de colisão, onde a função mapeia termos diferentes para o mesmo recurso: http://preshing.com/20110504/hash-collision-probabilities/Dependendo do caso de uso dos vetores de palavras, pode ser possível reduzir significativamente o comprimento do vetor de recurso de hash (e, portanto, a complexidade) com perda aceitável de precisão / eficácia (devido ao aumento da colisão). O Scikit-learn possui alguns parâmetros de hash que podem ajudar, por exemplo
alternate_sign
.Se a matriz de hash for maior que o dicionário, isso significará que muitas das entradas da coluna na matriz de hash estarão vazias, e não apenas porque um determinado documento não contém um termo específico, mas porque elas estão vazias no conjunto. matriz. Caso contrário, poderá enviar vários termos para o mesmo hash do recurso - é sobre a "colisão" que estamos falando.
HashingVectorizer
tem uma configuração que funciona para atenuar essa chamada ativadaalternate_sign
por padrão, descrita aqui: en.wikipedia.org/wiki/Feature_hashing#Properties'Frequência de termos - frequência inversa de documentos' pega frequências de termos em cada documento e as pondera penalizando palavras que aparecem com mais frequência em todo o corpus. A intuição é que os termos encontrados situacionalmente têm maior probabilidade de serem representativos do tópico de um documento específico. Isso é diferente de uma função de hash, pois é necessário ter um dicionário completo de palavras no corpus para calcular a frequência inversa do documento. Espero que suas dimensões da matriz tf.idf sejam 45339 documentos por 663307 palavras no corpus; Manning et al fornecem mais detalhes e exemplos de cálculo: https://nlp.stanford.edu/IR-book/html/htmledition/term-frequency-and-weighting-1.html
'Mining of Massive Datasets' de Leskovec et al. Tem muitos detalhes sobre hash de recursos e tf.idf, os autores disponibilizaram o pdf aqui: http://www.mmds.org/
fonte
tfidf vectorizer
precisar de um dicionário completo de palavras para cálculos do IDF, os termos na matriz tfidf não deveriam ser mais do que os termos na matriz de hash?n_features=1048576
, se tiver tempo, experimente 640k, 320k e veja se isso afeta bastante sua precisão. Deve acelerar pelo menos o seu tempo de treinamento. Veja a resposta de @ Nathan paran_features=5
!O
HashingVectorizer
tem um parâmetron_features
que é1048576
por padrão. Ao fazer o hash, eles não calculam os termos de mapeamento de dicionário para um índice exclusivo a ser usado em cada um. Em vez disso, você só botar para cada termo e usar um tamanho grande o suficiente para que você não esperar que haja muitas colisões:hash(term) mod table_size
. Você pode fazer com que a matriz retornada seja do tamanho que desejar, definindon_features
. Você deve ajustá-lo para estar no estádio certo para o seu corpus, se não achar que o padrão é razoável (tê-lo maior causará menos colisões, embora consuma mais memória).fonte
HashingVectorizer e CountVectorizer (note que não Tfidfvectorizer) devem fazer a mesma coisa. Que é converter uma coleção de documentos de texto em uma matriz de ocorrências de token.
Se você deseja obter frequências de termo ponderadas por sua importância relativa (IDF), o Tfidfvectorizer é o que você deve usar. Se você precisar de contagens brutas ou normalizadas (frequência de termo), use CountVectorizer ou HashingVectorizer.
Para aprender sobre o HashingVectorizer, consulte este artigo em HashingVectorizer vs. CountVectorizer .
Para obter mais informações sobre o Tfidfvectorizer, consulte este artigo em Como usar o Tfidftransformer e o Tfidfvectorizer .
fonte