最近开始学习深度学习,有很多概念听起来很复杂和难以理解,所以我从很简单的线性回归来深度理解一下。
引入库函数
这里主要用了三个库:pytorch\numpy\matplotlib,其中matplotlib主要是用于绘图的。
#%%
import torch.nn as nn
import torch
from torch.autograd import Variable
import numpy as np
from matplotlib import pyplot as plt
定义模型
之后这个模型可类似于我们的经典网络模型,现在模型只是一个线性计算。这个模型类是个超类,继承了nn.Module的类,包含两个方法。
- init类,这是个初始类,用于进行公共变量的赋值等,主要是将其赋为self,其余方法都可以用。这里可以看到是根据输入和输出,定义了权重w1和截距b1,并给定了初始值。
- forward类,这是一个返回函数,这里主要是进行线性计算,返回预测值。
class mylinermodel(nn.Module):
def __init__(self,D_in,D_out):
super().__init__()
self.w1 = torch.nn.Parameter(torch.randn(D_in,D_out).type(torch.FloatTensor),requires_grad = True)
self.b1 = torch.nn.Parameter(torch.randn(D_out).type(torch.FloatTensor),requires_grad = True)
def forward(self,x):
x = (x.mm(self.w1)+self.b1)
return x
定义损失函数
用于计算预测值和真实值之间的差异
def myloss(y_pred,y_true):
loss = torch.mean((y_pred-y_true).pow(2)/2)
return loss
定义步长,寻找最优解
这个感觉类似与不断训练,得到最优解,核心是对求导,根据导数进行不断优化。
class SGD:
def __init__(self,params,lr):
self.params = params
self.lr = lr
#更新梯度
def step(self):
for param in self.params:
param.data -= self.lr*param.grad.data
#导数值归零
def zero_grad(self):
for param in self.params:
if param.grad is not None:
param.grad.data.zero_()
数据导入
通过模拟100个点进行模型的训练
#创建随机数,用于之后的训练
np.random.seed(0)
a = 3
b = 10
numOfSample = 100
x = np.random.rand(numOfSample)
y_true = a * x + b
y_observations = y_true + np.random.rand(numOfSample)
plt.scatter(x,y_observations)
plt.title('observation data')
plt.xlabel('x')
plt.ylabel('y')
x = x.reshape([numOfSample,1])
y_observations = y_observations.reshape([numOfSample,1])
为模型设定初始化值
# %%
#为模型设定初始化的值
N,D_in,D_out = numOfSample,1,1
model = mylinermodel(D_in,D_out)
parameters = list(model.parameters())
optimizer = SGD(parameters,lr = 1e-2)
x = torch.FloatTensor(x)
训练模型
通过多次循环进行模型的训练
for t in range(5000):
y_pred = model(x)
loss = myloss(y_pred,torch.FloatTensor(y_observations))
loss.backward()
optimizer.step()
optimizer.zero_grad()
结论
深度学习的过程可能包括:
- 数据导入。(在这个案例里面我们是自己模拟了数据,我们要将数据整理为标准的格式)
- 模型初始值计算。(在这个案例里面,刚开始给了一个随机的W和B,然后计算预测值)
- 损失函数计算。(这里面是求的差值的平方根)
- 权重参数求导。(这里面是用的loss.backward())
- 更新步长,探求最优解。