2017-05-11 3 views
0

J'essaye d'imiter le paramètre n_gram dans CountVectorizer() avec gensim. Mon but est de pouvoir utiliser LDA avec Scikit ou Gensim et de trouver des bigrams très similaires.Essayer d'imiter Scikit ngram avec gensim

Par exemple, nous pouvons trouver les bigrammes avec scikit suivantes: « ordinateur abc », « non ordonnée binaire » et avec gensim « Une enquête », « mineurs Graphique » ...

Je joins mon code ci-dessous faire une comparaison entre Gensim et Scikit en termes de bigrammes/unigrams.

Merci pour votre aide

documents = [["Human" ,"machine" ,"interface" ,"for" ,"lab", "abc" ,"computer" ,"applications"], 
     ["A", "survey", "of", "user", "opinion", "of", "computer", "system", "response", "time"], 
     ["The", "EPS", "user", "interface", "management", "system"], 
     ["System", "and", "human", "system", "engineering", "testing", "of", "EPS"], 
     ["Relation", "of", "user", "perceived", "response", "time", "to", "error", "measurement"], 
     ["The", "generation", "of", "random", "binary", "unordered", "trees"], 
     ["The", "intersection", "graph", "of", "paths", "in", "trees"], 
     ["Graph", "minors", "IV", "Widths", "of", "trees", "and", "well", "quasi", "ordering"], 
     ["Graph", "minors", "A", "survey"]] 

Avec le modèle gensim nous trouvons 48 jetons uniques, nous pouvons imprimer le unigramme/bigrams avec impression (dictionary.token2id)

# 1. Gensim 
from gensim.models import Phrases 

# Add bigrams and trigrams to docs (only ones that appear 20 times or more). 
bigram = Phrases(documents, min_count=1) 
for idx in range(len(documents)): 
    for token in bigram[documents[idx]]: 
     if '_' in token: 
      # Token is a bigram, add to document. 
      documents[idx].append(token) 

documents = [[doc.replace("_", " ") for doc in docs] for docs in documents] 
print(documents) 

dictionary = corpora.Dictionary(documents) 
print(dictionary.token2id) 

Et avec le scikit 96 jetons uniques, nous pouvons imprimer le vocabulaire de scikit avec l'impression (vocab)

# 2. Scikit 
import re 
token_pattern = re.compile(r"\b\w\w+\b", re.U) 

def custom_tokenizer(s, min_term_length = 1): 
    """ 
    Tokenizer to split text based on any whitespace, keeping only terms of at least a certain length which start with an alphabetic character. 
    """ 
    return [x.lower() for x in token_pattern.findall(s) if (len(x) >= min_term_length and x[0].isalpha()) ] 

from sklearn.feature_extraction.text import CountVectorizer 

def preprocess(docs, min_df = 1, min_term_length = 1, ngram_range = (1,1), tokenizer=custom_tokenizer): 
    """ 
    Preprocess a list containing text documents stored as strings. 
    doc : list de string (pas tokenizé) 
    """ 
    # Build the Vector Space Model, apply TF-IDF and normalize lines to unit length all in one call 
    vec = CountVectorizer(lowercase=True, 
         strip_accents="unicode", 
         tokenizer=tokenizer, 
         min_df = min_df, 
         ngram_range = ngram_range, 
         stop_words = None 
        ) 
    X = vec.fit_transform(docs) 
    vocab = vec.get_feature_names() 

    return (X,vocab) 

docs_join = list() 

for i in documents: 
    docs_join.append(' '.join(i)) 

(X, vocab) = preprocess(docs_join, ngram_range = (1,2)) 

print(vocab) 

Répondre

1

gensimPhrases classe est conçu pour "détecter automatiquement les phrases courantes (expressions multi-mots) à partir d'un flux de phrases." Donc, cela ne vous donne que bigrams qui "apparaissent plus souvent que prévu". C'est pourquoi avec le paquet gensim vous obtenez seulement quelques bigrams comme: 'response time', 'Graph minors', 'A survey'.

Si vous regardez bigram.vocab, vous verrez que ces bigrams apparaissent 2 fois alors que tous les autres bigrams n'apparaissent qu'une seule fois. La classe CountVectorizer vous donne tous les bigrammes.