用于聚类(和分类)短句的 NLP bag-of-words/TF-IDF

Posted

技术标签:

【中文标题】用于聚类(和分类)短句的 NLP bag-of-words/TF-IDF【英文标题】:NLP bag-of-words/TF-IDF for clustering (and classifying) short sentences 【发布时间】:2017-07-03 20:36:03 【问题描述】:

我想通过其中一个字符串键值 (description) 对 javascript 对象进行聚类。我已经尝试了多种解决方案,希望获得一些有关如何解决问题的指导。

我想要什么: 假设我有一个对象数据库。它们可能有很多(可能有数千个,也可能有数万个)。我需要能够:

    按逻辑(有点)组中的相似性对对象进行聚类。语义匹配会很棒,但现在只需要字符串相似性就足够了。将它们聚类后,我需要为它们中的每一个分配一些 categoryId(代表它们所属的集群)。 每当将新对象添加到数据库时,我都需要将它们分类到现有组/提出新集群。

我还没有尝试解决问题 #2,但这是我尝试解决的问题 #1。

具有 Levenshtein 距离(单链接)的层次聚类 - 这里的问题是性能,结果令人满意(我使用了来自 npmhierarchical-clustering 库)但在 150 左右我将不得不等待大约一分钟。不会为数千人工作。

TF-IDF,矢量化 + k-means - 性能非常好。它将轻松通过 5000 个对象。但是结果肯定是错误的(可能是我的实现中的一个错误)。我使用(npm 中的natural 库来计算 TF-IDF 和 node-kmeans)。

Bag-of-Words + k-means - 我现在正在尝试实现这个,还没有任何运气。

对于#2,我想使用朴素贝叶斯(但我还没有尝试过)。

有什么建议吗?如果对象只是聚集在一起就好了。如果我能提取出集群所依据的标签(比如从 TF-IDF 中),那就更好了。

【问题讨论】:

一年九个月,没有答案。我很好奇你是否解决了这个问题?因为我有类似的问题。谢谢,N 您能否添加一些带有键值对的这些 java 对象的示例?这听起来很可行,但举个例子就好了。 【参考方案1】:

使用 tensorflow,可以创建一个深度学习模型,该模型一旦经过训练就可以用于预测输入单词的类别。

假设这是数据集:

let data = [description: 'just something', label: '1', description: 'something else', label: '2']

在文本分类中首先要做的就是将文本编码为张量。可以使用许多算法,前提是它们在给定感兴趣的领域时能带来良好的准确性。特别是,universal-sentence encoder 会将每个句子转换为大小为 512 的一维张量。

const useModel = await use.load()
let features = data.map(d => useModel.embed(d.description))
features = tf.stack(features) // create a 2d tensor from the array of 1d tensor
let labels = tf.oneHot([0, 1], 2) // encode it as oneHot
// more details on labels encoding in this answer 
// https://***.com/questions/59127861/how-may-i-define-my-own-labels-in-tensorflow-js/59128300#59128300

第二件事是为分类创建一个模型。虽然可以使用 FCNN,但对于 NLP 处理,主要使用 LSTM 或双向 LSTM,因为在将输出转发到其他层时,单元格会考虑数据的上下文。这是此类模型的示例

const model = tf.sequential(
    layers: [
        tf.layers.lstm( inputShape: [1, 512], units: 16, activation: "relu", returnSequences: true ),
        tf.layers.lstm( units: 16, activation: "relu", returnSequences: true ),
        tf.layers.lstm( units: 16, activation: "relu", returnSequences: false ),
        tf.layers.dense( units: numberOfCategories, activation: "softmax" ),
    ]
) // in this example of the numberOfCategories is 2

[n, 512] 的 inputShape 用于指示模型将一次输入n 句子。如果句子数量可变,则 inputShape 将为[null, 512]

模型将被训练

model.compile(
    optimizer: "adam",
    loss: "categoricalCrossentropy",
    metrics: ["accuracy"]
)
model.fit(features, labels, 
    epochs: number,// as needed to have a good accuracy
    callbacks: 
        onBatchEnd(batch, logs) 
            console.log(logs.acc)
        
    
)

模型训练完成后,对于每个传入的单词,都会有一个预测。但传入的单词需要首先转换为上述张量 a。

let prediction = model.predict( await useModel.embed('newWord').reshape([1, 1, -1])).argMax([-1])
prediction.print() // will print the index of the label

如果训练数据还没有被标记(意味着对象没有标签属性),数据应该被聚类。 tensorflow.js 中还没有聚类算法。 对于文本聚类,我们首先需要创建标记。 use 包有分词器;还有包natural。标记化后,node-kmeans 可用于标记数据集。从这一步开始,可以使用第一种方法。

另一种方法可能是使用标记化的句子来训练模型。但是由于所有句子的形状都不相同,因此需要使用tf.pad添加填充

【讨论】:

以上是关于用于聚类(和分类)短句的 NLP bag-of-words/TF-IDF的主要内容,如果未能解决你的问题,请参考以下文章

用于词聚类/NLP 的 PHP 库?

为 NLP 聚类/主题建模寻找一个好的数据集

学界 | 从文本挖掘综述分类聚类和信息提取等算法

NLP工具

用于预测发电量的聚类、分类和回归管道

如何将拥抱脸模型用于 NLP音频分类和计算机视觉