[TOC]
关于深度学习的一些理解的参考链接:
https://www.cnblogs.com/bamtercelboo/p/7469005.html
一、 基础知识
1)激活函数
sigmoid和tanh函数的导数都是原函数的函数。这样,我们一旦计算原函数的值,就可以用它来计算出导数的值。
二、循环神经网络层
1)LSTM
t.manual_seed(1000)
input=V(t.randn(2,3,4))
print('input:')
print(input)
lstm=nn.LSTM(4,3,1)
h0=V(t.randn(1,3,3))
c0=V(t.randn(1,3,3))
out,hn=lstm(input, (h0,c0))
print('out:')
print(out)
结果:
input:
tensor([[[-0.5306, -1.1300, -0.6734, -0.7669],
[-0.7029, 0.9896, -0.4482, 0.8927],
[-0.6043, 1.0726, 1.0481, 1.0527]],
[[-0.6424, -1.2234, -1.0794, -0.6037],
[-0.7926, -0.1414, -1.0225, -0.0482],
[ 0.6610, -0.8908, 1.4793, -0.3934]]])
out:
tensor([[[-0.3610, -0.1643, 0.1631],
[-0.0613, -0.4937, -0.1642],
[ 0.5080, -0.4175, 0.2502]],
[[-0.0703, -0.0393, -0.0429],
[ 0.2085, -0.3005, -0.2686],
[ 0.1482, -0.4728, 0.1425]]])
2)LSTMCell
t.manual_seed(1000)
input=V(t.randn(2,3,4))
print('input:')
print(input)
lstm=nn.LSTMCell(4,3)
hx=V(t.randn(3,3))
cx=V(t.randn(3,3))
out=[]
for i_ in input:
hx,cx=lstm(i_, (hx,cx))
out.append(hx)
print('out:')
print(out)
结果:
input:
tensor([[[-0.5306, -1.1300, -0.6734, -0.7669],
[-0.7029, 0.9896, -0.4482, 0.8927],
[-0.6043, 1.0726, 1.0481, 1.0527]],
[[-0.6424, -1.2234, -1.0794, -0.6037],
[-0.7926, -0.1414, -1.0225, -0.0482],
[ 0.6610, -0.8908, 1.4793, -0.3934]]])
out:
[tensor([[-0.3610, -0.1643, 0.1631],
[-0.0613, -0.4937, -0.1642],
[ 0.5080, -0.4175, 0.2502]]), tensor([[-0.0703, -0.0393, -0.0429],
[ 0.2085, -0.3005, -0.2686],
[ 0.1482, -0.4728, 0.1425]])]
三、损失函数(Loss Function)
在深度学习中要用到各种各样的损失函数,这些损失函数可看做是一种特殊的layer, Pytorch也将这些损失函数专门提取出来,作为独立的一部分。
这里以交叉熵损失CrossEntripyliss为例:
#batchsize=3 计算对应每个类别的分数(只有两个类别0, 1)
score=V(t.randn(3,2))
#三个样本分别属于1,0,1类,label必须是LongTensor
label=V(t.Tensor([1,0,1])).long()
#loss与普通的layer无差异
criterion=nn.CrossEntropyLoss()
loss=criterion(score,label)
loss
结果:
tensor(0.8908)
四、优化器
Pytorch将深度学习中所有的优化方法都封装在torch.optim
中,其设计十分灵活,能够很方便地扩展成自定义的优化方法。
所有的优化方法都是继承基类optim.Optimizer, 并实现了自己的优化步骤。
下面以最基本的 优化方法——随机梯度下降法(SGD)举例说明。
这里需要掌握:
1. 优化方法的基本使用方法;
2. 如何对模型的不同部分设置不同的学习率;
3. 如何调整学习率
from torch import optim
import torch as t
from torch import nn
from torch.autograd import Variable as V
#首先定义一个Lenet网络
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.features=nn.Sequential(
nn.Conv2d(3,6,5),
nn.ReLU(),
nn.MaxPool2d(2,2),
nn.Conv2d(6,16,5),
nn.ReLU(),
nn.MaxPool2d(2,2)
)
self.classifier=nn.Sequential(
nn.Linear(16*5*5, 120),
nn.ReLU(),
nn.Linear(120, 84),
nn.ReLU(),
nn.Linear(84, 10),
)
def forward(self,x):
x=self.features(x)
x=x.view(-1,16*5*5)
x=self.classifier(x)
return x
net=Net()
optimizer=optim.SGD(params=net.parameters(), lr=1)
optimizer.zero_grad() #梯度清零等价于net.zero_grad()
input=V(t.randn(1,3,32,32))
output=net(input)
output.backward(output)
optimizer.step() #执行优化
#为不同的子网络设置不同的学习率,在finetune中经常用到
#如果对某个参数不指定学习率,就使用默认的学习率
optimizer=optim.SGD([
{'params':net.features.parameters()},
{'params':net.classifier.parameters()}
], lr=1e-5)
#只在全连接层设置较大的学习率,其余层设置较小的学习率
special_layers=nn.ModuleList([net.classifier[0], net.classifier[3]])
special_layers_params=list(map(id, special_layers.parameters())
base_params = filter(lambda p:id(p) not in special_layers_params,
net.parameters())
optimizer=t.optim.SGD([
{'params':base_params},
{'params':special_layers.parameters(),'lr':0.01}
], lr=0.01)
调整学习率的方法主要有两种。
一种是修改optimizer.params_groups
中对应的学习率,另一种是新建优化器(更简单也是更推荐的做法)。由于optimizer十分轻量级,构建开销很小,故可以构建新的optimizer.
但是构建新的优化器会重新初始化动量等状态信息,这对使用动量的优化器来说(如带momentum的sgd),可能会造成损失函数在收敛过程中出现 震荡。
#调整学习率 新建一个optimizer
old_lr=0.1
optimizer=optim.SGD([
{'params':net.features.parameters()},
{'params':net.classifier.parameters(),'lr':old_lr*0.1}
],lr=1e-5)