做自然语言处理,第一步肯定是数据的预处理了,对于图像数据,我们可以把图像转化为矩阵,那么对于自然语言,我们又应该进行怎样的转化呢。
方法有很多,在网上一搜,会发现word2vec、分布式表示、word embedding等等一大堆名次,但是可以说,他们都是为了让文本能够以数字的形式呈现,要么是一维向量,要么是矩阵等等,不同的方法模型有不同的优缺点,这里先从比较简单的方法说起,也就是本文的主角词袋模型。词袋模型忽略了文本的语法语序等要素,构建了一个词汇的无序集合,通过这个集合去表达一段文字或一个文档:
![](https://i-blog.csdnimg.cn/blog_migrate/1cc1fb2d93d5c079fde14733452b2bdd.jpeg)
举一个简单的例子比如现在我们有一句话:today is a good day, tomorrow is a bad day;我们就可以基于这句话构建一个词袋:“today”、“is”、“a”、“good”、“day”、“tomorrow”、“bad”。然后,我们就可以根据词袋中的元素在句子中出现的次数,用矩阵去表示这句话:
1 2 2 1 2 1 1 \begin{matrix} 1 & 2 & 2 & 1 & 2 & 1 & 1 \\ \end{matrix} 1221211
顺带说明一下,统计词频有时候对情感的表达是有用的,比如一个句子里面出现了很多次good,如果我们不考虑它出现次数而只是用1表示它出现过,就无法准确表达句子的情感,对文本分类等问题造成偏差。
另外,这种无序表示方法,我觉得有点像小时候学习语文做的练习题,给出一堆无序的词语,比如"去哪里"、“明天”、“你”,然后做排序,就可以得到"你明天去哪里",这时候,其实不论是有序还是无序,我们都能猜出句子的意思,所以像这种通过矩阵表示一个句子是可行的。
但是词袋的缺点也很明显,当我们的词汇量增大时,对于每句话用到的词最多还是十来个,于是就导致了每句话的矩阵都是稀疏的,严重影响了内存和计算资源。除此之外,因为词袋是基于一个个独立的单词的,在一个句子中没有考虑到词与词之间的顺序和联系,所以在部分情况下可能会导致句义表达不准确,比如"你打了我"和"我打了你",虽然意思相反但是通过词袋模型表达都是一样的。
基于词袋模型的这些缺点,我们还能进一步改进,比如采取n元特征(N-gram特征),把句子的顺序也考虑进去,比如原来我们针对"today is a good day"构建的词袋是:(“today”、“is”、“a”、“good”、“day”),如果采取二元特征就可以变成:(“today is”、“is a”、“a good”、“good day”),这里构建的词袋就不再是单一的词,考虑了词与词之间的顺序。
想浏览更多关于数学、机器学习、深度学习的内容,可浏览本人博客