线性回归利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的,表达形式为 y = w x + b + e y = wx+b+e y=wx+b+e, e e e为误差服从均值为0的正态分布。首先让我们来确认线性回归的损失函数:
l o s s = ∑ i N 1 2 ( y i − ( w x i + b ) ) 2 loss = \sum_i^N \frac 1 2 ({y_i-(wx_i+b)})^2 loss=i∑N21(yi−(wxi+b))2
然后利用随机梯度下降法更新参数 w \textbf{w} w和 b \textbf{b} b来最小化损失函数,最终学得 w \textbf{w} w和 b \textbf{b} b的数值。
import torch as t
from matplotlib import pyplot as plt
from IPython import display
device = t.device('cpu')#或cuda:0
#实验数据
t.manual_seed(1000)#设置随机数种子
def get_fake_data(batch_size=8):
#产生随机数据:y=x*2+3,再加一些噪声
x = t.rand(batch_size, 1, device=device) * 5
y = x * 2 + 3 + t.randn(batch_size, 1, device=device)
return x, y
#查看x-y分布
x, y = get_fake_data(batch_size=16)
plt.scatter(x.squeeze().cpu().numpy(), y.squeeze().cpu().numpy())
plt.show()
plt.ion() #动态绘图,开启interactive mode 成功的关键函数
plt.figure(1)
#参数初始化
w = t.rand(1,1).to(device)
b = t.zeros(1,1).to(device)
lr = 0.02
#训练模型
for ii in range(500):
x, y = get_fake_data(batch_size=4)
#forward
y_pred = t.mm(x, w) + b.expand_as(y)
loss = 0.5 * (y_pred - y) ** 2 # 均方误差
loss = loss.mean()
#backward
dloss = 1
dy_pred = dloss * (y_pred - y)
dw = t.mm(x.t(), dy_pred)
db = dy_pred.sum()
#update
w.sub_(lr * dw)
b.sub_(lr * db)
if ii % 50 == 0:
plt.clf()
x = t.arange(0,6).view(-1,1)
y = t.mm(x.float(), w) + b.expand_as(x)
plt.plot(x.cpu().numpy(), y.cpu().numpy())#predicted直线图
x2, y2 = get_fake_data(batch_size=32)
plt.scatter(x2.numpy(),y2.numpy())#true data散点图
plt.xlim(0,5)
plt.ylim(0,13)
plt.show()
plt.pause(0.5)
print('w: ', w.item(), 'b: ',b.item())
'''
w: 1.8913463354110718 b: 2.991603136062622
'''
拓展:torch.Tensor的4中乘法
补充:python中plot实现即时数据动态显示方法
import matplotlib.pyplot as plt
import numpy as np
import time
from math import *
#1、保存历史数据
plt.ion() #开启interactive mode 成功的关键函数
plt.figure(1)
x = []
y = []
for i in range(2000):
plt.clf() #清空画布上的所有内容
#x.append(...) y.append(...)
plt.plot(t,m,'-r')
plt.show()
plt.pause(0.01)
#2、不保存历史数据
for i in range(2000):
# plt.clf() # 清空画布上的所有内容。此处不能调用此函数,不然之前画出的点,将会被清空。
t_now = i*0.1
"""
由于第次只画一个点,所以此处有两种方式,第一种plot函数中的样式选
为点'.'、'o'、'*'都可以,就是不能为线段'-'。因为一条线段需要两
个点才能确定。第二种方法是scatter函数,也即画点。
"""
plt.plot(t_now,sin(t_now),'.') # 第次对画布添加一个点,覆盖式的。
# plt.scatter(t_now, sin(t_now))
plt.show()
plt.pause(0.01)
import torch as t
from matplotlib import pyplot as plt
from IPython import display
import numpy as np
t.manual_seed(1000)#设置随机数种子
def get_fake_data(batch_size=8):
#产生随机数据:y=x*2+3,再加一些噪声
x = t.rand(batch_size, 1) * 5
y = x * 2 + 3 + t.randn(batch_size, 1)
return x, y
plt.ion() #开启interactive mode 成功的关键函数
plt.figure(1)
#参数初始化
w = t.rand(1,1, requires_grad=True)
b = t.zeros(1,1, requires_grad=True)
losses = []
#print(losses.shape)
lr = 0.005
#训练模型
for ii in range(500):
x, y = get_fake_data(batch_size=32)
#forward
y_pred = t.mm(x, w) + b.expand_as(y)
loss = 0.5 * (y_pred - y) ** 2 # 均方误差
loss = loss.mean()
losses.append(loss.item())
#backward
loss.backward()
#update
w.data.sub_(lr * w.grad.data)
b.data.sub_(lr * b.grad.data)
#梯度清零
w.grad.data.zero_()
b.grad.data.zero_()
if ii % 50 == 0:
plt.clf()
x = t.arange(0,6).view(-1,1).float()
y = t.mm(x.float(), w) + b.expand_as(x)
plt.plot(x.data.numpy(), y.data.numpy())#predicted直线图
x2, y2 = get_fake_data(batch_size=32)
plt.scatter(x2.numpy(),y2.numpy())#true data散点图
plt.xlim(0,5)
plt.ylim(0,13)
plt.show()
plt.pause(0.5)
print(losses)
plt.clf()
plt.plot(np.squeeze(losses))
plt.show()
plt.pause(10)
print('w: ', w.item(), 'b: ',b.item())