algorithm - 用于聚类(和分类)短句的 NLP 词袋/TF-IDF

标签 algorithm nlp k-means hierarchical-clustering tensorflow.js

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

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

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

  • 我还没有尝试解决问题 #2,但这是我尝试解决问题 #1 的方法。
  • 具有 Levenshtein 距离的层次聚类(单链接) - 这里的问题是性能,结果令人满意(我使用了来自 hierarchical-clusteringnpm 库)但是在 150 左右我将不得不等待大约一分钟。不会为数千人工作。
  • TF-IDF,矢量化 + k-means - 表演很棒。它将轻松通过 5000 个对象。但结果肯定是关闭的(可能是我的实现中的一个错误)。我使用(来自 naturalnpm 库来计算 TF-IDF 和 node-kmeans)。
  • Bag-of-Words + k-means - 我现在正在尝试实现这个,还没有任何运气。

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

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

    最佳答案

    使用 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://stackoverflow.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]的输入形状用于指示模型将被输入 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 添加填充。

    关于algorithm - 用于聚类(和分类)短句的 NLP 词袋/TF-IDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42245050/

    相关文章:

    c++ - 点云数据的 K 均值聚类

    javascript - 对总分区权重有限制的分区加权元素

    design-patterns - 并行实现树遍历算法的策略?

    algorithm - 在 MATLAB 中快速查找互补向量的方法

    google-cloud-platform - 如何使用 Google NLP 在单个注释中提取多个标签文本项

    mysql - 电子邮件的可靠和准确的线程结构?

    java - “麻省理工学院 Java Wordnet 接口(interface) (JWI)”-edu.mit.jwi.data.IHasLifecycle$ObjectClosedException

    python - 为什么在 for 循环中将单词从复数转换为单数需要这么长时间 (Python 3)?

    python - PCA 分解的 k 均值簇的质心是多少?