注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Explore in Data

Just enjoy it.

 
 
 

日志

 
 

Python 文本挖掘:使用机器学习方法进行情感分析(一、特征提取和选择)  

2013-11-20 01:49:43|  分类: Python 文本挖掘 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
用Python 进行机器学习及情感分析,需要用到两个主要的程序包:nltk 和 scikit-learn
nltk 主要负责处理特征提取(双词或多词搭配需要使用nltk 来做)和特征选择(需要nltk 提供的统计方法)。
scikit-learn 主要负责分类算法,评价分类效果,进行分类等任务。

接下来会有四篇文章按照以下步骤来实现机器学习的情感分析。

首先是特征提取和选择
一、特征提取方法
1. 把所有词作为特征

def bag_of_words(words):
return dict([(word, True) for word in words])

返回的是字典类型,这是nltk 处理情感分类的一个标准形式。

2. 把双词搭配(bigrams)作为特征

import nltk
from nltk.collocations import BigramCollocationFinder
from nltk.metrics import BigramAssocMeasures


def bigram(words, score_fn=BigramAssocMeasures.chi_sq, n=1000):
bigram_finder = BigramCollocationFinder.from_words(words) #把文本变成双词搭配的形式
bigrams = bigram_finder.nbest(score_fn, n) #使用了卡方统计的方法,选择排名前1000的双词
return bag_of_words(bigrams)

除了可以使用卡方统计来选择信息量丰富的双词搭配,还可以使用其它的方法,比如互信息(PMI)。而排名前1000也只是人工选择的阈值,可以随意选择其它值,可经过测试一步步找到最优值。

3. 把所有词和双词搭配一起作为特征

def bigram_words(words, score_fn=BigramAssocMeasures.chi_sq, n=1000):
bigram_finder = BigramCollocationFinder.from_words(words)
bigrams = bigram_finder.nbest(score_fn, n)
return bag_of_words(words + bigrams) #所有词和(信息量大的)双词搭配一起作为特征


二、特征选择方法
有了提取特征的方法后,我们就可以提取特征来进行分类学习了。但一般来说,太多的特征会降低分类的准确度,所以需要使用一定的方法,来“选择”出信息量最丰富的特征,再使用这些特征来分类。
特征选择遵循如下步骤:
1. 计算出整个语料里面每个词的信息量
2. 根据信息量进行倒序排序,选择排名靠前的信息量的词
3. 把这些词作为特征

1. 计算出整个语料里面每个词的信息量
1.1 计算整个语料里面每个词的信息量

from nltk.probability import FreqDist, ConditionalFreqDist


def create_word_scores():
posWords = pickle.load(open('D:/code/sentiment_test/pos_review.pkl','r'))
negWords = pickle.load(open('D:/code/sentiment_test/neg_review.pkl','r'))

posWords = list(itertools.chain(*posWords)) #把多维数组解链成一维数组
negWords = list(itertools.chain(*negWords)) #同理

word_fd = FreqDist() #可统计所有词的词频
cond_word_fd = ConditionalFreqDist() #可统计积极文本中的词频和消极文本中的词频
for word in posWords:
word_fd.inc(word)
cond_word_fd['pos'].inc(word)
for word in negWords:
word_fd.inc(word)
cond_word_fd['neg'].inc(word)

pos_word_count = cond_word_fd['pos'].N() #积极词的数量
neg_word_count = cond_word_fd['neg'].N() #消极词的数量
total_word_count = pos_word_count + neg_word_count

word_scores = {}
for word, freq in word_fd.iteritems():
pos_score = BigramAssocMeasures.chi_sq(cond_word_fd['pos'][word], (freq, pos_word_count), total_word_count) #计算积极词的卡方统计量,这里也可以计算互信息等其它统计量
neg_score = BigramAssocMeasures.chi_sq(cond_word_fd['neg'][word], (freq, neg_word_count), total_word_count) #同理
word_scores[word] = pos_score + neg_score #一个词的信息量等于积极卡方统计量加上消极卡方统计量

return word_scores #包括了每个词和这个词的信息量


1.2 计算整个语料里面每个词和双词搭配的信息量

def create_word_bigram_scores():

posdata = pickle.load(open('D:/code/sentiment_test/pos_review.pkl','r'))
negdata = pickle.load(open('D:/code/sentiment_test/neg_review.pkl','r'))

posWords = list(itertools.chain(*posdata))
negWords = list(itertools.chain(*negdata))

bigram_finder = BigramCollocationFinder.from_words(posWords)
bigram_finder = BigramCollocationFinder.from_words(negWords)
posBigrams = bigram_finder.nbest(BigramAssocMeasures.chi_sq, 5000)
negBigrams = bigram_finder.nbest(BigramAssocMeasures.chi_sq, 5000)

pos = posWords + posBigrams #词和双词搭配
neg = negWords + negBigrams

word_fd = FreqDist()
cond_word_fd = ConditionalFreqDist()
for word in pos:
word_fd.inc(word)
cond_word_fd['pos'].inc(word)
for word in neg:
word_fd.inc(word)
cond_word_fd['neg'].inc(word)

pos_word_count = cond_word_fd['pos'].N()
neg_word_count = cond_word_fd['neg'].N()
total_word_count = pos_word_count + neg_word_count

word_scores = {}
for word, freq in word_fd.iteritems():
pos_score = BigramAssocMeasures.chi_sq(cond_word_fd['pos'][word], (freq, pos_word_count), total_word_count)
neg_score = BigramAssocMeasures.chi_sq(cond_word_fd['neg'][word], (freq, neg_word_count), total_word_count)
word_scores[word] = pos_score + neg_score

return word_scores


2. 根据信息量进行倒序排序,选择排名靠前的信息量的词

def find_best_words(word_scores, number):

best_vals = sorted(word_scores.iteritems(), key=lambda (w, s): s, reverse=True)[:number] #把词按信息量倒序排序。number是特征的维度,是可以不断调整直至最优的
best_words = set([w for w, s in best_vals])
return best_words

然后需要对find_best_words 赋值,如下:

word_scores_1 = create_word_scores()

word_scores_2 = create_word_bigram_scores()


3. 把选出的这些词作为特征(这就是选择了信息量丰富的特征)

def best_word_features(words):
return dict([(word, True) for word in words if word in best_words])


三、检测哪中特征选择方法更优
  评论这张
 
阅读(10692)| 评论(57)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017