TL;DR; 如何使用 mllib
训练我的维基数据(文本和类别)以预测推文?
我无法弄清楚如何转换我的标记化维基数据,以便可以通过 NaiveBayes
或 LogisticRegression
进行训练 . 我的目标是使用经过训练的模型与推文进行比较* . 我已经尝试使用带有LR的管道和带有 IDF
的 HashingTF
用于 NaiveBayes
,但我一直得到错误的预测 . 在这里_1184927已尝试:
*请注意,我想在我的标签中使用维基数据中的许多类别...我只看到二元分类(它是一个或另一个类别)....是否可以做我想要的?
管道w LR
import org.apache.spark.rdd.RDD
import org.apache.spark.SparkContext
import org.apache.spark.ml.feature.HashingTF
import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.ml.feature.RegexTokenizer
case class WikiData(category: String, text: String)
case class LabeledData(category: String, text: String, label: Double)
val wikiData = sc.parallelize(List(WikiData("Spark", "this is about spark"), WikiData("Hadoop","then there is hadoop")))
val categoryMap = wikiData.map(x=>x.category).distinct.zipWithIndex.mapValues(x=>x.toDouble/1000).collectAsMap
val labeledData = wikiData.map(x=>LabeledData(x.category, x.text, categoryMap.get(x.category).getOrElse(0.0))).toDF
val tokenizer = new RegexTokenizer()
.setInputCol("text")
.setOutputCol("words")
.setPattern("/W+")
val hashingTF = new HashingTF()
.setNumFeatures(1000)
.setInputCol(tokenizer.getOutputCol)
.setOutputCol("features")
val lr = new LogisticRegression()
.setMaxIter(10)
.setRegParam(0.01)
val pipeline = new Pipeline()
.setStages(Array(tokenizer, hashingTF, lr))
val model = pipeline.fit(labeledData)
model.transform(labeledData).show
朴素贝叶斯
val hashingTF = new HashingTF()
val tf: RDD[Vector] = hashingTF.transform(documentsAsWordSequenceAlready)
import org.apache.spark.mllib.feature.IDF
tf.cache()
val idf = new IDF().fit(tf)
val tfidf: RDD[Vector] = idf.transform(tf)
tf.cache()
val idf = new IDF(minDocFreq = 2).fit(tf)
val tfidf: RDD[Vector] = idf.transform(tf)
//to create tfidfLabeled (below) I ran a map set the labels...but again it seems to have to be 1.0 or 0.0?
NaiveBayes.train(tfidfLabeled)
.predict(hashingTF.transform(tweet))
.collect
1 回答
ML
LogisticRegression
尚不支持多项分类,但MLLibNaiveBayes
和LogisticRegressionWithLBFGS
都支持它 . 在第一种情况下,它应该默认工作:但是对于逻辑回归,你应该提供一些类:
关于预处理步骤,这是一个相当广泛的主题,如果没有访问您的数据,很难给您一个有意义的建议,所以您在下面找到的所有内容只是一个疯狂的猜测:
据我所知,您使用维基数据进行培训和推文进行测试 . 如果这是真的,一般来说这是一个坏主意 . 您可以预期两组使用显着不同的词汇,语法和拼写
简单的正则表达式标记符可以在标准化文本上很好地执行,但根据我的经验,它不会像推文那样在非正式文本上运行良好
HashingTF
可以是获得基线模型的好方法,但它是极其简化的方法,特别是如果您不应用任何过滤步骤 . 如果您决定使用它,至少应增加功能数量或使用默认值(2 ^ 20)EDIT (用IDF为朴素贝叶斯准备数据)
注意:由于变换器需要JVM访问,因此MLlib版本在PySpark中不起作用 . 如果你更喜欢Python,你必须split data transform and zip .
EDIT (为ML算法准备数据):
虽然下面的代码看起来有点乍一看
它不会为
ML
算法生成有效标签 .首先
ML
期望标签在(0.0,1.0,...,n.0)中,其中n是类的数量 . 如果你的示例管道中有一个类得到标签0.001,你将得到如下错误:显而易见的解决方案是在生成映射时避免除法
虽然它适用于
LogisticRegression
其他ML
算法仍然会失败 . 例如RandomForestClassifier
你会得到有趣的是,
RandomForestClassifier
的ML版本与MLlib
版本不同,它没有提供设置多个类的方法 . 事实证明,它希望在DataFrame
列上设置特殊属性 . 最简单的方法是使用错误消息中提到的StringIndexer
: