人工神经网络基础:最小二乘法线性回归

直接用numpy实现最小二乘法线性回归

先放上代码和注释吧,有空再写

#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''最小二乘法回归y=wx+b。(numpy实现)
by lei<hustlei@sina.cn>
'''

import numpy as np
import matplotlib.pyplot as plt

#回归数据集

##生成数据集
'''在线性方程y=2x+3上,随机取N个点,加上随机噪声,作为回归对象'''
N=200  #回归数据点个数。
x = np.random.normal(size=N)
y = 2*x + 3 + np.random.normal(size=N)

##查看数据集
plt.scatter(x,y)
plt.plot(x, 2*x+3)
plt.show()


#线性回归

##初始化参数
w=0  #初始化权重(y=wx+b斜率)
b=0  #初始化偏置(y=wx+b截距)
lr=0.03  #递归下降学习率(迭代步长)

##循环回归(最小二乘法)
for epoch in range(100):
    y_pre = w*x+b  #根据预估参数预测y
    loss = np.sum((y_pre-y)**2)  #残差的平方(二乘)和表征误差。误差最小时,拟合精度最高。
    grad_w = np.mean(2*(y_pre-y)*x)  #梯度公式为np.sum(2*(y_pre-y)*x)。除以N,可以让梯度和权重w在同一个数量级。
    grad_b = np.mean(2*(y_pre-y))  #计算梯度
    w -= grad_w*lr  #更新权重
    b -= grad_b*lr  #更新偏置量
    if (epoch+1)%10==0:  
        print(f"loop count:{epoch+1},weight:{w:.2f},bias:{b:.2f},loss:{loss:.2f}")
    # loss稳定后退出循环
    # if(abs(loss-losslast)<0.001):  #需要在重新计算loss前保存lastloss
        # break
        
plt.scatter(x,y)
plt.plot(x,w*x+b)
plt.show()

最小二乘法线性回归解析解

最小二乘法,最优数学解(残差的平方和最小值在导数为0处,依此可求出最优解公式)

  • w的最优解 w = x T y − x ‾ y ‾ x T x − x ‾ 2 w=\frac{x^Ty-\overline x \overline y}{x^Tx-\overline x^2} w=xTxx2xTyxy,其中x,y均为列向量。
x=x[:,None]
w=(x.T@y-np.mean(x)*np.mean(y))/(x.T@x-np.mean(x)**2)
print(w.item())  #最优解为2.016666

b的最优解: b = y ‾ − w x ‾ b=\overline y - w \overline x b=ywx

b=np.mean(y)-w*np.mean(x)   #b最优解为2.97

pytorch 自动求梯度功能

pytorch可以实现自动求梯度,从而免去我们根据公式推导导数的麻烦。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''最小二乘法回归y=wx+b。应用pytorch自动求梯度功能
by lei<hustlei@sina.cn>
'''

import torch
import numpy as np
import matplotlib.pyplot as plt

#数据集

##生成数据集
'''在线性方程y=2x+3上,随机取N个点,加上随机噪声,作为回归对象'''
N=200  #回归数据点个数。
x = torch.randn(N)  #使用torch的自动求梯度功能时,需要求梯度的量与numpy数组运算会出错。
y = 2*x + 3 + torch.randn(N)

##查看数据集
plt.scatter(x,y)
plt.plot(x, 2*x+3)
plt.show()


#线性回归

##初始化参数
w=torch.tensor(0.0, requires_grad=True)  #初始化权重(y=wx+b斜率),注意只有浮点类型数据才能自动求梯度
b=torch.tensor(0.0, requires_grad=True)  #初始化偏置(y=wx+b截距)
lr=0.03  #递归下降学习率(迭代步长),注意步长不能太大

##循环回归(最小二乘法)
for epoch in range(100):
    y_pre = w*x+b  #根据预估参数预测y
    loss = torch.sum((y_pre-y)**2)  #残差的平方(二乘)和表征误差。注意不能用np.sum
    loss.backward()  #反向传播求梯度
        
    w.data -= w.grad*lr/N  #更新权重。注意用-=,即inplace算法时,不能直接作用在leaf节点w上。
    b.data -= b.grad*lr/N  #更新偏置量。
        
    w.grad.data.zero_()  #清零梯度值。注意:对grad的数值data进行清零,避免把清零操作当作求梯度的一部分。
    b.grad.data.zero_()

    if (epoch+1)%10==0:  
        print(f"loop count:{epoch+1},weight:{w:.2f},bias:{b:.2f},loss:{loss:.2f}")
    # loss稳定后退出循环
    # if(abs(loss-losslast)<0.001):  #需要在重新计算loss前保存lastloss
        # break

with torch.no_grad():#因为w*x+b计算中会把tensor转换为numpy数组,但是自动求梯度的tensor不能转换
    plt.scatter(x,y)
    plt.plot(x,w*x+b)#直接用w.item()或者w.detach().numpy()也可以消除自动求梯度
    plt.show()

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hustlei

您的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值