机器学习实战之SVM
支持向量机 主要用在分类问题上,其效果也是非常好的。下面代码是基于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) {
//设置日志级别
val rootLogger = Logger.getRootLogger()
Logger.getLogger("com.gizwits").setLevel(Level.ERROR)
val conf = new SparkConf().setAppName("SparkSVM").setMaster("local")
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
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表示,其中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()
}
}
页:
[1]