如何理解线性回归

第一次使用线性回归时,一直无法想象电脑是怎么找到这条最佳的拟合直线的。知道看过了机器学习我想才对此有了一点点理解

回归分析是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。一元线性回归只包括一个x和一个y,可以用一条直线来近似表达他们之间的关系

比如我们在python中制造一个数据,数据按照 y = 2 x + 3 y=2x+3 y=2x+3设计,每一个x对应的y的值上下波动0.2

x = [1, 2, 3, 4, 5]
y = [4.8, 7.2, 8.8, 11.2, 12.8]
plt.scatter(x, y)
plt.xlim(0,6)
plt.ylim(0,14)
plt.show()

就得到这样的一个图形,现在我们就需要用一条直线 y = a x + b y=ax+b y=ax+b最好地拟合这些点,那么如何确定这里的 a a a b b b
在这里插入图片描述

我们需要一个评价它拟合的好不好的指标,那就是每个点向 x x x轴做垂线到这条直线的距离的平方和最小(也就是这里的 d 1 2 + d 2 2 + d 3 2 d_1^2+d_2^2+d_3^2 d12+d22+d32最小,这里的 d i d_i di就是真实值和预测值的距离,我们用 y y y表示真实值, y h y_h yh表示预测值)
在这里插入图片描述

这里我们用 J = ∑ ( y − y h ) 2 J=\sum(y-y_h)^2 J=(yyh)2这个函数表示,我们需要J的值最小时,就是最佳的拟合直线,这个 J J J也可以写为 J = ∑ [ y − ( a x + b ) ] 2 J=\sum[y-(ax+b)]^2 J=[y(ax+b)]2,所以我们就是要寻找 a a a b b b使得 J J J最小
现在我们假设 b = 0 b=0 b=0,不断改变 a a a的值,去做出 J J J关于 a a a的一个函数图形如下(横轴为 a a a,竖轴为 J J J

a = 0
b = 0
J = 0
Js = []
for i in range(0,10):
    a = i
    J = 0
    for j in range(0,5):
        y_h = (a*x[j])+b
        J = J+(y[j]-y_h)**2
    Js.append(J)
plt.plot(Js)
plt.show()

在这里插入图片描述

同理我们使 a = 0 a=0 a=0,不断改变 b b b的值,得到 J J J关于 b b b的一个函数图像如图(横轴为 b b b,竖轴为 J J J

a = 0
b = 0
J = 0
Js = []
for i in range(0,20):
    b = i
    J = 0
    for j in range(0,5):
        y_h = (a*x[j])+b
        J = J+(y[j]-y_h)**2
    Js.append(J)
plt.plot(Js)
plt.show()

在这里插入图片描述

这时我们可以看到, J J J a a a和与 b b b都是一个二次函数的图像,分别在只有 a a a和只有 b b b时都有 J J J有一个最小值 J m i n J_{min} Jmin,也就是说当 b = 0 b=0 b=0,方程为大概 y = 3 x y=3x y=3x,使得 J J J最小;当 a = 0 a=0 a=0时,方程大概为 y = 8 y=8 y=8,使得 J J J最小。可是我们知道这个方程应该为 y = 2 x + 3 y=2x+3 y=2x+3。由以上的内容我们想想一个三维的图形,平面坐标是 a a a b b b z z z轴是 J J J,那么这个曲面应该是一个凹面,它拥有一个最低点,而这个最低点对应的平面坐标 a a a b b b就是使得 J J J最小的 a a a b b b,也就是方程的最佳拟合时的参数 a a a b b b的值。这里我们试着绘制一下,先导入一个包

from mpl_toolkits.mplot3d import Axes3D

绘制

def func(x, y, a, b):
    J = 0
    for k in range(0,5):
        y_h = (a*x[k])+b
        J = J+(y[k]-y_h)**2
    return J

figure = plt.figure()
ax = Axes3D(figure)
a = np.arange(0, 4, 0.01)
b = np.arange(-1, 9, 0.01)
a, b = np.meshgrid(a, b)
ax.plot_surface(a, b, func(x, y, a, b), cmap='rainbow')
plt.show()

在这里插入图片描述

这个看起来效果不太理想,但是大概能看出其中有一个最低点。现在线性回归要做的就是到这个最低点找到 a a a b b b。这里我们使用梯度下降的方法(还可以使用正规方程),就是一个梯度下降的过程了。初始化 a a a b b b为零,它会对应这个曲面上的某个点,然后开始用梯度下降逐渐滑到最低点去。比如一个二次函数 y = x 2 y=x^2 y=x2

在这里插入图片描述

梯度下降就是沿着这个曲面下降到最低点,这里就涉及到求导,因为你不知道开始是在坐标轴的坐标还是右边。导数为 y ′ = 2 x y'=2x y=2x,在对称轴的左边,导数为负;在对称轴的右边,导数为正。这样如果用 x = x − y ′ x=x-y' x=xy的话,无论 x x x为正还是为负,都会向着中间 x = 0 x=0 x=0的最低处移动。比如在下图中的 p p p点, p p p的值为负, y ′ = 2 p y'=2p y=2p,此时y’为负,若 x = x − y ′ x=x-y' x=xy,则 x x x实际是向右边移动了,也就是向着最低点前进。同时由于导数越来越小,最后就会基本到到最低点

在这里插入图片描述

这里我们只需要不断地求 J J J,然后让 a = a − α ( ∂ J / ∂ a ) a=a-\alpha (\partial J/\partial a) a=aα(J/a) b = b − α ( ∂ J / ∂ b ) b=b-\alpha(\partial J/\partial b) b=bα(J/b)(这里的 α \alpha α是一个常数),又不断地更新 a a a b b b,再求 J J J,再重复,直到 J J J基本到达最低点就可以说此时的 a a a b b b就是让方程 y = a ∗ x + b y=a*x+b y=ax+b满足的最好拟合参数。

a = 0
b = 0
J = 0
ah = 0.0005

def updata(x, y, a, b):
    Ja = 0
    Jb = 0
    for j in range(0,5):
        y_h = (a*x[j])+b
        Ja = Ja+(y_h-y[j])
        Jb = Jb+Ja*x[j]
    a = a-ah*Ja
    b = b-ah*Jb
    return a, b
    
for i in range(20000):
    J = func(x, y, a, b)   # 前面定义了
    a, b = updata(x, y, a, b)
    if i % 2000 == 0:
        print('a='+str(a)+' b='+str(b)+' J='+str(J))

这里我们看一下循环得到的结果

a=0.0224 b=0.2216 J=441.6
a=1.7664841446040385 b=3.580773535019366 J=0.770107135157793
a=1.9492674087971757 b=3.0994595812218364 J=0.21858310750245388
a=1.9784539542211008 b=3.02260412272189 J=0.19666523846829964
a=1.9831144160940348 b=3.010331963449066 J=0.19485203231430406
a=1.983858591348545 b=3.0083723642721525 J=0.19460550610000818
a=1.9839774200879534 b=3.0080594585439284 J=0.19456723765429518
a=1.9839963944749992 b=3.0080094942471955 J=0.19456115496582815
a=1.983999424275414 b=3.008001516026525 J=0.19456018440448342
a=1.9839999080691983 b=3.0080002420767453 J=0.1945600294449439

可以发现随着 a a a b b b的改变,梯度下降使得 J J J越来越小,此时对应的 a = 1.98 a=1.98 a=1.98 b = 3.01 b=3.01 b=3.01就可以得到方程 y = 1.98 x + 3.01 y=1.98x+3.01 y=1.98x+3.01,与结果就基本差不多了,因为有波动,所以 J J J是不可能等于0的,就是说一条直线不能完全地经过这些点,我们看看拟合的效果

plt.scatter(x, y)
x2 = np.linspace(0, 6, 100)
fy = a*x2+b
plt.plot(x2, fy)
plt.xlim(0,6)
plt.ylim(0,14)
plt.show()

在这里插入图片描述

在python中可以使用sklearn这个包里的工具快速实现线性回归

from sklearn.linear_model import LinearRegression

x = [[1], [2], [3], [4], [5]]
y = [[4.8], [7.2], [8.8], [11.2], [12.8]]
model = LinearRegression()
model.fit(x, y)
model.score(x, y)
beta= model.intercept_[0]
alpha= model.coef_[0][0]
print('线性回归函数为:\n')
print(str(alpha) + ' x + '+ str(beta))

得到结果就是这样的

线性回归函数为:

2.0000000000000004 x + 2.9599999999999973

都差不多的,好了,这就是关于线性回归的简单理解

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 线性回归是一种传统的统计学习算法,可以用于建立输入变量与输出变量之间线性关系的模型。在编程实现时,我们需要编写一定的代码来实现自变量和因变量之间的线性关系建模,并使用优化方法进行参数估计。因此,代码和理解需要相互结合,通过代码的实现来加深对线性回归算法的理解和掌握。 ### 回答2: 线性回归是一种机器学习算法,用于建立一个线性模型来预测连续型的数值输出。在理解线性回归时,我们可以通过编写和运行代码来加深对其原理和工作方式的理解。 首先,我们需要导入相关的库,如numpy和pandas,来处理数据和执行数学计算。然后,我们可以创建一个线性回归的模型对象,例如使用sklearn库中的LinearRegression类。 接下来,我们要读取包含训练数据的csv文件或使用内置的模拟数据集。我们可以使用pandas库中的read_csv函数来加载数据,然后使用head函数检查数据的内容和格式。 在进行线性回归之前,我们需要对数据进行预处理。这包括处理缺失值、标准化数据和分割数据为训练集和测试集。我们可以使用pandas库中的fillna函数填充缺失值、使用sklearn库中的StandardScaler类标准化数据,并使用train_test_split函数分割数据。 接下来,我们可以使用线性回归模型对象来训练模型。我们可以调用模型对象的fit方法,将训练数据作为输入,通过最小化损失函数拟合数据。在这个过程中,模型会调整权重和偏差的值,以找到最佳的直线拟合数据。 当模型训练完成后,我们可以使用测试数据集来评估模型的性能。我们可以调用模型对象的predict方法,将测试数据作为输入,预测输出值。然后,我们可以使用模型评估指标,如均方误差(Mean Squared Error)或决定系数(Coefficient of Determination),来衡量预测结果与实际结果之间的差异。 通过运行这些代码,我们可以更好地理解线性回归的工作原理。我们可以观察权重和偏差的变化,了解模型是如何拟合数据的。同时,我们也可以通过修改模型参数和尝试不同的数据,来观察模型的性能和变化。这种通过代码来实践的方法,可以帮助我们深入理解线性回归算法的功能和特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值