2014-10-28 57 views
3

我有一些bigrams,可以說:[('word','word'),('word','word'),...,('word','word')]。我怎樣才能使用scikit的HashingVectorizer來創建一個特徵向量,隨後將會呈現給一些分類算法,例如: SVC或樸素貝葉斯或任何類型的分類算法?如何使用scikit-learn中的哈希技巧對bigrams進行矢量化?

+0

你的意思是你已經有了bigrams?然後我推薦使用'FeatureHasher';這會跳過你明顯已經執行的術語提取階段。 – 2014-10-28 20:29:51

+0

是的,我已經準備好了這樣的格式:'[''''''''',',','''']' – tumbleweed 2014-10-28 21:38:10

回答

6

首先,你需要明白不同的矢量化器在做什麼。大多數向量化器都基於bag-of-word方法,其中文檔是令牌映射到矩陣。

從sklearn文檔,CountVectorizerHashVectorizer

轉換文本文檔的集合令牌的矩陣計算

例如,這些句子

的富爾頓縣大陪審團星期五表示,對亞特蘭大最近一次選舉的 進行調查並沒有發現任何證據發生任何違規行爲 。

在期末presentments進一步對陪審團說,該城執行 委員會,其中有過所有電荷的選舉,``值得 在 的方式亞特蘭大市'的讚揚和感謝選舉進行了。

這種粗糙的矢量化:

from collections import Counter 
from itertools import chain 
from string import punctuation 

from nltk.corpus import brown, stopwords 

# Let's say the training/testing data is a list of words and POS 
sentences = brown.sents()[:2] 

# Extract the content words as features, i.e. columns. 
vocabulary = list(chain(*sentences)) 
stops = stopwords.words('english') + list(punctuation) 
vocab_nostop = [i.lower() for i in vocabulary if i not in stops] 

# Create a matrix from the sentences 
matrix = [Counter([w for w in words if w in vocab_nostop]) for words in sentences] 

print matrix 

將成爲:

[Counter({u"''": 1, u'``': 1, u'said': 1, u'took': 1, u'primary': 1, u'evidence': 1, u'produced': 1, u'investigation': 1, u'place': 1, u'election': 1, u'irregularities': 1, u'recent': 1}), Counter({u'the': 6, u'election': 2, u'presentments': 1, u'``': 1, u'said': 1, u'jury': 1, u'conducted': 1, u"''": 1, u'deserves': 1, u'charge': 1, u'over-all': 1, u'praise': 1, u'manner': 1, u'term-end': 1, u'thanks': 1})] 

所以這可能是相當低效的考慮非常大的數據集,所以sklearn開發者建立更高效的代碼。 sklearn最重要的特性之一就是在矢量化數據集之前,您甚至不需要將數據集加載到內存中。

由於目前還不清楚你的任務是什麼,我認爲你有點在尋找一種普遍的用途。假設您正在使用它來獲取語言ID。

比方說,在train.txt訓練數據輸入文件:

Pošto je EULEX obećao da će obaviti istragu o prošlosedmičnom izbijanju nasilja na sjeveru Kosova, taj incident predstavlja još jedan ispit kapaciteta misije da doprinese jačanju vladavine prava. 
De todas as provações que teve de suplantar ao longo da vida, qual foi a mais difícil? O início. Qualquer começo apresenta dificuldades que parecem intransponíveis. Mas tive sempre a minha mãe do meu lado. Foi ela quem me ajudou a encontrar forças para enfrentar as situações mais decepcionantes, negativas, as que me punham mesmo furiosa. 
Al parecer, Andrea Guasch pone que una relación a distancia es muy difícil de llevar como excusa. Algo con lo que, por lo visto, Alex Lequio no está nada de acuerdo. ¿O es que más bien ya ha conseguido la fama que andaba buscando? 
Vo väčšine golfových rezortov ide o veľký komplex niekoľkých ihrísk blízko pri sebe spojených s hotelmi a ďalšími možnosťami trávenia voľného času – nie vždy sú manželky či deti nadšenými golfistami, a tak potrebujú iný druh vyžitia. Zaujímavé kombinácie ponúkajú aj rakúske, švajčiarske či talianske Alpy, kde sa dá v zime lyžovať a v lete hrať golf pod vysokými alpskými končiarmi. 

和你對應的標籤是波斯尼亞語,葡萄牙語,西班牙語和斯洛伐克,即

[bs,pt,es,sr] 

這裏使用的一種方式CountVectorizer和樸素貝葉斯分類器。以下示例來自DSL shared taskhttps://github.com/alvations/bayesline

讓我們從矢量化器開始。首先,矢量化器獲取輸入文件,然後將訓練集轉換成矢量化矩陣,並初始化矢量化器(即,功能):

import codecs 

from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.naive_bayes import MultinomialNB 

trainfile = 'train.txt' 
testfile = 'test.txt' 

# Vectorizing data. 
train = [] 
word_vectorizer = CountVectorizer(analyzer='word') 
trainset = word_vectorizer.fit_transform(codecs.open(trainfile,'r','utf8')) 
tags = ['bs','pt','es','sr'] 
print word_vectorizer.get_feature_names() 

[出]:

[u'acuerdo', u'aj', u'ajudou', u'al', u'alex', u'algo', u'alpsk\xfdmi', u'alpy', u'andaba', u'andrea', u'ao', u'apresenta', u'as', u'bien', u'bl\xedzko', u'buscando', u'come\xe7o', u'como', u'con', u'conseguido', u'da', u'de', u'decepcionantes', u'deti', u'dificuldades', u'dif\xedcil', u'distancia', u'do', u'doprinese', u'druh', u'd\xe1', u'ela', u'encontrar', u'enfrentar', u'es', u'est\xe1', u'eulex', u'excusa', u'fama', u'foi', u'for\xe7as', u'furiosa', u'golf', u'golfistami', u'golfov\xfdch', u'guasch', u'ha', u'hotelmi', u'hra\u0165', u'ide', u'ihr\xedsk', u'incident', u'intranspon\xedveis', u'in\xedcio', u'in\xfd', u'ispit', u'istragu', u'izbijanju', u'ja\u010danju', u'je', u'jedan', u'jo\u0161', u'kapaciteta', u'kde', u'kombin\xe1cie', u'komplex', u'kon\u010diarmi', u'kosova', u'la', u'lado', u'lequio', u'lete', u'llevar', u'lo', u'longo', u'ly\u017eova\u0165', u'mais', u'man\u017eelky', u'mas', u'me', u'mesmo', u'meu', u'minha', u'misije', u'mo\u017enos\u0165ami', u'muy', u'm\xe1s', u'm\xe3e', u'na', u'nada', u'nad\u0161en\xfdmi', u'nasilja', u'negativas', u'nie', u'nieko\u013ek\xfdch', u'no', u'obaviti', u'obe\u0107ao', u'para', u'parecem', u'parecer', u'pod', u'pone', u'pon\xfakaj\xfa', u'por', u'potrebuj\xfa', u'po\u0161to', u'prava', u'predstavlja', u'pri', u'prova\xe7\xf5es', u'pro\u0161losedmi\u010dnom', u'punham', u'qual', u'qualquer', u'que', u'quem', u'rak\xfaske', u'relaci\xf3n', u'rezortov', u'sa', u'sebe', u'sempre', u'situa\xe7\xf5es', u'sjeveru', u'spojen\xfdch', u'suplantar', u's\xfa', u'taj', u'tak', u'talianske', u'teve', u'tive', u'todas', u'tr\xe1venia', u'una', u've\u013ek\xfd', u'vida', u'visto', u'vladavine', u'vo', u'vo\u013en\xe9ho', u'vysok\xfdmi', u'vy\u017eitia', u'v\xe4\u010d\u0161ine', u'v\u017edy', u'ya', u'zauj\xedmav\xe9', u'zime', u'\u0107e', u'\u010dasu', u'\u010di', u'\u010fal\u0161\xedmi', u'\u0161vaj\u010diarske'] 

比方說,你的測試文件中test.txt,其中標籤是西班牙es和葡萄牙pt

Por ello, ha insistido en que Europa tiene que darle un toque de atención porque Portugal esta incumpliendo la directiva del establecimiento del peaje 
Estima-se que o mercado homossexual só na Cidade do México movimente cerca de oito mil milhões de dólares, aproximadamente seis mil milhões de euros 

現在,你可以用訓練有素的分類器標記測試文檔:

import codecs, re, time 
from itertools import chain 

from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.naive_bayes import MultinomialNB 

trainfile = 'train.txt' 
testfile = 'test.txt' 

# Vectorizing data. 
train = [] 
word_vectorizer = CountVectorizer(analyzer='word') 
trainset = word_vectorizer.fit_transform(codecs.open(trainfile,'r','utf8')) 
tags = ['bs','pt','es','sr'] 

# Training NB 
mnb = MultinomialNB() 
mnb.fit(trainset, tags) 

# Tagging the documents 
codecs.open(testfile,'r','utf8') 
testset = word_vectorizer.transform(codecs.open(testfile,'r','utf8')) 
results = mnb.predict(testset) 

print results 

[出]:

['es' 'pt'] 

對於文本分類的詳細信息,可能你會發現這個NLTK相關提問/回答有用,看nltk NaiveBayesClassifier training for sentiment analysis

要使用HashingVectorizer,需要注意它產生的負向矢量值和MultinomialNaiveBayes分類器不會做負值,因此您將不得不使用另一個分類器,例如:

import codecs, re, time 
from itertools import chain 

from sklearn.feature_extraction.text import HashingVectorizer 
from sklearn.linear_model import Perceptron 

trainfile = 'train.txt' 
testfile = 'test.txt' 

# Vectorizing data. 
train = [] 
word_vectorizer = HashingVectorizer(analyzer='word') 
trainset = word_vectorizer.fit_transform(codecs.open(trainfile,'r','utf8')) 
tags = ['bs','pt','es','sr'] 

# Training Perceptron 
pct = Perceptron(n_iter=100) 
pct.fit(trainset, tags) 

# Tagging the documents 
codecs.open(testfile,'r','utf8') 
testset = word_vectorizer.transform(codecs.open(testfile,'r','utf8')) 
results = pct.predict(testset) 

print results 

[OUT]:

['es' 'es'] 

但是千萬注意,感知的結果是在這個小例子更糟。不同的分類器適合不同的任務,不同的特徵適合不同的向量,不同的分類器接受不同的向量。

沒有完美的模式,只是好還是壞

+0

好的,非常感謝你的反饋。問題是我只檢查了scikit-learn中可用的向量化程序,並且據我所知,我可以使用frecuencies(例如bow,Tf-idf)和這個哈希方法創建一個特徵向量。這是一個情感分析任務,我想用一個不同的方法來代替經典的frecuency來構建這個特徵向量。我可以使用什麼其他方法來構建這個特徵向量? – tumbleweed 2014-10-30 05:36:57

+1

更改分析器,爲分析器編寫自己的函數,請參閱http://stackoverflow.com/questions/21600196/how-do-i-use-sklearn-countvectorizer-with-both-word-and-char-analyzer- pyt – alvas 2014-10-30 06:36:59

+0

再次@alvas,謝謝你的反饋,你的例子給予了很多亮點。我不明白你如何標記兩個文本(例如火車和測試)。你能幫我解決這個問題嗎? – tumbleweed 2014-11-14 06:15:46

3

既然你已經自己提取的二元語法,你可以向量化使用FeatureHasher。你需要做的主要事情是把bigrams壓縮成字符串。例如,

>>> data = [[('this', 'is'), ('is', 'a'), ('a', 'text')], 
...   [('and', 'one'), ('one', 'more')]] 
>>> from sklearn.feature_extraction import FeatureHasher 
>>> fh = FeatureHasher(input_type='string') 
>>> X = fh.transform(((' '.join(x) for x in sample) for sample in data)) 
>>> X 
<2x1048576 sparse matrix of type '<type 'numpy.float64'>' 
    with 5 stored elements in Compressed Sparse Row format> 
+0

如果'data'是一個西班牙文本(即符號,重音等),我怎麼解決編碼問題。 – tumbleweed 2014-10-30 05:28:39

+0

通過使用'decode'方法? – 2014-10-30 07:38:44

+0

你能否提供一些例子?謝謝! – tumbleweed 2014-11-03 18:31:21

相關問題