当前位置: 首页>>机器学习>>正文


Spark机器学习库指南[Spark 1.3.1版]——线性模型(Linear Models)

下面是章节线性模型的目录(其他内容参见全文目录)

数学公式

很多标准的机器学习方法都可以归结为凸优化问题。例如,寻找凸函数f(w)极小值的任务(w[weights]为d维权值向量,它是函数f的自变量)。比较正式地,我们可以将之写作优化问题:min f(w), w∈Rd,其目标函数如下:

QQ图片20150423152537

这里向量xi∈Rd(1<=i<=n)是训练样本,yi∈R是相应的标签,标签也是训练出模型之后需要预测的值。当用到的损失函数L(w; x, y)表示为wTxy(wTw的转置,转置之后才能和x做矩阵乘法,机器学习方法就可以认为是线性的。MLlib中的几个分类和回归算法就是这个线性类型,是我们这里要讨论的。

目标函数f分为两部分:正则化部分控制模型的复杂度,损失函数部分评估模型在训练数据上的错误率。损失函数L(w;.)一般是w的凸函数。固定的正则化参数(λ>=0)用于调节最小化损失函数和最小化模型复杂段这两个目标之间的平衡(例如,避免过拟合)。

损失函数

下表汇总了MLlib支持的损失函数和对应的梯度或者次梯度[1](次梯度可用于不可微函数,没有梯度的限制严格)。

1正则化

正则化是为了约束训练过程,使其向生成简单模型的方向收敛,从而避免过拟合。MLlib目前支持下面的正则化方法:1Here sign(w) is the vector consisting of the signs (±1) of all the entries of w.

注:提到正则化,必须要说一下数学中范数(norm)的概念。范数是具有“长度”概念的函数。最常用的范数是p-范数,其定义为:若x = [x1, x2, x3, …, xn]T,那么||x||p = (|x1| p+ |x2|p + |x3|p + … + |xn|p)1/p 。当p取值为1和2时,就是我们的L1和L2【2-范数的平方除以2】正则化:

1-范数:||x||1=|x1|+|x2|+…+|xn|
2-范数:||x||2=(|x1|2+|x2|2+…+|xn|2)½
 

由于平滑的特性,L2正则化问题比L1正则化更容易解决。但是,L1正则可以促进产生稀疏的权值,从而产生简单可解释的模型。并且,L1由于产生稀疏的权值(即大部分取值为0),相当于做了特征选择。不建议做没有正则化的模型训练,特别是训练样本特别少的时候。

优化

线性模型底层使用凸函数优化方法来优化目标函数。MLlib中使用了两种方法,SGD和L-BFGS,章节 optimization section会有具体介绍。当前,绝大多数MLlib的算法API支持随机梯度下降法(SGD),部分支持L-BFGS。

分类

分类旨在将多个条目分到不同的类别。最常见的分类类型是二分类,两个类型通常被比较为正和负。 如果多于两个类型的话,就是多分类。MLlib提供两种线性方法用于分类:线性支持向量机(SVM)和逻辑回归。SVM只支持二分类,而逻辑回归既支持二分类又支持多分类。这两种方法,都提供了L1和L2正则化。训练数据集用RDD[LabeledPoint]表示,其中label是分类类型的索引,从0开始,即0, 1, 2, …。注意在上文的数学公式部分,二分类标签y使用+1和-1标记,这个是为了方便公式化。实际再MLlib中,使用0代替了-1,从而更多分类保持一致。

线性支持向量机(SVMs)

线性SVM是用于大规模分类任务的一种标准方法。它用到的线性方法上文的等式(1)中已经有说明,使用的损失函数为hinge loss:

1

默认情况下,线性SVM使用L2正则化做训练。也可以替换为L1正则化,这样就成了线性优化问题。

线性SVM算法输出的是SVM模型。给定一个新的数据点(用x表示),模型基于wTx的值做预测。默认情况下, 如果wTx>=0则结果为正例,否则为负例。

下面的代码片(Spark Pthon SVM)段说明了如何导入一个样本数据集,进行模型训练,并做出预测。(Python中的SVMModel目前还不支持load和save数据)

#!/usr/bin/python
from pyspark import SparkContext;
from pyspark.mllib.util import MLUtils;
from pyspark.mllib.classification import SVMWithSGD;

sc = SparkContext(appName="svmTesting");

# Load training data in LIBSVM format.
data = MLUtils.loadLibSVMFile(sc, 'data/mllib/sample_libsvm_data.txt');
print "FirstRecord:", data.take(1);

# Split data into training (70%) and test (30%).
splits = data.randomSplit([0.7, 0.3], seed = 11L);
training = splits[0].cache();
print "TrainingCount:[%d]"%training.count();
test = splits[1];
print "TestingCount:[%d]"%test.count();

# Run training algorithm to build the model
numIterations = 100;
model = SVMWithSGD.train(training, numIterations);

# Clear the default threshold.
model.clearThreshold();

# Compute raw scores on the test set.
scoreAndLabels = test.map(lambda point : (model.predict(point.features), point.label));

# output score and label.
for score, label in scoreAndLabels.collect():
	print score, label;

SVMWithSGD.train(data, iterations=100, step=1.0, regParam=0.01, miniBatchFraction=1.0, initialWeights=None, regType=’l2′, intercept=False)的参数说明:

Parameters:
  • data – 训练集,RDD[LabeledPoint]
  • iterations – 迭代次数,默认100
  • step – SGD步长,默认为1.0
  • regParam – 正则化参数,默认0.01T
  • miniBatchFraction – 每一轮迭代,参入训练的样本比例,默认1.0(全部参入).
  • initialWeights – 初始取值,默认是0向量
  • regType – 正则化类型,默认”l2″
    Allowed values:
    • “l1” for using L1 regularization
    • “l2” for using L2 regularization
    • None for no regularization

    (default: “l2”)

  • intercept – Boolean parameter which indicates the use or not of the augmented representation for training data (i.e. whether bias features are activated or not).

 

逻辑回归(Logistic regression)

逻辑回归广泛应用于二分类问题。它是线性分类方法(参见公式(1)),损失函数是logistic loss:

render

 

其中exp是以自然常数e为底的指数函数。对二分类问题来说,这个算法输出一个二分逻辑回归模型。给定一个新的数据点(x),模型应用下面的逻辑函数给出预测:

render
 其中 z=wTx,f(z)也叫sigmoid函数,它将实数范围内的值映射到(0,1)区间默认情况下, 如果f(wTx) > 0.5, 输出为正,否则为负。不过跟线性SVM不同的是,逻辑回归模型的原始输出(f(z)),可以解释为概率(例如,x 是正例的概率)。

二分逻辑回归可以泛化为多项式逻辑回归 ,用于训练和预测多分类问题。例如,对于K个可能的输出,其中一个输出可被选作“中心点”(pivot),另外的K-1个输出可以分别跟中心点输出进行回归。在MLlib中,第一个类0被选作“中心点”类。可以参考《The Elements of Statistical Learning》的章节4.4了解详情。

对于多分类问题,算法会输出一个多项式回归模型,它包含K-1个跟第一类配对的二元回归模型。给定一个新的数据点,K-1个模型都会被执行,概率最大的类会被选作预测的类型。

我们实现了两种算法用于解决逻辑回归问题:min-batch梯度下降和L-BFGS。推荐使用L-BFGS,因为它收敛更快。

下面的例子说明了怎样导入样本数据集,建立逻辑回归模型,使用结果模型进行预测并计算训练的错误率。

from pyspark.mllib.classification import LogisticRegressionWithLBFGS
from pyspark.mllib.regression import LabeledPoint
from numpy import array

# Load and parse the data
def parsePoint(line):
    values = [float(x) for x in line.split(' ')]
    return LabeledPoint(values[0], values[1:])

data = sc.textFile("data/mllib/sample_svm_data.txt")
parsedData = data.map(parsePoint)

# Build the model
model = LogisticRegressionWithLBFGS.train(parsedData)

# Evaluating the model on training data
labelsAndPreds = parsedData.map(lambda p: (p.label, model.predict(p.features)))
trainErr = labelsAndPreds.filter(lambda (v, p): v != p).count() / float(parsedData.count())
print("Training Error = " + str(trainErr))

回归

线性最小二乘法,Lasso,岭回归(Linear least squares, Lasso, and ridge regression)

线性最小二乘法是回归问题中最常用的公式,如公式(1)所述它是一个线性方法,损失函数是squared loss:

render
通过使用不同的正则化方法,上面的回归公式派生出了各种各样相关的回归方法:普通最小二乘法线性最小二乘法 没有使用正则化方法;岭回归 使用了L2正则化; Lasso 使用了 L1 正则化。对上述这些模型,平均的训练误差(见下面的表达式),叫做均方误差
QQ图片20150423224533
下面的例子说明了如何导入训练数据,解析为RDD[LabeledPoint],然后使用LinearRegressionWithSGD建立简单的线性模型预测标签值。我们最后计算了均方误差来评估拟合度
from pyspark.mllib.regression import LabeledPoint, LinearRegressionWithSGD
from numpy import array

# Load and parse the data
def parsePoint(line):
    values = [float(x) for x in line.replace(',', ' ').split(' ')]
    return LabeledPoint(values[0], values[1:])

data = sc.textFile("data/mllib/ridge-data/lpsa.data")
parsedData = data.map(parsePoint)

# Build the model
model = LinearRegressionWithSGD.train(parsedData)

# Evaluate the model on training data
valuesAndPreds = parsedData.map(lambda p: (p.label, model.predict(p.features)))
MSE = valuesAndPreds.map(lambda (v, p): (v - p)**2).reduce(lambda x, y: x + y) / valuesAndPreds.count()
print("Mean Squared Error = " + str(MSE))

流式线性回归(Streaming linear regression)

当数据以流的方式到达时,就很有必要使回归模型适应在线环境,每当有新的数据到来时就得更新模型参数。MLlib当前支持普通最小二乘法的流式线性回归。拟合过程跟离线情况类似,但是要实时拟合每一批数据,使得模型能够及时持续更新从而能够预测流式数据。(目前只有Scala支持流式线性回归)

实现 (developer)

幕后,MLlib实现了一个简单分布式版本的随机梯度下降算法,建立在底层的梯度下降优化原语上(参见 optimization )。所有算法都会接受一个正则化参数(regParam)和多个其他的梯度下降相关的参数(stepSize, numIterations, miniBatchFraction)。每种算法都支持三种可能的正则化(none, L1或者L2)。

对于逻辑回归,L-BFGS 版本在LogisticRegressionWithLBFGS中实现。这个版本支持二分逻辑回归和多项式逻辑回归,而SGD版本只能支持二分逻辑回归。但是,L-BFGS版本不支持L1正则化,SGD版本支持L1正则化。当L1不是必须的时候,强烈推荐用L-BFGS版本,因为相对于SGD来说,它通过拟牛顿近似逆Hessian矩阵收敛得更快更准。

算法都是使用Scala语言实现的:

Python通过 PythonMLLibAPI 调用Scala的实现。

 

参考:

[1] http://zh.wikipedia.org/wiki/%E6%AC%A1%E5%AF%BC%E6%95%B0

[2] http://baike.baidu.com/link?url=x8hkYh5wI-5wQItUQTbMUwPTkNhCBFqPzh7DTaSf8z8cUZgxGrnviVvPeBEPbgQ_3AjiX7gtwtQ_defHP_r22K

本文由《纯净天空》出品。文章地址: https://vimsky.com/article/500.html,未经允许,请勿转载。