| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> 天池-新闻文本分类-task1机器学习算法(未完待续) -> 正文阅读 |
|
[人工智能]天池-新闻文本分类-task1机器学习算法(未完待续) |
一、文本挖掘原理1 分词的基本原理??现代分词都是基于统计的分词,而统计的样本内容来自于一些标准的语料库。假如有一个句子:“小明来到荔湾区”,我们期望语料库统计后分词的结果是:“小明/来到/荔湾/区”,而不是“小明/来到/荔/湾区”。那么如何做到这一点呢? ??其中下标 n i n_i ni?代表第 i i i种分词的词个数。如果我们从中选择了最优的第 r r r种分词方法,那么这种分词方法对应的统计分布概率应该最大,即: r = a r g ?? m a x ? i P ( A i 1 , A i 2 , . . . , A i n i ) r = \underbrace{arg\;max}_iP(A_{i1},A_{i2},...,A_{in_i}) r=i argmax??P(Ai1?,Ai2?,...,Aini??) ??但是我们的概率分布
P
(
A
i
1
,
A
i
2
,
.
.
.
,
A
i
n
i
)
P(A_{i1},A_{i2},...,A_{in_i})
P(Ai1?,Ai2?,...,Aini??)并不好求出来,因为它涉及到
n
i
n_i
ni?个分词的联合分布。在NLP中,为了简化计算,我们通常使用马尔科夫假设,即每一个分词出现的概率仅仅和前一个分词有关,即:
P
(
A
i
j
∣
A
i
1
,
A
i
2
,
.
.
.
,
A
i
(
j
?
1
)
)
=
P
(
A
i
j
∣
A
i
(
j
?
1
)
)
P(A_{ij}|A_{i1},A_{i2},...,A_{i(j-1)}) = P(A_{ij}|A_{i(j-1)})
P(Aij?∣Ai1?,Ai2?,...,Ai(j?1)?)=P(Aij?∣Ai(j?1)?) ??而通过我们的标准语料库,我们可以近似的计算出所有的分词之间的二元条件概率,比如任意两个词 w 1 , w 2 w_1,w_2 w1?,w2?,它们的条件概率分布可以近似的表示为: P ( w 2 ∣ w 1 ) = P ( w 1 , w 2 ) P ( w 1 ) ≈ f r e q ( w 1 , w 2 ) f r e q ( w 1 ) P(w_2|w_1) = \frac{P(w_1,w_2)}{P(w_1)} \approx \frac{freq(w_1,w_2)}{freq(w_1)} P(w2?∣w1?)=P(w1?)P(w1?,w2?)?≈freq(w1?)freq(w1?,w2?)? P ( w 1 ∣ w 2 ) = P ( w 2 , w 1 ) P ( w 2 ) ≈ f r e q ( w 1 , w 2 ) f r e q ( w 2 ) P(w_1|w_2) = \frac{P(w_2,w_1)}{P(w_2)} \approx \frac{freq(w_1,w_2)}{freq(w_2)} P(w1?∣w2?)=P(w2?)P(w2?,w1?)?≈freq(w2?)freq(w1?,w2?)? ??其中 f r e q ( w 1 , w 2 ) freq(w_1,w_2) freq(w1?,w2?)表示 w 1 , w 2 w_1,w_2 w1?,w2?在语料库中相邻一起出现的次数,而其中 f r e q ( w 1 ) , f r e q ( w 2 ) freq(w_1),freq(w_2) freq(w1?),freq(w2?)分别表示 w 1 , w 2 w_1,w_2 w1?,w2?在语料库中出现的统计次数。 ??利用语料库建立的统计概率,对于一个新的句子,我们就可以通过计算各种分词方法对应的联合分布概率,找到最大概率对应的分词方法,即为最优分词。 1.2 N元模型??当然,你会说,只依赖于前一个词太武断了,我们能不能依赖于前两个词呢?即: P ( A i 1 , A i 2 , . . . , A i n i ) = P ( A i 1 ) P ( A i 2 ∣ A i 1 ) P ( A i 3 ∣ A i 1 , A i 2 ) . . . P ( A i n i ∣ A i ( n i ? 2 ) , A i ( n i ? 1 ) ) P(A_{i1},A_{i2},...,A_{in_i}) = P(A_{i1})P(A_{i2}|A_{i1})P(A_{i3}|A_{i1},A_{i2})...P(A_{in_i}|A_{i(n_i-2)},A_{i(n_i-1)}) P(Ai1?,Ai2?,...,Aini??)=P(Ai1?)P(Ai2?∣Ai1?)P(Ai3?∣Ai1?,Ai2?)...P(Aini??∣Ai(ni??2)?,Ai(ni??1)?) ??这样也是可以的,我们一般称只依赖于前一个词的模型为二元模型(Bi-Gram model),而依赖于前两个词的模型为三元模型。以此类推,一直到通用的 N N N元模型。 ??在实际应用中, N N N一般都较小,一般都小于4,主要原因是N元模型概率分布的空间复杂度为 O ( ∣ V ∣ N ) O(|V|^N) O(∣V∣N),其中 ∣ V ∣ |V| ∣V∣为语料库大小,而 N N N为模型的元数,当 N N N增大时,复杂度呈指数级的增长。(二元模型前后两个词都有V种选择)常用汉字三四千,但是常用词是20w,二元模型就是400亿可能。 ?? N N N元模型的分词方法虽然很好,但是要在实际中应用也有很多问题:
1.3 维特比算法与分词??为了简化原理描述,我们本节的讨论都是以二元模型为基础。 ??对于一个有很多分词可能的长句子,我们当然可以用暴力方法去计算出所有的分词可能的概率,再找出最优分词方法。但是用维特比算法可以大大简化求出最优分词的时间。具体介绍参考《文本挖掘》。 1. 4常用分词工具??简单的英文分词不需要任何工具,通过空格和标点符号就可以分词了,而进一步的英文分词推荐使用nltk。对于中文分词,则推荐用结巴分词(jieba)。 ??分词是文本挖掘的预处理的重要的一步,分词完成后,我们可以继续做一些其他的特征工程,比如向量化(vectorize),TF-IDF以及Hash trick。 2.文本挖掘预处理之向量化与Hash Trick??分词后,如果我们是做文本分类聚类,则后面关键的特征预处理步骤有向量化或向量化的特例Hash Trick。 2.1 词袋模型??词袋模型(Bag of Words,简称BoW)。词袋模型假设我们不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重。而权重与词在文本中出现的频率有关。 ??词袋模型首先会进行分词,在分词之后,通过统计每个词在文本中出现的次数,我们就可以得到该文本基于词的特征,如果将各个文本样本的这些词与对应的词频放在一起,就是我们常说的向量化。向量化完毕后一般也会使用TF-IDF进行特征的权重修正,再将特征进行标准化。 再进行一些其他的特征工程后,就可以将数据带入机器学习算法进行分类聚类了。 ??总结下词袋模型的三部曲:分词(tokenizing),TF-IDF修订词特征值(counting)与标准化(normalizing)。 2.2 词袋模型之向量化??在词袋模型的统计词频这一步,我们会得到该文本中所有词的词频,有了词频,我们就可以用词向量表示这个文本。例如直接用scikit-learn的CountVectorizer类来完成文本的词频统计与向量化,代码如下: ??完整代码参见我的github:https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/hash_trick.ipynb
我们看看对于上面4个文本的处理输出如下:
??可以看出4个文本的词频已经统计出,在输出中,左边的括号中的第一个数字是文本的序号,第2个数字是词的序号,注意词的序号是基于所有的文档的。第三个数字就是我们的词频。 ??我们可以进一步看看每个文本的词向量特征和各个特征代表的词,代码如下:
输出如下:
??可以看到我们一共有19个词,所以4个文本都是19维的特征向量。而每一维的向量依次对应了下面的19个词。另外由于词"I"在英文中是停用词,不参加词频的统计。 ??由于大部分的文本都只会使用词汇表中的很少一部分的词,因此我们的词向量中会有大量的0。也就是说词向量是稀疏的。在实际应用中一般使用稀疏矩阵来存储。 ??将文本做了词频统计后,我们一般会通过TF-IDF进行词特征值修订,这部分我们后面再讲。 ??向量化的方法很好用,也很直接,但是在有些场景下很难使用,比如分词后的词汇表非常大,达到100万+,此时如果我们直接使用向量化的方法,将对应的样本对应特征矩阵载入内存,有可能将内存撑爆,在这种情况下我们怎么办呢?第一反应是我们要进行特征的降维,说的没错!而Hash Trick就是非常常用的文本特征降维方法。 2.3 Hash Trick??在大规模的文本处理中,由于特征的维度对应分词词汇表的大小,所以维度可能非常恐怖,此时需要进行降维,不能直接用我们上一节的向量化方法。而最常用的文本降维方法是Hash Trick。 ??其中
J
\mathcal{J}
J是原始特征的维度。 ??此时我们有 ? ˉ ( j ) = ∑ i ∈ J ; h ( i ) = j ξ ( i ) ? ( i ) \bar{\phi}(j) = \sum_{i\in \mathcal{J}; h(i) = j}\xi(i)\phi(i) ?ˉ?(j)=i∈J;h(i)=j∑?ξ(i)?(i) ??这样做的好处是,哈希后的特征仍然是一个无偏的估计,不会导致某些哈希位置的值过大。
??大家可以看到结果里面有负数,这是因为我们的哈希函数 ξ \xi ξ可以哈希到1或者-1导致的。 ??和PCA类似,Hash Trick降维后的特征我们已经不知道它代表的特征名字和意义。此时我们不能像上一节向量化时候可以知道每一列的意义,所以Hash Trick的解释性不强。 2.4 向量化与Hash Trick小结??一般来说,只要词汇表的特征不至于太大,大到内存不够用,肯定是使用一般意义的向量化比较好。因为向量化的方法解释性很强,我们知道每一维特征对应哪一个词,进而我们还可以使用TF-IDF对各个词特征的权重修改,进一步完善特征的表示。 ??而Hash Trick用大规模机器学习上,此时我们的词汇量极大,使用向量化方法内存不够用,而使用Hash Trick降维速度很快,降维后的特征仍然可以帮我们完成后续的分类和聚类工作。当然由于分布式计算框架的存在,其实一般我们不会出现内存不够的情况。因此,实际工作中我使用的都是特征向量化。 3. 文本挖掘预处理之TF-IDF3.1 TF-IDF概述??TF-IDF是Term Frequency - Inverse Document Frequency的缩写,即“词频-逆文本频率”。它由两部分组成,TF和IDF。 ??IDF反应了一个词在所有文本中出现的频率(也可以理解为词的信息量),如果一个词在很多的文本中出现,那么它的IDF值应该低,比如上文中的“to”。而反过来如果一个词在比较少的文本中出现,那么它的IDF值应该高。比如一些专业的名词如“Machine Learning”。这样的词IDF值应该高。一个极端的情况,如果一个词在所有的文本中都出现,那么它的IDF值应该为0。 ??一个词 x x x的IDF的基本公式如下: I D F ( x ) = l o g N N ( x ) IDF(x) = log\frac{N}{N(x)} IDF(x)=logN(x)N? ??其中, N N N代表语料库中文本的总数,而 N ( x ) N(x) N(x)代表语料库中包含词 x x x的文本总数。为什么IDF的基本公式应该是是上面这样的而不是像 N / N ( x ) N/N(x) N/N(x)这样的形式呢?这就涉及到信息论相关的一些知识了。感兴趣的朋友建议阅读吴军博士的《数学之美》第11章。 ??某一个生僻词在语料库中没有,这样我们的分母为0, IDF没有意义了。所以常用的IDF我们需要做一些平滑,使语料库中没有出现的词也可以得到一个合适的IDF值。平滑的方法有很多种,最常见的IDF平滑后的公式之一为: I D F ( x ) = l o g N + 1 N ( x ) + 1 + 1 IDF(x) = log\frac{N+1}{N(x)+1} + 1 IDF(x)=logN(x)+1N+1?+1 ??有了IDF的定义,我们就可以计算某一个词的TF-IDF值了: T F ? I D F ( x ) = T F ( x ) ? I D F ( x ) TF-IDF(x) = TF(x) * IDF(x) TF?IDF(x)=TF(x)?IDF(x) ??这个值可以表示一个词在文档中的权重。其中
T
F
(
x
)
TF(x)
TF(x)指词
x
x
x在 当前文本中的词频。IDF是一个全量信息,综合全局文档得出每个词的IDF值。 3.2 用scikit-learn进行TF-IDF预处理在scikit-learn中,有两种方法进行TF-IDF的预处理,完整代码参见github。
首先我们来看第一种方法,CountVectorizer+TfidfTransformer的组合,代码如下:
在输出中,左边的括号中的第一个数字是文本的序号,第2个数字是词的序号,注意词的序号是基于所有的文档的。第三个数字就是TF-IDF值。
3.4 TF-IDF小结??TF-IDF是非常常用的文本挖掘预处理基本步骤,但是如果预处理中使用了Hash Trick,则一般就无法使用TF-IDF了,因为Hash Trick后我们已经无法得到哈希后的各特征的IDF的值。使用了IF-IDF并标准化以后,我们就可以使用各个文本的词特征向量作为文本的特征,进行分类或者聚类分析。 ??当然TF-IDF不光可以用于文本挖掘,在信息检索等很多领域都有使用。因此值得好好的理解这个方法的思想。 三、代码解析下面分类代码的本质,都是讲文本text经过TF/TF-IDF处理之后,转换成为文章向量(文章向量维度表示词向量的长度),之后将文章向量经过各种分类器,进行分类。本质上和fasttext、textcnn没有区别。(向量和label进行训练拟合,进行分类) max_features表示每篇文章的词向量维度,即一篇文章设置为多少维向量来表示 3.1 TF + RidgeClassifiermax_features可以设置每篇文章的词向量维度,todense方法可以将稀疏矩阵转换为密集矩阵。
3.1.2 max_features举例在大规模语料上训练TFIDF会得到非常多的词语,如果再使用了ngram_range,那么我们词表的大小就会爆炸。出于时间和空间效率的考虑,可以限制最多使用多少个词语,模型会优先选取词频高的词语留下。
如果设置vectorizer = CountVectorizer(max_features=1000),则结果如下:
3.1.3 todense方法用todense方法可以将稀疏矩阵转换为密集矩阵:
其实就是1-1000篇文章的列向量(二维列表,第一个维度是文章,第二个维度是文章的词)转换1000*3000的矩阵。 或者看这个例子:
使用岭回归RidgeClassifier分类器训练模型
没有使用todense方法,整个训练时间是1分钟,准确率0.742。
使用todense方法训练时间12秒,大大缩短,但是准确率0.741,稍有下降。 3.1.4 F1_score(sklearn)
参考:sklearn中 F1-micro 与 F1-macro区别和计算原理、F1_score(sklearn) 3.2 TF-IDF + RidgeClassifier
可以看到跟3.1TF相比,词频转换成了TF-IDF值
TfidfVectorizer参数:
TF-IDF的计算时间比TF长很多。 3.3 TF-IDF+朴素贝叶斯
3.4 TF-IDF+决策树
3.5 TF-IDF+随机森林
3.6 TF-IDF+XGBoost
3.7 TF-IDF+LightGBM
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 8:22:55- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |