当前位置:网站首页>手推卷积神经网络参数(卷积核)求导
手推卷积神经网络参数(卷积核)求导
2022-08-11 05:15:00 【种树家】
手推卷积神经网络求导(卷积链式法则如何理解)
对于卷积如何求参数的导数问题(特别是对多个卷积层如何对初始层数的参数如何求导)困扰我许久了,也一直没有找到这方面的资料,所以自己研究了一下,在这里与大家分享,如果有错误还请大家不吝赐教,有任何疑问请留言。
一个参数求导
torch中的求导需要最后的损失函数值是一个标量。下面以L1损失为例进行分析。我们想自己定义输入和卷积核,所以使用torch.nn.functional中的conv2d进行卷积操作,方便进行分析。具体代码如下
import torch
import torch.nn as nn
import torch.nn.functional as f
loss=nn.L1Loss()
x1=torch.tensor([[[[1,2,3,4],
[4,3,2,1],
[1,2,3,4],
[4,3,2,1]]]],dtype=torch.float,requires_grad=True)
w1=torch.tensor([[[[1,1,1],
[1,1,1],
[1,1,1]]]],dtype=torch.float,requires_grad=True)
bias1=torch.tensor([1],requires_grad=True,dtype=torch.float)
print(a.shape)
print(b.shape)
c=f.conv2d(x1,w1,bias1,padding=1)
print(c)
zero=torch.zeros_like(c)
c=loss(c,zero)
c.backward()
print(w1.grad)
输出结果如下:
C:\software\Anaconda3\python.exe "D:/SZ/runned code/test.py"
torch.Size([1, 1, 4, 4])
torch.Size([1, 1, 3, 3])
tensor([[[[11., 16., 16., 11.],
[14., 22., 25., 18.],
[18., 25., 22., 14.],
[11., 16., 16., 11.]]]], grad_fn=<ThnnConv2DBackward>)
tensor([[[[1.3125, 1.8750, 1.5000],
[1.8750, 2.5000, 1.8750],
[1.5000, 1.8750, 1.3125]]]])
Process finished with exit code 0
我们定义了一个输入,它的shape是[1,1,4,4],具体数值可以参看代码,定义了一个卷积核,它的shape是[1,1,3,3],数值全是1,对输入做卷积,padding是1,所以输出保持和输入一样的尺寸。首先我们要明确L1loss是什么?L1loss是平均绝对误差,即对误差矩阵所有元素求平均值。对于本文损失函数来说,用输出和0做L1损失,即是对输出矩阵中的所有元素求平均值。
下面插图进行详解(自己手画的 emo)先研究只有一个w时怎么求梯度
两个参数求导
下面研究两个参数时怎么对两个参数进行求导
import torch
import torch.nn as nn
import torch.nn.functional as f
loss=nn.L1Loss()
x1=torch.tensor([[[[1,2,3,4],
[4,3,2,1],
[1,2,3,4],
[4,3,2,1]]]],dtype=torch.float,requires_grad=True)
w1=torch.tensor([[[[1,1,1],
[1,1,1],
[1,1,1]]]],dtype=torch.float,requires_grad=True)
bias1=torch.tensor([1],requires_grad=True,dtype=torch.float)
bias2=torch.tensor([1],requires_grad=True,dtype=torch.float)
w2=torch.tensor([[[[1,1,1],
[1,1,1],
[1,1,1]]]],dtype=torch.float,requires_grad=True)
w3=torch.tensor([[[[1,1,1],
[1,1,1],
[1,1,1]]]],dtype=torch.float,requires_grad=True)
print(x1.shape)
print(w1.shape)
x2=f.conv2d(x1,w1,bias1,padding=1)
print(x2)
x3=f.conv2d(x2,w2,bias2,padding=1)
print(x3)
zero=torch.zeros_like(x3)
l=loss(x3,zero)
l.backward()
print(w1.grad)
print(w2.grad)
输出结果如下:
C:\software\Anaconda3\python.exe "D:/SZ/runned code/test.py"
torch.Size([1, 1, 4, 4])
torch.Size([1, 1, 3, 3])
tensor([[[[11., 16., 16., 11.],
[14., 22., 25., 18.],
[18., 25., 22., 14.],
[11., 16., 16., 11.]]]], grad_fn=<ThnnConv2DBackward>)
tensor([[[[ 64., 105., 109., 71.],
[107., 170., 170., 107.],
[107., 170., 170., 107.],
[ 71., 109., 105., 64.]]]], grad_fn=<ThnnConv2DBackward>)
tensor([[[[ 9.3750, 12.5000, 10.6250],
[12.5000, 15.6250, 12.5000],
[10.6250, 12.5000, 9.3750]]]])
tensor([[[[10.5625, 13.2500, 10.5625],
[13.2500, 16.6250, 13.2500],
[10.5625, 13.2500, 10.5625]]]])
下面插图进行详解(自己手画的 emo)
三个参数求导
下面研究卷积层为三层时怎么对各层参数求导
import torch
import torch.nn as nn
import torch.nn.functional as f
loss=nn.L1Loss()
x1=torch.tensor([[[[1,2,3,4],
[4,3,2,1],
[1,2,3,4],
[4,3,2,1]]]],dtype=torch.float,requires_grad=True)
w1=torch.tensor([[[[1,1,1],
[1,1,1],
[1,1,1]]]],dtype=torch.float,requires_grad=True)
bias1=torch.tensor([1],requires_grad=True,dtype=torch.float)
bias2=torch.tensor([1],requires_grad=True,dtype=torch.float)
bias3=torch.tensor([1],requires_grad=True,dtype=torch.float)
w2=torch.tensor([[[[1,1,1],
[1,1,1],
[1,1,1]]]],dtype=torch.float,requires_grad=True)
w3=torch.tensor([[[[1,1,1],
[1,1,1],
[1,1,1]]]],dtype=torch.float,requires_grad=True)
print(x1.shape)
print(w1.shape)
x2=f.conv2d(x1,w1,bias1,padding=1)
print(x2)
x3=f.conv2d(x2,w2,bias2,padding=1)
print(x3)
x4=f.conv2d(x3,w3,bias3,padding=1)
print(x4)
zero=torch.zeros_like(x4)
l=loss(x4,zero)
l.backward()
print(w1.grad)
print(w2.grad)
print(w3.grad)
输出结果为:
C:\software\Anaconda3\python.exe "D:/SZ/runned code/test.py"
torch.Size([1, 1, 4, 4])
torch.Size([1, 1, 3, 3])
tensor([[[[11., 16., 16., 11.],
[14., 22., 25., 18.],
[18., 25., 22., 14.],
[11., 16., 16., 11.]]]], grad_fn=<ThnnConv2DBackward>)
tensor([[[[ 64., 105., 109., 71.],
[107., 170., 170., 107.],
[107., 170., 170., 107.],
[ 71., 109., 105., 64.]]]], grad_fn=<ThnnConv2DBackward>)
tensor([[[[ 447., 726., 733., 458.],
[ 724., 1173., 1180., 735.],
[ 735., 1180., 1173., 724.],
[ 458., 733., 726., 447.]]]], grad_fn=<ThnnConv2DBackward>)
tensor([[[[ 64.6875, 85.3125, 73.1250],
[ 85.3125, 105.6250, 85.3125],
[ 73.1250, 85.3125, 64.6875]]]])
tensor([[[[ 72.4375, 90.3125, 73.3750],
[ 90.3125, 111.8750, 90.3125],
[ 73.3750, 90.3125, 72.4375]]]])
tensor([[[[ 73.2500, 91.0625, 73.6875],
[ 91.0625, 112.8750, 91.0625],
[ 73.6875, 91.0625, 73.2500]]]])
所以可以得到以下结论:
所以我们推导出了卷积神经网络如何更新参数的链式求导法则
有任何问题求留言!
边栏推荐
- 【win10+cuda7.5+cudnn6.0安装caffe①】安装cuda和cudnn
- [No 2022 Shanghai Security Officer A Certificate Exam Question Bank and Mock Exam
- Mysql introductory exercise
- 什么是三次握手和四次挥手(清晰易懂)
- Day38 LeetCode
- MySQL索引
- Idea essential skills to improve work efficiency
- 华为od德科面试数据算法解析 2022-8-10 迷宫问题
- (1) Docker installs Redis in practice (one master, two slaves, three sentinels)
- The most complete installation tutorial of Pytorch (one step)
猜你喜欢
随机推荐
(1) Construction of a real-time performance monitoring platform (Grafana+Influxdb+Jmeter)
Apache Commons OGNL语法说明_翻译
Keras与tensorflow 使用基础
Decryption of BitLocker
0708作业---商品信息
【动态代理】CGLIB 动态代理的使用及原理
Oracle中如何用一个表的数据更新另一个表中的数据_转载
【备忘】从零开始搭建Yolo5训练环境
2022年Android面试中最常问的问题是什么?
性能效率测试
vftpd本地可以连接,远程连接超时的解决
pytorch和tensorflow函数对应表
MySQL索引
BitLocker的解密
task02 fashion-mnist分类实战
基础数据之double和float区别
让你代码越来越高大上的技巧——代码规范,你得知道
redis分布式锁
Idea 2021.3.3版本文件目录展开
curl 命令调用接口demo