|
支持向量机 主要用在分类问题上,其效果也是非常好的。下面代码是基于sparkML lib svm 算法的实现
- package com.gizwits.mllib
- import org.apache.log4j.{Level, Logger}
- import org.apache.spark.mllib.classification.SVMWithSGD
- import org.apache.spark.mllib.evaluation.{BinaryClassificationMetrics, MulticlassMetrics}
- import org.apache.spark.mllib.optimization.{HingeGradient, L1Updater}
- import org.apache.spark.mllib.util.MLUtils
- import org.apache.spark.{SparkConf, SparkContext}
- /**
- * Created by feel
- * <p>
- *
- * SVM(线性支持向量机)是一个有监督的学习模型,通常用来进行模式识别、分类、以及回归分析。SVM只支持二分类
- *
- * </p>
- *
- */
- object SparkSVM {
- def main(args: Array[String]) {
- // 设置日志级别
- val rootLogger = Logger.getRootLogger()
- Logger.getLogger("com.gizwits").setLevel(Level.ERROR)
- val conf = new SparkConf().setAppName("SparkSVM").setMaster("local[2]")
- val sc = new SparkContext(conf)
- /*
- 数据解释,如下, 第一个是标签也就是分类,0 表示1类,1 表示另一类. 冒号2边 表示 特征维度:特征值, 如 128:51 表示 第128维度, 特征值为51,比如单词出现的 次数
- 0 128:51 129:159
- 1 159:124 160:253b
- 1 159:124 160:253
- */
- val dataInputPath = "file:///Users/feel/githome/idea/spark-exercise/src/main/resources/sample_libsvm_data.txt"
- // 加载 LIBSVM 格式的数据
- val data = MLUtils.loadLibSVMFile(sc, dataInputPath)
- // 切分数据,60%用于训练,40%用于测试
- val splits = data.randomSplit(Array(0.6, 0.4), seed = 11L)
- // 60% 用于训练 训练集,RDD[LabeledPoint]
- val training = splits(0).cache()
- // 40% 用于测试
- val test = splits(1)
- // 运行训练算法 来构建模型
- val numIterations = 200 // 迭代次数,默认是100
- /**
- * SVMWithSGD类中参数说明:
- *
- * stepSize: 迭代步长,默认为1.0
- *
- * numIterations: 迭代次数,默认为100
- *
- * regParam: 正则化参数,默认值为0.0
- *
- * miniBatchFraction: 每次迭代参与计算的样本比例,默认为1.0
- *
- * gradient:HingeGradient (),梯度下降; 其损失函数是 hinge los
- *
- * updater:SquaredL2Updater (),正则化,L2范数;线性SVM使用L2正则化做训练。也可以替换为L1正则化,这样就成了线性优化问题
- *
- * optimizer:GradientDescent (gradient, updater),梯度下降最优化计算。
- */
- // val model = SVMWithSGD.train(data, iterations=100, step=1.0, regParam=0.01, miniBatchFraction=1.0, initialWeights=None, regType=’l2′, intercept=False)
- // val model = SVMWithSGD.train(training, numIterations) // 随机梯度下降法 简单模式
- val svmAlg = new SVMWithSGD()
- /**
- * 为了防止过拟合,需要在loss function后面加入一个正则化项一起求最小值。
- * 正则化项相当于对weights向量的惩罚,期望求出一个更简单的模型。
- * MLlib目前支持两种正则化方法L1和L2。
- * L2正则化假设模型参数服从高斯分布,L2正则化函数比L1更光滑,所以更容易计算;
- * L1假设模型参数服从拉普拉斯分布,L1正则化具备产生稀疏解的功能,从而具备feature selection的能力。
- */
- svmAlg.optimizer
- .setGradient(new HingeGradient()) // HingeGradient,支持ANNGradient,LogisticGradient,LeastSquaresGradient
- .setNumIterations(numIterations)
- .setRegParam(0.1). //设置正则化参数
- setUpdater(new L1Updater) // 目前支持 SquaredL2Updater,ANNUpdater,SimpleUpdater
- val model = svmAlg.run(training)
- // 清空默认值
- model.clearThreshold()
- // 用训练集计算原始分数
- val scoreAndLabels = test.map { point =>
- val score = model.predict(point.features)
- (score, point.label)
- }
- //训练数据集用RDD[LabeledPoint]表示,其中label是分类类型的索引,从0开始,即0, 1, 2, …。
- val result = scoreAndLabels.map { t =>
- val str = "point.label=" + t._2 + " score= " + t._1
- println(str)
- str
- }
- result.collect()
- // 以下是2种分类模型的评估
- // 获得评价指标,二分类评估
- /**
- * ROC的全名叫做Receiver Operating Characteristic,是一个画在二维平面上的经过(0, 0),(1, 1)的曲线,
- * 一般情况下,这个曲线都应该处于(0, 0)和(1, 1)连线的上方,如果不幸的出现在了下方,说明分类器的结果反了。
- * 程序里的结果其实是计算的AUC,也就是Area Under roc Curve,
- * 也就是处于ROC curve下方的那部分面积的大小,一般是0.5至1,越大就说明分类效果越好
- */
- val metrics = new BinaryClassificationMetrics(scoreAndLabels)
- val auROC = metrics.areaUnderROC() //受试者操作特征
- println("Area under ROC = " + auROC)
- // 计算测试误差,多分类
- val metricsLabel = new MulticlassMetrics(scoreAndLabels)
- val precision = metricsLabel.precision
- println("Precision = " + precision)
- sc.stop()
- }
- }
复制代码
|
|