首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Scala星火中使用数据帧的朴素贝叶斯多项式文本分类器

Scala星火中使用数据帧的朴素贝叶斯多项式文本分类器
EN

Stack Overflow用户
提问于 2016-01-18 13:33:31
回答 1查看 2.1K关注 0票数 3

我正在尝试构建一个NaiveBayes分类器,将数据库中的数据加载为包含(标签、文本)的DataFrame。以下是数据示例(多项标签):

代码语言:javascript
运行
复制
label|             feature|
+-----+--------------------+
|    1|combusting prepar...|
|    1|adhesives for ind...|
|    1|                    |
|    1| salt for preserving|
|    1|auxiliary fluids ...|

我对令牌化、秒针、n克和hashTF进行了如下转换:

代码语言:javascript
运行
复制
val selectedData = df.select("label", "feature")
// Tokenize RDD
val tokenizer = new Tokenizer().setInputCol("feature").setOutputCol("words")
val regexTokenizer = new   RegexTokenizer().setInputCol("feature").setOutputCol("words").setPattern("\\W")
val tokenized = tokenizer.transform(selectedData)
tokenized.select("words", "label").take(3).foreach(println)

// Removing stop words
val remover = new        StopWordsRemover().setInputCol("words").setOutputCol("filtered")
val parsedData = remover.transform(tokenized) 

// N-gram
val ngram = new NGram().setInputCol("filtered").setOutputCol("ngrams")
val ngramDataFrame = ngram.transform(parsedData) 
ngramDataFrame.take(3).map(_.getAs[Stream[String]]("ngrams").toList).foreach(println)

//hashing function
val hashingTF = new HashingTF().setInputCol("ngrams").setOutputCol("hash").setNumFeatures(1000)
val featurizedData = hashingTF.transform(ngramDataFrame)

转型的产出:

代码语言:javascript
运行
复制
+-----+--------------------+--------------------+--------------------+------    --------------+--------------------+
|label|             feature|               words|            filtered|                  ngrams|                hash|
+-----+--------------------+--------------------+--------------------+------    --------------+--------------------+
|    1|combusting prepar...|[combusting, prep...|[combusting, prep...|    [combusting prepa...|(1000,[124,161,69...|
|    1|adhesives for ind...|[adhesives, for, ...|[adhesives, indus...| [adhesives indust...|(1000,[451,604],[...|
|    1|                    |                  []|                  []|                     []|        (1000,[],[])|
|    1| salt for preserving|[salt, for, prese...|  [salt, preserving]|   [salt   preserving]|  (1000,[675],[1.0])|
|    1|auxiliary fluids ...|[auxiliary, fluid...|[auxiliary, fluid...|[auxiliary fluids...|(1000,[661,696,89...|

要构建朴素的Bayes模型,我需要将标签和特性转换为LabelPoint。下面是我尝试将数据have转换为RDD并创建标签点的方法:

代码语言:javascript
运行
复制
val rddData = featurizedData.select("label","hash").rdd

val trainData = rddData.map { line =>
  val parts = line.split(',')
  LabeledPoint(parts(0), parts(1))
}


val rddData = featurizedData.select("label","hash").rdd.map(r =>   (Try(r(0).asInstanceOf[Integer]).get.toDouble,   Try(r(1).asInstanceOf[org.apache.spark.mllib.linalg.SparseVector]).get))

val trainData = rddData.map { line =>
  val parts = line.split(',')
  LabeledPoint(parts(0).toDouble,   Vectors.dense(parts(1).split(',').map(_.toDouble)))
}

我得到了以下错误:

代码语言:javascript
运行
复制
 scala> val trainData = rddData.map { line =>
 |   val parts = line.split(',')
 |   LabeledPoint(parts(0).toDouble, Vectors.dense(parts(1).split(',').map(_.toDouble)))
 | }
 <console>:67: error: value split is not a member of (Double,    org.apache.spark.mllib.linalg.SparseVector)
     val parts = line.split(',')
                      ^
<console>:68: error: not found: value Vectors
     LabeledPoint(parts(0).toDouble,   Vectors.dense(parts(1).split(',').map(_.toDouble)))

编辑1:

按照下面的建议,我创建了LabelPoint并对模型进行了培训。

代码语言:javascript
运行
复制
val trainData = featurizedData.select("label","features")

val trainLabel = trainData.map(line =>  LabeledPoint(Try(line(0).asInstanceOf[Integer]).get.toDouble,Try(line(1).asInsta nceOf[org.apache.spark.mllib.linalg.SparseVector]).get))

val splits = trainLabel.randomSplit(Array(0.8, 0.2), seed = 11L)
val training = splits(0)
val test = splits(1)

val model = NaiveBayes.train(training, lambda = 1.0, modelType = "multinomial")

val predictionAndLabels = test.map { point => 
   val score = model.predict(point.features)
   (score, point.label)}

我得到了40%左右的精度与N克和没有N克,以及不同的散列特征数。我的数据集包含5000行和45个变体标签。有什么方法可以提高模型的性能吗?提前感谢

EN

回答 1

Stack Overflow用户

发布于 2016-01-18 14:16:22

您不需要将您的featurizedData转换为RDD,因为Apache Spark有两个库MLMLLib,第一个库用于DataFrames,而MLLib使用RDDs。因此,您可以使用ML,因为您已经有了一个DataFrame

为了实现这一点,您只需要将您的列重命名为(labelfeatures),并适合您的模型,如在NaiveBayes中所示,示例如下所示。

代码语言:javascript
运行
复制
df = sqlContext.createDataFrame([
    Row(label=0.0, features=Vectors.dense([0.0, 0.0])),
    Row(label=0.0, features=Vectors.dense([0.0, 1.0])),
    Row(label=1.0, features=Vectors.dense([1.0, 0.0]))])
nb = NaiveBayes(smoothing=1.0, modelType="multinomial")
model = nb.fit(df)

关于您得到的错误,是因为您已经有了一个SparseVector,而且该类没有一个split方法。因此,考虑到这一点,您的RDD几乎有您实际需要的结构,但是您必须将Tuple转换为LabeledPoint

有一些提高性能的技术,我首先想到的是删除停止词(例如,a,an,to,虽然……),第二个技术是计算文本中不同的单词数,然后手工构造向量,也就是说,如果哈希数较低,不同的单词可能有相同的散列,因此性能不佳。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34856042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档