文本分类器
python分类器环境安装
安装NLTK
下载地址:http://www.nltk.org/
分类器介绍
分类器是模式识别中的一种应用,模式识别是自然语言处理的一个核心部分。
分类任务是对给定的输入,选择正确的"类别标签"。并且输入和所有其他输入隔离。
由于分类器的各自特点分为以下几类:
有监督分类器
如果分类的标签集是预先定义的,称为有监督分类器。
例如:
- 垃圾邮件的判断。
- 根据名字的最后一个字母,分辨性别。
如果分类的建立是根据每个输入的正确标签的训练预料,称为有监督分类。
有监督分类器框架:
label和features在配对后输入机器学习算法
简单应用:
性别分类器:
根据英文姓名的最后一个字母,男女名字有明显区分的特点,用来鉴别这个人的性别。
性别猜测:
from nltk.corpus import names
import random
import nltk
def gender_features(word):
return {'last_letter': word[-1]}
names = ([(name, 'male') for name in names.words('male.txt')] +
[(name, 'female') for name in names.words('female.txt')])
random.shuffle(names)
featuresets = [(gender_features(n), g) for (n, g) in names]
train_set = featuresets[500:]
classifier = nltk.NaiveBayesClassifier.train(train_set)
print classifier.classify(gender_features('Trinity'))
输出:
female
评估分类器:
from nltk.corpus import names
import random
import nltk
def gender_features(word):
return {'last_letter': word[-1]}
names = ([(name, 'male') for name in names.words('male.txt')] +
[(name, 'female') for name in names.words('female.txt')])
random.shuffle(names)
featuresets = [(gender_features(n), g) for (n, g) in names]
train_set, test_set = featuresets[500:], featuresets[:500]
classifier = nltk.NaiveBayesClassifier.train(train_set)
radio = nltk.classify.accuracy(classifier, test_set)
print radio
输出:
0.744
查看区分效果最好的特征:
from nltk.corpus import names
import random
import nltk
def gender_features(word):
return {'last_letter': word[-1]}
names = ([(name, 'male') for name in names.words('male.txt')] +
[(name, 'female') for name in names.words('female.txt')])
random.shuffle(names)
featuresets = [(gender_features(n), g) for (n, g) in names]
train_set, test_set = featuresets[500:], featuresets[:500]
classifier = nltk.NaiveBayesClassifier.train(train_set)
classifier.show_most_informative_features(5)
输出结果:
Most Informative Features
last_letter = 'a' female : male = 35.8 : 1.0
last_letter = 'k' male : female = 31.7 : 1.0
last_letter = 'f' male : female = 15.9 : 1.0
last_letter = 'p' male : female = 11.2 : 1.0
last_letter = 'd' male : female = 9.9 : 1.0
这些比率称为似然比,用来比较特征和分类结果的相关关系。如姓名末尾为"a"的男女比例是35.8:1,可以看出这个特征的区分度比较高。
朴素贝叶斯分类器
算法原理
先计算每个标签的先验概率,计算方法为每个标签出现在训练数据中的频率。
计算公式:
P1:每个标签的先验概率,计算方式:每个标签出现在训练集里的频率。
$$
P1(Label)=Freq/DocCount
$$
P2:每个标签的似然得分的和与
决策树
简介
决策树可以类比为输入值选择标签的流程图,流程图由检查特征值的决策节点和分配标签的叶子节点组成。流程图的初始节点称为根节点。
姓名预测性别决策树:
算法原理
首先定义决策树桩:即只有一个决策节点的决策树,基于单个特征决定输入的分类。每个可能的特征值一个叶子,并分配一个类标签。
建立的决策树桩的方法:为每个可能的特征建立一个决策树桩,看哪个决策树桩在训练数据有最高的准确度。作为决策树的根节点。
决策树的生长:
检查选择出来的决策树桩,在训练集上检查每个叶子节点的准确度,没达到足够准确度的叶子被新的决策树桩替换,然后再该路径的训练子集训练新的决策树桩,查看新决策树桩每个叶子节点的准确度,知道所有的叶子节点满足准确度要求。
评价标准
熵:在分类器中用来衡量数据集中无序的程度,比如训练集中不同的标签越混乱,熵越高,标签越趋向同类,熵越低。
标签数据集熵的计算公式如下:
$$
H = Σl ∈ labelsP(l) × log2P(l)
$$
如果训练集中全是相同的标签,如"姓名-性别"数据集,如P(male)=1,P(femal)=0.P(femal)对熵的贡献为0,由于log2P(male)=0,对熵的贡献也为0,所以整体的熵为0."姓名-性别"标签数据集的熵分布函数图如下:
可以看出,P(female)=0.5时,熵最大。也就是说类别越无序,熵越大。
信息增益:
在分类器中引入了熵之后,可以计算出分类前后的无序程度,也就是熵的大小。分类前后熵的差值就是信息增益。如果信息增益越大高,决策树桩的分类效果越好。
算法特点
算法特点
- 简单明了,容易理解。适合多层次的分类。
- 分支会划分训练数据,流转到低节点的训练数据集比较少,导致这些决策节点过拟合训练集。
- 强迫特征按照一定的顺序进行检查,适合多层次的分类检查。而相对独立的特征区分度不好,可使用贝叶斯分类方法解决,允许特征“并行”生效。
优化方法:
- 训练数据变小时停止分裂节点。
- 长出一颗完整决策树时进行枝剪,剪去信息增益值低的节点。
- 采用贝叶斯分类解决相对独立的特征。
最大熵分类器
文本信息提取
信息提取系统的流水线结构
就目前而言,我们需要做的是提取句子中的实体,用来对文档进行分类。
主要通过以下3步实现:
分词
中文分词算法包括两类
- 在词典的基础上对语句进行子串匹配,优点是时间复杂度低O(n),缺点是对歧义和词库里没有的词,分词效果不好。比如:IK,庖丁。
- 基于统计和机器学习的方法分词,基于人工标注的词性和统计特征,训练模型,然后通过模型计算各种分词的概率,把概率最大分词结果作为分词结果,常见的序列标注模型有HMM和CRF。
词性标注
命名实体识别
采用的技术为分块(chunking)
每一个块是分词的一个子集,并且分块的片段不重叠。
分词和词性标注以及分块
示例:
名词短语分块
NP块的信息来源是词性标注。
分块方法:
- 正则表达式分块
- N-gram方法
词性标注
电商分类识别
在已有电商购物分类的情况下,如何把用户关键词输入,映射到商品分类下。使得搜索结果约束在相关的分类下,以此提高召回率。
流程图如下:
图:关键词匹配分类树的流程图
如:用户输入的关键词如:"华硕(ASUS)ROG STRIX-GTX1080TI-O11G-GAMING 1569-1708MHz 11G/11100MHz GDDR5X PCI-E3.0显卡"
分类树节点匹配法
通过自定义关键词抽取,自定义指的是词库为所有的商品的分类词汇。
将提取的关键词在分类树上做映射,映射的方式可以是全词匹配(准确度会高一些)。或者采用词向量的方式找最相关的分类节点(准确度不可控,计算量大)。
然后将上图中匹配上的节点回路路径,作为一种分类情形。收集所有可能的回路,并进行路径合并。产生所有的分类过滤情形,取最多3种(可配置)情形,所谓类别过滤条件,结合标题产生搜索结果。
这种方式经过测试数据集的验证,准确率为0.2908883847884619
,可以看出分类的准确率并不高,不到三成。
基于统计方法
先把类别分级别,从第一级开始分类。
比如“电脑办公”分类,统计这个大分类下的所有商品的名称分词后的词语分布。
比如
商品名称分词-词频统计图
可以看到,商品名称分词后的词语,会对词库的词频贡献分数。
算法原理:
假设"电脑办公"的商品名称,包含大量的“华硕”这个词语,并且其他分类很少有“华硕”这个词,可以总结出:商品名称里的“华硕“关键词,是”电脑办公“分类里相对特有的,相比其他分类,这个词有很好的类别区分效果。
把一个分类类比成一份文档,所有的商品名称组建成文档里的文字。分类的匹配就变成了普通的文档匹配了,可以用TF-IDF算法进行分类匹配。
影响因子:
- 词频(Term frequency):在训练(索引)的时候构建的分类下词语的统计数。即Term 在文档中出现的个数,计算方法函数是:
public float tf(float freq) {
return (float)Math.sqrt(freq);
}
有个文档叫做”this is book about chinese book”, 我的搜索项为”book”,那么这个搜索项对应文档的freq就为2
,那么tf值就为根号2,即1.4142135
。Term的freq值是在索引期间存储的。
- 逆文档频率:(Inerse document frequency),基于Term的一个因子,表示Term在所有文档里的稀有程度,以此提升包含稀有词的文档的得分。默认实现:
public float idf(long docFreq, long numDocs) {
return (float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0);
}
其中:
docFreq
指的是Term出现的文档数,就是有多少个文档符合这个搜索
numDocs
指的是索引库中有多少个文档。
- 文档权重(Document boost):在这个应用场景下也叫分类权重。设置方法可以根据经验值 来设置不同分类的权重。
- 调整因子(Coord):关键词分词后,出现在当前分类文档中的个数。
计算方法函数:
public float coord(int overlap, int maxOverlap) {
return overlap / (float)maxOverlap;
}
其中:
overlap:query中检索命中term的个数
maxOverlap:query中总共的term个数
比如:
检索''english book”, 现在有一个文档是”this is an chinese book”。那么,这个搜索对应这个文档的overlap为1(因为匹配了book),而maxOverlap为2(因为检索条件有两个book和english)。最后得到的这个搜索对应这个文档的coord值为0.5。
Lucene Classifier
计算每个标签的分值
- 标签的先验概率:
$$
p(c)=log2freq(label)-log2sum(labels)
$$
freq(label)表示整个样本空间里label标签出现的次数。
sum(lables)表示样本空间的大小。
- 标签的似然估计:
$$
p(w|c)=wordFreqForClass(word,c)/textTermFreqForClass(c)
$$
wordFreqForClass(word,c) 函数计算方法:search with text:word AND class:c 表示标签c下包含word的文档数
textTermFreqForClass(c)函数计算方法:c标签下的所有词总数+总文档数