jjzjj

有监督学习——线性回归

zh-jp 2023-03-28 原文

1. 线性模型

有监督学习是通过已知的样本产生预测模型的学习方法,任何有监督学习模型都可被想象成一个函数:

\[y=f(x_1,x_2,x_3,...x_n) \tag{1-1} \]

其中,\(x_1,x_2,x_3...x_n\)是模型的n维的特征值,\(y\)是要预测的目标值/分类,当\(y\)是可枚举的类型时,对应分类问题(classification);\(y\)为连续值时,该模型解决回归问题(regression)。

线性回归(Linear Regression)在机器学习中被用来解决学习特征和目标值都是连续值类型的问题,可定义为多项式函数:

\[y=w_0+w_1x_1+w_2x_2+...+w_nx_n \tag{1-2} \]

线性模型学习的目标就是确定\(w_0 w_1..w_n\)的值,使\(y\)可以根据特征值直接通过函数计算得到,\(w_0\)成为截距,\(w_1...w_n\)被成为回归系数(coefficient)。

公式(2)可以有其他变体,注意:是否是线性模型取决于其被要求的系数\(w_0...w_n\)之间是否为线性关系,与样本特征变量\(x_0..x_n\)的形式无关。e.g.以下前者为线性模型,后者为非线性模型。

\[y=2w_0+w_1x^1+w_1x^2+...w_nx^n \]

\[y=w_0+sin(w_1)x_1+cos(x_2)x_2+... \]

2. 最小二乘法

最简单的线性模型算法便是最小二乘法(Ordinary Least Squares, OLS),通过样本真值与预测值之间的方差和来达到计算出\(w_1,w_2..w_n\)的目的,即:

\[argmin(\sum(\hat{y}-y)^2) \tag{1-3} \]

arg min就是使后面这个式子达到最小值时的变量的取值,其中\(\hat{y}\)是样本预测值,\(y\)是样本中的真值(ground truth)

在python使用

import numpy as np
from sklearn import linear_model

x = np.array([[0, 1], [3, -2], [2, 3]]) # 训练样本特征
y = np.array([0.5, 0.3, 0.9])   # 训练样本目标值

reg = linear_model.LinearRegression()  # 最小二乘法回归对象
reg.fit(x, y)   # 训练、拟合

print("intercept_:", reg.intercept_)    # 读取截距
# intercept_: 0.36666666666666686

print("coef_:", reg.coef_)  # 读取回归参数
# coef_: [0.06666667 0.13333333]

reg.predict([[1, 2], [-3, 9]]) # 预测
# array([0.7       , 1.36666667])

通过intercept_coef_属性可知道上述代码拟合的线性模型为:

\[y=0.36666666666666686+0.06666667x_1+0.13333333x_2 \]

最小二乘的不足

随着特征维度的增加,模型的求得的参数\(w_0 w_2...w_n\)的值显著增加,OLS始终试图最小化公式的值,因此为了拟合训练数据中很小的\(x\)的值差异产生的较大\(y\)值差异,必须使用较大的\(w\)值,结果是任何一个微小的变化都会导致最终预测目标值大幅度变化,即过拟合。请看:

# 测试数据
def make_data(nDim):
    x0 = np.linspace(1, np.pi, 50)  # 一个维度的特征
    x = np.vstack([[x0,], [i**x0 for i in range(2, nDim+1)]])   # nDim个维度的特征
    y = np.sin(x0) + np.random.normal(0, 0.15, len(x0)) # 目标值
    return x.transpose(), y
x, y = make_data(12)

使用最小二乘法拟合:

def linear_regression():
    dims = [1,3,6,12]   # 需要训练的维度
    for idx, i in enumerate(dims):
        plt.subplot(2, int(len(dims)/2), idx+1)
        reg = linear_model.LinearRegression()

        sub_x = x[:, 0:i]   # 取x中前i个维度的特征
        reg.fit(sub_x, y)   # 训练
        plt.plot(x[:,0], reg.predict(sub_x))    # 绘制模型
        plt.plot(x[:,0], y, '.')
        plt.title("dim %s"%i)

        print("dim %d :"%i)
        print("intercept_: %s"%(reg.intercept_))    # 查看截距参数
        print("coef_: %s"%(reg.coef_))  # 查看回归参数
    plt.show()

linear_regression()
## 输出
# dim 1 :
# intercept_: 1.5190767802159115
# coef_: [-0.39131134]
# dim 3 :
# intercept_: 1.1976858427101735
# coef_: [ 1.91353693 -1.39387114  0.16182502]
# dim 6 :
# intercept_: -221.70126917849046
# coef_: [-104.46259453  520.30421899 -573.61812163  429.72658285 -181.37364277
#    32.5448376 ]
# dim 12 :
# intercept_: -7992016.158635169
# coef_: [-1.83126880e+06  5.87461130e+07 -2.99765476e+08  9.72248992e+08
#  -1.92913886e+09  2.18748658e+09 -8.81323910e+08 -1.12973621e+09
#   2.01475457e+09 -1.40758872e+09  4.94058411e+08 -7.17485861e+07]

可以明显看到dim=12已经过拟合了

3. 岭回归

岭回归(Ridge Regression 或称Tikhonov Regularization)由俄罗斯科学家Tikhonov提出,通过改变回归目标系数,达到了控制回归参数随着维度疯狂增长的目的。新的回归函数:

\[argmin(\sum(\hat{y}-y)^2+\alpha\sum w^2) \tag{2-1} \]

OLS的差别在于将\(\alpha\sum w^2\)加入最小化目标(也被称为L2惩罚项,即L2 Penalty),其中\(\alpha\)是一个可调节的超参数,\(w\)是线性模型中的所有参数。

Ridge与原来的LinearRegression类使用方法相似,只是在初始化对象需要超参数α

def ridge_regression():
    alphas = [1e-15, 1e-12, 1e-5, 1, ]      # α参数

    for idx, i in enumerate(alphas):
        plt.subplot(2, int(len(alphas)/2), idx+1)
        reg = linear_model.Ridge(alpha=i)  # 岭回归模型

        sub_x = x[:, 0:12]   # 取x中前i个维度的特征
        reg.fit(sub_x, y)   # 训练
        plt.plot(x[:,0], reg.predict(sub_x))    # 绘制模型
        plt.plot(x[:,0], y, '.')
        plt.title("dim=12, alpha=%e"%i)

        print("alpha %e :"%i)
        print("intercept_: %s"%(reg.intercept_))    # 查看截距参数
        print("coef_: %s"%(reg.coef_))  # 查看回归参数
    plt.show()
ridge_regression()
#输出结果
# dim 1 :
# intercept_: 1.5190767802159115
# coef_: [-0.39131134]
# dim 3 :
# intercept_: 1.1976858427101735
# coef_: [ 1.91353693 -1.39387114  0.16182502]
# dim 6 :
# intercept_: -221.70126917849046
# coef_: [-104.46259453  520.30421899 -573.61812163  429.72658285 -181.37364277
#    32.5448376 ]
# dim 12 :
# intercept_: -7992016.158635169
# coef_: [-1.83126880e+06  5.87461130e+07 -2.99765476e+08  9.72248992e+08
#  -1.92913886e+09  2.18748658e+09 -8.81323910e+08 -1.12973621e+09
#   2.01475457e+09 -1.40758872e+09  4.94058411e+08 -7.17485861e+07]

比较OLS模型的12维结果,模型参数\(w\)显著降低。并且\(\alpha\)参数大小与训练结果成反比:\(\alpha\)越大,回归参数越小,模型越平缓。

3. Lasso回归

Ridge已经可以解决了多特征情况下参数太大导致的过度拟合,但在该模型中,无论\(\alpha\)多大,回归模型都存在绝对值极小的参数,难以到达零值,这部分参数对最终预测结果影响甚微但消耗计算资源,因此需要将不重要的特征参数计算为零,即压缩特征。这便是Lasso回归:

\[argmin(\sum(\hat{y}-y)^2+\alpha\sum|w|) \tag{3-1} \]

对上面的代码略作修改

def lasso_regression():
    alphas = [1e-12, 1e-5, 1, 10]      # α参数

    for idx, i in enumerate(alphas):
        plt.subplot(2, int(len(alphas)/2), idx+1)
        reg = linear_model.Lasso(alpha=i)  # Lasso模型

        sub_x = x[:, 0:12]   # 取x中前12个维度的特征
        reg.fit(sub_x, y)   # 训练
        plt.plot(x[:,0], reg.predict(sub_x))    # 绘制模型
        plt.plot(x[:,0], y, '.')
        plt.title("dim=12, alpha=%e"%i)

        print("alpha %e :"%i)
        print("intercept_: %s"%(reg.intercept_))    # 查看截距参数
        print("coef_: %s"%(reg.coef_))  # 查看回归参数
    plt.show()
lasso_regression()
## 输出
# alpha 1.000000e-12 :
# intercept_: 0.6298258513945978
# coef_: [ 1.22542814e+00 -4.54947716e-01 -3.93085543e-02 -5.49725917e-03
#  -5.88010501e-04  2.47220823e-04  3.36442748e-04  2.85372733e-04
#   2.20237636e-04  1.66111569e-04  1.25225041e-04  9.51371122e-05]
# alpha 1.000000e-05 :
# intercept_: 0.6275025198172812
# coef_: [ 1.21848162e+00 -4.48693464e-01 -4.01246675e-02 -5.58492834e-03
#  -6.02833485e-04  2.41969131e-04  3.37470151e-04  2.86500656e-04
#   2.21159502e-04  1.66823390e-04  1.25767364e-04  9.55513093e-05]
# alpha 1.000000e+00 :
# intercept_: 0.9304502324995079
# coef_: [-0.00000000e+00 -0.00000000e+00 -0.00000000e+00 -0.00000000e+00
#  -0.00000000e+00 -0.00000000e+00 -0.00000000e+00 -0.00000000e+00
#  -0.00000000e+00 -6.76060251e-04 -7.30714077e-05 -0.00000000e+00]
# alpha 1.000000e+01 :
# intercept_: 0.9076753246287685
# coef_: [-0.        -0.        -0.        -0.        -0.        -0.
#  -0.        -0.        -0.        -0.        -0.        -0.0004185]

参考文献

[1]刘长龙. 从机器学习到深度学习[M]. 1. 电子工业出版社, 2019.3.

有关有监督学习——线性回归的更多相关文章

  1. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  2. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  3. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  4. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  5. ruby - 我如何学习 ruby​​ 的正则表达式? - 2

    如何学习ruby​​的正则表达式?(对于假人) 最佳答案 http://www.rubular.com/在Ruby中使用正则表达式时是一个很棒的工具,因为它可以立即将结果可视化。 关于ruby-我如何学习ruby​​的正则表达式?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1881231/

  6. 深度学习12. CNN经典网络 VGG16 - 2

    深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG

  7. 机器学习——时间序列ARIMA模型(四):自相关函数ACF和偏自相关函数PACF用于判断ARIMA模型中p、q参数取值 - 2

    文章目录1、自相关函数ACF2、偏自相关函数PACF3、ARIMA(p,d,q)的阶数判断4、代码实现1、引入所需依赖2、数据读取与处理3、一阶差分与绘图4、ACF5、PACF1、自相关函数ACF自相关函数反映了同一序列在不同时序的取值之间的相关性。公式:ACF(k)=ρk=Cov(yt,yt−k)Var(yt)ACF(k)=\rho_{k}=\frac{Cov(y_{t},y_{t-k})}{Var(y_{t})}ACF(k)=ρk​=Var(yt​)Cov(yt​,yt−k​)​其中分子用于求协方差矩阵,分母用于计算样本方差。求出的ACF值为[-1,1]。但对于一个平稳的AR模型,求出其滞

  8. Unity Shader 学习笔记(5)Shader变体、Shader属性定义技巧、自定义材质面板 - 2

    写在之前Shader变体、Shader属性定义技巧、自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用,方便后续回顾查看,如有以偏概全、不祥不尽之处,还望海涵。1、Shader变体先看一段代码......Properties{ [KeywordEnum(on,off)]USL_USE_COL("IsUseColorMixTex?",int)=0 [Toggle(IS_RED_ON)]_IsRed("IsRed?",int)=0}......//中间省略,后续会有完整代码 #pragmamulti_c

  9. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  10. jquery - 使用 Rails 3 学习 Ajax 的资源 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。有没有学习Ajax(jQuery)和Rails3的好资源?

随机推荐