您似乎正在尝试回答几个相关的问题:
- 如何衡量文档 A 和 B 之间的相似度? (度量学习)
- 与某些文档集合相比,如何衡量文档 C 的异常程度? (异常检测)
- 如何将一组文档分成相似的组? (聚类)
- 如何预测文档属于哪个类? (分类)
所有这些问题通常分两步解决:
- 提取特征:文档 --> 表示(通常是数字向量)
- 应用模型:表示 --> 结果(通常是单个数字)
特征工程和建模都有很多选择。这里只是一些。
特征提取
- 词袋:文档 --> 每个词的出现次数(即词频)。这是基本选项,但不是唯一选项。
- n-gram 包(在单词级别或字符级别):考虑了多个标记的共现。
- 词袋 + 语法特征(例如 POS 标签)
- 词嵌入包(通过外部模型学习,例如 word2vec)。您可以将嵌入用作序列或取它们的加权平均值。
- 您可以发明的任何东西(例如基于字典查找的规则)...
特征可能会被预处理,以减少其中的相对噪声量。一些预处理选项是:
- 按 IDF 划分,如果您没有硬性停用词列表或认为这些词可能或多或少是“停用词”
- 将每列(例如字数)归一化,使其均值和单位方差为零
- 记录字数以减少噪音
- 标准化每一行以使 L2 范数等于 1
您无法提前知道哪个选项最适合您的特定应用 - 您必须进行实验。
现在您可以构建 ML 模型。 4 个问题中的每一个都有自己好的解决方案。
对于分类这个研究得最好的问题,您可以使用多种模型,包括朴素贝叶斯、k-最近邻、逻辑回归、SVM、决策树和神经网络。同样,您无法提前知道哪个性能最好。
这些模型中的大多数都可以使用几乎任何类型的功能。但是,KNN 和基于内核的 SVM 要求您的特征具有特殊的结构:在欧几里德距离度量的意义上,一类文档的表示应该彼此接近。这有时可以通过简单的线性和/或对数归一化来实现(见上文)。更困难的情况需要非线性变换,原则上可以通过神经网络学习。学习这些变换就是人们称之为度量学习的东西,一般来说这是一个尚未解决的问题。
最传统的距离度量确实是欧几里得。然而,其他距离度量(例如曼哈顿距离)或不同的方法也是可能的,而不是基于文本的向量表示。例如,您可以尝试根据将一个文本转换为另一个文本所需的操作数来计算文本之间的 Levenstein 距离。或者您可以计算“word mover distance” - 具有最接近嵌入的词对的距离总和。
对于聚类,基本选项是 K-means 和 DBScan。这两种模型都要求您的特征空间具有此欧几里得属性。
对于异常检测,您可以使用由各种概率算法产生的密度估计:分类(例如朴素贝叶斯或神经网络)、聚类(例如混合高斯模型)或其他无监督方法(例如概率 PCA)。对于文本,您可以利用顺序语言结构,以前面的单词为条件估计每个单词的概率(使用 n-gram 或卷积/递归神经网络) - 这称为 语言模型,它是通常比忽略词序的朴素贝叶斯的词袋假设更有效。多个语言模型(每个类别一个)可以组合成一个分类器。
无论您解决什么问题,强烈建议使用已知“ground truth”的良好测试集:哪些文档彼此接近,或者属于同一类,或者是(异常。使用此套件,您可以评估特征工程和建模的不同方法,并选择最佳方法。
如果您没有资源或不愿意进行多次实验,我建议您选择以下方法之一来评估文本之间的相似性:
- 字数+idf归一化+L2归一化(相当于@mcoav的解)+欧几里得距离
- 平均 word2vec 嵌入文本中的所有单词(嵌入字典可以用谷歌搜索和下载)+ 欧几里得距离
基于这些表示之一,您可以为其他问题构建模型 - 例如。用于分类的 KNN 或用于聚类的 k-means。