待修改

2、文本特征

如何从这些英文中抽取情感态度而进行分类呢?

最直观的做法就是抽取单词。通常认为,很多关键词能够反映说话者的态度。比如上面这个简单的数据集,很容易发现,凡是说了“shit”的,就一定属于neg类。

当然,上面数据集是为了方便描述而简单设计的。现实中一个词经常会有穆棱两可的态度。但是仍然有理由相信,某个单词在neg类中出现的越多,那么他表示neg态度的概率越大。

同样我们注意到有些单词对情感分类是毫无意义的。比如上述数据中的“of”,“I”之类的单词。这类词有个名字,叫“Stop_Word“(停用词)。这类词是可以完全忽略掉不做统计的。显然忽略掉这些词,词频记录的存储空间能够得到优化,而且构建速度也更快。

把每个单词的词频作为重要的特征也存在一个问题。比如上述数据中的”movie“,在12个样本中出现了5次,但是出现正反两边次数差不多,没有什么区分度。而”worth“出现了2次,但却只出现在pos类中,显然更具有强烈的刚晴色彩,即区分度很高。

因此,我们需要引入TF-IDF(Term Frequency-Inverse Document Frequency,词频和逆向文件频率)对每个单词做进一步考量。

TF词频)的计算很简单,就是针对一个文件t,某个单词Nt 出现在该文档中的频率。比如文档“I love this movie”,单词“love”的TF为1/4。如果去掉停用词“I"和”it“,则为1/2。

IDF逆向文件频率)的意义是,对于某个单词t,凡是出现了该单词的文档数Dt,占了全部测试文档D的比例,再求自然对数。

比如单词“movie“一共出现了5次,而文档总数为12,因此IDF为ln(5/12)。

很显然,IDF是为了凸显那种出现的少,但是占有强烈感情色彩的词语。比如“movie”这样的词的IDF=ln(12/5)=0.88,远小于“love”的IDF=ln(12/1)=2.48。

TF-IDF就是把二者简单的乘在一起即可。这样,求出每个文档中,每个单词的TF-IDF,就是我们提取得到的文本特征值。

 

 

# -*- coding: utf-8 -*-  
import scipy as sp  
import numpy as np  
from sklearn.datasets import load_files  
from sklearn.cross_validation import train_test_split  
from sklearn.feature_extraction.text import  TfidfVectorizer  
  
'''''加载数据集,切分数据集80%训练,20%测试'''  
movie_reviews = load_files('endata')    
doc_terms_train, doc_terms_test, y_train, y_test\  
    = train_test_split(movie_reviews.data, movie_reviews.target, test_size = 0.3)  
      
'''''BOOL型特征下的向量空间模型,注意,测试样本调用的是transform接口'''  
count_vec = TfidfVectorizer(binary = False, decode_error = 'ignore',\  
                            stop_words = 'english')  
x_train = count_vec.fit_transform(doc_terms_train)  
x_test  = count_vec.transform(doc_terms_test)  
x       = count_vec.transform(movie_reviews.data)  
y       = movie_reviews.target  
print(doc_terms_train)  
print(count_vec.get_feature_names())  
print(x_train.toarray())  
print(movie_reviews.target)

运行结果如下:

[b'waste of time.', b'a shit movie.', b'a nb movie.', b'I love this movie!', b'shit.', b'worth my money.', b'sb movie.', b'worth it!']
['love', 'money', 'movie', 'nb', 'sb', 'shit', 'time', 'waste', 'worth']
[[ 0.          0.          0.          0.          0.          0.   0.70710678  0.70710678  0.        ]
 [ 0.          0.          0.60335753  0.          0.          0.79747081   0.          0.          0.        ]
 [ 0.          0.          0.53550237  0.84453372  0.          0.          0.   0.          0.        ]
 [ 0.84453372  0.          0.53550237  0.          0.          0.          0.   0.          0.        ]
 [ 0.          0.          0.          0.          0.          1.          0.   0.          0.        ]
 [ 0.          0.76642984  0.          0.          0.          0.          0.   0.          0.64232803]
 [ 0.          0.          0.53550237  0.          0.84453372  0.          0.   0.          0.        ]
 [ 0.          0.          0.          0.          0.          0.          0.   0.          1.        ]]
[1 1 0 1 0 1 0 1 1 0 0 0]

python输出的比较混乱。我这里做了一个表格如下:

从上表可以发现如下几点:

1、停用词的过滤。

初 始化count_vec的时候,我们在count_vec构造时传递了stop_words = 'english',表示使用默认的英文停用词。可以使用count_vec.get_stop_words()查看TfidfVectorizer内置 的所有停用词。当然,在这里可以传递你自己的停用词list(比如这里的“movie”)

2、TF-IDF的计算。

这里词频的计算使用的是sklearn的TfidfVectorizer。这个类继承于CountVectorizer,在后者基本的词频统计基础上增加了如TF-IDF之类的功能。

我们会发现这里计算的结果跟我们之前计算不太一样。因为这里count_vec构造时默认传递了max_df=1,因此TF-IDF都做了规格化处理,以便将所有值约束在[0,1]之间。

3、count_vec.fit_transform的结果是一个巨大的矩阵。我们可以看到上表中有大量的0,因此sklearn在内部实现上使用了稀疏矩阵。本例子数据较小。如果读者有兴趣,可以试试机器学习科研工作者使用的真实数据,来自康奈尔大学:http://www.cs.cornell.edu/people/pabo/movie-review-data/。这个网站提供了很多数据集,其中有几个2M左右的数据库,正反例700个左右。这样的数据规模也不算大,1分钟内还是可以跑完的,建议大家试一试。不过要注意这些数据集可能存在非法字符问题。所以在构造count_vec时,传入了decode_error = 'ignore',以忽略这些非法字符。

上表的结果,就是训练8个样本的8个特征的一个结果。这个结果就可以使用各种分类算法进行分类了。

#encoding utf-8
"""
英文切词特征提取
CountVectorizer(input=u'content', encoding=u'utf-8', decode_error=u'strict', strip_accents=None,
lowercase=True, preprocessor=None, tokenizer=None, stop_words=None, token_pattern=u'(?u)\b\w\w+\b',
ngram_range=(1, 1),analyzer=u'word', max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False,
dtype=<type 'numpy.int64'>)

stopword = "english" 去除停用词。


"""
"""
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(min_df=1) 
print vectorizer
corpus = [ 'This is the first document.','This is the second second document.', 'And the third one.', 'Is this the first document?'] 
X = vectorizer.fit_transform(corpus)
#X返回的是矩阵,
print X[2][0]
print vectorizer.get_feature_names()
#输出上述的词语变量
print X.toarray()
#转化成矩阵向量
print vectorizer.vocabulary_.get('document')
#得到这个词语的序号
print vectorizer.transform(['Something completely new.','Something completely new.']).toarray()
#将待定文本转化成向量。
print(X.toarray().sum(axis=0))
#统计词语每一列相当与每一个词在该类别中的数量总和。

"""
# -*- coding: utf-8 -*-  
import scipy as sp  
import numpy as np  
from sklearn.datasets import load_files  
from sklearn.cross_validation import train_test_split  
from sklearn.feature_extraction.text import  TfidfVectorizer

data1 = load_files('yang')
print data1.target
print data1.data

 

posted on 2016-12-10 16:46  星海一哥  阅读(126)  评论(0)    收藏  举报

导航