本文是通过学习 AI研习社 炼丹兄 所做笔记!!!
2.搭建一个超简单的网络
目录
2.1 任务
2.2 实现思路
2.3 实现过程
2.1任务
需要搭建的网络要完成的学习任务:
让神经网络学会逻辑异或运算,也就是俗称的“相同取0,不同取1”
即在输入(1,1)时输出0,输入(1,0)时输出1(相同取0,不同取1),以此类推
2.2实现思路
任务需要有两个输入,一个输出,因此需要在输入层设置两个输入节点,输出层设置一个输出节点。
- 隐含层设置10个节点
- 隐含层的激活函数采用ReLU函数
- 输出层的激活函数采用Sigmoid函数(让输出保持在0到1的一个范围,如果输出大于0.5,即可让输出结果为1,小于0.5,让输出结果为0)
2.3实现过程
- 导入库
- 创建训练集
- 搭建网络
- 设置优化器
- 训练网络
- 测试
2.3.1导入库
# 导入库 import torch import torch.nn as nn import numpy as np
- 使用 pytorch 导入 torch 包
- 用 nn 代替 torch 包里的 nn , nn 这个包是 neural network 的缩写(专门用来搭建神经网络的包)
- numpy 是为了创建矩阵作为输入
2.3.2创建训练集
# 创建训练集 # 构建输入集 x = np.mat('0 0;' '0 1;' '1 0;' '1 1') x = torch.tensor(x).float() y = np.mat('1;' '0;' '0;' '1') y = torch.tensor(y).float()
- 用 np.mat 构建矩阵
- 构建完矩阵使用 torch.tensor(x).float() 将所创建的输入转换成 tensor 变量
- tensor 就是 pytorch 中用的一种变量,使用 pytorch 这个框架就必须把变量转换成 tensor 变量
- 神经网络要求输入和输出必须是 float 浮点型的,即 tensor 变量中的浮点型
- np.mat 创建的输入是 int 型的,转换成 tensor 会自动转换成 tensor 的 int 型
2.3.3搭建网路
# 搭建网络 myNet = nn.Sequential( nn.Linear(2,10), nn.ReLU(), nn.Linear(10,1), nn.Sigmoid() ) # 输出网络结构 print(myNet)
运行结果如下:
Sequential( (0): Linear(in_features=2, out_features=10, bias=True) (1): ReLU() (2): Linear(in_features=10, out_features=1, bias=True) (3): Sigmoid() )
- 使用 nn 包中的 Sequential 搭建网络
- nn.Linear(2,10) 的意思是搭建输入层,里面的 2 代表输入节点个数,10 代表输出节点个数(Linear 也就是英文的线性,意思就是这层不包括任何其它的激活函数,输入啥就给输出啥)
- nn.ReLU() 代表刚刚的输入扔到 ReLU 函数中
- 接着 Linear()
- 再扔到 Sigmoid 函数中
- 2,10,1分别代表了三个层的个数
2.3.4设置优化器
需要一个优化的方法来训练创建的网络,这步设置了我们所要采用的优化方法
# 设置优化器 optimzer = torch.optim.SGD(myNet.parameters(),lr=0.05) loss_func = nn.MSELoss()
- torch.optim.SGD 采用 SGD(随机梯度下降)方法训练,只需将网络的参数和学习率传进去即可分别是 myNet.paramets 和 lr
- loss_func 设置了代价函数,此处采用 MSE(均方误差代价函数)
查看未经过网络结果
输出 x 与 myNet(x).data 同最终结果做对比
# 输出x print(x) # 输出未经过参数训练的网络结果 print(myNet(x).data)
运行结果如下:
tensor([[0., 0.], [0., 1.], [1., 0.], [1., 1.]]) tensor([[0.4075], [0.3987], [0.4553], [0.4269]])
2.3.5训练网络
# 训练网络 for epoch in range(5000): out = myNet(x) loss = loss_func(out,y) optimzer.zero_grad() loss.backward() optimzer.step()
- 设置5000次循环(非必要),让训练的动作迭代5000次
- 每一次的输出直接用 myNet(x) ,将输入扔进构建网络就得到了输出 out
- 用代价函数 loss_func 和设置的标准输出 y 求误差 loss
- optimzer.zero_grad() 作用是清楚梯度,为了每一次重新迭代时清除上一次所求出的梯度
- loss.backward() 让误差反向传播
- optimzer.step() 让刚刚设置的优化器开始工作
输出训练结果
# 输出经过参数训练的网络结果 print(myNet(x).data)
运行结果如下:
tensor([[0.9618], [0.0405], [0.0403], [0.9479]])
- 结果明显接近期待结果
- tensor 变量包含两个部分,一部分是 tensor 数据,另一部分是 tensor 的自动求导参数,加上 .data 即输出取 tensor 中的数据
print(myNet(x))
运行结果如下:
tensor([[0.9618], [0.0405], [0.0403], [0.9479]], grad_fn=<SigmoidBackward>)
代码整理如下:
# 导入库 import torch import torch.nn as nn import numpy as np # 创建训练集 # 构建输入集 x = np.mat('0 0;' '0 1;' '1 0;' '1 1') x = torch.tensor(x).float() y = np.mat('1;' '0;' '0;' '1') y = torch.tensor(y).float() # 搭建网络 myNet = nn.Sequential( nn.Linear(2,10), nn.ReLU(), nn.Linear(10,1), nn.Sigmoid() ) # 输出网络结构 print('输出网络结构:') print(myNet) # 设置优化器 optimzer = torch.optim.SGD(myNet.parameters(),lr=0.05) loss_func = nn.MSELoss() # 输出x print('输出x:') print(x) # 输出未经过参数训练的网络结果 print('输出未经过参数训练的网络结果:') print(myNet(x).data) # 训练网络 for epoch in range(5000): out = myNet(x) loss = loss_func(out,y) optimzer.zero_grad() loss.backward() optimzer.step() # 输出经过参数训练的网络结果 print('输出经过参数训练的网络结果:') print(myNet(x).data) print(myNet(x))