A. 自然语言处理中的N-Gram模型详解
N-Gram(有时也称为N元模型)是 自然语言 处理中一个非常重要的概念,通常在NLP中,人们基于一定的语料库,可以利用N-Gram来预计或者评估一个句子是否合理。另外一方面,N-Gram的另外一个作用是用来评估两个字符串之间的差异程度。这是模糊匹配中常用的一种手段。本文将从此开始,进而向读者展示N-Gram在自然语言处理中的各种powerful的应用。
基于N-Gram模型定义的字符串距离
利用N-Gram模型评估语句是否合理
使用N-Gram模型时的数据平滑算法
欢迎关注白马负金羁的博客 http://blog.csdn.net/mafujinji ,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客 主要关注方向 包括:数字图像处理、 算法 设计与分析、 数据结构 、 机器学习 、数据挖掘、统计分析方法、自然语言处理。
基于N-Gram模型定义的字符串距离
在自然语言处理时,最常用也最基础的一个操作是就是“模式匹配”,或者称为“字符串查找”。而模式匹配(字符串查找)又分为 精确匹配 和 模糊匹配 两种。
所谓精确匹配,大家应该并不陌生,比如我们要统计一篇文章中关键词 “ information ” 出现的次数,这时所使用的方法就是精确的模式匹配。这方面的算法也比较多,而且应该是计算机相关专业必修的基础课中都会涉及到的内容,例如KMP算法、BM算法和BMH算法等等。
另外一种匹配就是所谓的模糊匹配,它的应用也随处可见。例如,一般的文字处理软件(例如,Microsoft Word等)都会提供拼写检查功能。当你输入一个错误的单词,例如 “ informtaion ” 时,系统会提示你是否要输入的词其实是 “ information ” 。将一个可能错拼单词映射到一个推荐的正确拼写上所采用的技术就是模糊匹配。
模糊匹配的关键在于如何衡量两个长得很像的单词(或字符串)之间的“差异”。这种差异通常又称为“距离”。这方面的具体算法有很多,例如基于编辑距离的概念,人们设计出了 Smith-Waterman 算法和Needleman-Wunsch 算法,其中后者还是历史上最早的应用动态规划思想设计的算法之一。现在Smith-Waterman 算法和Needleman-Wunsch 算法在生物信息学领域也有重要应用,研究人员常常用它们来计算两个DNA序列片段之间的“差异”(或称“距离”)。甚至于在LeetCode上也有一道 “No.72 Edit Distance” ,其本质就是在考察上述两种算法的实现。可见相关问题离我们并不遥远。
N-Gram在模糊匹配中的应用
事实上,笔者在新出版的 《算法之美——隐匿在数据结构背后的原理》 一书中已经详细介绍了包括Needleman-Wunsch算法、Smith-Waterman算法、N-Gram算法、Soundex算法、Phonix算法等在内的多种距离定义算法(或模糊匹配算法)。而今天为了引出N-Gram模型在NLP中的其他应用,我们首先来介绍一下如何利用N-Gram来定义字符串之间的距离。
我们除了可以定义两个字符串之间的编辑距离(通常利用Needleman-Wunsch算法或Smith-Waterman算法)之外,还可以定义它们之间的N-Gram距离。N-Gram(有时也称为N元模型)是自然语言处理中一个非常重要的概念。假设有一个字符串 s
,那么该字符串的N-Gram就表示按长度 N 切分原词得到的词段,也就是 s
中所有长度为 N 的子字符串。设想如果有两个字符串,然后分别求它们的N-Gram,那么就可以从它们的共有子串的数量这个角度去定义两个字符串间的N-Gram距离。但是仅仅是简单地对共有子串进行计数显然也存在不足,这种方案显然忽略了两个字符串长度差异可能导致的问题。比如字符串 girl 和 girlfriend,二者所拥有的公共子串数量显然与 girl 和其自身所拥有的公共子串数量相等,但是我们并不能据此认为 girl 和girlfriend 是两个等同的匹配。
为了解决该问题,有学者便提出以非重复的N-Gram分词为基础来定义 N-Gram距离这一概念,可以用下面的公式来表述:
|GN(s)|+|GN(t)|−2×|GN(s)∩GN(t)|
此处,|GN(s)|
是字符串 s
的 N-Gram集合,N 值一般取2或者3。以 N = 2 为例对字符串Gorbachev和Gorbechyov进行分段,可得如下结果(我们用下画线标出了其中的公共子串)。
有兴趣的读者可以在引用相关JAR包之后在Eclipse中执行上述java程序,你会发现,和我们预期的一样,字符串Gorbachev和Gorbechyov所得之距离评分较高(=0.7),说明二者很接近;而girl和girlfriend所得之距离评分并不高(=0.3999),说明二者并不很接近。
利用N-Gram模型评估语句是否合理
从现在开始,我们所讨论的N-Gram模型跟前面讲过N-Gram模型从外在来看已经大不相同,但是请注意它们内在的联系(或者说本质上它们仍然是统一的概念)。
为了引入N-Gram的这个应用,我们从几个例子开始。首先,从统计的角度来看,自然语言中的一个句子 s
可以由任何词串构成,不过概率 P(s)
有大有小。例如:
s1
= 我刚吃过晚饭
s2
= 刚我过晚饭吃
显然,对于中文而言 s1
是一个通顺而有意义的句子,而s2
则不是,所以对于中文来说,P(s1)>P(s2)
。但不同语言来说,这两个概率值的大小可能会反转。
其次,另外一个例子是,如果我们给出了某个句子的一个节选,我们其实可以能够猜测后续的词应该是什么,例如
the large green __ . Possible answer may be “mountain” or “tree” ?
Kate swallowed the large green __ . Possible answer may be “pill” or “broccoli” ?
显然,如果我们知道这个句子片段更多前面的内容的情况下,我们会得到一个更加准确的答案。这就告诉我们,前面的(历史)信息越多,对后面未知信息的约束就越强。
如果我们有一个由 m
个词组成的序列(或者说一个句子),我们希望算得概率 P(w1,w2,⋯,wm)
,根据链式规则,可得
P(w1,w2,⋯,wm)=P(w1)P(w2|w1)P(w3|w1,w2)⋯P(wm|w1,⋯,wm−1)
这个概率显然并不好算,不妨利用马尔科夫链的假设,即当前这个词仅仅跟前面几个有限的词相关,因此也就不必追溯到最开始的那个词,这样便可以大幅缩减上诉算式的长度。即P(wi|w1,⋯,wi−1)=P(wi|wi−n+1,⋯,wi−1)
特别地,对于 n
取得较小值的情况当 n=1
, 一个一元模型(unigram model)即为P(w1,w2,⋯,wm)=∏i=1mP(wi)
当 n=2
, 一个二元模型(bigram model)即为P(w1,w2,⋯,wm)=∏i=1mP(wi|wi−1)
当 n=3
, 一个三元模型(trigram model)即为P(w1,w2,⋯,wm)=∏i=1mP(wi|wi−2wi−1)
接下来的思路就比较明确了,可以利用最大似然法来求出一组参数,使得训练样本的概率取得最大值。
对于unigram model而言,其中c(w1,..,wn)
表示 n-gram w1,..,wn
在训练语料中出现的次数,M
是语料库中的总字数(例如对于 yes no no no yes 而言,M=5
)P(wi)=C(wi)M
对于bigram model而言,P(wi|wi−1)=C(wi−1wi)C(wi−1)
对于n
-gram model而言,P(wi|wi−n−1,⋯,wi−1)=C(wi−n−1,⋯,wi)C(wi−n−1,⋯,wi−1)
来看一个具体的例子,假设我们现在有一个语料库如下,其中<s1><s2>
是句首标记,</s2></s1>
是句尾标记:
<s1><s2>yesnonononoyes</s2></s1><s1><s2>nononoyesyesyesno</s2></s1>
下面我们的任务是来评估如下这个句子的概率:<s1><s2>yesnonoyes</s2></s1>
我们来演示利用trigram模型来计算概率的结果P(yes|<s1><s2>)=12,P(no|<s2>yes)=1P(no|yesno)=12,P(yes|nono)=25P(</s2>|noyes)=12,P(</s1>|yes</s2>)=1
所以我们要求的概率就等于:12×1×12×25×12×1=0.05
再举一个来自文献[1]的例子,假设现在有一个语料库,我们统计了下面一些词出现的数量
下面这个概率作为其他一些已知条件给出:P(i|<s>)=0.25P(english|want)=0.0011P(food|english)=0.5P(</s>|food)=0.68
,则可以算得P(s1)=P(i|<s>)P(want|i)P(english|want)P(food|english)P(</s>|food)=0.25×0.33×0.0011×0.5×0.68=0.000031
使用N-Gram模型时的数据平滑算法
有研究人员用150万词的训练语料来训练 trigram 模型,然后用同样来源的 测试 语料来做验证,结果发现23%的 trigram 没有在训练语料中出现过。这其实就意味着上一节我们所计算的那些概率有空为 0,这就导致了数据稀疏的可能性,我们的表3中也确实有些为0的情况。对语言而言,由于数据稀疏的存在,极大似然法不是一种很好的参数估计办法。
这时的解决办法,我们称之为“平滑技术”(Smoothing)或者 “减值” (Discounting)。其主要策略是把在训练样本中出现过的事件的概率适当减小,然后把减小得到的概率密度分配给训练语料中没有出现过的事件。实际中平滑算法有很多种,例如:▸ Laplacian (add-one) smoothing▸ Add-k smoothing▸ Jelinek-Mercer interpolation▸ Katz backoff▸ Absolute discounting▸ Kneser-Ney
对于这些算法的详细介绍,我们将在后续的文章中结合一些实例再来进行讨论。
A Final Word
如果你能从前面那些繁冗、复杂的概念和公式中挺过来,恭喜你,你对N-Gram模型已经有所认识了。尽管,我们还没来得及探讨平滑算法(但它即将出现在我的下一篇博文里,如果你觉得还未过瘾的话),但是其实你已经掌握了一个相对powerful的工具。你可以能会问,在实践中N-Gram模型有哪些具体应用,作为本文的结束,主页君便在此补充几个你曾见过的或者曾经好奇它是如何实现的例子。
Eg.1 搜索引擎 (Google或者Bai)、或者输入法的猜想或者提示。你在用网络时,输入一个或几个词,搜索框通常会以下拉菜单的形式给出几个像下图一样的备选,这些备选其实是在猜想你想要搜索的那个词串。再者,当你用输入法输入一个汉字的时候,输入法通常可以联系出一个完整的词,例如我输入一个“刘”字,通常输入法会提示我是否要输入的是“刘备”。通过上面的介绍,你应该能够很敏锐的发觉,这其实是以N-Gram模型为基础来实现的,如果你能有这种觉悟或者想法,那我不得不恭喜你,都学会抢答了!
Eg.2 某某作家或者语料库风格的文本自动生成。这是一个相当有趣的话题。来看下面这段话(该例子取材自文献【1】):
“You are uniformly charming!” cried he, with a smile of associating and now and then I bowed and they perceived a chaise and four to wish for.
你应该还没有感觉到它有什么异样吧。但事实上这并不是由人类写出的句子,而是计算机根据Jane Austen的语料库利用trigram模型自动生成的文段。(Jane Austen是英国着名女作家,代表作有《傲慢与偏见》等)
再来看两个例子,你是否能看出它们是按照哪位文豪(或者语料库)的风格生成的吗?
This shall forbid it should be branded, if renown made it empty.
They also point to ninety nine point six billion dollars from two hundred four oh three percent of the rates of interest stores as Mexico and Brazil on market conditions.
答案是第一个是莎士比亚,第二个是华尔街日报。最后一个问题留给读者思考,你觉得上面两个文段所运用的n-gram模型中,n应该等于多少?
推荐阅读和参考文献:
[1] Speech and Language Processing. Daniel Jurafsky & James H. Martin, 3rd. Chapter 4[2] 本文中的一些例子和描述来自 北京大学 常宝宝 以及 The University of Melbourne “Web Search and Text Analysis” 课程的幻灯片素材
B. java word分词器怎样安装在java中
word分词是一个Java实现的分布式的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型来消除歧义。
如果需要安装word分词器可以参考下面的步骤:
JDK官网:http://www.oracle.com/technetwork/java/javase/downloads/index.html
Eclipse官网:http://www.eclipse.org
打开word分词器的官方github主页:https://github.com/ysc/word
导入成功之后就可以在自己的项目中使用word分词器了。
C. java中文分词组件word怎么使用
参考如下
1、快速体验
运行项目根目录下的脚本demo-word.bat可以快速体验分词效果
用法: command [text] [input] [output]
命令command的可选值为:demo、text、file
demo
text 杨尚川是APDPlat应用级产品开发平台的作者
file d:/text.txt d:/word.txt
exit
2、对文本进行分词
移除停用词:List<Word> words = WordSegmenter.seg("杨尚川是APDPlat应用级产品开发平台的作者");
保留停用词:List<Word> words = WordSegmenter.segWithStopWords("杨尚川是APDPlat应用级产品开发平台的作者");
System.out.println(words);
输出:
移除停用词:[杨尚川, apdplat, 应用级, 产品, 开发平台, 作者]
保留停用词:[杨尚川, 是, apdplat, 应用级, 产品, 开发平台, 的, 作者]
3、对文件进行分词
String input = "d:/text.txt";
String output = "d:/word.txt";
移除停用词:WordSegmenter.seg(new File(input), new File(output));
保留停用词:WordSegmenter.segWithStopWords(new File(input), new File(output));
4、自定义配置文件
默认配置文件为类路径下的word.conf,打包在word-x.x.jar中
自定义配置文件为类路径下的word.local.conf,需要用户自己提供
如果自定义配置和默认配置相同,自定义配置会覆盖默认配置
配置文件编码为UTF-8
5、自定义用户词库
自定义用户词库为一个或多个文件夹或文件,可以使用绝对路径或相对路径
用户词库由多个词典文件组成,文件编码为UTF-8
词典文件的格式为文本文件,一行代表一个词
可以通过系统属性或配置文件的方式来指定路径,多个路径之间用逗号分隔开
类路径下的词典文件,需要在相对路径前加入前缀classpath:
指定方式有三种:
指定方式一,编程指定(高优先级):
WordConfTools.set("dic.path", "classpath:dic.txt,d:/custom_dic");
DictionaryFactory.reload();//更改词典路径之后,重新加载词典
指定方式二,Java虚拟机启动参数(中优先级):
java -Ddic.path=classpath:dic.txt,d:/custom_dic
指定方式三,配置文件指定(低优先级):
使用类路径下的文件word.local.conf来指定配置信息
dic.path=classpath:dic.txt,d:/custom_dic
如未指定,则默认使用类路径下的dic.txt词典文件
6、自定义停用词词库
使用方式和自定义用户词库类似,配置项为:
stopwords.path=classpath:stopwords.txt,d:/custom_stopwords_dic
7、自动检测词库变化
可以自动检测自定义用户词库和自定义停用词词库的变化
包含类路径下的文件和文件夹、非类路径下的绝对路径和相对路径
如:
classpath:dic.txt,classpath:custom_dic_dir,
d:/dic_more.txt,d:/DIC_DIR,D:/DIC2_DIR,my_dic_dir,my_dic_file.txt
classpath:stopwords.txt,classpath:custom_stopwords_dic_dir,
d:/stopwords_more.txt,d:/STOPWORDS_DIR,d:/STOPWORDS2_DIR,stopwords_dir,remove.txt
8、显式指定分词算法
对文本进行分词时,可显式指定特定的分词算法,如:
WordSegmenter.seg("APDPlat应用级产品开发平台", SegmentationAlgorithm.BidirectionalMaximumMatching);
SegmentationAlgorithm的可选类型为:
正向最大匹配算法:MaximumMatching
逆向最大匹配算法:ReverseMaximumMatching
正向最小匹配算法:MinimumMatching
逆向最小匹配算法:ReverseMinimumMatching
双向最大匹配算法:BidirectionalMaximumMatching
双向最小匹配算法:BidirectionalMinimumMatching
双向最大最小匹配算法:
全切分算法:FullSegmentation
最少分词算法:MinimalWordCount
最大Ngram分值算法:MaxNgramScore
9、分词效果评估
运行项目根目录下的脚本evaluation.bat可以对分词效果进行评估
评估采用的测试文本有253 3709行,共2837 4490个字符
评估结果位于target/evaluation目录下:
corpus-text.txt为分好词的人工标注文本,词之间以空格分隔
test-text.txt为测试文本,是把corpus-text.txt以标点符号分隔为多行的结果
standard-text.txt为测试文本对应的人工标注文本,作为分词是否正确的标准
result-text-***.txt,***为各种分词算法名称,这是word分词结果
perfect-result-***.txt,***为各种分词算法名称,这是分词结果和人工标注标准完全一致的文本
wrong-result-***.txt,***为各种分词算法名称,这是分词结果和人工标注标准不一致的文本
D. 自然语言处理(NLP)的基础难点:分词算法
自然语言处理(NLP,Natural Language Processing)是人工智能领域中的一个重要方向,主要研究人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理的底层任务由易到难大致可以分为词法分析、句法分析和语义分析。分词是词法分析(还包括词性标注和命名实体识别)中最基本的任务,也是众多NLP算法中必不可少的第一步,其切分准确与否往往与整体结果息息相关。
金融领域分词的难点
分词既简单又复杂。简单是因为分词的算法研究已经很成熟了,大部分的算法(如HMM分词、CRF分词)准确率都可以达到95%以上;复杂则是因为剩下的5%很难有突破,主要可以归结于三点:
▲粒度,即切分时的最小单位,不同应用对粒度的要求不一样,比如“融资融券”可以是一个词也可以是两个词
▲歧义,比如“恒生”一词,既可指恒生公司,又可指恒生指数
▲未登录词,即未出现在算法使用的词典中的词,比如不常见的专业金融术语,以及各种上市公司的名称
在金融领域中,分词也具有上述三个难点,并且在未登录词方面的难点更为突出,这是因为金融类词汇本来就多,再加上一些专有名词不仅有全称还有简称,这就进一步增大了难度。
在实际应用中,以上难点时常会造成分词效果欠佳,进而影响之后的任务。尤其是在一些金融业务中,有许多需要与用户交互的场景,某些用户会用口语化的词汇描述业务,如果分词错误会影响用户意图的解析,这对分词的准确性提出了更高的要求。因此在进行NLP上层应用开发时,需要对分词算法有一定的了解,从而在效果优化时有能力对分词器进行调整。接下来,我们介绍几种常用的分词算法及其应用在金融中的优劣。
几种常见的分词算法
分词算法根据其核心思想主要分为两种:
第一种是基于字典的分词,先把句子按照字典切分成词,再寻找词的最佳组合方式,包括最大匹配分词算法、最短路径分词算法、基于N-Gram model的分词算法等;
第二种是基于字的分词,即由字构词,先把句子分成一个个字,再将字组合成词,寻找最优的切分策略,同时也可以转化成序列标注问题,包括生成式模型分词算法、判别式模型分词算法、神经网络分词算法等。
最大匹配分词寻找最优组合的方式是将匹配到的最长词组合在一起,主要的思路是先将词典构造成一棵Trie树(也称为字典树),Trie树由词的公共前缀构成节点,降低了存储空间的同时可以提升查找效率。
最大匹配分词将句子与Trie树进行匹配,在匹配到根结点时由下一个字重新开始进行查找。比如正向(从左至右)匹配“他说的确实在理”,得出的结果为“他/说/的确/实在/理”。如果进行反向最大匹配,则为“他/说/的/确实/在理”。
这种方式虽然可以在O(n)时间对句子进行分词,但是只单向匹配太过绝对,尤其是金融这种词汇较丰富的场景,会出现例如“交易费/用”、“报价单/位”等情况,所以除非某些词的优先级很高,否则要尽量避免使用此算法。
最短路径分词算法首先将一句话中的所有词匹配出来,构成词图(有向无环图DAG),之后寻找从起始点到终点的最短路径作为最佳组合方式,例:
我们认为图中每个词的权重都是相等的,因此每条边的权重都为1。
在求解DAG图的最短路径问题时,总是要利用到一种性质:即两点之间的最短路径也包含了路径上其他顶点间的最短路径。比如S->A->B->E为S到E到最短路径,那S->A->B一定是S到B到最短路径,否则会存在一点C使得d(S->C->B)<d(S->A->B),那S到E的最短路径也会变为S->C->B->E,这就与假设矛盾了。利用上述的最优子结构性质,可以利用贪心算法或动态规划两种求解算法:
(1)基于Dijkstra算法求解最短路径,该算法适用于所有带权有向图,求解源节点到其他所有节点的最短路径,并可以求得全局最优解;
(2)N-最短路径分词算法,该方法是对Dijkstra算法的扩展,在每一步保存最短的N条路径,并记录这些路径上当前节点的前驱,在最后求得最优解时回溯得到最短路径。这种方法的准确率优于Dijkstra算法,但在时间和空间复杂度上都更大。
相较于最大匹配分词算法,最短路径分词算法更加灵活,可以更好地把词典中的词组合起来,能更好地解决有歧义的场景。比如上述“他说的确实在理”这句话,用最短路径算法的计算结果为“他/说/的/确实/在理”,避免了正向最大匹配的错误。但是对于词典中未存在的词基本没有识别能力,无法解决金融领域分词中的“未登录词”难点。
N-Gram(又称N元语法模型)是基于一个假设:第n个词出现与前n-1个词相关,而与其他任何词不相关。在此种假设下,可以简化词的条件概率,进而求解整个句子出现的概率。
现实中,常用词的出现频率或者概率肯定比罕见词要大。因此,可以将求解词图最短路径的问题转化为求解最大概率路径的问题,即分词结果为“最有可能的词的组合“。
计算词出现的概率,仅有词典是不够的,还需要充足的语料,所以分词任务已经从单纯的“算法”上升到了“建模”,即利用统计学方法结合大数据挖掘,对“语言”(句子出现的概率)进行建模。
我们将基于N-gram模型所统计出的概率分布应用到词图中,可以得到词的概率图。对该词图用最短路径分词算法求解最大概率的路径,即可得到分词结果。
相较于前两种分词算法,基于N-Gram model的分词算法对词频进行了统计建模,在切分有歧义的时候力求得到全局最优值,比如在切分方案“证券/自营/业务”和“证券/自/营业/务”中,统计出“证券/自营/业务”出现的概率更大,因此结果有更高的准确率。但也依然无法解决金融场景中未登录词的问题。
生成式模型主要有隐马尔可夫模型(HMM,Hidden Markov Model)、朴素贝叶斯分类等。HMM是常用的分词模型,基于Python的jieba分词器和基于Java的HanLP分词器都使用了HMM。
HMM模型认为在解决序列标注问题时存在两种序列,一种是观测序列,即人们显性观察到的句子,另一种是隐状态序列,即观测序列的标签。假设观测序列为X,隐状态序列是Y,则因果关系为Y->X。因此要得到标注结果Y,必须对X的概率、Y的概率、P(X|Y)进行计算,即建立P(X,Y)的概率分布模型。
HMM算法可以在一定程度上解决未登录词的问题,但生成式模型的准确率往往没有接下来要谈到的判别式模型高。
判别式模型主要有感知机、支持向量机(SVM,Support Vector Machine)、条件随机场(CRF,Conditional Random Field)、最大熵模型等,其中感知机模型和CRF模型是常用的分词模型。
(1)平均感知机分词算法
感知机是一种简单的二分类线性模型,通过构造超平面,将特征空间(输入空间)中的样本分为正负两类。通过组合,感知机也可以处理多分类问题。但由于每次迭代都会更新模型的所有权重,被误分类的样本会造成很大影响,因此采用平均的方法,在处理完一部分样本后对更新的权重进行平均。
(2)CRF分词算法
CRF可以看作一个无向图模型,假设给定的标注序列为Y,观测序列为X,CRF对条件概率P(Y|X)进行定义,而不是对联合概率建模。
平均感知机算法虽然速度快,但仍不够准确。适合一些对速度要求高、对准确性要求相对不那么高的场景。CRF分词算法可以说是目前最常用的分词、词性标注和实体识别算法,它对未登陆词也有很好的识别能力,是目前在速度、准确率以及未登录词识别上综合表现最突出的算法,也是我们目前所采用的解决方案,但速度会比感知机慢一些。
在NLP中,最常用的神经网络为循环神经网络(RNN,Recurrent Neural Network),它在处理变长输入和序列输入问题中有着巨大的优势。LSTM(Long Short-Term Memory,长短期记忆网络)为RNN变种的一种,在一定程度上解决了RNN在训练过程中梯度消失和梯度爆炸的问题。
目前对于序列标注任务,业内公认效果最好的模型是BiLSTM+CRF。相比于上述其它模型,双向循环神经网络BiLSTM,可以更好地编码当前字等上下文信息,并在最终增加CRF层,核心是用Viterbi算法进行解码,以得到全局最优解,避免B,S,E这种不可能的标记结果的出现,提高准确率。
神经网络分词虽然能在准确率、未登录词识别上有更好的表现,但RNN无法并行计算,在速度上没有优势,所以该算法通常在算法研究、句子精确解析等对速度要求不高的场景下使用。
分词作为NLP底层任务之一,既简单又重要,很多时候上层算法的错误都是由分词结果导致的。因此,对于底层实现的算法工程师,不仅需要深入理解分词算法,更需要懂得如何高效地实现和调试。
而对于上层应用的算法工程师,在实际分词时,需要根据业务场景有选择地应用上述算法,比如在搜索引擎对大规模网页进行内容解析时,对分词对速度要求大于精度,而在智能问答中由于句子较短,对分词的精度要求大于速度。
E. ngram模型在哪些场景运动较多
首页
博客
研修院
VIP
APP
问答
下载
社区
推荐频道
活动
招聘
专题
打开CSDN APP
Copyright © 1999-2020, CSDN.NET, All Rights Reserved
风控模型特征工程
打开APP
风控建模二、特征工程---通用 原创
2022-09-17 11:46:33
1点赞
沐自礼
码龄8年
关注
目录
一、数据预处理
1.1 缺失值
1.2 异常值处理
1.3 样本不均衡处理
二、特征生成
2.1 特征归一化(or 标准化)
2.2 特征放缩(统计信息+ 简单加减乘除)
2.3 哑变量
2.3 分桶
2.4 日期类
2.5 组合特征
2.6 文本型(风控场景中应用比较少,传统nlp应用较多)
2.6.1 词袋模型+Ngram
2.6.2 tf-idf
2.6.3 word2vev/fastext
2.7 embedding
2.8 特征分解 (应用较少)
三、特征筛选
3.1 移除低方差的特征 (Removing features with low variance)
3.2. 单变量特征选择 (Univariate feature selection)
3.2.1 卡方(Chi2)检验
3.2.2 Pearson相关系数 (Pearson Correlation)
3.3 递归特征消除 (Recursive Feature Elimination)
3.4 基于L1的特征选择 (L1-based feature selection)
3.5 xgboost, lightGBM
参考文献
“特征决定了模型的上限, 而算法只是逼近这个上限”,由此可见特征工程在风控建模中的重要程度。 特征工程的本质是基于原始数据的信息提炼, 风控场景中的很多数据源, 单独来看可能和风险表现关联性并不强,但是加工成特征后, 却会与我们想要预测的目标产生紧密的联系。
下面我们将从特征预处理,特征生成,特征筛选三个模块对特征工程进行拆解。
一、数据预处理
1.1 缺失值
一般来说,未经处理的原始数据中通常会存在缺失值,因此在建模训练之前需要处理好缺失值。
1)缺失数据占比小于 20%。可以通过直接填充法,连续特征一般取均值填充,离散特征可以取众数填充;可以模型预测法,通过随机森林或者决策树进行预测结果填充;也可以通过插值法填充。
2)缺失数据占比大于 20% 小于 50%,这个时候可以把缺失值构建为新的特征,增加一列离散特征,即有缺失数据和无缺失数据。
3)缺失数据占比大于 50%,因为信息量较少,模型可能会学到大量噪音建议直接删除该特征。
像 xgboost 模型自带缺失值处理功能,可以不进行缺失值处理。
缺失值填充方法:
1). 如果是连续性,就使用平均值插补,如果是离散性,就使用众数来插补。 当然也可以用特殊值、中位数等代替。 其中采用均值填充的缺点:大大降低数据的方差
2). 随机插补法----从总体中随机抽取某个样本代替缺失样本
3). 引入预测模型,可考虑辅助回归,通过变量间的关系来预测缺失数据
下面代码就是均值填充的两种方案:
df_train['Age'].fillna(value=df_train['Age'].mean()).sample(10)
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
df_train.loc[:,'Age'] = df_train['Age'].fillna(value=df_train['Age'].mean()).()
df_train.head(10)
1.2 异常值处理
异常值,即在数据集中存在不合理的值,又称离群点、极值等。可以通过统计分析、箱线图、聚类、3σ 原则、孤立森林等方法进行检查。
一般的处理方法如下:
1)直接删除含有异常值的样本。
2)视为缺失值。利用缺失值处理的方法进行处理。
3)最近值修正。可以用相近的观测值修正该异常值。
4)不处理。可以直接在具有异常值的数据集上进行数据建模。
大部分建模时,通过画图的方式进行看一下即可。
提供的方法:
统计分析,看四分位数,看数据分布。
箱线图:使用画图工具比如seaborn库 调用boxplot,distplot看一下。
聚类:使用sklearn中的聚类函数。
3σ: 需要自己同统计,类似看四分位数。
1.3 样本不均衡处理
推荐包:imbalance learn (https://imbalanced-learn.org/stable/references/index.html)
后面章节会对样本不均衡做详细的介绍,暂时可以先简单了解一下。一般应用场景中,常用样本不均衡的是解决方案为1,2。
样本不均衡现象是指正样本数目与负样本数目比列相差很大。处理方法如下:
1)下采样/欠采样(under sampling):从多数类中随机抽取样本从而减少多数类别样本数据,使数据达到平衡的方式。比如本来样本正负例的比例是 10:1,可以对正样本进行下采样构建 10 个正负样本比例为 1:1 的模型,回归结果取平均值,分类结果进行投票。
2)上采样/过采样(Over Sampling):和欠采样采用同样的原理,通过抽样来增加少数样本的数目,从而达到数据平衡的目的。同样比如本来样本正负例的比例是 10:1,可以对负样本进行上采样构建正负样本比例为 1:1 的模型。
3)Smote 算法:Smote 算法属于上采样的一种,通过人工合成的方法来生成少类别的样本。方法也很简单,对于某一个缺少样本的类别,它会随机找出几个该类别的样本,再找出最靠近这些样本的若干个该类别样本,组成一个候选合成集合,然后在这个集合中不停的选择距离较近的两个样本,在这两个样本之间,比如中点,构造一个新的该类别样本。举个例子,比如该类别的候选合成集合有两个样本(x1,y),(x2,y)(x1,y),(x2,y),那么Smote采样后,可以得到一个新的训练样本(x1+x22,y)(x1+x22,y),通过这种方法,我们可以得到不改变训练集分布的新样本,让训练集中各个类别的样本数趋于平衡。
4)Focal loss :主要解决分类样本不平衡问题,通过修改交叉熵损失函数,通过增加类别权重 α 和样本难度权重调因子(molating factor)(1−pt)γ(1−pt)γ,来减缓上述问题。
5)设置损失函数的权重:使得少数类别数据判断错误的损失大于多数类别数据判断错误的损失,即当我们的少数类别数据预测错误的时候,会产生一个比较大的损失值,从而导致模型参数往让少数类别数据预测准确的方向偏。
二、特征生成
2.1 特征归一化(or 标准化)
应用于数值类特征。
归一化(标准化),就是要把你需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。其目的一是把不同量纲的东西放在同一量纲下,保正程序运行时收敛加快,大部分模型归一化后收敛速度会加快。但像树模型不受特征归一化影响,所以不需要特征归一化。
归一化处理:最大最小值归一化或者叫 0-1 归一化,取值范围在 [0,1] 处理,max 为样本最大值, min 为样本最小值。
标准化处理:这里只介绍一种经常使用的 z-score 标准化,经过处理后的数据均值为 0,标准差为 1,符合标准的正态分布。其中 mean 为平均值,б 为标准差。
# 幅度缩放,最大最小值缩放到[0,1]区间内
from sklearn.preprocessing import MinMaxScaler
mm_scaler = MinMaxScaler()
fare_trans = mm_scaler.fit_transform(df_train[['Fare']])
# 幅度缩放,将每一列的数据标准化为正态分布的
from sklearn.preprocessing import StandardScaler
std_scaler = StandardScaler()
fare_std_trans = std_scaler.fit_transform(df_train[['Fare']])
#中位数或者四分位数去中心化数据,对异常值不敏感
from sklearn.preprocessing import robust_scale
fare_robust_trans = robust_scale(df_train[['Fare','Age']])
#将同一行数据规范化,前面的同一变为1以内也可以达到这样的效果
from sklearn.preprocessing import Normalizer
normalizer = Normalizer()
fare_normal_trans = normalizer.fit_transform(df_train[['Age','Fare']])
fare_normal_trans
2.2 特征放缩(统计信息+ 简单加减乘除)
应用于数值类特征,可以引入log非线性进行放缩。
import numpy as np
log_age = df_train['Age'].apply(lambda x:np.log(x))
df_train.loc[:,'log_age'] = log_age
# 最大最小值
max_age = df_train['Age'].max()
min_age = df_train["Age"].min()
# 分位数,极值处理,我们最粗暴的方法就是将前后1%的值抹去
age_quarter_01 = df_train['Age'].quantile(0.01)
print(age_quarter_01)
age_quarter_99 = df_train['Age'].quantile(0.99)
print(age_quarter_99)
df_train.loc[:,'family_size'] = df_train['SibSp']+df_train['Parch']+1
df_train.head() df_train.loc[:,'tmp'] = df_train['Age']*df_train['Pclass'] + 4*df_train['family_size']
df_train.head()
2.3 哑变量
哑变量用于类别,一般如性别,分为男女两列。
embarked_oht = pd.get_mmies(df_train[['Embarked']])
embarked_oht.head()
2.3 分桶
应用于数值。
可以等频分桶,也可以自行指定区间分桶。非线性变化。
# 等频切分
df_train.loc[:,'fare_qcut'] = pd.qcut(df_train['Fare'], 10)
df_train.head()
df_train = df_train.sort_values('Fare')
alist = list(set(df_train['fare_qcut']))
badrate = {}
for x in alist:
a = df_train[df_train.fare_qcut == x]
bad = a[a.label == 1]['label'].count()
good = a[a.label == 0]['label'
F. n-gram语言模型
在自然语言处理中的一个基本问题: 如何计算一段文本序列在某种语言下出现的概率? 之所为称其为一个基本问题,是因为它在很多NLP任务中都扮演着重要的角色。例如,"我经常会去图书馆____",预测该句后面的词。我们会通过已有的语料或上下文,来统计预测这句话可以填某个词的概率。将概率最大的作为预测结果返回。再比如机器翻译中,‘I like Tom so much.’ ===>{‘我’,‘喜欢’,‘汤姆’,‘非常’} 将这个集合里的字词排列组合成句子,然后用语言模型去计算形成句子的概率大小。概率越大,说明翻译越顺畅,越好,就作为最终的答案返回。
统计语言模型给出了这一类问题的一个基本解决框架。对于一段文本序列
它的概率可以表示为:
即将序列的联合概率转化为一系列条件概率的乘积。问题变成了如何去预测这些给定previous words下的条件概率:
由于其巨大的参数空间,这样一个原始的模型在实际中并没有什么用。我们更多的是采用其简化版本—— Ngram模型 :
常见的如bigram模型(N=2)和trigram模型(N=3)。事实上,由于模型复杂度和预测精度的限制,我们很少会考虑N>3的模型。
我们可以用最大似然法去求解Ngram模型的参数——等价于去统计每个Ngram的条件词频。
为了避免统计中出现的零概率问题,针对于Ngram模型有很多处理的小技巧。
n-gram语言模型的思想,可以追溯到信息论大师香农的研究工作,他提出一个问题: 给定一串字母,如“for ex”,下一个最大可能性出现的字母是什么? 从训练语料数据中,我们可以通过极大似然估计的方法,得到N个概率分布:是a的概率是0.4,是b的概率是0.0001,是c的概率是…,当然, 别忘记约束条件:所有的N个概率分布的总和为1.
n-gram模型概率公式推导。根据条件概率和乘法公式:
得到
拿一个应用来讲,假设T是由词序列A1,A2,A3,…An组成的,那么P(T)=P(A1A2A3…An)=P(A1)P(A2|A1)P(A3|A1A2)…P(An|A1A2…An-1)
如果直接这么计算,是有很大困难的,需要引入马尔科夫假设,即:一个item的出现概率,只与其前m个items有关 ,当m=0时,就是unigram,m=1时,是bigram模型。
因此,P(T)可以求得,例如,当利用bigram模型时,P(T)=P(A1)P(A2|A1)P(A3|A2)…P(An|An-1)
而P(An|An-1)条件概率可以通过极大似然估计求得,等于Count(An-1,An)/Count(An-1)。
·着名的 google books Ngram Viewer ,它的n-gram数据格式是这样的:
代表了一个 1-gram的数据片段 ,第一行的意思是,“circumvallate”这个单词在1978年出现335次,存在91本书中。这些元数据,除了频率335次是必须的,其他的元数据(例如,还有词性等)可以根据应用需求来定。下面是一个 5-gram数据片段 :
当然,也可以是其他形式,例如, HanLP 的n-gram模型是bigram:
每一行代表,两个相邻单词共同出现时的频率(相对于背后的语料库)。
· 文化研究 ·分词算法 ·语音识别 ·输入法 ·机器翻译
文化研究:n-gram模型看起来比较枯燥和冰冷,但实际上,google books ngram项目,催生了一门新学科( Culturomics )的成立,通过数字化的文本,来研究人类行为和文化趋势。可查看知乎上的 详细介绍 ,。《可视化未来》这本书也有详细介绍。还有TED上的视频 《what_we_learned_from_5_million_books》 ,十分精彩。
输入法:大家每天都在使用的东西,请看:输入“tashiyanjiushengwude”,可能的输出有:
究竟哪个是输入者最想表达的意思,这背后的技术就要用到n-gram语言模型了。item就是每一个拼音对应的可能的字。还记得智能ABC吗? 据说 是运用n-gram的鼻祖了。 不过搜狗输入法后来居上,它采用更先进的 云计算技术 (n-gram模型的数据量可是相当之大,后面会说到) 。
做概率统计的都知道,语料库的规模越大,做出的n-gram对统计语言模型才更有用。n-gram,无论是存储还是检索,对技术都是极大的挑战。
主要参考文章:
【1】 N-Gram语言模型 原文更精彩