2. 线性回归

2. 线性回归

将线性回归作为深度学习第一个入门的模型,让我们一起来实现吧!
因为要用到画图,数据制图,所以需要安装matplotlip,使用pip或者anaconda安装都可以。

pip install matplotlib

我们可以利用**scatter( )**方法制作散点图,但是需要注意,使用matplotlib制图时,**传入的Tensor数据格式必须转换成Numpy格式的数据。**示例如下:

import torch
import matplotlib.pyplot as plt
#数据
x=torch.Tensor([1.4,5,11,16,21])
y=torch.Tensor([14.4,29.6,62,85.5,113.4])
#将x,y转化为numpy数据类型,绘制散点图
plt.scatter(x.numpy(),y.numpy())
plt.show()

运行结果如下:可以看到这五个点符合线性规律,也就是能用一条直线去拟合这五个点。
在这里插入图片描述
理论部分不做讲解,可以查看线性回归传送门

2.1 简单数据线性回归

结合理论知识,利用pytorch来进行编程。
首先对输入变量和各参数进行初始化。构建Produce_X( )函数主要是生成矩阵X,X是由x和x0合并的,而rand函数随机初始化参数向量w,而且需要对其进行梯度下降法更新,所以设置requires_grad=True

import torch
import matplotlib.pyplot as plt
#准备数据
#生成矩阵X
def Produce_X(x):
	x0 = torch.ones(x.numpy().size) #用ones产生初始值为1,大小与x相同的向量
	X = torch.stack((x,x0),dim=1)   #stack函数将两个向量拼合
	return X
x = torch.Tensor([1.4,5,11,16,21])
y = torch.Tensor([14.4,29.6,62,85.5,113.4])
X = Produce_X(x)
#定义权重w的变量
w = torch.rand(2,requires_grad=True)

接下来进行训练过程。定义一个train函数,用来不断地调整w的值,epochs代表轮数,表示遍历所有数据的次数,learning_rate代表学习率。output = inputs.mv(w)表示先进行前向传播,然后根据loss = (output - target).pow(2).sum()求出损失函数,然后进行反向传播loss.backward() 自动求出损失函数梯度,w.data -= learning_rate * w.grad 逐步对w进行更新。
但是更新完之后一定要清空w的grad值,使用**w.grad.zero_()**清空梯度值

inputs = X 
target = y
def train(epochs=1,learning_rate=0.01):
	for epoch in range(epochs):
		#前向传播
		output = inputs.mv(w) #公式:y=Xw
		loss = (output - target).pow(2).sum()#公式:J = ∑(y-y')^2
		#反向传播
		loss.backward() 
		w.data -= learning_rate * w.grad  #更新权重w,公式:w_(t+1)= w_(t) - 𝜼*▽J
		w.grad.zero_() #清空grad的值
		if epoch % 80 == 0:
			draw(output,loss)
	#plt.savefig('plot1.png', format='png')
	return w,loss

为了能够观察到训练的变化,让程序80次打印输出一次图像,定义一个draw( )函数。

def draw(output,loss):
	plt.cla()#清空图像画布
	plt.scatter(x.numpy(), y.numpy())#绘制散点图样本点
	plt.plot(x.numpy(), output.data.numpy(),'r-', lw=5)绘制出回归直线
	plt.text(0.5, 0,'Loss=%s' % (loss.item()),fontdict={'size':20,'color':'red'})#打印出loss值
	plt.pause(0.005)

在这里插入图片描述

设轮数为10000,学习率为1e-4,返回最终打印的损失值和权重

w,loss = train(10000,learning_rate = 1e-4)  #学习率设置为1x10^(-4)
print("final loss:",loss.item())
print("weights:",w.data)

输出:

final loss: 8.217347145080566
weights: tensor([5.0818, 5.6184])

2.2 大规模数据线性回归

上面的例子只有5个样本,样本数过少,在一般场景肯定不适用,现在尝试输入10万个数据样本,再次进行线性回归,完整代码放下面:

import torch
import matplotlib.pyplot as plt
from time import perf_counter
#准备数据
#生成矩阵X
def Produce_X(x):
	x0 = torch.ones(x.numpy().size) #用ones产生初始值为1,大小与x相同的向量
	X = torch.stack((x,x0),dim=1)   #stack函数将两个向量拼合
	return X
x = torch.linspace(-3,3,100000)#用linspace产生(-3,3)区间内的100000个点
X = Produce_X(x)
y = x +1.2*torch.rand(x.size())#假设真实函数是y=x,我们在上面增加一些误差,更加符合实际情况
w = torch.rand(2) #定义权重w的变量
#如果支持CUDA,则采用CUDA加速
CUDA =  torch.cuda.is_available()
if CUDA:
	inputs = X.cuda() 
	target = y.cuda()
	w = w.cuda()
	w.requires_grad=True
else:
	inputs = X 
	target = y
	w = w
	w.requires_grad=True
def draw(output,loss):
	#print loss
	if CUDA:
		output= output.cpu()
	plt.cla()
	plt.scatter(x.numpy(), y.numpy())
	plt.plot(x.numpy(), output.data.numpy(),'r-', lw=5)
	plt.text(5,5,'Loss=%s' % (loss.item()),fontdict={'size':20,'color':'red'})
	plt.pause(0.005)

def train(epochs=1,learning_rate=0.01):
	for epoch in range(epochs):
		#前向传播
		output = inputs.mv(w) #公式:y=Xw
		loss = (output - target).pow(2).sum()/100000 #公式:J = (∑(y-y')^2)/100000
		#反向传播
		loss.backward() 
		w.data -= learning_rate * w.grad  #更新权重w,公式:w_(t+1)= w_(t) - 𝜼*▽J
		w.grad.zero_() #清空grad的值
		if epoch % 80 == 0:
			draw(output,loss)
			plt.show()
	return w,loss
start = perf_counter()
w,loss = train(10000,learning_rate=1e-4)  #学习率设置为1x10^(-4)
finish = perf_counter()
time = finish-start
print("计算时间:%s" % time)
print("final loss:",loss.item())
print("weights:",w.data)

在这里插入图片描述

计算时间:58.723048899999995
final loss: 0.12094969302415848
weights: tensor([0.9979, 0.5756], device='cuda:0')

2.3 神经网络的方法

实际上,pytorch中已经预先定义好了我们要用到的损失函数及优化函数,直接上代码,细节在代码注释:

import torch
import matplotlib.pyplot as plt
from torch import nn,optim
from time import perf_counter

#用linspace产生(-3,3)区间内的100000个点,并使用unsqueeze函数增加一个维度
x = torch.unsqueeze(torch.linspace(-3,3,100000),dim=1)
#假设真实函数是y=x,我们在上面增加一些误差,更加符合实际情况
y = x +1.2*torch.rand(x.size())
#定义一个回归的类LR,继承pytorch中nn(Neural Network)模块中的Module
class LR(nn.Module):
	def __init__(self):
		super(LR,self).__init__()
		self.linear = nn.Linear(1,1)  # 两个参数分别代表输入输出的维度

	def forward(self,x):  # 定义前向传播,反向传播好像本来就有不用再定义
		out = self.linear(x)
		return out

#如果支持CUDA,则采用CUDA加速
CUDA = torch.cuda.is_available()

if CUDA:
	LR_model = LR().cuda()
	inputs = x.cuda()
	target = y.cuda()
else:
	LR_model = LR()
	inputs = x
	target = y

criterion = nn.MSELoss()  # nn模块预设有均方误差函数
optimizer = optim.SGD(LR_model.parameters(),lr=1e-4)  # 以及随机梯度下降函数SGD,
                                            # 第一个是需要优化的神经网络的参数,第二个是学习率

def draw(output,loss):
	
	if CUDA:
		output = output.cpu()
	plt.cla()
	plt.scatter(x.numpy(), y.numpy())
	plt.plot(x.numpy(), output.data.numpy(),'r-', lw=5)
	plt.text(0.5,0,'Loss=%s' % (loss.item()),fontdict={'size':20,'color':'red'})
	plt.pause(0.005)
# 训练函数,参数依次是被训练的神经网络模型、损失函数、优化器、训练轮数
def train(model,criterion,optimizer,epochs):
	for epoch in range(epochs):
		#forward
		output = model(inputs)  # 将input传入神经网络模型,得到output
		loss = criterion(output,target)  # 用损失函数计算损失值

		#backward
		optimizer.zero_grad()  # 清空权重梯度值
		loss.backward()  # 计算梯度
		optimizer.step()   # 权值更新 
		
		
		if epoch % 80 == 0:
			draw(output,loss)
			plt.show()
		
	return model,loss

start = perf_counter()
LR_model,loss = train(LR_model,criterion,optimizer,10000)
finish = perf_counter()
time = finish-start
print("计算时间:%s" % time)
print("final loss:",loss.item())
print("weights:",list(LR_model.parameters()))

这就大功告成了,线性回归基本就这些,要仿照程序结构去写,神经网络的程序个人认为就是这种模块化的,因为他预设了很多库函数,简直不要方便太多!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值