我有一段基于免费文本描述的分类需求。例如,描述可能是关于某事件的。根据事件的描述,我需要预测与该事件相关的风险。例如:“镇上发生了一起谋杀案”——这种描述属于“高”风险的候选。
我尝试过使用逻辑回归,但发现目前仅支持二分类。对于基于免费文本描述的多类分类(只有三个可能的值),最合适的算法是什么?(线性回归还是朴素贝叶斯)
回答:
这是我解决上述问题的方法。
虽然预测准确率还不错,但模型仍需进一步调整以获得更好的结果。
专家们,如果发现有什么不对的地方,请回复我。
我的输入数据框架有两个列:“文本”和“风险分类”
以下是在Java中使用朴素贝叶斯进行预测的步骤序列
- 在输入数据框架中添加一个新的列“标签”。该列将基本解码风险分类,如下所示
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")));
- 创建训练数据集(80%)和测试数据集(20%)
例如:
DataFrame lowRisk = samplingData.filter(samplingData.col("label").equalTo(1));DataFrame lowRiskTraining = lowRisk.sample(false, 0.8);
-
联合所有数据框架以构建完整的训练数据
-
构建测试数据稍微有些 tricky。测试数据应包含训练数据中不存在的所有数据
-
开始转换训练数据并构建模型
6 . 对训练数据集中的文本列进行分词
Tokenizer tokenizer = new Tokenizer().setInputCol("text").setOutputCol("words");DataFrame tokenized = tokenizer.transform(trainingRiskData);
- 移除停用词。(在这里您还可以使用斯坦福NLP库执行更高级的操作,如词形还原、词干提取、词性标注等)
StopWordsRemover remover = new StopWordsRemover().setInputCol("words").setOutputCol("filtered");DataFrame stopWordsRemoved = remover.transform(tokenized);
- 使用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);
- 将特征化的输入转换为JavaRDD。朴素贝叶斯在LabeledPoint上运行
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; } });
- 构建模型
NaiveBayes naiveBayes = new NaiveBayes(1.0, "multinomial");NaiveBayesModel naiveBayesModel = naiveBayes.train(labelledJavaRDD.rdd(), 1.0);
-
对测试数据也运行上述所有转换
-
遍历测试数据框架并执行以下操作
-
使用测试数据框架中的“标签”和“特征”创建一个LabeledPoint
例如:如果测试数据框架的第三列和第七列分别是标签和特征,那么
LabeledPoint labeledPoint = new LabeledPoint(new Double(dataFrameRow.get(3).toString()),(org.apache.spark.mllib.linalg.Vector) dataFrameRow.get(7));
- 使用预测模型预测标签
double predictedLabel = naiveBayesModel.predict(labeledPoint.features());
-
将预测的标签也作为一列添加到测试数据框架中。
-
现在测试数据框架中包含了预期标签和预测标签。
-
您可以将测试数据导出为csv进行分析,或者也可以编程计算准确率。