使用 Spark ML 进行文本分类

Text Classification using Spark ML

我有一个自由文本描述,我需要根据它执行 class化。例如,描述可以是事件的描述。根据事件的描述,我需要预测与事件相关的风险。例如:"A murder in town" - 此描述是 "high" 风险的候选者。

我尝试了逻辑回归,但意识到目前仅支持二进制 class化。对于基于自由文本描述的Multi class classification(只有三个可能的值),最合适的算法是什么? (线性回归或朴素贝叶斯)

这就是我解决上述问题的方法。

虽然预测精度还不错,但模型还需要进一步调整 以获得更好的结果。

专家,如有发现不妥请回复

我的输入数据框有两列 "Text" 和 "RiskClassification"

以下是在 Java

中使用朴素贝叶斯进行预测的步骤序列
  1. 向输入数据框添加新列 "label"。本专栏将基本上解码如下风险分类
sqlContext.udf().register("myUDF", new UDF1<String, Integer>() {
            @Override
            public Integer call(String input) throws Exception {
                if ("LOW".equals(input))
                    return 1;
                if ("MEDIUM".equals(input))
                    return 2;
                if ("HIGH".equals(input))
                    return 3;
                return 0;
            }
        }, DataTypes.IntegerType);

samplingData = samplingData.withColumn("label", functions.callUDF("myUDF", samplingData.col("riskClassification")));
  1. 创建训练 ( 80 % ) 和测试数据集 ( 20 % )

例如:

DataFrame lowRisk = samplingData.filter(samplingData.col("label").equalTo(1));
DataFrame lowRiskTraining = lowRisk.sample(false, 0.8);
  1. 联合所有数据帧构建完整的训练数据

  2. 构建测试数据有点棘手。测试数据应包含所有数据 不存在于训练数据中

  3. 开始转换训练数据并构建模型

6。标记训练数据集中的文本列

Tokenizer tokenizer = new Tokenizer().setInputCol("text").setOutputCol("words");
DataFrame tokenized = tokenizer.transform(trainingRiskData);
  1. 删除停用词。 (在这里您还可以使用 Stanford NLP 库执行 lemme、stemmer、POS 等高级操作)
StopWordsRemover remover = new StopWordsRemover().setInputCol("words").setOutputCol("filtered");
DataFrame stopWordsRemoved = remover.transform(tokenized);
  1. 使用 HashingTF 计算词频。 CountVectorizer 是另一种方法
int numFeatures = 20;
HashingTF hashingTF = new HashingTF().setInputCol("filtered").setOutputCol("rawFeatures")
        .setNumFeatures(numFeatures);
DataFrame rawFeaturizedData = hashingTF.transform(stopWordsRemoved);

IDF idf = new IDF().setInputCol("rawFeatures").setOutputCol("features");
IDFModel idfModel = idf.fit(rawFeaturizedData);

DataFrame featurizedData = idfModel.transform(rawFeaturizedData);
  1. 将特征化输入转换为 JavaRDD。朴素贝叶斯在 LabeledPoint
  2. 上工作
JavaRDD<LabeledPoint> labelledJavaRDD = featurizedData.select("label", "features").toJavaRDD()
    .map(new Function<Row, LabeledPoint>() {

        @Override
        public LabeledPoint call(Row arg0) throws Exception {
            LabeledPoint labeledPoint = new LabeledPoint(new Double(arg0.get(0).toString()),
                    (org.apache.spark.mllib.linalg.Vector) arg0.get(1));
            return labeledPoint;
        }
    });
  1. 构建模型
NaiveBayes naiveBayes = new NaiveBayes(1.0, "multinomial");
NaiveBayesModel naiveBayesModel = naiveBayes.train(labelledJavaRDD.rdd(), 1.0);
  1. 运行以上所有对测试数据的转换也

  2. 循环测试数据帧并执行以下操作

  3. 使用测试数据框中的"label"和"features"创建一个LabeledPoint

例如:如果测试数据框在第三和第七列有标签和特征,那么

LabeledPoint labeledPoint = new LabeledPoint(new Double(dataFrameRow.get(3).toString()),
(org.apache.spark.mllib.linalg.Vector) dataFrameRow.get(7));
  1. 使用预测模型预测标签
double predictedLabel = naiveBayesModel.predict(labeledPoint.features());
  1. 将预测标签也作为列添加到测试数据框中。

  2. 现在测试数据帧具有预期标签和预测标签。

  3. 您可以将测试数据导出到 csv 并进行分析,或者您也可以通过编程方式计算准确度。

由于您使用的是, I assume you have ,所以-我不是专家-但在阅读了您的回答后,我想提出几点意见。

Create the Training (80%) and Testing Data Sets (20%)

我会将我的数据划分为 Training (60-70%)、Testing (15-20%) 和 评价 (15-20%) 集..

这个想法是您可以微调您的分类算法 w.r.t。训练集,但我们真正想要处理的是分类任务,是让它们对看不见的数据进行分类。因此,使用测试集微调您的算法,完成后使用评估集,以真正了解事物的工作原理!

Stop words

如果您的数据是来自报纸等的文章,我个人没有发现使用更复杂的停用词删除方法有任何显着改善...

但这只是个人陈述,但如果我是你,我不会专注于这一步。

Term Frequency

如何使用Term Frequency-Inverse Document Frequency (TF-IDF) term weighting instead? You may want to read: How can I create a TF-IDF for Text Classification using Spark?

我会尝试两者并进行比较!

Multinomial

您有什么特别的理由要尝试多项式分布吗?如果否,因为当 n 为 1 且 k 为 2 时,多项式分布为伯努利分布,如 Wikipedia, which is supported.

中所述

尝试两者并比较(如果你想让你的模型更好,这是你必须习惯的事情!:))


我也看到 offers Random forests,至少值得一读! ;)


如果 你的数据不是那么大,我也会尝试支持向量机 (SVM),来自 scikit-learn, which however supports , so you should switch to or plain , abandoning . BTW, if you are actually going for sklearn, this might come in handy: How to split into train, test and evaluation sets in sklearn?,因为 Pandas 配合得很好用 sklearn.

希望对您有所帮助!


题外话:

这真的不是在 Stack Overflow 中提问的方式。阅读 How to ask a good question?

就个人而言,如果我是你,我会先做你在回答中所做的所有事情,然后 post 一个问题,总结我的方法。

关于赏金,您可能需要阅读:How does the Bounty System work?