文本倾向性分析(情感分析 )是将用户的观点分为“正面”和“负面”,有时候会多一个“中性”。文本倾向性分析一个比较直观的应用就是追踪用户对于一个事物的观点和偏好,比如分析豆瓣上一个电影的评论进行分析。正因为如此情感分析又被称为观点挖掘。
lingpipe 是alias公司开发的一款自然语言处理软件包,包括主题分类、句题检测、字符语言建模等十余个模块。而且文档完整,甚至每一个算法都有论文参考。更难能可贵的是它支持中文。
官方地址:http://alias-i.com/lingpipe/
下载地址:http://alias-i.com/lingpipe/web/download.html
LingPipe分为两个大块,一块是LingPipe核心文件,另外一块是LingPipe的模型类。需要支持中文的话需要下载Chinese Word Segmentation模块。
语料库在语言学上意指大量的文本,通常经过整理,具有既定格式与标记。
一般而言做情感分析有个很重要的步骤就是采集观点并进行整理,但由于应用场景不同,处理方法也不同。为了方便起见,这里使用已经处理好的语料库。Movie Review Data的polarity dataset v2.0,包含1000个正面的观点和1000个负面观点。当然这个是英文的哈。
基本极性是指事物从样本来看所处的整体倾向,比如:一本书,用户对其的情感倾向是正面的,这样的断言就是一个基本极性断言。
基本极性的分析直接使用LingPipi的DynamicLMClassifier即可。
大致上来讲分为两步,第一步训练,第二步进行分析。
新建一个类名为PolarityBasic。
1
2
3
4
5
6
|
publicPolarityBasic
(
String
basePath
)
{
pDir
=
new
File
(
basePath
,
"txt_sentoken"
)
;
//获取语料集
categories
=
pDir
.
list
(
)
;
//获取类别
int
nGram
=
4
;
classifer
=
DynamicLMClassifier
.
createNGramProcess
(
categories
,
nGram
)
;
//新建动态分类器
}
|
我们先来看看如何训练。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
publicvoidtrain
(
)
throws
IOException
{
for
(
int
i
=
0
;
i
<
categories
.
length
;
++
i
)
{
String
category
=
categories
[
i
]
;
Classification
classification
=
new
Classification
(
category
)
;
//新建类别
File
dir
=
new
File
(
pDir
,
categories
[
i
]
)
;
File
[
]
trainFiles
=
dir
.
listFiles
(
)
;
for
(
int
j
=
0
;
j
<
trainFiles
.
length
;
++
j
)
{
File
trainFile
=
trainFiles
[
j
]
;
if
(
isTrainingFile
(
trainFile
)
)
{
//判断一下是为了让一部分数据作为训练集、一部分作为测试集
String
review
=
Files
.
readFromFile
(
trainFile
,
"ISO-8859-1"
)
;
Classified
classified
=
new
Classified
(
review
,
classification
)
;
//指定内容和类别
classifer
.
handle
(
classified
)
;
//训练
}
}
}
}
|
这里说明一下isTrainingFile方法。我们需要一份测试集和一个训练集,但是我们只有一个语料库,只有人为分割。我原本是每次随机数一下来干的,但是有点影响速度,这里直接用文件名作为判断依据了。
1
2
3
|
boolean
isTrainingFile
(
File
file
)
{
return
file
.
getName
(
)
.
charAt
(
2
)
!=
'1'
;
//如果第2位为1就是测试集
}
|
训练完成后使用classifer就可以进行极性分析了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
publicvoidevaluate
(
)
throws
IOException
{
int
numTests
=
0
;
int
numCorrect
=
0
;
for
(
int
i
=
0
;
i
<
categories
.
length
;
++
i
)
{
String
category
=
categories
[
i
]
;
File
file
=
new
File
(
pDir
,
categories
[
i
]
)
;
File
[
]
testFiles
=
file
.
listFiles
(
)
;
for
(
int
j
=
0
;
j
<
testFiles
.
length
;
++
j
)
{
File
testFile
=
testFiles
[
j
]
;
if
(
!
isTrainingFile
(
testFile
)
)
{
String
review
=
Files
.
readFromFile
(
testFile
,
"ISO-8859-1"
)
;
++
numTests
;
Classification
classification
=
classifer
.
classify
(
review
)
;
String
resultCategory
=
classification
.
bestCategory
(
)
;
if
(
resultCategory
.
equals
(
category
)
)
++
numCorrect
;
}
}
}
System
.
out
.
println
(
"测试总数:"
+
numTests
)
;
System
.
out
.
println
(
"正确数:"
+
numCorrect
)
;
System
.
out
.
println
(
"正确率"
+
(
(
double
)
numCorrect
)
/
(
double
)
numTests
)
;
}
|
效果:
将isTrainingFile修改一下
1
2
3
|
boolean
isTrainingFile
(
File
file
)
{
return
file
.
getName
(
)
.
charAt
(
2
)
!=
'2'
;
//如果第2位为2就是测试集
}
|