最近老师布置了一个关于搭建神经网络的作业,水平较低,做了很长时间,因网上对其原理性文章非常丰富,故现对其中细枝末节做简要说明:
dataset=np.array([[[1],[1]],[[2],[2.5]],[[3],[2.7]],[[4],[4.1]],[[5],[5.2]],[[6],[6]],[[7],[7.1]],[[8],[8.2]],[[9],[9.3]],[[10],[9.9]],[[11],[11.3]],[[12],[12.2]]],dtype=np.float32)
数据十分简单,输入层1,输出层1,共12个数据,其中数据一定要是float型,其中每一个数据的输入和输出应该单独为一个个体,比如第一个数据[[1],[1]]绝对不能写成[1,1],因为在后面时torch.utils.data会把输入的12个数据当成一个数据,原则就是你的输入层几维,你的最里面的[]的数据就是几维。
首先导如必要包:
import torch
import torch.nn as nn #这里我们要引用torch.nn模块
import torch.nn.functional as F #这是神经网络里面的函数
import numpy as np
import torch.optim as optim #这里是优化器,这里我们用的SGD(随机梯度下降算法)寻找loss的最低点。
from torch.utils.data import Dataset #这个必须要导入 ,有__getitem__(self, index)函数来根据索引序号获取图片和标签,
# 有__len__(self)函数来获取数据集的长度.
from torch.utils.data import DataLoader #作用:是加载数据的核心,返回可迭代的数据。PyTorch中数据读取的一个重要接口是torch.utils.data.DataLoader,
#该接口定义在dataloader.py脚本中,只要是用PyTorch来训练模型基本都会用到该接口。
#该接口主要用来将自定义的数据读取接口的输出或者PyTorch已有的数据读取接口的输入按照batch size封装成Tensor,
#因此该接口有点承上启下的作用,比较重要’‘’
创建神经网络模块:
class Net(nn.Module): #创建类class,继承nn.Module
def __init__(self):
super(Net, self).__init__() #初始化
self.fc1 = nn.Linear(1, 20) #神经网络结构(1,20,10,1)
self.fc2 = nn.Linear(20, 10)
self.fc3 = nn.Linear(10, 1)
def forward(self, x): #定义前向传播
x = F.relu(self.fc1(x)) # 定义fc1(fullconnect),为线性函数:y = Wx + b,并将个节点连接到20个节点上。
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
class FD(Dataset): #返回数据len和idx
def __init__(self,dataset):
self.x=dataset[:,0]
self.y=dataset[:,1]
def __len__(self):
return len(self.x)
def __getitem__(self, idx):
return self.x[idx],self.y[idx]
创建训练函数:
def train(DL): #训练函数
epoch = 1000 #训练1000次
for i in range(epoch):
for i_batch, sample_batched in enumerate(DL): #讲input和target提取出来
input = sample_batched[0]
target = sample_batched[1]
output = net(input) #放入到函数中进行前向传播
loss = criterion(output, target) #计算loss,这里我们用的是MSE(均方误差)
optimizer.zero_grad() # 这三个函数的作用是先将梯度归零(optimizer.zero_grad())
loss.backward() # 然后反向传播计算得到每个参数的梯度值(loss.backward())
optimizer.step() # 最后通过梯度下降执行一步参数更新(optimizer.step())
if i%50==0: #每50次打印一次loss
print("i_batch:", i_batch, "loss:", loss)
net=Net() #为什么把括号去掉,这句不是很懂,希望大佬评论下,万分感谢!!!!
optimizer = optim.SGD(net.parameters(), lr=0.001) #随机梯度优化器 步长设置为0.001
criterion = nn.MSELoss() #损失为均方误差函数
dataset=np.array([[[1],[1]],[[2],[2.5]],[[3],[2.7]],[[4],[4.1]],[[5],[5.2]],[[6],[6]],[[7],[7.1]],[[8],[8.2]],[[9],[9.3]],[[10],[9.9]],[[11],[11.3]],[[12],[12.2]]],dtype=np.float32)
dataset=FD(dataset)
dl=DataLoader(dataset=dataset,batch_size=4) #设置batch_size
train(dl)
with torch.no_grad(): #不再进行梯度计算
y_pred=net(torch.tensor([[13.0],[14.0],[15.0]])) #预测函数
print(y_pred)
下面分别为lr为0.1,0.01,0.001和batch_size为3和4的loss和Pred:
可见步长的影响很大!!!!!!
loss:
lr batch_size | 0.1 | 0.01 | 0.001 |
3 | 22.0041 | 0.9735 | 0.0303 |
4 | 19.9261 | 17.9238 | 0.0271 |
Pred:
lr batch_size | 0.1 | 0.01 | 0.001 |
3 | tensor([[7.4578], [7.4578], [7.4578]]) | tensor([[8.6393], [9.1157], [9.5889]]) | tensor([[13.1478], [14.1503], [15.1528]]) |
4 | tensor([[7.2225], [7.2225], [7.2225]]) | tensor([[6.6795], [6.6795], [6.6795]]) | tensor([[13.2087], [14.2157], [15.2227]]) |
全部代码:
import torch
import torch.nn as nn #这里我们要引用torch.nn模块
import torch.nn.functional as F #这是神经网络里面的函数
import numpy as np
import torch.optim as optim #这里是优化器,这里我们用的SGD(随机梯度下降算法)寻找loss的最低点。
from torch.utils.data import Dataset #这个必须要导入 ,有__getitem__(self, index)函数来根据索引序号获取图片和标签,
# 有__len__(self)函数来获取数据集的长度.
from torch.utils.data import DataLoader #作用:是加载数据的核心,返回可迭代的数据。PyTorch中数据读取的一个重要接口是torch.utils.data.DataLoader,
#该接口定义在dataloader.py脚本中,只要是用PyTorch来训练模型基本都会用到该接口。
#该接口主要用来将自定义的数据读取接口的输出或者PyTorch已有的数据读取接口的输入按照batch size封装成Tensor,
#因此该接口有点承上启下的作用,比较重要’‘’
class Net(nn.Module): #创建类class,继承nn.Module
def __init__(self):
super(Net, self).__init__() #初始化
self.fc1 = nn.Linear(1, 20) #神经网络结构(1,20,10,1)
self.fc2 = nn.Linear(20, 10)
self.fc3 = nn.Linear(10, 1)
def forward(self, x): #定义前向传播
x = F.relu(self.fc1(x)) # 定义fc1(fullconnect),为线性函数:y = Wx + b,并将个节点连接到20个节点上。
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
class FD(Dataset): #返回数据len和idx
def __init__(self,dataset):
self.x=dataset[:,0]
self.y=dataset[:,1]
def __len__(self):
return len(self.x)
def __getitem__(self, idx):
return self.x[idx],self.y[idx]
def train(DL): #训练函数
epoch = 1000 #训练1000次
for i in range(epoch):
for i_batch, sample_batched in enumerate(DL): #讲input和target提取出来
input = sample_batched[0]
target = sample_batched[1]
output = net(input) #放入到函数中进行前向传播
loss = criterion(output, target) #计算loss,这里我们用的是MSE(均方误差)
optimizer.zero_grad() # 这三个函数的作用是先将梯度归零(optimizer.zero_grad())
loss.backward() # 然后反向传播计算得到每个参数的梯度值(loss.backward())
optimizer.step() # 最后通过梯度下降执行一步参数更新(optimizer.step())
if i%50==0: #每50次打印一次loss
print("i_batch:", i_batch, "loss:", loss)
net=Net() #为什么把括号去掉,这句不是很懂,希望大佬评论下,万分感谢!!!!
optimizer = optim.SGD(net.parameters(), lr=0.001) #随机梯度优化器 步长设置为0.001
criterion = nn.MSELoss() #损失为均方误差函数
dataset=np.array([[[1],[1]],[[2],[2.5]],[[3],[2.7]],[[4],[4.1]],[[5],[5.2]],[[6],[6]],[[7],[7.1]],[[8],[8.2]],[[9],[9.3]],[[10],[9.9]],[[11],[11.3]],[[12],[12.2]]],dtype=np.float32)
dataset=FD(dataset)
dl=DataLoader(dataset=dataset,batch_size=4) #设置batch_size
train(dl)
with torch.no_grad(): #不再进行梯度计算
y_pred=net(torch.tensor([[13.0],[14.0],[15.0]])) #预测函数
print(y_pred)