一.使用Pytorch构建“层(layer)”
1.代码
1 import torch
2 from torch.autograd import Variable
3 from torch.nn import Linear
4 inp = Variable(torch.randn(1,10))
5 myLayer = Linear(in_features = 10,out_features = 5,bias = True)
6 myLayer(inp)
7 print(myLayer.weight)
8 print(myLayer.bias)
2.如何构建
导入包含Variable类的包和Linear类的包
第4行:inp为一个随机生成的1×10的张量,作为输入
第5行:构建一个输入大小为10张量,通过线性变换后,输出大小为5张量的层
第6行:初始化myLayer
构建好层(layer)后,可以使用myLayer.weight 和myLayer.bias来查看所构建层的课训练参数,这两个属性是在层构建后自动生成的。
3.一层的输出传递给另一层
myLayer1 = Linear(10,5)
myLayer2 = Linear(5,2)
myLayer2(myLayer1(inp))
myLayer1输入为10张量大小,输出为5张量大小
myLayer2输入为5张量大小,输出为2张量大小
初始化参数为Inp
二.使用Pytorch构建“非线性激活函数”
1.为何要构建非线性激活函数?
第一部分介绍了如何构建层,是构建线性函数层,但是由于堆叠多个线性层并不能帮助我们的算法学习任何新东西,两个不同的线性层可以合并表示为一个线性层,所以可以使用非线性函数来帮助学习新东西。
2.常用的非线性激活函数介绍
sigmoid
曾一度被不同的架构使用,但是会出现梯度消失的问题,具体来说就是当sigmoid函数输出值接近0或者1时,前一层网络的梯度会接近于0,由于前一层网络的梯度接近0就会使得权重不能经常调整,从而产生类无效神经元。
ReLU
优点:1.加快梯度下降收敛速度
2.计算成本低,因为只用判断阈值
缺点:当一个很大的梯度进行反向传播时,流经的神经元经常会变得无效,解决办法:通过谨慎选择学习率来控制
tanh
3.构建非线性激活函数实例
1 import torch
2 from torch.autograd import Variable
3 import torch.nn as nn
4 sample_data = Variable(torch.Tensor([1,2,-1,-1]))
5 myRelu =nn.ReLU(inplace=True)
6 myRelu(sample_data)
7 print(sample_data)
提前加载包含ReLU的包torch.nn,输入张量为sample_data为(1,2,-1,-1)经过ReLU后输出为(1,2,0,0)
三.使用Pytorch构建深度学习算法的方法
1.使用“类”构建深度学习网络
Pytorch中所有网络都是以“类”的方式实现的,创建Pytorch类的子类要使用nn.Module方法,并且实现__init__和forward方式,其中__init__用来对网络进行初始化,通俗点就是规定包括layer是线性layer还是什么layer等,forward用来表示网络的前向结构,通俗点就是层layer的顺序,哪一层下来是哪一层。在forward方法中把输入数据传递给__init__,然后返回输出后在forward中继续向下传递。
1 import torch
2 import torch.nn as nn
3 class MyFirstNetwork(nn.Module):
4 def __init__(self,input_size,hidden_size,out_size):
5 super(MyFirstNetwork,self).__init__()
6 self.layer1 = nn.Linear(input_size,hidden_size)
7 self.layer2 = nn.Linear(hidden_size,out_size)
8
9 def __forward__(self,input):
10 out = self.layer1(input)
11 out = nn.ReLU(out)
12 out = self.layer2(out)
13 return out
上述网络以“类”的形式构建,包括2层,并且使用类非线性激活函数ReLU,从python的角度来理解上述代码,功能就是继承一个父类nn.Module,并实现父类中的两个方法init和forward。通过将父类的名字nn.Module作为参数传入来创建子类,super方法用于将MyFirstNetwork的父类nn.Module的参数传递给self
注: super(class A,self)的用法,将对象self转换为class A的父类,比如定义class A(B),则通过super将对象self转换为A的父类B的对象self
3.不同机器学习问题的模型架构
使用机器学习或者深度学习解决的问题通常有3类,最后一层的情况如下:
(1)回归问题,例如预测T恤衫的销售价格,最后使用有输出的线性层,输出值为连续
(2)给定一张图片归类为T恤衫或衬衫,使用sigmoid函数,由于它的输出值不是1就是0,此类问题为二分类问题
(3)多分类问题,必须把给定的图片归类为T恤衫,衬衫,短袖或者网格衫,网络层最后使用softmax层
四.使用Pytorch构建loss函数
1.loss函数构建实例
1 import torch
2 from torch.autograd import Variable
3 import torch.nn as nn
4 loss = nn.MSELoss()
5 input = Variable(torch.randn(3,5),requires_grad = True)
6 target = Variable(torch.randn(3,5))
7 output = loss(input,target)
8 output.backward()
Variable的用法
直接用numpy或者Tensor来实现神经网络时,前向传播和反向传播等网络都需要人工手写,当网络简单时是可行的,反向传播的导数容易求得,但是当遇到复杂网络就很难实现了,Variable是Pytorch提供的autograd包的子类,通过语句from torch.autograd import Variable来加载,autograd是用来自动求导的,Variable是对Tensor进行了封装。
Variable默认不求梯度,需要求梯度时 requires_grad = True。
Variable包含了3个属性:
data:存储类Tensor,是本体的数据
grad: 存储data的梯度,本身是个Variable
grad_fn:指向了Function对象,用于反向传播时的梯度计算
import torch
from torch.autograd import Variable
x = Variable(torch.randn(3,5),requires_grad = True)
x.data
x.grad
x.grad_fn
Pytorch常用的loss函数
L1 loss:通常作为正则化器使用
MSE loss:均饭误差损失,用于回归问题的损失函数
Cross-entropy loss:交叉熵损失,用于二分类和多分类问题
NLL Loss:用于分类问题,允许使用特定权重处理不平衡数据集