sparkmllib实战例子(sparkmllib学习方法)

技术基于Spark Mllib文本分类的示例分析这篇文章将为大家详细讲解有关基于Spark Mllib文本分类的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。基于Spark M

本文将详细阐述基于Spark Mllib的文本分类的实例分析。边肖觉得挺实用的,分享给大家参考。希望你看完这篇文章能有所收获。

基于Spark Mllib的文本分类

文本分类是一个典型的机器学习问题,其主要目标是通过训练已有的语料库文本数据得到分类模型,进而预测新文本的类别标签。在很多领域都有实际的应用场景,比如新闻网站的新闻自动分类、垃圾邮件检测、非法信息过滤等等。本文将对一个手机短信样本数据集进行训练,对新的数据样本进行分类,进而检测其是否为垃圾短信。基本步骤是:首先将文本句子转换成单词数组,然后使用Word2Vec工具将单词数组转换成k维向量。最后通过训练k维向量样本数据得到前馈神经网络模型,从而实现文本的类别标签预测。本文利用单词矢量量化工具Word2Vec和Spark ML中的多层感知器分类器来实现这种情况。

Word2Vec简介

Word2Vec是一个用来将单词表示为数字向量的工具。它的基本思想是将文本中的单词映射成K维数值向量(通常用K作为算法的超参数),使文本中的所有单词形成一个K维向量空间,这样我们就可以通过计算向量之间的欧氏距离或余弦相似度得到文本的语义相似度。Word2Vec采用分布式表示的词向量表示,既能有效控制词向量的维数,避免维数灾难(相对于一热表示),又能保证相似意义的词在向量空间中更接近。

Word2Vec的实现有两种模式:CBOW(连续词包)和Skip-Gram。简单总结一下,区别在于CBOW根据上下文预测目标词,Skip-Gram根据当前词预测上下文。Spark是通过Skip-Gram模型实现的。假设我们有n个待训练的单词序列样本,表示为W1,W2.Wn,而Skip-Gram模型的训练目标是最大化平均对数似然,即

基于Spark  Mllib文本分类的示例分析

其中n是单词的数量,k是单词上下文的窗口大小。在Skip-Gram模型中,在某个上下文窗口中每两个单词之间计算概率,通常上下文窗口越大,可以覆盖的单词组合越全面,可以带来更准确的结果,但缺点是也会增加训练时间。

在Skip-Gram模型中,每个单词与两个向量相关联,这两个向量分别表示单词向量和上下文向量。也正是因为如此,Word2Vec才能比传统的LDA(潜在狄利克雷分配)过程表达更丰富、更准确的语义信息。

Spark的Word2Vec实现提供了以下主要可调参数:

Col,存储在源数据数据框中的文本单词数组列的名称。

输出,已处理的数字特征向量存储列的名称。

默认情况下,目标数值向量的尺寸大小为100。

窗口大小,上下文窗口的大小,默认为5。

NumPartitions,训练数据的分区数,默认为1。

MaxIter,算法找到最大迭代次数,小于或等于分区数。默认值为1。

minCount,只有当一个单词的出现次数大于等于MinCount时,才会被包含在词汇中,否则会被忽略。

步长,优化算法每次迭代的学习速率。默认值为0.025。

这些参数可以在构造Word2Vec实例时通过setXXX方法进行设置。

多层感知器

多层感知器(MLP)是一种多层前馈神经网络模型。所谓前馈神经网络是指它只从输入层接收前一层的输入,并将计算结果输出到下一层,而不对前一层给出反馈。整个过程可以用一个有向无环图来表示。这种类型的神经网络由三层组成,即输入层、一个或多个隐藏层和输出层,如图所示:

基于Spark  Mllib文本分类的示例分析

Spark ML在1.5版之后提供了一个由BP(反向传播)算法训练的多层感知器实现。BP算法的学习目的是研究网络。

的连接权值进行调整,使得调整后的网络对任一输入都能得到所期望的输出。BP 算法名称里的反向传播指的是该算法在训练网络的过程中逐层反向传递误差,逐一修改神经元间的连接权值,以使网络对输入信息经过计算后所得到的输出能达到期望的误差。Spark 的多层感知器隐层神经元使用 sigmoid 函数作为激活函数,输出层使用的是 softmax 函数。

Spark 的多层感知器分类器 (MultilayerPerceptronClassifer) 支持以下可调参数:

  • featuresCol:输入数据 DataFrame 中指标特征列的名称。

  • labelCol:输入数据 DataFrame 中标签列的名称。

  • layers:这个参数是一个整型数组类型,第一个元素需要和特征向量的维度相等,最后一个元素需要训练数据的标签取值个数相等,如 2 分类问题就写 2。中间的元素有多少个就代表神经网络有多少个隐层,元素的取值代表了该层的神经元的个数。例如val layers = Array[Int](100,6,5,2)。

  • maxIter:优化算法求解的最大迭代次数。默认值是 100。

  • predictionCol:预测结果的列名称。

  • tol:优化算法迭代求解过程的收敛阀值。默认值是 1e-4。不能为负数。

  • blockSize:该参数被前馈网络训练器用来将训练样本数据的每个分区都按照 blockSize 大小分成不同组,并且每个组内的每个样本都会被叠加成一个向量,以便于在各种优化算法间传递。该参数的推荐值是 10-1000,默认值是 128。

算法的返回是一个 MultilayerPerceptronClassificationModel 类实例。

目标数据集预览

在引言部分,笔者已经简要介绍过了本文的主要任务,即通过训练一个多层感知器分类模型来预测新的短信是否为垃圾短信。在这里我们使用的目标数据集是来自 UCI 的 SMS Spam Collection 数据集,该数据集结构非常简单,只有两列,第一列是短信的标签 ,第二列是短信内容,两列之间用制表符 (tab) 分隔。虽然 UCI 的数据集是可以拿来免费使用的,但在这里笔者依然严正声明该数据集的版权属于 UCI 及其原始贡献者。

基于Spark Mllib文本分类的示例分析

数据集下载链接:http://archive.ics.uci.edu/ml/datasets/SMS+Spam+Collection

案例分析与实现

在处理文本短信息分类预测问题的过程中,笔者首先是将原始文本数据按照 8:2 的比例分成训练和测试数据集。整个过程分为下面几个步骤

  • 从本地读取原始数据集,并创建一个 DataFrame。

  • 使用 StringIndexer 将原始的文本标签 (“Ham”或者“Spam”) 转化成数值型的表型,以便 Spark ML 处理。

  • 使用 Word2Vec 将短信文本转化成数值型词向量。

  • 使用 MultilayerPerceptronClassifier 训练一个多层感知器模型。

  • 使用 LabelConverter 将预测结果的数值标签转化成原始的文本标签。

  • 最后在测试数据集上测试模型的预测精确度。

算法的具体实现如下:

1, 首先导入包

import org.apache.spark.ml.Pipeline

import org.apache.spark.ml.classification.MultilayerPerceptronClassifier

import org.apache.spark.ml.evaluation.MulticlassClassificationEvaluator

import org.apache.spark.ml.feature.{IndexToString, StringIndexer, Word2Vec}

2, 创建 集并分词

val parsedRDD = sc.textFile("file:///opt/datas/SMSSpamCollection").map(_.split(" ")).map(eachRow => {

(eachRow(0),eachRow(1).split(" "))

})

val msgDF = spark.createDataFrame(parsedRDD).toDF("label","message")

3, 将标签转化为索引值

val labelIndexer = new StringIndexer().setInputCol("label").setOutputCol("indexedLabel").fit(msgDF)

4, 创建Word2Vec,分词向量大小100

final val VECTOR_SIZE = 100

val word2Vec = new Word2Vec().setInputCol("message").setOutputCol("features").setVectorSize(VECTOR_SIZE).setMinCount(1)

5, 创建多层感知器

输入层VECTOR_SIZE个,中间层两层分别是6,,5个神经元,输出层2个

val layers = Array[Int](VECTOR_SIZE,6,5,2)

val mlpc = new MultilayerPerceptronClassifier().setLayers(layers).setBlockSize(512).setSeed(1234L).setMaxIter(128).setFeaturesCol("features").setLabelCol("indexedLabel").setPredictionCol("prediction")

6, 将索引转换为原有标签

val labelConverter = new IndexToString().setInputCol("prediction").setOutputCol("predictedLabel").setLabels(labelIndexer.labels)

7, 数据集分割

val Array(trainingData, testData) = msgDF.randomSplit(Array(0.8, 0.2))

8, 创建pipeline并训练数据

val pipeline = new Pipeline().setStages(Array(labelIndexer,word2Vec,mlpc,labelConverter))

val model = pipeline.fit(trainingData)

val predictionResultDF = model.transform(testData)

//below 2 lines are for debug use

predictionResultDF.printSchema

predictionResultDF.select("message","label","predictedLabel").show(30)

9, 评估训练结果

val evaluator = new MulticlassClassificationEvaluator().setLabelCol("indexedLabel").setPredictionCol("prediction").setMetricName("precision")

val predictionAccuracy = evaluator.evaluate(predictionResultDF)

println("Testing Accuracy is %2.4f".format(predictionAccuracy * 100) + "%")

基于Spark Mllib文本分类的示例分析

关于“基于Spark Mllib文本分类的示例分析”这篇文章就分享到这里了,希望

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/148261.html

(0)

相关推荐

  • debug E命令怎样改变指定地址的数据实现同时看新旧内容

    技术debug E命令怎样改变指定地址的数据实现同时看新旧内容本篇文章给大家分享的是有关debug E命令怎样改变指定地址的数据实现同时看新旧内容,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收

    攻略 2021年11月11日
  • 安装rac时需要注意的问题有哪些

    技术安装rac时需要注意的问题有哪些这篇文章将为大家详细讲解有关安装rac时需要注意的问题有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。安装rac时需要注意的问题1.虚拟机添加共

    攻略 2021年11月10日
  • 全导数,什么是全导数,偏导数,方向导数

    技术全导数,什么是全导数,偏导数,方向导数偏导数全导数:函数在某点处延坐标轴正向,随着该自变量的变化,而引起的函数值的变化率.方向导数:函数在某点的任一方向上,随着该自变量的变化,而引起的函数值的变化率.因此它们的区别主

    生活 2021年10月27日
  • 将JavaDoc注释生成API文档的操作是怎样的

    技术将JavaDoc注释生成API文档的操作是怎样的本篇文章为大家展示了将JavaDoc注释生成API文档的操作是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。将JavaD

    攻略 2021年11月24日
  • Redis中怎么用setbit统计活跃用户

    技术Redis中怎么用setbit统计活跃用户这篇文章主要讲解了“Redis中怎么用setbit统计活跃用户”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Redis中怎么

    攻略 2021年11月4日
  • Scala的标识符构成方式有哪些

    技术Scala的标识符构成方式有哪些本篇内容介绍了“Scala的标识符构成方式有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够

    攻略 2021年12月9日