Machine Learning in Action -- 回归

机器学习问题分为分类和回归问题 
回归问题,就是预测连续型数值,而不像分类问题,是预测离散的类别

至于这类问题为何称为回归regression,应该就是约定俗成,你也解释不通 
比如为何logistic regression叫逻辑回归,明明解决的是分类问题,而且和逻辑没有半点关系

谈到回归,最简单的就是线性回归 
用直线去拟合数据点,

我们通常用平方误差来作为目标函数,称为最小二乘(ordinary least squares),参考AndrewNG的讲义

如何解这个问题,可以用梯度下降,但其实更简单的是,这个问题是有解析解的,可以直接求出

目标函数可以表示为,

 
对w求导,得到

让导数=0,即可求出w

源码,

from numpy import *
def standRegres(xArr,yArr):
    xMat = mat(xArr); yMat = mat(yArr).T
    xTx = xMat.T*xMat
    if linalg.det(xTx) == 0.0: #判断行列式是否为0,为0是奇异矩阵,求不出逆
        print "This matrix is singular, cannot do inverse"
        return
    ws = xTx.I * (xMat.T*yMat)
    return ws

对于线性回归,是典型的高bias,低variance的模型,因为它可以说是最简单的模型 
所以会出现欠拟合(underfit)的问题

 

Locally weighted linear regression

线性回归是最小均方差的无偏估计,局部加权也可以看成在估计中引入一些偏差,以降低预测的均方差

其实局部加权,是对训练集的一个选择(选择部分样本,所以产生偏差),选择离当前预测点比较近的那部分训练样本来进行线性回归,具体算法参考AndrewNG的讲义

如何选择,通过给每个训练样本加上一个权值w

基本思路是,离预测点越近则权值越大,抽象表示就是高斯核 

其中k代表,选取训练样本的范围

源码,

def lwlr(testPoint,xArr,yArr,k=1.0):
    xMat = mat(xArr); yMat = mat(yArr).T
    m = shape(xMat)[0]
    weights = mat(eye((m))) #weight初始化为单位矩阵
    for j in range(m):
        diffMat = testPoint - xMat[j,:] #预测x和每个样本的差值
        weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2)) #计算每个样本的权值
    xTx = xMat.T * (weights * xMat)
    if linalg.det(xTx) == 0.0:
        print "This matrix is singular, cannot do inverse"
        return
    ws = xTx.I * (xMat.T * (weights * yMat))
    return testPoint * ws

和线性回归的差别就是多了权值的计算,注意这里权值矩阵是对角矩阵,对角线上表示每个样本的权值,其他都为0

当然局部加权可以解决欠拟合问题,拟合程度取决于k的取值

可见如果k选的过小,也会导致过拟合问题

当然这个算法的问题是,它是non-parametric algorithm,在预测的时候,需要保留完整的训练集,并每次预测都需要遍历整个训练集

 

Ridge regression

前面说的局部加权通过选择部分训练样本,来加入偏差,从而解决欠拟合的问题

下面要看看另外一类问题,

求解线性回归的时候,需要求解 
但有些时候,X协方差矩阵是求不出逆的,这个问题我们在因子分解里面也看到过

比如当样本数小于特征数时,或X非满秩,即某些样本是线性相关的,比如x1 = 2*x2

对于这种问题,直接求解会有问题,解决办法就是shringking特征,即选取部分特征,加入偏差

其中一种方法,叫做岭回归, 
ridge regression中的目标函数为,加入了罚项

其中两部分,第一部分其实就是把线性回归中的y-xTw展开了,等价的 
多的就是第二部分,可见如果要整个式子最小,那么如果单纯看第二部分,那么它为0是最优的 
即所有参数都为0,这就是加入罚项,会趋于让某些不重要的特征的参数接近0,从而达到减少特征的目的 
其中lamda是复杂度,lamda越大,shringking越厉害,即参数越趋向于0

也可以表示为,意思是一样的,限制参数

岭回归的解析解为,

源码,

def ridgeRegres(xMat,yMat,lam=0.2):
    xTx = xMat.T*xMat
    denom = xTx + eye(shape(xMat)[1])*lam #加入罚项
    if linalg.det(denom) == 0.0:
        print "This matrix is singular, cannot do inverse"
        return
    ws = denom.I * (xMat.T*yMat)
    return ws

注意任意要做特征shrinking的算法,包括PCA,因子分析。。。首先都要对所有特征做normalization,否则无法评判各个特征

所以给出如何使用ridge regression的代码,看看如何做normalization

def ridgeTest(xArr,yArr):
    xMat = mat(xArr); yMat=mat(yArr).T
    yMean = mean(yMat,0)
    yMat = yMat - yMean
    xMeans = mean(xMat,0)
    xVar = var(xMat,0)
    xMat = (xMat - xMeans)/xVar #各个特征的scale不一样,所以要除以方差
    numTestPts = 30
    wMat = zeros((numTestPts,shape(xMat)[1]))
    for i in range(numTestPts):
        ws = ridgeRegres(xMat,yMat,exp(i-10))
        wMat[i,:]=ws.T
    return wMat

这里尝试30个不同的lamda,这里lamda以指数级别变化,可以看看极大和极小的lamda对结果的影响

可以看到当lamda很小时,最左边,特征参数没有任何shrinking,和线性回归得到的值基本相同 
而lamda很大时,最右边,特征参数会全部shrinking成0

所以要通过交叉验证来找到中间那个比较合适的lamda值

 

lasso

和ridge regression很像 
只是从ridge regression的L2罚项 ,替换成L1罚项 
其中L1,和L2分别表示绝对值和平方,不要纠结

所以lasso可以表示为,

你可能会问,这个有毛区别,从平方变成绝对值?

答案是,lasso当t足够小的时候,更容易让某些特征参数直接=0,而不仅仅接近0,这样shrinking的效果更好

但是平方约束,是凸的,而换成绝对值,非凸约束,所以计算的时候会很麻烦(个人理解) 
所以lasso很难求解

所以介绍一个近似方法

Forward stagewise regression

贪心算法,每次比较小的修正一个参数,然后如果可以减小误差,则保留,不停迭代找到最优的参数

def stageWise(xArr,yArr,eps=0.01,numIt=100):
    xMat = mat(xArr); yMat=mat(yArr).T
    yMean = mean(yMat,0)
    yMat = yMat - yMean
    xMat = regularize(xMat)
    m,n=shape(xMat)
    ws = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy() #权值初始化为0
    for i in range(numIt):  #迭代次数
        print ws.T
        lowestError = inf;  #最小误差初始化为无穷
        for j in range(n):  #对于每个特征
            for sign in [-1,1]: #增加或减少权值
                wsTest = ws.copy()
                wsTest[j] += eps*sign #改变权值
                yTest = xMat*wsTest  #计算预测值
                rssE = rssError(yMat.A,yTest.A)  #计算预测平方误差,
                if rssE < lowestError:
                    lowestError = rssE
                    wsMax = wsTest
        ws = wsMax.copy()
        returnMat[i,:]=ws.T
    return returnMat

通过设置不同的eps值,即步长,来找到更合适的eps值

这个方法在足够次的迭代后,可以得到和lasso接近的结果

使用这个方法还有个很大的好处,是可以帮助理解当前的模型,可以简单的找到那些不重要的特征 

可以看到这迭代过程中,第二个和第七个特征的参数一直是0,说明这两个特征对误差没有贡献

本文章摘自博客园,原文发布日期:2014-09-05

时间: 2024-10-26 16:26:44

Machine Learning in Action -- 回归的相关文章

Splunk Machine Learning Toolkit在回归问题上的应用

在前面的文章中,我们对Splunk Machine Learning Toolkit 3.0.0进行了介绍,今天我们就来聊一下机器学习中最常见的问题:回归. 什么是回归? 回归对数值连续的通常是来预测一个值,比如预测房屋价格.股票走势.产品销售量.未来的天气情况等.线性回归是最简单的一种回归算法,它期望使用一条直线去拟合数据,如图所示: 可以看出,这样直线有很多,那么哪条才是最佳拟合线呢?这就是寻找最佳拟合的问题. 如果预测值和实际值最接近,它应该是最佳拟合线.我们可以用最小二乘法(Least

机器学习实战(Machine Learning in Action)笔记--Chapter1:机器学习基础

Part1 分类 监督学习一般使用两种类型的目标变量:标称型(主要用于分类).数值型(主要用于回归). 非均衡分类问题 第1章 机器学习基础 专家系统 训练样本.特征.目标变量(分类问题中为类别) 训练数据和测试数据 知识表示 监督学习:分类.回归 无监督学习 将数据集合分成由类似的对象组成的多个类的过程被称为聚类 将寻找描述数据统计值的过程称之为密度估计 监督学习的用途:k-近邻算法.朴素贝叶斯算法.支持向量机.决策树.线性回归.局部加权线性回归.Ridge回归.Lasso最小回归系数估计 无

Machine Learning in Action -- Logistic regression

这个系列,重点关注如何实现,至于算法基础,参考Andrew的公开课 相较于线性回归,logistic回归更适合用于分类 因为他使用Sigmoid函数,因为分类的取值是0,1 对于分类,最完美和自然的函数,当然是Heaviside step function,即0-1阶跃函数,但是这个函数中数学上有时候比较难处理 所以用Sigmoid函数来近似模拟阶跃函数, 可以看到Sigmoid在增大坐标尺度后,已经比较接近于阶跃函数 其中, 而logistic回归就是要根据训练集找到,最优的w向量 下面就通过

Machine Learning in Action – PCA和SVD

降维技术,  首先举的例子觉得很好,因为不知不觉中天天都在做着降维的工作 对于显示器显示一个图片是通过像素点0,1,比如对于分辨率1024×768的显示器,就需要1024×768个像素点的0,1来表示,这里每个像素点都是一维,即是个1024×768维的数据.而其实眼睛真正看到的只是一副二维的图片,这里眼睛其实在不知不觉中做了降维的工作,把1024×768维的数据降到2维 降维的好处,显而易见,数据更易于显示和使用,去噪音,减少计算量,更容易理解数据  主流的降维技术,包含:  主成分分析,pri

Machine Learning in Action -- Support Vector Machines

虽然SVM本身算法理论,水比较深,很难懂 但是基本原理却非常直观易懂,就是找到与训练集中支持向量有最大间隔的超平面 形式化的描述: 其中需要满足m个约束条件,m为数据集大小,即数据集中的每个数据点function margin都是>=1,因为之前假设所有支持向量,即离超平面最近的点,的function margin为1 对于这种有约束条件的最优化问题,用拉格朗日定理,于是得到如下的形式, 现在我们的目的就是求出最优化的m个拉格朗日算子,因为通过他们我们可以间接的算出w和b,从而得到最优超平面 考

Machine Learning in Action -- AdaBoost

初始的想法就是,结合不同的分类算法来给出综合的结果,会比较准确一些  称为ensemble methods or meta-algorithms,集成方法或元算法 集成方法有很多种,可以是不同算法之间的,也可以是同一个算法但不同参数设置之间的,也可以是将数据集分成多分给不同的分类器之间的  总的来说,有3个维度可以进行集成,算法,算法参数和数据集 下面简单介绍两种比较流行的元算法思路, 1. Building classifiers from randomly resampled data: b

Machine Learning in Action -- FP-growth

要解决的问题,频繁项集 最暴力的方法,就是遍历所有的项集组合,当然计算量过大  最典型的算法apriori, 算法核心思想,当一个集合不是频繁项集,那么它的超集也一定不是频繁项集  这个结论是很明显的,基于这样的思路,可以大大减少频繁项集的候选项  因为你只要发现一个集合非频繁项集,那么他所有的超集都可以忽略 但apriori算法的问题是,计算每个候选项的出现频率的时候都需要遍历整个数据集,这个明显是低效的  很自然的想法,就是否有办法可以尽量少的遍历数据集?比如遍历一遍就可以得到所有的项集的出

《Machine Learning with Spark》书评与作者访谈

机器学习是基于现有数据,通过数据驱动做出决策或者预测的技术.Apache Spark及其机器学习库MLlib为开发可伸缩的机器学习应用,提供了多种有用的算法.InfoQ采访了<Machine Learning with Spark>一书的作者Nick Pentreath,共同探讨了有关数据科学和机器学习的话题. By Srini Penchikala 机器学习以现有数据为基础创建模型,通过数据驱动,对未来做出决策或者预测.机器学习在最近几年获得大量的关注,因为它对企业与商业做出决策非常有帮助.

Learning Machine Learning, Part 3: Application

This post features a basic introduction to machine learning (ML). You don't need any prior knowledge about ML to get the best out of this article. Before getting started, let's address this question: "Is ML so important that I really need to read thi