【问题标题】:Text classification - how to approach文本分类 - 如何处理
【发布时间】:2016-03-24 13:07:52
【问题描述】:

我会尽量描述我的想法。

有一个文本内容存储在 MS SQL 数据库中。内容每天都以流的形式出现。有些人每天都会浏览内容,如果内容符合某些标准,则将其标记为已验证。只有一类。它要么“有效”,要么无效。

我想要的是基于已经验证的内容创建一个模型,保存它并使用这个模型来“预验证”或标记新的传入内容。也偶尔根据新验证的内容更新模型。希望我能清楚地解释自己。

我正在考虑根据创建的模型使用 Spark 流进行数据分类。和朴素贝叶斯算法。但是您将如何创建、更新和存储模型?有大约 200K+ 不同长度的经过验证的结果(文本)。我需要这么多的模型吗? 以及如何在 Spark Streaming 中使用这个模型。

提前致谢。

【问题讨论】:

    标签: apache-spark machine-learning apache-spark-mllib apache-spark-ml


    【解决方案1】:

    哇,这个问题非常广泛,与Machine Learning 的相关性比Apache Spark 的相关性更高,但是我会尝试给你一些提示或步骤来遵循(我不会为你做这项工作)。

    1. 导入所有你需要的库

      from pyspark.mllib.classification import LogisticRegressionWithSGD, LogisticRegressionModel
      from pyspark.mllib.linalg import SparseVector
      from pyspark.mllib.regression import LabeledPoint
      import re
      
    2. 将您的数据加载到RDD

      msgs = [("I love Star Wars but I can't watch it today", 1.0),
              ("I don't love Star Wars and people want to watch it today", 0.0),
              ("I dislike not being able to watch Star Wars", 1.0),
              ("People who love Star Wars are my friends", 1.0),
              ("I preffer to watch Star Wars on Netflix", 0.0),
              ("George Lucas shouldn't have sold the franchise", 1.0),
              ("Disney makes better movies than everyone else", 0.0)]
      
      rdd = sc.parallelize(msgs)
      
    3. 标记您的数据(如果您使用ML 可能会更容易)和

      rdd = rdd.map(lambda (text, label): ([w.lower() for w in re.split(" +", text)], label))
      
    4. 删除所有不必要的词(广泛称为停用词)和符号,例如,.&

      commons = ["and", "but", "to"]
      rdd = rdd.map(lambda (tokens, label): (filter(lambda token: token not in commons, tokens), label))
      
    5. 所有数据集中创建一个包含所有distinct 单词的字典,这听起来很庞大,但它们并没有您期望的那么多,我敢打赌它们会适合您的主节点(但是还有其他方法可以解决这个问题,但为简单起见,我将保持这种方式)。

      # finds different words
      words = rdd.flatMap(lambda (tokens, label): tokens).distinct().collect()
      diffwords = len(words)
      
    6. 将您的features 转换为DenseVectorSparseVector,我显然会推荐第二种方式,因为通常SparseVector 需要更少的空间来表示,但这取决于数据。请注意,有更好的选择,例如 hashing,但我试图保持对我冗长的方法的忠诚。之后将tuple 转换为LabeledPoint

      def sparsify(length, tokens):
          indices = [words.index(t) for t in set(tokens)]
          quantities = [tokens.count(words[i]) for i in indices]
      
          return SparseVector(length, [(indices[i], quantities[i]) for i in xrange(len(indices))])
      
      rdd = rdd.map(lambda (tokens, label): LabeledPoint(label, sparsify(diffwords, tokens)))
      
    7. 适合你最喜欢的模型,在这种情况下我使用了LogisticRegressionWithSGD,因为别有用心。

      lrm = LogisticRegressionWithSGD.train(rdd)
      
    8. Save你的模特。

      lrm.save(sc, "mylovelymodel.model")
      
    9. Load 你的LogisticRegressionModel 在另一个应用程序中。

      lrm = LogisticRegressionModel.load(sc, "mylovelymodel.model")
      
    10. Predict 类别。

      lrm.predict(SparseVector(37,[2,4,5,13,15,19,23,26,27,29],[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]))
      # outputs 0
      

    请注意,我没有评估模型的accuracy,但它看起来不是吗?

    【讨论】:

    • 感谢 Alberto 提供如此详细的回答。正好赶上星球大战的发布:)。一个问题。我总是需要 2 个数据集吗?在我的情况下,一个由数据验证器验证,一个被忽略?我不能只使用一个数据集吗?就像我只是用星球大战的句子。
    • 您只需要一个 training 数据集来训练模型,但如果您想评估模型(准确性和过拟合),您需要 2 个数据集(均已标记)一个来训练您的模型和其他评估它,第二个称为validation数据。拟合模型后,您可以预测label 之后的任何其他文本sparsify,但我推荐您使用Machine Learning by Stanford 的课程,如果您像我一样买不起证书,请不要担心,您可以审核它并学习,因为它对所有人开放。
    • 嗨,阿尔贝托。我建立了模型,现在我有另一个问题。在另一个程序中加载模型后,如何将模型应用于传入数据?假设一条文本出现在“我今天看了《星球大战》,很棒”。如何应用模型?我想我需要对其进行标记并创建向量。但是我如何标记它?我能找到的所有示例都在标记集上进行测试。提前致谢。
    • 别忘了你是在尝试classify新数据基于旧的labeled数据,因此你试图predict基于几个features,在文本分类中的特征可以是文中使用的词。因此,如果您尝试对数据进行分类,很明显它们不会被标记,模型将预测标签,这就是 supervised learning 的工作原理。我建议您审核本课程Scalable Machine Learning
    • 我想我需要将传入的数据转换为向量并将其传递给模型的预测方法。如果我使用 TF-IDF 方法来准备模型,我需要以同样的方式准备向量。对吗?
    猜你喜欢
    • 2021-08-03
    • 2011-08-03
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2019-05-24
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多