文本的向量化和分类器的训练

本项目仓库

在上周,我们爬取了 CSDN 和 Wikipedia 上的部分数据。那么在这周,我们将对数据进行处理,并用于训练我们的分类器。本文将介绍如何进一步对爬下来存储为 .jsonl 文件的数据进行处理,以及后续的随机森林算法来训练我们的分类器。

文本的向量化

在自然语言处理等领域,一个最基本的问题就是,如何让计算机“认识”对我们而言十分日常十分熟悉的语言。虽然我们能够很自如的运用,但计算机可是看不懂一点。在我们的数据中的体现就是问题和回答等,这些直接给计算机的话,显然是不行的。因此,要将语言喂给计算机,我们肯定是要对其进行一些处理。

这个视频 对从 one-hot 到 word2vec 都有介绍,并且给出了许多可以探索的学习资料。这些部分在此就不再赘述。在视频中是用的 python 的 gensim 库,这自然不失为一种选择。

而另一种 word2vec 的选择是 TfidfVectorizer这篇文章对其进行了简单的介绍,从用 jieba 分词到一些参数的含义都已经说明了,这里也就不展开讲述。

当然,可供选择的模型还有很多,但作者并没有一一尝试了。但总之,通过 word2vec,我们将数据中的若干个句子转化为了计算机可以运算的向量,来进行接下来的训练。

分类器的训练

让我们回顾一下,我们最终的任务究竟是要做什么?

实际上,到这一步,我才理清我们的任务的关系。对于我们爬下来的问答对,自然是有好的问题和回答,也有不好的问题和回答。而我们最终其实是要实现一个分类器,能够用于判断一对问答是“好的”还是“坏的”。这其实就归类到了机器学习中的分类算法了。这个视频的 p1 到 p4 可以让我们初步了解一点机器学习。而具体训练时,我们需要先喂给模型一些训练集,给它一些问答对,告诉它“这些是好的”,“这些是坏的”。之后它将通过算法学习分类,并对我们给出的测试集进行预测。当然,我们自己手中也是有测试集的实际“答案”的,因此可以对模型的预测进行评价打分。自然,我们是希望它的得分越高越好。

而模型究竟是如何进行学习和分类的呢?这就是各种算法大展神通的时候了。本次我们采用的是随机森林算法。它的前置知识决策树在这个视频中有介绍,而随机森林算法在这个视频中同样也已经介绍了,这里就不再展开讲。

而具体到代码实现上面,sklearn已经给我们造好了轮子。我们只需使用其中的 RandomForestClassifier 类便能实现随机森林算法。它的 fit() 函数能够接受我们的数据集 (X, y),在这里 X 代表我们的问答对,y 表示我们对问答对的标注(好坏)。而 predict() 函数则能接受问答对的数据,并给出预测。再通过 accuracy_score() 函数传入预测的结果和实际的好坏标注,便能给出模型的得分,为 0~1 之间的一个实数。

或许上文讲的还是非常抽象,可以参考我的代码

至此,我们的分类器训练就基本可以宣布结束了。

一些问题

多个特征的处理

细心的读者可能会发现,对于究竟是如何把向量化后的数据丢给RandomForestClassifier的这件事情,我讲的非常含糊。事实的确如此。让我们回顾一下分类算法,我们的数据应该是有若干个特征,落到我们的问答对中应该就至少是 QuestionAnswer(在实际操作时发现Knowledge_PointTag 对于效果并没有什么影响)。这也就意味着我们的数据集至少得有两个特征。但是我目前还没有找到在向量化后实现多个特征的方法。那么经过与同学间的交流,我发现同学们都是采用的讲 QuestionAnswer 拼成一个句子,然后当做一个向量来进行后续操作的。那么与多个特征相比究竟效果如何呢?这依旧有待进一步的探索。

代码的处理

在问题和回答中,都可能出现代码块。而代码和我们平时使用的语言又有所不同。比如同样效果的代码变量名称可能差别很大,也可能递归和循环看上去完全不同,但实际上是一样的效果。以上其实是我的猜测。但在我们的处理中,我们是直接无视了代码相对的特殊性,直接一股脑处理的。但一种可能更好的方案则是将其处理为一个特殊的 token,再进行训练。但很遗憾,对于给定的数据,如何将代码从文本中分离出来(即知道哪段是代码)就难倒了我们。因此到目前对于这个问题我们还没有应对的办法。

赞赏