精华内容
下载资源
问答
  • 这部分原理内容有点难啃,需要恶补很多知识,比如这一期总体都在证明为什么线性回归中不能存在多重共线性这个问题。当然,如果你只记住了这个结论,那么也完全OK的,丝毫不影响你使用,但是如果希望知其所以然的,...
    这部分原理内容有点难啃,需要恶补很多知识,比如这一期总体都在证明为什么线性回归中不能存在多重共线性这个问题。当然,如果你只记住了这个结论,那么也完全OK的,丝毫不影响你使用,但是如果希望知其所以然的,可以在准备了线性代数的前几章的基础知识后,再来看看这期,保证逻辑感满满的。在 线性回归(1)—— 理论及公式推导 一文中,我们推导了线性回归的损失函数,并对多元线性回归的损失函数求导,得出求解 w 系数的式子和过程:

    fd55eaab4ad93b87647dafae82b28258.png

    在最后一步中我们需要左乘的逆矩阵,而逆矩阵存在的充分必要条件是特征矩阵不存在多重共线性。多重共线性这个词对于许多人来说都不陌生,然而却很少有人能够透彻理解这个性质究竟是什么含义,会有怎样的影响。这部分内容我们一起聊了什么是多重共线性,我们是如何一步步从逆矩阵必须存在推导到多重共线性不能存在的

    逆矩阵与多重共线性

    1. 逆矩阵存在的充分必要条件

    首先,我们需要先理解逆矩阵存在与否的意义和影响。一个矩阵什么情况下才可以有逆矩阵呢?来看逆矩阵的计算公式:

    619d81ff5f8f9a93555d293d872c2590.png

    分子上A*是伴随矩阵,任何矩阵都可以有伴随矩阵,因此这一部分不影响逆矩阵的存在性。而分母上的行列式就不同了,位于分母的变量不能为0,一旦为0则无法计算出逆矩阵。因此逆矩阵存在的充分必要条件是:矩阵的行列式

    不能为0,对于线性回归而言,即是说|XTX|不能为0。这是使用最小二乘法来求解线性回归的核心条件之一。

    2. 行列式不为0的充分必要条件

    那行列式要不为0,需要满足什么条件呢?在这里,我们来复习一下线性代数中的基本知识。假设我们的特征矩阵结构为(m,n),则XTX就是结构为(n,m)的矩阵乘以结构为(m,n)的矩阵,从而得到结果为(n,n)的方阵。

    63f2242e74ed5c65bb6b7aa1e21e321d.png

    因此以下所有的例子都将以方阵进行举例,方便大家理解。首先区别一下矩阵和行列式:

    4f7dc9cff7f7616e034fa83b5764f724.png

    重要定义:矩阵和行列式

    矩阵是一组数按一定方式排列成的数表,一般记作A;

    行列式是这一组数按某种运算法则最后计算出来的一个数,通常记作|A|或者detA矩阵。

    任何矩阵都可以有行列式。以一个3*3的行列式为例,我们来看看行列式是如何计算的:

    0b21375361ac1fb56fc5b9eb7e87b5b1.png

    这个式子乍一看非常混乱,其实并非如此,我们把行列式按照下面的方式排列一下,就很容易看出这个式子实际上是怎么回事了: 

    e917a6694b648b4735f30969bae6f94a.png

    三个特征的特征矩阵的行列式就有六个交互项,在现实中我们的特征矩阵不可能是如此低维度的数据,因此使用这样的方式计算行列式就变得异常困难。在线性代数中,我们可以通过行列式的计算将一个行列式整合成一个梯形的行列式:

    5a76519700f23a7e203af14bf778bc4f.png

    梯形的行列式表现为,所有的数字都被整合到对角线的上方或下方(通常是上方),虽然具体的数字发生了变化(比如由X11变成了a11),但是行列式的大小在初等行变换/列变换的过程中是不变的。对于梯形行列式,行列式的计算要容易很多:

    11113ee755ff54ea43cf3ee96814c7e3.png

    不难发现,由于梯形行列式下半部分为0,整个矩阵的行列式其实就是梯形行列式对角线上的元素相乘。并且此时此刻,只要对角线上的任意元素为0,整个行列式都会为0。那只要对角线上没有一个元素为0,行列式就不会为0了。在这里,我们来引入一个重要的概念:满秩矩阵

    重要定义:满秩矩阵

    满秩矩阵:A是一个n行n列的矩阵,若A转换为梯形矩阵后,没有任何全为0的行或者全为0的列,则称A为满秩矩阵。简单来说,只要对角线上没有一个元素为0,则这个矩阵中绝对不可能存在全为0的行或列。举例来说,下面的矩阵就不是满秩矩阵,因为它的对角线上有一个0,因此它存在全为0的行

    9e3525a496c8955092208c4a709aa900.png

    即是说,矩阵满秩(即转换为梯形矩阵后对角线上没有0)是矩阵的行列式不为0的充分必要条件 

    3. 矩阵满秩的充分必要条件

    一个矩阵要满秩,则转换为梯形矩阵后的对角线上没有0,那什么样的矩阵在转换为梯形矩阵后对角线上才没有0呢?来看下面的三个矩阵:

    6303bdf2a4ba68a2e66b8cb0b6611997.png

    我们可以对矩阵做初等行变换和列变换,包括交换行/列顺序,将一列/一行乘以一个常数后加减到另一列/一行上,来将矩阵化为梯形矩阵。对于上面的两个矩阵我们可以有如下变换:

    5f126689919a3a516e5d06a8ae93b806.png

    继续进行变换:

    91a02bbe598522fbd0253b1d3caace90.png

    如此就转换成了梯形矩阵。我们可以看到,矩阵A明显不是满秩的,它有全零行所以行列式会为0。而矩阵B和C没有全零行所以满秩。而矩阵A和矩阵B的区别在于,A中存在着完全具有线性关系的两行(1,1,2和2,2,4),而B和C中则没有这样的两行。而矩阵B虽然对角线上每个元素都不为0,但具有非常接近于0的元素0.02,而矩阵C的对角线上没有任何元素特别接近于0.

    矩阵A中第一行和第三行的关系,被称为“精确相关关系”,即完全相关,一行可使另一行为0。在这种精确相关关系下,矩阵A的行列式为0,则矩阵A的逆不可能存在。在我们的最小二乘法中,如果矩阵中存在这种精确相关关系,则逆不存在,最小二乘法完全无法使用,线性回归会无法求出结果。

    4c24980894af20a10d09d4d8020610bb.png

    矩阵B中第一行和第三行的关系不太一样,他们之间非常接近于”精确相关关系“,但又不是完全相关,一行不能使另一行为0,这种关系被称为”高度相关关系“。在这种高度相关关系下,矩阵的行列式不为0,但是一个非常接近0数,矩阵A的逆存在,不过接近于无限大。在这种情况下,最小二乘法可以使用,不过得到的逆会很大,直接影响我们对w参数向量的求解。

    d8ccfceca6ca07cfe11dc79933605082.png

    这样求解出来的参数w向量会很大,因此会影响建模的结果,造成模型有偏差或者不可用。精确相关关系和高度相关关系并称为"多重共线性"在多重共线性下,模型无法建立,或者模型不可用
    相对的,矩阵C的行之间结果相互独立,梯形矩阵看起来非常正常,它的对角线上没有任何元素特别接近于0,因此其行列式也就不会接近0或者为0,因此矩阵C得出的参数向量就不会有太大偏差,对于我们拟合而言是比较理想的。

    df3f5d790c147bccc2eda6f1ea80f496.png

    从上面的所有过程我们可以看得出来,一个矩阵如果要满秩,则要求矩阵中每个向量之间不能存在多重共线性,这也构成了线性回归算法对于特征矩阵的要求。

    ee3662d63c63c0e6a8dca8b6836d35e9.png

    多重共线性与相关性

    多重共线性如果存在,则线性回归就无法使用最小二乘法来进行求解,或者求解就会出现偏差。幸运的是,不能存在多重共线性,不代表不能存在相关性——机器学习不要求特征之间必须独立,必须不相关,只要不是高度相关或者精确相关就好。多重共线性是一种统计现象,是指线性模型中的特征(解释变量)之间由于存在精确相关关系或高度相关关系,多重共线性的存在会使模型无法建立,或者估计失真。多重共线性使用指标方差膨胀因子(variance inflation factor,VIF)来进行衡量,通常当我们提到“共线性”,都特指多重共线性。相关性是衡量两个或多个变量一起波动的程度的指标,它可以是正的,负的或者0。当我们说变量之间具有相关性,通常是指线性相关性,线性相关一般由皮尔逊相关系数进行衡量,非线性相关可以使用斯皮尔曼相关系数或者互信息法进行衡量。
    划重点:在现实中特征之间完全独立的情况其实非常少,因为大部分数据统计手段或者收集者并不考虑统计学或者机器学习建模时的需求现实数据多多少少都会存在一些相关性,极端情况下,甚至还可能出现收集的特征数量比样本数量多的情况。通常来说,这些相关性在机器学习中通常无伤大雅(在统计学中他们可能是比较严重的问题),即便有一些偏差,只要最小二乘法能够求解,我们都有可能会无视掉它。毕竟,想要消除特征的相关性,无论使用怎样的手段,都无法避免进行特征选择,这意味着可用的信息变得更加少,对于机器学习来说,很有可能尽量排除相关性后,模型的整体效果会受到巨大的打击。这种情况下,我们选择不处理相关性,只要结果好,一切万事大吉然而多重共线性就不是这样一回事了,它的存在会造成模型极大地偏移,无法模拟数据的全貌,因此这是必须解决的问题
    为了保留线性模型计算快速,理解容易的优点,我们并不希望更换成非线性模型,这促使统计学家和机器学习研究者们钻研出了多种能够处理多重共线性的方法,其中有三种比较常见的:
    • 使用统计学的先验思路:在开始建模之前先对数据进行各种相关性检验,如果存在多重共线性则可考虑对数据的特征进行删减筛查,或者使用降维算法对其进行处理,最终获得一个完全不存在相关性的数据集。

    • 使用向前逐步回归:逐步归回能够筛选对标签解释力度最强的特征,同时对于存在相关性的特征们加上⼀个惩罚项,削弱其对标签的贡献,以绕过最小二乘法对共线性较为敏感的缺陷。

    • 改进线性回归:在原有的线性回归算法基础上进行修改,使其能够容忍特征列存在多重共线性的情况,并且能够顺利建模,且尽可能的保证RSS取得最小值。

    这三种手段中,第一种相对耗时耗力,需要较多的人工操作,并且会需要混合各种统计学中的知识和检验来进行使用。在机器学习中,能够使用一种模型解决的问题,我们尽量不用多个模型来解决,如果能够追求结果,我们会尽量避免进行一系列检验。况且,统计学中的检验往往以“让特征独立”为目标,与机器学习中的”稍微有点相关性也无妨“不太一致。第二种手段在现实中应用较多,不过由于理论复杂,效果也不是非常高效,因此向前逐步回归不是机器学习的首选。在接下来的分享中,我们的核心会是使用第三种方法:改进线性回归来处理多重共线性。为此,一系列算法,岭回归,Lasso,弹性网就被研究出来了。下期见哦!
    展开全文
  • 全文共4968字,预计学习时长15分钟或更长本文旨在为读者理解和应用线性回归时提供参考。虽然线性回归算法很简单,但是只有少数人能真正理解其基本原则。本文首先会深入挖掘线性回归理论,理解其内在的工作机制,然后...
    全文共4968字,预计学习时长15分钟或更长
    b5d8056fc0fa702e3fd00a21de961002.png

    本文旨在为读者理解和应用线性回归时提供参考。虽然线性回归算法很简单,但是只有少数人能真正理解其基本原则。

    本文首先会深入挖掘线性回归理论,理解其内在的工作机制,然后利用Python实现该算法,为商业问题建模。

    0b107659d1f47c6649087a9334559b21.png

    理论

    线性回归或许是学习统计学最简单的方法。在学习更高级的方法之前,这是一个很好的入门方法。事实上,许多更高级的方法可被视为线性回归的延伸。因此,理解好这一简单模型将为将来更复杂的学习打下良好基础。

    线性回归可以很好地回答以下问题:

    · 两个变量间有关系吗?

    · 关系有多强?

    · 哪一个变量的影响最大?

    · 预测的各个变量影响值能有多精确?

    · 预测的目标值能有多精确?

    · 其关系是线性的吗?

    · 是否有交互作用?

    预估系数

    假设仅有一个自变量和因变量,那么线性回归表达如下:

    85f3dc29fa51073b311d39b371113b4b.png

    一个自变量和因变量线性模型的方程式

    在上图的方程中,两个β就是系数。在模型中预测结果需要用到这些系数。

    那么,如何算出这些参数呢?

    为此,需要最小化最小二乘法或者误差平方和。当然,线性模型也不是完美的,也不能准确预测出所有数据,这就意味着实际值和预测值间存在差异。该误差能用以下方程简单算出:

    0fce3ea85586d0024cd40fd3ecfe3aa3.png

    实际值减去预测值

    但为什么要平方误差呢?

    平方误差,是因为预测值可能大于也可能小于实际值,从而分别产生负或正的误差。如果没有平方误差值,误差的数值可能会因为正负误差相消而变小,而并非因为模型拟合好。

    此外,平方误差会加大误差值,所以最小化平方误差可以保证模型更好。

    下图有助于更好地理解这个概念:

    1d130cf9ccc48b9f0c8194b7bda52d91.png

    线性拟合数据集

    在上述图表中,红点是实际值,而蓝线是线性模型。灰线展现了预测值和实际值之间的误差。因此,蓝线就是灰线长度平方的最小值。

    经过一系列超出本文难度的数学计算,最终可以得到以下这个方程式,用以计算参数。

    49c14b53c516e163bb7edacc291ba65a.png
    bf2493a215f767cea5bb2ad6952118c4.png

    x和y代表平均值

    预估系数的相关性

    目前已得知系数,那么如何证明系数与因变量是否相关?

    最好的方法就是找到p值。p值被用于量化数据的重要性,它能判断零假设是否被否定。

    什么是零假设?

    所有建模任务都是在自变量和因变量存在一定关联的假设下进行的。而零假设则正好相反,也就是说自变量和因变量之间没有任何关联。

    因此,算出每一个系数的p值就能得知,从数据值上来说,该变量对于预估因变量是否重要。一般来说,如果p值小于0.05,那么自变量和因变量就之间存在强烈关系。

    评估模型的准确性

    通过找出p值,从数据值上来说,自变量是非常重要的。

    如何得知该线性模型是拟合好呢?

    通常使用RSE(残差标准差)和 R² 来评估模型。

    cee6b34ea275243ff34761595f65ffe3.png

    RSE计算公式

    59a0a2bf581ffb5e5968c6861c414873.png

    R²计算公式

    第一个误差度量很容易理解:残差越小,模型数据拟合越好(在这种情况下,数据越接近线性关系)。

    R²可以衡量因变量的变化比例,并用自变量x表述。因此,假设在一个线性方程中,自变量x可以解释因变量,那么变化比例就高, R² 将接近1。反之,则接近0。

    0b107659d1f47c6649087a9334559b21.png

    多元线性回归理论

    在现实生活中,不会出现一个自变量预测因变量的情况。所以,线性回归模型是一次只分析一个自变量吗?当然不是了,实际情况中采取多元线性回归。

    该方程式和一元线性回归方程很像,只不过是再加上预测数和相应的系数。

    d42145359c627a8ee04800795506a47b.png

    多元线性回归等式。p表示自变量的个数。

    评估自变量的相关性

    在前文中,通过找出p值来评估一元线性回归中自变量的相关性。在多元线性回归中,F统计量将被用于评估相关性。

    4f2b206ce1a9f0e94ec8220498c6b7a2.png

    F统计量计算公式。n表示数据量,p表示自变量的个数。

    F统计量在整个方程中计算,而p值则针对特定的自变量。如果两者有强烈的相关性,F大于1。相反,F大约等于1。

    比1大多少是足够大呢?

    这是一个很难回答的问题。通常,如果数据中有一个很大的数值的话,F可以仅比1大一点点,而又代表了强烈的相关性。如果数据集中的数据量很小的话,F值一定要比1大很多,才能表示强烈的相关性。

    为什么在这种情况下不能使用p值呢?

    因为我们拟合了许多自变量,所以我们需要考虑一个有很多自变量的情况(p值很大)。当自变量的数量较大时,通常会有大约5%的自变量的p值会很小——即使它们在统计上并不显著。因此,我们使用F统计量来避免将不重要的自变量视为重要的自变量。

    评估模型准确性

    和一元线性回归模型一样,多元线性回归模型的准确性也可以用R²来评估。然而,需要注意的是,随着自变量数量的增加,R²的数值也会增大。这是因为模型必然和训练数据拟合得更好。

    但是,这并不意味着该模型在测试数据上(预测未知数据时)也会有很好的表现。

    增加干扰

    在线性模型中,多元自变量意味着其中一些自变量会对其他自变量产生影响。

    比如说,已知一个人年龄和受教育年数,去预测她的薪资。很明显,年龄越大,受教育时长就越长。那么,在建模时,要怎样处理这种干扰呢?

    以两个自变量为例:

    a28aacf20a736abd73636dfa02280aa0.png

    多元线性回归中的干扰

    从上式可知,我们将两个自变量相乘,得到一个新的系数。从简化的公式中可以看到,该系数受到另一个特征值的影响。

    通常来说,在将干扰模型考虑在内时,也需要考虑个体特征的影响,即使在p值不重要时也要这么做。这就是分层递阶原则。该原则背后的根据是,如果两个自变量互相干扰,那么将它们个体影响考虑在内将会对建模有很小的影响。

    以上就是线性回归的基本原理。接下来本文将介绍如何在Python中实现一元线性回归和多元线性回归,以及如何评估两种模型的模型参数质量和模型整体表现。

    代码和数据传送门:https://github.com/marcopeix/ISL-linear-regression

    强烈建议读者在阅读本文之后动手在Jupyter notebook上复现整个过程,这将有助于读者充分理解和利用该教程。

    0b107659d1f47c6649087a9334559b21.png

    那么开始吧!

    本文用到的数据集包括在电视、广播和报纸上花费的广告费用及各自带来的销售额。

    该实验旨在利用线性代数了解广告费用对销售额的影响。

    导入库

    利用Python编程有一个好处,就是它可以提供多个库的渠道,使得我们可以快速读取数据、绘制数据和执行线性回归。

    笔者习惯于将所有必要的库放在代码的开头,使代码井然有序。导入:

    import pandas as pdimport numpy as np import matplotlib.pyplot as pltfrom sklearn.linear_model import LinearRegressionfrom sklearn.metrics import r2_score import statsmodels.api as sm

    读取数据

    下载数据集后,将数据集放在项目文件的数据目录中,读取数据:

    data = pd.read_csv("data/Advertising.csv")

    查看数据时,输入:

    data.head()

    得到结果如下:

    d923f3309b6b0ffba1a2e93bc33e0d0e.png

    可以看到,“未命名:0”列是多余的。所以,我们把这一列删除。

    data.drop(['Unnamed: 0'], axis=1)

    现在数据已经清理完毕,可以运行线性回归了!

    0b107659d1f47c6649087a9334559b21.png

    简单线性回归

    建模

    使用简单线性回归建模时,这里只考虑电视广告对销售额的影响。在正式建模之前,首先查看一下数据。

    可以利用matplotlib(一个常用的Python绘制库)来画一个散点图。

    plt.figure(figsize=(16, 8))plt.scatter( data['TV'], data['sales'], c='black')plt.xlabel("Money spent on TV ads ($)")plt.ylabel("Sales ($)")plt.show()

    运行上述代码,可以得到下图:

    bc1ed3329b54a32172bcec5a1e31bc5f.png

    电视广告费用和销售额散点图

    从图中可以看到,电视广告费用和销售额明显相关。

    基于此数据,可以得出线性近似。操作如下:

    X = data['TV'].values.reshape(-1,1)y = data['sales'].values.reshape(-1,1)reg = LinearRegression()reg.fit(X, y)print("The linear model is: Y = {:.5} + {:.5}X".format(reg.intercept_[0], reg.coef_[0][0]))

    就这么简单?

    对的!对数据集给出一条拟合直线并查看等式参数就是这么简单。在该案例中,可以得到:

    1b0240d6afdcf98e51b351febb6395c4.png

    一元线性回归等式

    接下来将数据拟合线可视化。

    predictions = reg.predict(X) plt.figure(figsize=(16, 8))plt.scatter( data['TV'], data['sales'], c='black')plt.plot( data['TV'], predictions, c='blue', linewidth=2)plt.xlabel("Money spent on TV ads ($)")plt.ylabel("Sales ($)")plt.show()

    可以得到:

    3125a060abbc9eeac1d7282ff93daadb.png

    线性拟合

    从上图可以发现,一元线性回归模型似乎就可以大致解释电视广告费用对销售额的影响。

    评估模型相关性

    接下来是检验一个模型表现是否良好,需要查看它的R²值和每个系数的p值。

    输入以下代码:

    X = data['TV']y = data['sales'] X2 = sm.add_constant(X)est = sm.OLS(y, X2)est2 = est.fit()print(est2.summary())

    可以得到如下输出:

    9c27bdaf95992c904b4f96344828a49e.png

    R²值和p值

    观察两个系数可以发现,p值虽然并不一定是0,但是非常低。这意味着这些系数和目标值(此处即销售额)之间有很强烈的联系。

    同时可以观察到,R²值为0.612。这说明大约60%的销售额变化是可以由电视广告花费来解释的。这样的结果是合理的。但是,这一定不是可以用来准确预测销售额的最好的结果。在报纸和广播广告上的花费必定对销售额有一定的影响。

    接下来将检测多元线性回归模型是否能取得更好的结果。

    0b107659d1f47c6649087a9334559b21.png

    多元线性回归

    建模

    和一元线性回归的建模过程一样,定义特征值和目标变量,并利用scikit-learn库来执行线性回归模型。

    Xs = data.drop(['sales', 'Unnamed: 0'], axis=1)y = data['sales'].reshape(-1,1)reg = LinearRegression()reg.fit(Xs, y)print("The linear model is: Y = {:.5} + {:.5}*TV + {:.5}*radio + {:.5}*newspaper".format(reg.intercept_[0], reg.coef_[0][0], reg.coef_[0][1], reg.coef_[0][2]))

    就是这么简单!根据上述代码可以得到如下等式:

    8e55ba2367ac729e9d1a5a96bc997ba7.png

    多元线性回归等式

    当然,由于一共有四个变量,这里无法把三种广告媒介对销售额的影响可视化,那将需要一个四维图形。

    需要注意的是,报纸的系数是负数,并且很小。这和模型有关吗?为了回答这个问题,我们需要计算模型的F统计量、R²值以及每个系数的p值。

    评估模型相关性

    正如你所想,这一步骤和一元线性回归模型中的相应步骤非常相似。

    X = np.column_stack((data['TV'], data['radio'], data['newspaper']))y = data['sales']X2 = sm.add_constant(X)est = sm.OLS(y, X2)est2 = est.fit()print(est2.summary())

    可以得到:

    20a7014a7761b3ce62416915459f4971.png

    R²值,p值和F统计量

    可以看到,多元线性回归模型的R²值比一元线性回归模型要高得多,达到了0.897!

    其F统计量为570.3。这比1要大得多。由于本文使用的数据集比较小(只有200个数据),这说明广告花费和销售额之间有强烈的联系。

    最后,由于本文只用了三个自变量可以利用p值来衡量它们是否与模型相关。从上表可以发现,第三个系数(即报纸广告的系数)的p值比另外两个要大。这说明从数据来看,报纸广告花费并不重要。去除这个自变量可能会使R²有轻微下降,但是可以帮助得到更加准确的预测结果。

    线性回归模型也许不是表现最好的模型,但了解线性回归是非常重要的,这将帮助我们打好基础,理解更加复杂的统计学方法。

    4ea19f235a2077b1a3f23b170d98afa1.png

    留言 点赞 关注

    我们一起分享AI学习与发展的干货

    展开全文
  • 模型之母:简单线性回归的代码实现关于作者:饼干同学,某人工智能公司交付开发工程师/建模科学家。专注于AI工程化及场景落地,希望和大家分享成长中的专业知识与思考感悟。0x00前言 在《模型之母:简单线性回归&...

    模型之母:简单线性回归的代码实现

    关于作者:饼干同学,某人工智能公司交付开发工程师/建模科学家。专注于AI工程化及场景落地,希望和大家分享成长中的专业知识与思考感悟。

    0x00 前言

    在《模型之母:简单线性回归&最小二乘法》中,我们从数学的角度理解了简单线性回归,并且推导了最小二乘法。

    本文内容完全承接于上一篇,我们来以代码的方式,实现简单线性回归。话不多说,码起来

    0x01 简单线性回归算法的实现

    首先我们自己构造一组数据,然后画图

    import numpy as npimport matplotlib.pyplot as pltx = np.array([1.,2.,3.,4.,5.])y = np.array([1.,3.,2.,3.,5,])plt.scatter(x,y)plt.axis([0,6,0,6])plt.show()

    下面我们就可以根据样本真实值,来进行预测。

    实际上,我们是假设线性关系为: 这根直线,然后再根据最小二乘法算a、b的值。我们还可以假设为二次函数:。可以通过最小二乘法算出a、b、c

    实际上,同一组数据,选择不同的f(x),即模型,通过最小二乘法可以得到不一样的拟合曲线。

    不同的数据,更可以选择不同的函数,通过最小二乘法可以得到不一样的拟合曲线。

    下面让我们回到简单线性回归。我们直接假设是一条直线,模型是:

    根据最小二乘法推导求出a、b的表达式:

    下面我们用代码计算a、b:

    # 首先要计算x和y的均值x_mean = np.mean(x)y_mean = np.mean(y)# a的分子num、分母dnum = 0.0d = 0.0for x_i,y_i in zip(x,y):   # zip函数打包成[(x_i,y_i)...]的形式    num = num + (x_i - x_mean) * (y_i - y_mean)    d = d + (x_i - x_mean) ** 2a = num / db = y_mean - a * x_mean

    在求出a、b之后,可以计算出y的预测值,首先绘制模型直线:

    y_hat = a * x + bplt.scatter(x,y)    # 绘制散点图plt.plot(x,y_hat,color='r')    # 绘制直线plt.axis([0,6,0,6])plt.show()

    然后进行预测:

    x_predict = 6y_predict = a * x_predict + bprint(y_predict)

    5.2

    0x02 向量化运算

    我们注意到,在计算参数a时:

    # a的分子num、分母dnum = 0.0d = 0.0for x_i,y_i in zip(x,y):   # zip函数打包成[(x_i,y_i)...]的形式    num = num + (x_i - x_mean) * (y_i - y_mean)    d = d + (x_i - x_mean) ** 2a = num / d

    我们发现有这样一个步骤:向量w和向量v,每个向量的对应项,相乘再相加。其实这就是两个向量“点乘”

    这样我们就可以使用numpy中的dot运算,非常快速地进行向量化运算。

    总的来说:

    向量化是非常常用的加速计算的方式,特别适合深度学习等需要训练大数据的领域。

    对于 y = wx + b,  若 w, x都是向量,那么,可以用两种方式来计算,第一是for循环:

    y = 0for i in range(n):    y += w[i]*x[i]    y += b

    另一种方法就是用向量化的方式实现:

    y = np.dot(w,x) + b

    二者计算速度相差几百倍,测试结果如下:

    import numpy as npimport timea = np.random.rand(1000000)b = np.random.rand(1000000)tic = time.time()c = np.dot(a, b)toc = time.time()print("c: %f" % c)print("vectorized version:" + str(1000*(toc-tic)) + "ms")c = 0tic = time.time()for i in range(1000000):    c += a[i] * b[i]toc = time.time()print("c: %f" % c)print("for loop:" + str(1000*(toc-tic)) + "ms")

    运行结果:

    c: 249981.256724vectorized version:0.998973846436msc: 249981.256724for loop:276.798963547ms

    对于独立的样本,用for循环串行计算的效率远远低于向量化后,用矩阵方式并行计算的效率。因此:

    只要有其他可能,就不要使用显示for循环。

    0x03 自实现的工程文件

    3.1 代码

    还记得我们之前的工程文件吗?创建一个SimpleLinearRegression.py,实现自己的工程文件并调用

    import numpy as npclass SimpleLinearRegression:    def __init__(self):        """模型初始化函数"""        self.a_ = None        self.b_ = None    def fit(self, x_train, y_train):        """根据训练数据集x_train,y_train训练模型"""        assert x_train.ndim ==1, \            "简单线性回归模型仅能够处理一维特征向量"        assert len(x_train) == len(y_train), \            "特征向量的长度和标签的长度相同"        x_mean = np.mean(x_train)        y_mean = np.mean(y_train)        num = (x_train - x_mean).dot(y_train - y_mean)  # 分子        d = (x_train - x_mean).dot(x_train - x_mean)    # 分母        self.a_ = num / d        self.b_ = y_mean - self.a_ * x_mean        return self    def predict(self, x_predict):        """给定待预测数据集x_predict,返回表示x_predict的结果向量"""        assert x_predict.ndim == 1, \            "简单线性回归模型仅能够处理一维特征向量"        assert self.a_ is not None and self.b_ is not None, \            "先训练之后才能预测"        return np.array([self._predict(x) for x in x_predict])    def _predict(self, x_single):        """给定单个待预测数据x_single,返回x_single的预测结果值"""        return self.a_ * x_single + self.b_    def __repr__(self):        """返回一个可以用来表示对象的可打印字符串"""        return "SimpleLinearRegression()"

    3.2 调用

    下面我们在jupyter中调用我们自己写的程序:

    首先创建一组数据,然后生成SimpleLinearRegression()的对象reg1,然后调用一下

    from myAlgorithm.SimpleLinearRegression import SimpleLinearRegressionx = np.array([1.,2.,3.,4.,5.])y = np.array([1.,3.,2.,3.,5,])x_predict = np.array([6])reg = SimpleLinearRegression()reg.fit(x,y)

    输出:SimpleLinearRegression()

    reg.predict(x_predict)reg.a_reg.a_

    输出:array([5.2]) 0.8 0.39999999999999947

    y_hat = reg.predict(x)plt.scatter(x,y)plt.plot(x,y_hat,color='r')plt.axis([0,6,0,6])plt.show()

    0xFF 总结

    在本篇文章中,我们实现了简单线性回归算法的代码,并且使用了向量化运算,事实证明,向量化运算能够提高运算效率。

    同时我们发现,只要数学公式推导清楚了,实际写代码时没有太多难度的。

    那么我们思考一个问题,在之前的kNN算法(分类问题)中,使用分类准确度来评价算法的好坏,那么回归问题中如何评价好坏呢?

    热门文章

    直戳泪点!数据从业者权威嘲讽指南!

    AI研发工程师成长指南

    数据分析师做成了提数工程师,该如何破局?

    算法工程师应该具备哪些工程能力

    数据团队思考:如何优雅地启动一个数据项目!

    数据团队思考:数据驱动业务,比技术更重要的是思维的转变

    503247f9520911de025a6f250859ea47.png

    展开全文
  • 01 解决何种问题 线性回归都知道是用来描述两个变量之间的线性关系,比如身高和体重,自变量身高每增加1个单位,因变量体重就变化多少,但是现实中能用线性回归描述的情况太少了,绝大部分关系都是非线性关系,这个...

    d4fc7bb961caed7688acb21316153ac6.png

    01 解决何种问题

    线性回归都知道是用来描述两个变量之间的线性关系,比如身高和体重,自变量身高每增加1个单位,因变量体重就变化多少,但是现实中能用线性回归描述的情况太少了,绝大部分关系都是非线性关系,这个时候就必须用其他回归来拟合了。例如类似下图这种数据,马上会想到用多项式回归,数据拐了2个弯,可以考虑用3次项回归,

    如图2,其大致反应了数据的变化趋势,但有不足的地方,多项式是基于所有数据的,即所有的数据都符合多项式规律,且常常随着次数的增加,模型的复杂度也在玄素增加。但有的数据在某个值之前成直线关系,某个值之后又是二次项或三次项关系,这种数据就不能用一种关系表示,而要把数据分开,分开拟合曲线。仔细看数据,每段都是一个明显的线性关系,在拐点的地方,数据前后趋势发生变化,可以考虑用样条回归,如图3,较好的拟合曲线。

    d790989c460d162dd965cb3cd2c1752c.png

    b37f9b994767d3317bcc9c759042afba.png

    924ce0ddfa13432458e1f77138b53a79.png

    02 方法说明

    样条回归是把数据集划分成k个连续区间,划分的点为节点,每一个连续区间都用单独的模型,线性函数或者低阶多项式函数(如二次或三次多项等),一般称为分段函数来拟合,很明显,节点越多,模型也越灵活。

    样条回归可以看成是分段回归,但又不是简单的分段回归,它是加了约束条件的分段回归,要求在节点处连续。上图3展示的是简单的线性样条,有些数据过于复杂,还要考虑多项式样条回归,即每个分段拟合多项式,若是多项式样条,则不仅要求在节点连续,还要求在节点一阶导数相等,这样拟合出来的曲线更光滑,连起来也很自然。

    03 R代码及解读

    library(ISLR)
    library(splines)
    data(Wage)
    set.seed(1234)
    index <- sample(1:nrow(Wage),200)
    dt <- Wage[index,]   ##加载数据集

    第一部分:分段多项式回归

    onefit <- lm(wage~poly(age,3),data=dt,subset = (age<=40))
    twofit <- lm(wage ~ poly(age,3),data=dt,subset = (age>40))
    agelim1 <- range(min(dt$age),40)
    age_grid1 <- seq(agelim1[1],agelim1[2])
    preds1 <- predict(onefit,newdata = list(age=age_grid1),se.fit = T)
    se_lim1 <- cbind(preds1$fit+2*preds1$se.fit,preds1$fit-2*preds1$se.fit)
    
    agelim2 <- range(40,max(dt$age))
    age_grid2 <- seq(agelim2[1],agelim2[2])
    preds2 <- predict(twofit,newdata = list(age=age_grid2),se.fit = T)
    se_lim2 <- cbind(preds2$fit+2*preds2$se.fit,preds2$fit-2*preds2$se.fit)
    
    agelim <- range(dt$age)
    plot(dt$age,dt$wage,xlim=agelim,cex=0.5,col='gray',
         cex.axis=0.8,cex.lab=0.8,
         ylab="Wage",
         xlab="age")
    lines(age_grid1,preds1$fit,lwd=2,col='purple')
    lines(age_grid2,preds2$fit,lwd=2,col='purple')
    abline(v=40,lwd=1,lty=3)

    b885e4b2198040f38310518f377b274e.png

    ①上述数据集是从原始工资数据集Wage随机抽取200个样本用来拟合数据。

    ②我们在age=40处,将原数据集一分为二,切成两段,分别拟合3次多项式回归。因此有两个分段回归模型,最终拟合结果见上图。

    ③ 一个很重要的问题,整个模型在x=40处不连续,为了使模型在整个取值区间连续且光滑,我们给分段多项式模型添加一个限制,即:限制性回归样条。

    第二部分:单节点的回归样条

    newwage=dt
    fit <- lm(wage~bs(age,degree=2,knots = c(40)),data=newwage)##注意bs
    agelim <- range(newwage$age)
    age_grid <- seq(agelim[1],agelim[2])
    preds <- predict(fit,newdata=list(age=age_grid),se.fit=T)
    plot(newwage$age,newwage$wage,col='gray',
         cex.axis=0.8,cex.lab=0.8,
         ylab="Wage",
         xlab="age" )
    lines(age_grid,preds$fit,col=rainbow(100)[40],lwd=2)
    abline(v=c(40),lty=2,lwd=1)

    bbd273f838216768f64c7396dcba3120.png

    采用splines包中ns,做样条回归,由图我们的拟合的样条回归,光滑且连续。该样条还可称之为B样条,它存在的缺点是在数据的开始和结尾处,由于数据量少,导致模型的预测方差很大,可以看出95%的置信区间比较宽,由下图所示,因此引出自然样条回归。

    第三部分:B样条vs自然样条

    fit <- lm(wage~bs(age,knots = c(25,40,60)),data=newwage) ##bs样条,ns 是自然样条
    agelim <- range(newwage$age)
    age_grid <- seq(agelim[1],agelim[2])
    preds <- predict(fit,newdata=list(age=age_grid),se.fit=T)
    se_lim <- cbind(preds$fit+2*preds$se.fit,preds$fit-2*preds$se.fit)
    
    plot(newwage$age,newwage$wage,col='gray',
         cex.axis=0.8,cex.lab=0.8,
         ylab="Wage",
         xlab="age" )
    lines(age_grid,preds$fit,col='red')
    matlines(age_grid,se_lim,lty=2,col='red')
    abline(v=c(25,40,60),lty=2,lwd=1)
    
    ############自然样条  ns
    fit <- lm(wage~ns(age,knots = c(25,40,60)),data=newwage)  
    agelim <- range(newwage$age)
    age_grid <- seq(agelim[1],agelim[2])
    preds <- predict(fit,newdata=list(age=age_grid),se.fit=T)
    se_lim <- cbind(preds$fit+2*preds$se.fit,preds$fit-2*preds$se.fit)
    
    lines(age_grid,preds$fit,col='blue')
    matlines(age_grid,se_lim,Ity=2,col='blue')
    abline(v=c(25,40,60),lty=2,lwd=0.8)
    legend(x=20,y=290,c('cubic spline','natural cubic spline'),col=c('red','blue'),
           lty=1,lwd=1,cex=0.8)

    2269255b651beedc3e9300fc34edeed2.png

    需要说明的几个点:

    ①函数bs()的使用说明:构建一个多次回归样条的操作是很简单的,将整个模型放到lm()中,bs()函数的右边是预测的变量,knots定义的是将age分成多段的节点。如果不知道选择什么节点,则可以定义df=7,表示定义3个节点,那么模型会自动选择3个节点进行拟合,其中df=节点数+4。里面还有个参数degree,表示的是多次样条回归的次数,默认是3次回归样条,可以传入其他参数,比如4和5。

    ②为了解决B样条回归的边界预测误差大的问题,统计学家们又在B样条回归增加约束,这种回归成为自然样条回归,对应函数是ns(),通过上图的对比,蓝色为自然样条回归,红色为B样条回归,蓝色的虚线间距比红色的虚线间距窄,尤其是在age的两端,表明自然回归在age的边界处得到的结果更加稳健。

    05 更多阅读

    文章在公粽号:易学统计

    文章里的干货更多哟

    欢迎交流,欢迎提问

    展开全文
  • 源宝导读:本文将讲解在大数据分析领域的线性回归统计计算方法,以及如何将非线性转化为线性回归的原理,同时介绍了两种的回归统计库的使用和对比,最后介绍线性回归在DMP产品的应用实践。一、背景 回归统计,是数据...
  • 在《大家的人工智能——线性回归》中,什么是拟合,代价函数,梯度下降,相信大家已经对这些基本概念有所了解。线性回归的应用场景是输出为连续的数值,比如下个月的房价多少,明天的气温多少。而在机器学习中还有一...
  • 例子来自QE回归2017年1月的第4题,目的是通过高中成绩排名X1与ACT分数X2预测大学第一年的GPA。数据在https://statistics.arizona.edu/sites/default/files/uagc_page/jan_17_data_sets.xlsx初始模型是然而高中成绩...
  • 代码 #include<iostream> #include<random> using namespace std; double w = 0;//y=w*x+b,初始w double b = 0;//y=w*x+b,初始b double true_w = 10.0;...double* x = new double[s
  • 逐步回归分析是以AIC信息统计量为准则,通过选择最小的AIC信息统计量,来达到...载入数据 首先对数据进行多元线性回归分析tdatax1=c( 7, 1,11,11, 7,11, 3, 1, 2,21, 1,11,10),x2=c(26,29,56,31,52,55,71,31,54,47,...
  • 原文链接:http://tecdat.cn/?p=18550​tecdat.cn我根据泊松Poisson回归、GAM样条曲线模型对一个十字路口的骑自行车者的数量进行预测,str(base)'data.frame': 214 obs. $ 日期 : chr "1-Apr" "2-Apr" "3-Apr7" "4-...
  • C++实现回归算法, 包含线性回归和逻辑回归, 代码干净, 整洁, 有注释, 具有良好的封装性, 可直接迁移使用
  • C++实现线性回归

    2015-03-04 22:13:25
    c++实现线性回归问题,实现房价的预测,VIM+GNU+Linux+MAKE+GDB
  • 实现多元线性回归的要求及假设条件: ''' 线性回归的假设条件: 1、样本独立,即每个预测样本之间没有依赖关系; 2、残差e要服从正态分布,即y_true-y_pred的残差需要服从高斯分布; 3、特征之间独立,即特征...
  • Photo by Michael Dziedzic on Unsplash从头开始学习为Python中任意数量的变量开发多元线性回归线性回归可能是最简单的机器学习算法。对于初学者来说非常好,因为它使用简单的公式。因此,这对学习机器学习概念很...
  • 一、实验背景回归主要关注确定一个唯一的因变量...关于视力的定量预测方法很多,本文主要介绍多元线性回归方法在右眼视力预测中的具体操作。训练集及测试集结构如下:二、提出问题1、在众多变量中判断哪些...
  • 1. 多元线性回归2. 多项式回归3. 正则化4. 线性回归应用举例(酒质量预测)4.1 数据预览4.2 模型验证5. 梯度下降法本文为 scikit-learn机器学习(第2版)学习笔记1. 多元线性回归模型 写成向量形式:还是披萨价格预测的...
  • 多元线性回归-梯度下降法 c++

    千次阅读 2018-11-08 16:31:00
    多元线性回归-梯度下降法 c++线性回归(Linear Regression)损失函数(Loss Function)梯度下降(gradient descent)批梯度下降(batch gradient descent)随机梯度下降(Stochastic Gradient Descent, SGD)代码...
  • 本文根据小红书的3万余条销售数据,利用Python进行线性回归,对小红书的销售额进行预测。以下为关键数据维度概览:下图为数据分析流程及思路:数据概况分析:年龄、性别及参加活动情况存在缺失值,占比为40%,计划用...
  • 线性回归c++实现

    2019-04-19 21:03:02
    线性回归模型的小demo,利用梯度下降法进行模型训练,在一个toy set上进行了验证。
  • 线性回归介绍及分别使用最小二乘法和梯度下降法对线性回归C++实现
  • 线性回归 c++

    千次阅读 2017-06-12 00:34:35
    多元线性回归指的是根据多个自变量拟合一条曲线可以根据给定的自变量输出尽可能准确的因变量。
  • 线性回归 c++代码实现

    热门讨论 2009-05-05 21:50:32
    线性回归 公式 线性回归 公式 线性回归 公式 线性回归 公式
  • 局部线性回归c++实现

    2014-03-11 23:27:53
    机器学习,非参数学习算法,局部加权线性回归c++实现
  • 一元线性回归,最小二乘法,C++语言VS2008下调试通过,可直接使用,有注释。
  • C++实现线性回归(多变量)

    千次阅读 2015-03-04 21:49:50
    本文主要介绍c++实现线性回归问题,实现房价的预测,参考链接:http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=DeepLearning&doc=exercises/ex2/ex2.html   1、测试数据:房价的估计 2、...
  • 亲测修改调试通过的基于GNU C++的控制台应用程序,C++实现多元线性回归,可指定几元,可给定的数据矩阵,训练给出回归方程式。

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 239
精华内容 95
关键字:

c++线性回归

c++ 订阅