2016-09-27 3 views
5

Scikit öğrenim kütüphanesinde atlama gramının uygulanmasının herhangi bir yolu var mı? El ile n-skim gramları içeren bir liste oluşturdum ve bunu CountVectorizer() yöntemi için kelime olarak skipgramlara geçirdim.scikit-learn ile atlama gramının uygulanmasının herhangi bir yolu var mı?

Maalesef, tahmin konusundaki performansı çok zayıftır: sadece% 63 doğruluk. Ancak, ngram_range(min,max) kullanarak CountVectorizer() numaralı telefondan 77-80% doğrulukta varsayılan koddan bir doğruluk elde ediyorum.

Scikit öğrenmede atlama gramlarını uygulamak için daha iyi bir yol var mıdır?

İşte kod benim parçasıdır:

corpus = GetCorpus() # This one get text from file as a list 

vocabulary = list(GetVocabulary(corpus,k,n)) 
# this one returns a k-skip n-gram 

vec = CountVectorizer(
      tokenizer=lambda x: x.split(), 
      ngram_range=(2,2), 
      stop_words=stopWords, 
      vocabulary=vocabulary) 

cevap

6

yılında atlama-gram ile metin vektörize için işe yaramaz CountVectorizer için kelime olarak atlama gram belirteçleri geçen basitçe scikit-öğrenirler. Özel bir analizör ile yapılabilecek tokenlerin işlenme şeklini değiştirmelisiniz. Aşağıda this Wikipedia example 1-atlama-2-gram üreten bir örnek vectorizer Örneğin,

from toolz import itertoolz, compose 
from toolz.curried import map as cmap, sliding_window, pluck 
from sklearn.feature_extraction.text import CountVectorizer 

class SkipGramVectorizer(CountVectorizer): 
    def build_analyzer(self):  
     preprocess = self.build_preprocessor() 
     stop_words = self.get_stop_words() 
     tokenize = self.build_tokenizer() 
     return lambda doc: self._word_skip_grams(
       compose(tokenize, preprocess, self.decode)(doc), 
       stop_words) 

    def _word_skip_grams(self, tokens, stop_words=None): 
     # handle stop words 
     if stop_words is not None: 
      tokens = [w for w in tokens if w not in stop_words] 

     return compose(cmap(' '.join), pluck([0, 2]), sliding_window(3))(tokens) 

, bu vectorizer aşağıdaki belirteçleri doğuracak olur

text = ['the rain in Spain falls mainly on the plain'] 

vect = SkipGramVectorizer() 
vect.fit(text) 
vect.get_feature_names() 

olduğu

['falls on', 'in falls', 'mainly the', 'on plain', 
'rain spain', 'spain mainly', 'the in'] 
+0

Cevabınız için teşekkürler, kardeşim. Yakında deneyeceğim ve bunu size bildireceğim. –

4

Bir atlama-gram vektörleştiricisinin kendi uygulamasından çıktım. Bu this mesajından esinlenmiştir. Ayrıca, özellik alanını sınırlamak için cümle sınırlarını geçmemek için (nltk.sent_tokenize kullanarak) atlama gramlarını da sınırlandırdım.

import nltk 
from itertools import combinations 
from toolz import compose 
from sklearn.feature_extraction.text import CountVectorizer 

class SkipGramVectorizer(CountVectorizer): 

    def __init__(self, k=1, **kwds): 
     super(SkipGramVectorizer, self).__init__(**kwds) 
     self.k=k 

    def build_sent_analyzer(self, preprocess, stop_words, tokenize): 
     return lambda sent : self._word_skip_grams(
       compose(tokenize, preprocess, self.decode)(sent), 
       stop_words) 

    def build_analyzer(self):  
     preprocess = self.build_preprocessor() 
     stop_words = self.get_stop_words() 
     tokenize = self.build_tokenizer() 
     sent_analyze = self.build_sent_analyzer(preprocess, stop_words, tokenize) 

     return lambda doc : self._sent_skip_grams(doc, sent_analyze) 

    def _sent_skip_grams(self, doc, sent_analyze): 
     skip_grams = [] 
     for sent in nltk.sent_tokenize(doc): 
      skip_grams.extend(sent_analyze(sent)) 
     return skip_grams 

    def _word_skip_grams(self, tokens, stop_words=None): 
     """Turn tokens into a sequence of n-grams after stop words filtering""" 
     # handle stop words 
     if stop_words is not None: 
      tokens = [w for w in tokens if w not in stop_words] 

     # handle token n-grams 
     min_n, max_n = self.ngram_range 
     k = self.k 
     if max_n != 1: 
      original_tokens = tokens 
      if min_n == 1: 
       # no need to do any slicing for unigrams 
       # just iterate through the original tokens 
       tokens = list(original_tokens) 
       min_n += 1 
      else: 
       tokens = [] 

      n_original_tokens = len(original_tokens) 

      # bind method outside of loop to reduce overhead 
      tokens_append = tokens.append 
      space_join = " ".join 

      for n in xrange(min_n, 
          min(max_n + 1, n_original_tokens + 1)): 
       for i in xrange(n_original_tokens - n + 1): 
        # k-skip-n-grams 
        head = [original_tokens[i]]      
        for skip_tail in combinations(original_tokens[i+1:i+n+k], n-1): 
         tokens_append(space_join(head + list(skip_tail))) 
     return tokens 

def test(text, ngram_range, k): 
    vectorizer = SkipGramVectorizer(ngram_range=ngram_range, k=k) 
    vectorizer.fit_transform(text) 
    print(vectorizer.get_feature_names()) 

def main(): 
    text = ['Insurgents killed in ongoing fighting.'] 

    # 2-skip-bi-grams 
    test(text, (2,2), 2) 
    # 2-skip-tri-grams 
    test(text, (3,3), 2) 
############################################################################################### 
if __name__ == '__main__': 
    main() 

Bu aşağıdaki özellik adlarını üretecektir: İşte benim kodudur Temelde VectorizerMixin sınıftan _word_ngrams fonksiyonunu aldı ve çizgi yerini aldığını,

[u'in fighting', u'in ongoing', u'insurgents in', u'insurgents killed', u'insurgents ongoing', u'killed fighting', u'killed in', u'killed ongoing', u'ongoing fighting'] 
[u'in ongoing fighting', u'insurgents in fighting', u'insurgents in ongoing', u'insurgents killed fighting', u'insurgents killed in', u'insurgents killed ongoing', u'insurgents ongoing fighting', u'killed in fighting', u'killed in ongoing', u'killed ongoing fighting'] 

Bildirimi

tokens_append(space_join(original_tokens[i: i + n])) 
Aşağıdaki ile

:

head = [original_tokens[i]]      
for skip_tail in combinations(original_tokens[i+1:i+n+k], n-1): 
    tokens_append(space_join(head + list(skip_tail))) 
İlgili konular