zoukankan      html  css  js  c++  java
  • Python实现线性回归3,局部加权线性回归,lasso回归,岭回归

    接上篇

    5.局部加权线性回归

    局部加权线性回归(LWLR),在该算法中,我们给待预测点附近的每个点赋予一定的权重,在这个自己上基于最小均方差进行普通的回归,每次预测均需要先选取出对应数据子集。该算法接触回归系数w的形式如下:
    普通线性回归:w^=(XTX)1XTyhat{w} = (X^TX)^{-1}·X^Ty
    加权(weight)线性回归:w^=(XTWX)1XTWyhat{w} = (X^TWX)^{-1}·X^TWy,w是一个矩阵,用来给每个数据点赋予权重。
    LWLR使用“核”对附近的点赋予更高的权重。核的类型可以自由选择,最常用的就是高斯核,其对应的权重:w(i,i)=exp(xix22k2)w(i,i) = exp(frac{|x^i-x|^2}{-2·k^2})(与支持向量机中的核一致)。w是只含有对角线元素的矩阵w,点x与x(i)越近,则w(i,i)机会越大,也就是说距离中心点越近的权重越大,对拟合曲线的影响也就越大,所以也有了局部加权这一名词。公式中的k为超参数,需要自行指定,他决定了对附近的点赋予多大的权重。
    LWLR方法对待预测的每个点赋予一定的权重,在这样的一个子集上基于最小均方差来进行普通的回归。因此,会增加计算量,它对每个点做预测时都必须使用整个数据集,实际预测结果一般。
    代码如下(代码参考自《机器学习实战》第8章):

    def linearRegLwlr(x,y,k=1.0):
        #局部加权线性回归,k为高斯核函数的参数
        # hat{w} = (X^TWX)^{-1}·X^TWy
        xMat = np.mat(x)
        yMat = np.mat(y).T  # 传入数据是1*m的矩阵,将其转置成m*1维矩阵
        m = np.shape(x)[0]  # 数据条数
        yHat = np.zeros(m)  # 初始化预测值y矩阵
        
        for i in range(m):  #遍历x,从1到m,使用解析解求每一个yhat
            weights = np.mat(np.eye((m)))     # 需要根据每条数据,计算权重,每条的权重都不相同
            for j in range(m):                # 遍历所有数据求解一条数据对应的权重
                diffMat = x[i] - xMat[j,:]    
                weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2)) # 高斯核函数
            xTx = xMat.T * (weights * xMat)   # x转置*x
            if np.linalg.det(xTx) == 0.0:     # 判断矩阵是否可逆,行列式是否等于0
                print("This matrix is singular, cannot do inverse")
            ws = xTx.I * (xMat.T * (weights * yMat)) # 求得这一条数据的解析解
            yHat[i]=x[i] * ws                 # x[i]为1,将值赋值给yHat矩阵
        return yHat
       
        print('')
        print('3.5、局部加权线性回归,linearRegLwlr函数,无theta解析式!')
        print('局部加权线性回归拟合结果图,使用第一列TV数据展示!')
        yHat=linearRegLwlr(x,y.T,k=1)
        # 绘图
        xMat = np.mat(x)
        srtIndex = xMat[:,0].argsort(axis=0)
        xSort = xMat[srtIndex][:,0,:]
        # 绘制散点图
        fig = plt.figure(1)
        ax = fig.add_subplot(111)
        ax.plot(xSort[:,0],yHat[srtIndex])
        ax.scatter(xMat[:,0].flatten().A[0],np.mat(yHat).flatten().A[0],s=2,c='red')    #必须是数组的形式
        plt.show()
    

    6.岭回归

    岭回归实际上相当于有约束条件情况的最小二乘法回归,即回归系数为:w^=(XTX+λI)1XTyhat{w} = (X^TX+λI)^{-1}·X^Ty,另一种写法:min wXwy22+αw22underset{w}{min\,} {{|| X w - y||_2}^2 + alpha {||w||_2}^2}。惩罚λ的引入能够减少不重要的参数,从而更好滴理解数据。参数λ的选择,需要将原训练数据分成训练数据和测试数据,在训练数据上训练回归系数,然后在测试数据上测试性能,通过选取不同的λ来重复上述过程,最终选取使得预测误差最小的λ。
    岭回归缺陷:
    1.主要靠目测选择岭参数
    2.计算岭参数时,各种方法结果差异较大
    所以一般认为,岭迹图只能看多重共线性,却很难做变量筛选。
    代码如下(代码参考自《机器学习实战》第8章):

    def linearRegRidge(x,y,k=1.0,lam=0.2):
        xMat = np.mat(x)
        yMat = np.mat(y)
        yMat = yMat - np.mean(y,0)     # 数据归一化
        xMat = (xMat - np.mean(xMat,0))/np.var(xMat,0) # 数据归一化,因为lambda*I在数值很大时,系数w平方会非常大
        
        numTestPts = 30  # N组lanba值
        wMat = np.zeros((numTestPts,np.shape(xMat)[1]))# 30组lanba值
        for i in range(numTestPts): # 求每组的w系数
            #ws = ridgeRegres(xMat,yMat,np.exp(i-10))
            # i=0
            print(i,np.exp(i-10))
            lam=np.exp(i-10) # 使用指数级递增,效果更有效
            xTx = xMat.T*xMat # x转置*x
            denom = xTx + np.eye(np.shape(xMat)[1])*lam # x转置*x 加上单位阵
            if np.linalg.det(denom) == 0.0: # 判断矩阵是否可逆,行列式是否等于0
                print("This matrix is singular, cannot do inverse")
                #return
            ws = denom.I * (np.dot(xMat.T,yMat)) # 求得一组w系数
            wMat[i,:]=ws.T
        
        print('30组wMat,不同lam下参数情况:',wMat)
        return wMat
        
        theta6=linearRegRidge(x,y)
        print('')
        print('3.6、岭回归,linearRegRidge函数,多组theta解析式!',theta6)
    

    7.lasso回归

    lasso回归通过构造一个一阶惩罚函数获得一个精炼的模型;通过最终确定一些指标(变量)癿系数为零(岭回归估计系数等于0癿机会微乎其微,造成筛选变量困难),解释力很强。
    擅长处理具有多重共线性的数据,筛选变量,与岭回归一样是有偏估计。lasso回归则是与岭回归略有不同,使用了L1正则:min wXwy22+αw2underset{w}{min\,} {{|| X w - y||_2}^2 + alpha {||w||_2}}
    lasso回归代码如下:

    待补充,!!!∑(゚Д゚ノ)ノ,有点复杂,以后再弄了,先去弄逻辑回归了!!
    
    

    以上算法完整代码如下

    # -*- coding: utf-8 -*-
    """
     @Time    : 2018/10/24 10:23
     @Author  : hanzi5
     @Email   : **@163.com
     @File    : linear_regression.py
     @Software: PyCharm
    """
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LinearRegression
    
    def linearRegLwlr(x,y,k=1.0):
        #局部加权线性回归,k为高斯核函数的参数
        # hat{w} = (X^TWX)^{-1}·X^TWy
        xMat = np.mat(x)
        yMat = np.mat(y).T  # 传入数据是1*m的矩阵,将其转职成m*1维矩阵
        m = np.shape(x)[0]  # 数据条数
        yHat = np.zeros(m)  # 初始化预测值y矩阵
        
        for i in range(m):  #遍历x,从1到m,使用解析解求每一个yhat
            weights = np.mat(np.eye((m)))     # 需要根据每条数据,计算权重,每条的权重都不相同
            for j in range(m):                # 遍历所有数据求解一条数据对应的权重
                diffMat = x[i] - xMat[j,:]    
                weights[j,j] = np.exp(diffMat*diffMat.T/(-2.0*k**2)) # 高斯核函数
            xTx = xMat.T * (weights * xMat)   # 求解析解
            if np.linalg.det(xTx) == 0.0:     # 判断矩阵是否可逆,行列式是否等于0
                print("This matrix is singular, cannot do inverse")
            ws = xTx.I * (xMat.T * (weights * yMat)) # 求得这一条数据的解析解
            yHat[i]=x[i] * ws                 # x[i]为1,将值赋值给yHat矩阵
        return yHat
    def linearRegRidge(x,y,k=1.0,lam=0.2):
        xMat = np.mat(x)
        yMat = np.mat(y)
        yMat = yMat - np.mean(y,0)     # 数据归一化
        xMat = (xMat - np.mean(xMat,0))/np.var(xMat,0) # 数据归一化,因为lambda*I在数值很大时,系数w平方会非常大
        
        numTestPts = 30  # N组lanba值
        wMat = np.zeros((numTestPts,np.shape(xMat)[1]))# 30组lanba值
        for i in range(numTestPts): # 求每组的w系数
            #ws = ridgeRegres(xMat,yMat,np.exp(i-10))
            # i=0
            print(i,np.exp(i-10))
            lam=np.exp(i-10) # 使用指数级递增,效果更有效
            xTx = xMat.T*xMat # x转置*x
            denom = xTx + np.eye(np.shape(xMat)[1])*lam # x转置*x 加上单位阵
            if np.linalg.det(denom) == 0.0: # 判断矩阵是否可逆,行列式是否等于0
                print("This matrix is singular, cannot do inverse")
                #return
            ws = denom.I * (np.dot(xMat.T,yMat)) # 求得一组w系数
            wMat[i,:]=ws.T
        
        print('30组wMat,不同lam下参数情况:',wMat)
        return wMat
           
    if __name__ == "__main__":
        path = 'D:/python_data/8.Advertising.csv'
        data = pd.read_csv(path)  # TV、Radio、Newspaper、Sales
        #data_matrix = data.as_matrix(columns=['TV', 'Radio', 'Newspaper', 'Sales'])  # 转换数据类型
        data_array = data.values[:,1:]  # 转换数据类型,去除第一列序号列
        x = data_array[:, :-1] #去除y对应列的数据,其他列作为x
        y = data_array[:, -1].reshape((-1,1))
        
        print('')
        print('3.5、局部加权线性回归,linearRegLwlr函数,无theta解析式!')
        print('局部加权线性回归拟合结果图,使用第一列TV数据展示!')
        yHat=linearRegLwlr(x,y.T,k=1)
        # 绘图
        xMat = np.mat(x)
        srtIndex = xMat[:,0].argsort(axis=0)
        xSort = xMat[srtIndex][:,0,:]
        # 绘制散点图
        fig = plt.figure(1)
        ax = fig.add_subplot(111)
        ax.plot(xSort[:,0],yHat[srtIndex])
        ax.scatter(xMat[:,0].flatten().A[0],np.mat(yHat).flatten().A[0],s=2,c='red')    #必须是数组的形式
        plt.show()
    
        theta6=linearRegRidge(x,y)
        print('')
        print('3.6、岭回归,linearRegRidge函数,多组theta解析式!',theta6)
    

    数据见以下链接,复制到txt文档中,另存为CSV格式即可。
    数据

    参考资料:
    1、python实现线性回归
    2、机器学习:线性回归与Python代码实现
    3、python实现简单线性回归
    4、Machine-Learning-With-Python
    5、《机器学习》西瓜书,周志华著
    6、机器学习视频,邹博
    7、 斯坦福大学公开课 :机器学习课程
    8、马同学高等数学 如何直观形象的理解方向导数与梯度以及它们之间的关系?
    9、【机器学习】线性回归的梯度下降法
    10、机器学习 线性回归 梯度下降 python实现
    11、《机器学习实战》Peter Harrington著
    12、Lasso Regression 作者:Duanxx

  • 相关阅读:
    老年人微信教程手绘版|微信入门教程1
    微信网页版朋友圈在哪?怎么找不到
    如何用<dl>标签做表格而不用table标签
    600万个!520元的微信红包发了这么多!
    微信红包最高能发520元啦!只限今天!
    微信和WeChat的合并月活跃账户数达到7.62亿了
    excel隔行选中内容如何操作
    各大公司广泛使用的在线学习算法FTRL详解
    在线最优化求解(Online Optimization)之五:FTRL
    在线最优化求解(Online Optimization)之四:RDA
  • 原文地址:https://www.cnblogs.com/hanzi5/p/10105621.html
Copyright © 2011-2022 走看看