zoukankan      html  css  js  c++  java
  • 机器学习:以分析红酒口感为例说明交叉验证的套索模型

         在线性回归问题中比较常用的一种算法就是最小二乘法(OLS),其核心思想是:通过最小化误差的平方和寻找数据的最佳函数匹配。

    但是普通的OLS最常见的一个问题是容易过度拟合:即在样本数据集上属性值(x)和目标值(y)是一一对应的。这样的结果看似拟合效果

    很好,但是在新数据集上的误差却会很大。

          解决这个问题,目前主要有两种思路:前向逐步回归和惩罚线性回归。之所以说是两种思路,而不是两种算法,是因为以这两种思想

    为基础,形成了两种算法族,尤其是后者有多种较出名的算法(例如岭回归、套索回归、最小角度回归、Glmnet等)。

         前向逐步回归基本算法思路:遍历属性中的每一列,找到均方误差(MSE)之和最小的一列(即效果最佳的列),然后寻找和这列组合效果

    最好的第二列属性,依次类推直到所有的列。在这个过程中MSE--属性个数在坐标系中行成的曲线会有明显的变化,可以通过观察曲线得到

    想要的结果,或者通过打印出来的MES值获得最终结果。

         惩罚线性回归基本算法思路:在普通最小二乘法的公式中添加一个惩罚项。如果最小二乘法以下面的数学公式表达:

    ,那么套索(Lasso)回归的公式为:.其中,α||W||=α(|w1|+|w2|+...+|Wn|)。

          Lasso通过构造一个惩罚函数得到一个较为精炼的模型,使得它压缩一些系数,同时设定一些系数为零,也就是说Lasso的系数向量是稀疏的。

    Lasso是采用的L1范数正则化(OLS在变量选择方面的三种扩展方法中的一种,也叫收缩方法): L1范数是指向量中各个元素绝对值之和。

          上面说了关于模型的问题,下面说说模型评估。

          目前主要的模型性能评估方法也有两种:预留测试集和n折交叉验证。

          预留测试集就是把样本数据分成两类:一类用于训练模型,另一类用于测试模型。一般情况下测试集可以占所有数据的25%~35%。

          n折交叉验证就是把数据分成n份不相交的子集,以其中的一份作为测试集,另外n-1份作为训练集。假如把数据分成5份,依次编号1~5,第一次把1号作为测试集,2、3、4、5号作为训练集,第二次把2号作为测试集,1、3、4、5作为训练集,依次类推,直到结束。

          这里的功能核心是:sklearn.linear_model.LassoCV

          LassoCV参数有很多,我们只用用到参数cv:表示使用几折交叉验证。

          重点是介绍下相关属性:

                 alpha_: 通过交叉验证后得到的处罚系数,即公式中的α值

                 coef_:  参数向量(公式中的w)

                 mse_path_: 每次交叉验证的均方误差

                 alphas_: 验证过程中使用过的alpha值

          本次测试相关的理论基础大概就这么多,下面开始实验:数据来源

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import linear_model
    from sklearn.linear_model import LassoCV
    import os
    
    ##运行脚本所在目录
    base_dir=os.getcwd()
    data=np.loadtxt(base_dir+r"wine.txt",delimiter=";")
    
    ##矩阵的长度:行数
    dataLen = len(data)
    ##矩阵的宽度:列数
    dataWid = len(data[0])
    ##每列的均值
    xMeans = []
    ##每列的方差
    xSD = []
    ##归一化样本集
    xNorm = []
    ##归一化标签
    lableNorm = []
    
    ##第一次处理数据:计算每列的均值和方差
    for j in range(dataWid):
        ##读取每列的值
        x = [data[i][j] for i in range(dataLen)]
        ##每列的均值
        mean = np.mean(x)
        xMeans.append(mean)
        ##每列的方差
        sd = np.std(x)
        xSD.append(sd)
        
    ##第二次处理数据:归一化样本集和标签
    for j in range(dataLen):
        ##样本集归一化
        xn = [(data[j][i]-xMeans[i])/xSD[i] for i in range(dataWid-1)]      
        xNorm.append(xn)
        ##标签归一化
        ln = (data[j][dataWid-1]-xMeans[dataWid-1])/xSD[dataWid-1]
        lableNorm.append(ln)
         
    ##参数格式是数组形式,所以需要转换一下
    X=np.array(xNorm)
    Y=np.array(lableNorm)
    ##开始做交叉验证:cv=10表示采用10折交叉验证
    wineModel = LassoCV(cv=10).fit(X,Y)
    
    ##打印出最佳解的每项的系数:[ 0,-0.22773828,0,0,-0.09423888,
             ##0.02215153,-0.09903605,0,-0.06787363,0.16804092,0.3750958 ]
    print(wineModel.coef_)
    ##打印出最佳解的惩罚系数:0.013561387701
    print(wineModel.alpha_)
    ##绘图
    plt.figure()
    ##随着alpha值的变化,均方误差的变化曲线
    plt.plot(wineModel.alphas_, wineModel.mse_path_, ':')
    ##验证过程中,随着alpha值的变化,均方误差的平均曲线
    plt.plot(wineModel.alphas_, wineModel.mse_path_.mean(axis=-1),
             label='Average MSE Across Folds', linewidth=2)
    ##每次验证系统认为的最合适的alpha值
    plt.axvline(wineModel.alpha_, linestyle='--',
                label='CV Estimate of Best alpha')
    plt.semilogx()
    plt.legend()
    ax = plt.gca()
    ax.invert_xaxis()
    plt.xlabel('alpha')
    plt.ylabel('Mean Square Error')
    plt.axis('tight')
    plt.show()

    最佳解的惩罚系数和向量系数已经在代码中以注释的方式写了,生成的结果图如下:

  • 相关阅读:
    第十二周作业
    第11周学习总结
    第十周学习总结(五一作业)
    第九周作业
    第八周作业
    第七周作业
    PAT1049、1048、1047
    例题3-5,例题4-2,例题4-3
    PAT甲级真题打卡:1002. A+B for Polynomials
    PAT甲级真题打卡:1001.A+B Format
  • 原文地址:https://www.cnblogs.com/lc1217/p/6728831.html
Copyright © 2011-2022 走看看