基于汉字字频特征实现99.99%准确率的新闻文本分类器(一)
基于汉字字频特征实现99.99%准确率的新闻文本分类器(二)
基于汉字字频特征实现99.99%准确率的新闻文本分类器(三)
基于汉字字频特征实现99.99%准确率的新闻文本分类器(四)
基于汉字字频特征实现99.99%准确率的新闻文本分类器(五)
回顾
上一节中,使用五层神经网络,对抽取出的汉字字频特征向量进行分类,得到了超过99%的准确率,在高准确率的前提下,没有陷入局部最优解,对一些在训练中,被指定了上千次不是军事类的新闻,只要内容是军事类的,就能被正确的找出,同样,混在军事类新闻里的【慈善捐款】等非军事的新闻,虽然被教育了数千次是军事类的,最终也没有被五层神经网络认定为军事类的。
从某种意义上讲,五层神经网络好像是真的理解了军事类新闻的涵义一样。
他/她是怎么做到的呢?本节,将先从前面的开源代码分析入手,一探究竟。
数据清洗
源码里有对新闻文字的简单数据清洗。即对某些页面上残留的汉字污染到了新闻文本本身进行排除。例如如下正则表达式
1
2
3
4
|
System.Text.RegularExpressions.Regex reg2 =
new
System.Text.RegularExpressions.Regex(
"共找到([\\d,\\s]+)个相关网页"
,
System.Text.RegularExpressions.RegexOptions.Singleline |
System.Text.RegularExpressions.RegexOptions.Compiled);
|
它是对搜索页面返回的汉字的清除。有趣的是,在我的第一版的实现中连这个清洗的步骤也是没有的,我根本没有兴趣去看每一个新闻文本,因为有八万个之多。所以,原来我本不知道有这些污染的数据。那么我是如何定位到它呢?并知道清除这些文本?在《提高》中,将会描述这个有趣的事。
字频特征抽取
在第二节的PreData项目中,有一个outzp.txt的资源文件,里面是统计的常用汉字在新闻资讯中出现的次数。
可以看到,【的|是|在|有】等常见汉字的出现次数,是非常高的。
在函数GetZiPin中,使用新闻文本的汉字部分的频率,即一个汉字对应此新闻文本的所有汉字的百分比作为字频特征。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public
static
float
[] GetZiPin(
string
str,
int
keycount)
{
float
[] res =
new
float
[keycount];
if
(str ==
null
|| keycount > zps.Length)
return
res;
System.Collections.Generic.Dictionary<
string
,
int
> dsi =
new
Dictionary<
string
,
int
>();
var
avcount = 0;
foreach
(
var
k
in
str)
{
if
(
char
.GetUnicodeCategory(k) == System.Globalization.UnicodeCategory.OtherLetter)
{
var
ks = k.ToString();
if
(dsi.ContainsKey(ks))
dsi[ks]++;
else
dsi[ks] = 1;
avcount++;
}
}
for
(
int
i = 0; i < keycount; i++)
{
if
(dsi.ContainsKey(zps[i].ch))
{
res[i] = dsi[zps[i].ch] * 1000f / avcount;
res[i] = res[i] / zps[i].zipin / 2;
}
}
return
res;
}
|
此函数返回了一段新闻文本的1000多个常见汉字的字频数组。这是一个关键点,我没有使用全部3000多个常用汉字,而是使用了Top 1000个常见汉字,这可以减少特征向量的大小,加快训练的速度,因为输入向量比较大的时候,多层神经网络和SVM消耗的内存将会大幅增加,训练时间也会大幅增加。但是,这个向量是不能直接用作SVM或者神经网络的输入数据进行处理的。因为,特征向量还要做一步“归一化”。归一化的本质是公平的对待每一个输入,不人为改变任何汉字在特征向量中的权重。
所以,特征向量的提取,是分两个阶段组成。第一个阶段,统计出每个汉字在每一个文章的频率数据,第二个阶段进行归一化。
1
2
3
|
var
fi = textzipin.GetZiPin(txt, weishu);
for
(
int
t = 0; t < mms.Length; t++)
fi[t] = fi[t] / mms[t].fmax;
|
归一化后,特征向量里的每个汉字的字频,被调整为从0到1的浮点数。(有两种归一化方法,一种是归一化到0-1之间,还有一种是归一化到 【-1 1】之间。在本文中,我采用0-1范围)
PreData小结
PreData项目比较短小,包含标准的命名空间代码,总共才200行左右。功能也比较单一,抽取所有八万个文本的常见汉字字频,并归一化,保存到数据文件中。数据文件中部分数据如下所示。
此处数据换行有问题,所以显示不对。
首列为0的,是搜狗文本分类语料库中非军事的新闻资讯,首列为1的,是军事类的新闻资讯。可以看到,这些资讯的文本特征,都是一个1024维的向量,每个向量最大值为1,最小值为0,多数都位于0-1之间。
数据的归一化,对SVM或者神经网络来说,是一样重要的步骤。未归一化的数据将严重降低分类器的效果。归一化除了线性归一化外,还有指数及对数的归一化,他们各自有自己擅长的数据领域。比如,声音的分贝数据,即是典型的对数归一化会拥有更好的效果。
下节预告
下节,解读五层神经网络分类器的源代码。
基于汉字字频特征实现99.99%准确率的新闻文本分类器(五)