当我们拿到一段文本的时候,要经过如何的处理才能进入模型呢,我们把这个过程称为文本预处理。一般经过这几个步骤:
原始文本>分词>清洗>标准化>特征提取>建模
1:分词
分词的常用工具:
Jieba分词 https://github.com/fxsjy/jieba
SnowNLP https://github.com/isnowfy/snownlp
LTP http://www.ltp-cloud.com/
HanNLP https://github.com/hankcs/HanLP/
分词的常用的方法:
- 前向最大匹配
- 后向最大匹配
- 基于语言模型的分词(考虑语义的分词方法)
前向最大匹配
后向最大匹配:
最大匹配的方法的缺点:
- 不能细分(有可能是更好的)
- 只能找局部最优
- 效率低(时间复杂度高)
- 歧义(不能考虑语义层面的信息)
基于语言模型的分词:
- 把所有可能的分割找到
- 放到工具箱中有工具箱选择最好的分词方法 (语言模型)
分词:维特比算法
维特比算法在这里解决的主要问题是将上面的两步(1找到所有分割,2:判断是不是最好的分词方法)
同时考虑进来,同时计算。
其中的本质算法其实也是用动态规划的方法来找到最短路径。
拼写错误纠正
待更新。。。。。
停用词过滤,stemming操作
比如在英文中的“the”,“an”,“their”这些都可以作为停用词来处理,但是也要考虑自己的应用场景。
(一般的思路是,可以直接将别人写好的停用词库拿出来用,然后在根据自己的需求改动词库)
porter stemmer基本上要依赖语言学家的指定的规则,然后又程序员来实现。
文本表示的方法:
one-hot编码
- boolean
- count
上面两个的表示方法的区别是,count方法会记录每个单词出现的次数。
计算句子之间的相似度。
- 欧式距离
- 余弦相似度
欧氏距离:
余弦相似度
文本的表示方法中 one-hot编码的缺点,不能更好的表达单词的重要程度。
在文本中单词:并不是出现的越多就越重要,并不是出现的越少就越不重要。
从而提出了有名的tf-idf分词方法。
例子:
1:定义词典
2:根据公式计算句子表示
上面的文本的表示方法都是基于one-hot得来的。但是这些表示方法是不能体现两个单词的之间的距离的。(因为每个单词的表示方法中只有单词出现的位置是有1的,其他的位置都是0,所以当计算两个单词的欧式距离或者是余弦距离是体现不出两个单词的相关性的。)看下面的例子:
那怎么体现两个单词之间的相关性呢?
sparsity:稀疏性的问题。
因为在我们用one -hot 表示文本的时候,只有在单词出现的位置是有数值的。那如果词库非常大比如说有10000个单词,对于一个只有四个单词的句子来说,表示起来就只有四个位置出现的是1,其他的位置都是0。这就造成了解严重的稀疏性。
所以总结来看,one -hot的表示方法有两个严重的缺点
- 不能表达语义相似性
- 太过稀疏 sparsity
所以我们要引入,另一种表示方法,分布是表示方法。
- 向量的长度是自己定义的,解决了稀疏性
- 向量的每个位置都是有数值的。(可以计算两个单词之间的距离)
两个小思考题:来体现one-hot和分布式两种表示方法容量空间的大小。
在分布式表示方法中,如果向量用实数表示的话,可以表示正无穷个单词;如果在计算机中用二进制表示的话,也可以表示2的100次方个单词。
问题:如何学习词向量 learn word embeddings
- 要保证词库的量级,1B或则10B。
- 训练词向量的模型:SKip-Gram;Glove;CBOW,RNN,,,,
- 前提是要定义好词向量的维度 dim = 100;200,,,。
词向量的主要目的是能够代表单词或者句子的意思,
如何检测训练好的词向量能不能代表这个向量可以代表这个meaning,可以将训练好点词向量降维到2维,然后进行可视化,可能会看到下面的情况。
如何从词向量去表达一个句子。
- 平均法 avergring
- LSTM;RNN
下面来看一下最重要的语言模型。
先了解noisy channel model
距离说明他的应用场景
语言模型
主要作用:判断一句话是否在语法上通顺。
在宏观上看如下图:
补一个知识点,链式法则用在贝叶斯公式上。可得到下面的公式
简单的例子:
那如何计算P(休息| 今天,是,春节,我们,都),是一个非常棘手的问题,我们用马尔科夫假设来解决这个问题。
常用的方法有:
- Unigram模型
- Bigram 模型
- N-gram模型
实际上我们是将最后一个单词只认定与离他最近的几个单词的相关性最大。
下面看一下比较通用的例子。
给定一个实例:
Unigram模型:
可以看到对于Unigram模型的缺点是不考虑每个单词出现的顺序的,只要是同样的单词在一个句子中的概率都是一样的。可以看下面的图。
Bigram模型。
可以考虑单词出现顺序的影响。(利用到了马尔科夫假设)
N-gram模型:就是考虑的单词数量变多了,n是可以自己设定的。
我们已经知道了这三种语言模型,那怎么去训练这个语言模型呢?或者是怎么评估这个语言模型呢?
unigram模型的评估。
缺点:如果一句话中间有一个单词没有出现在语料库中的时候,那他的语言模型为0了。
bigram模型的评估
N-gram模型的评估
可以看到做模型评估的时候我们会出现P为0的情况的。但是实际上并不是这样的。那怎么解决呢?
实际上我们可以通过添加平滑处理的操作来解决的。学习平滑处理之前我们要先学习如何评估一个模型的好坏。
那如何评估一个语言模型呢
上述的这种方法应该是一般都会想到的的比较方法,用两种模型去测试同一个任务,然后对比这个任务中的准确率,但是这个方法的问题是太耗费时间和内存。浪费时间。
其实是可以有另一个评估标准的。
将训练好的模型,放到语料库中之后希望我们的 likelihood是越大越好的,但是我们要求Perplexity
计算方法如上图所示。
我们可以通过添加平滑处理(smoothing)
- Add--one Smoothing
- Add-K Smoothing
- interpolation
- Good-Turning Smoothing
add-one smoothing 是通过将将分子上面加上1,在分母上加上一个V(语料库大小)
思考:这里的分母为什么要加上v?
add-K smoothing
这其实是add-one smoothing更一般的形式。
那如何去更好的自动去选择K呢。
- 一个一个去尝试
- 优化这个k这个常数。
思路:我们将训练好的语言模型尝试去计算perplextiy。我们把k看做一个参数,那我们得到的perplextiy的函数就是关于k的一个函数。然后最小化这个perplextiy,来找到最适合的k。
3:interpolation
为什么提出这样的方法论?之前的方法有什么问题?
之前的方法,只是从历史数据或者是训练数据中得来的。但是如果我们收集更多的语料库的话。可能会出现更多的词汇的。请看下面的例子:
那怎么解决这个问题呢?
4:Good-Turning Smoothing
先定义一下Nc是什么?
算法分为两个部分:
- 没有出现过的单词怎么赋予一个概率
- 出现过的单词怎么预测未来可能出现的概率
第一列:单词出现的次数;第二列:有多少个单词出现;第三列:计算出来出现的概率;第四列:真实出现的概率
那这种方法有什么缺点?
这种计算方法都是依赖出现更多的单词的个数来计算的。但是实际来说可能已经没有出现更多的单词了。