天鹅:
天鹅:
我想再一次向授课老师核实下,这里e.g. 6 5*5*3中的6应该是指channel数,3应该是指每个5*5的filter都有3个权重矩阵?是这个意思吧
张飞飞:
@天鹅 对的
我自己后来的补充:其实你把32*32*3理解为尺寸大小为32*32的图片的RGB三个通道,那么这里5*5*3的3你就可以理解为对应RGB三个通道的3个权重矩阵。
如果你把32*32*3理解为尺寸大小是32*32的feature map,并且channel(或者说depth,只不过现在很少有说depth了)等于3,那么这里的5*5*3
你就可以理解为对应这3个channel的3个权重矩阵。其实你RGB本质上也是3个channel。所以可以统一用后者的理解方式来理解。
张飞飞:
卷积核个数一般是通过实验来不断的尝试的,或者也可以参考其他的网络中的经验来确定@胡智群
@坚持 3,6,10 都叫做Channel, 你可以理解为,初始的RGB图像是 X*X*3个矩阵(channel) 的数据, 经过6个filter(每个filter都有三个权重矩阵)的卷积后,产生的是 6 个X1*X1矩阵的新数据,此时的Channel 个数是6, 在做第二层卷积的时候,卷积核的大小为y*y*6, filter 个数为10 (每个filter的权重矩阵数目为6)时, 产生的数据集为 10个X2*X2矩阵的新数据。
##############################################
天鹅:
请问下
max pooling的话,尺寸是必然会缩小的啊
Lily?:
加pading
天鹅:
@Lily? 好的,多谢。
##############################################
构造一个小型CNN
#coding=utf-8 import torch import torch.nn as nn import torch.nn.functional as F from torch.autograd import Variable class Net(nn.Module): #定义Net的初始化函数,这个函数定义了该神经网络的基本结构 def __init__(self): super(Net, self).__init__() #复制并使用Net的父类的初始化方法,即先运行nn.Module的初始化函数 self.conv1 = nn.Conv2d(1, 6, 5) # 定义conv1函数的是卷积函数:输入为图像(1个频道,即灰度图),输出为 6张特征图(feature map), 卷积核为5x5正方形 self.conv2 = nn.Conv2d(6, 16, 5) # 定义conv2函数的是卷积函数:输入为6张特征图(feature map),输出为16张特征图(feature map), 卷积核为5x5正方形 self.fc1 = nn.Linear(16*5*5, 120) # 定义fc1(fullconnect)全连接函数1为线性函数:y = Wx + b,并将16*5*5个节点连接到120个节点上。 self.fc2 = nn.Linear(120, 84) #定义fc2(fullconnect)全连接函数2为线性函数:y = Wx + b,并将120个节点连接到84个节点上。 self.fc3 = nn.Linear(84, 10) #定义fc3(fullconnect)全连接函数3为线性函数:y = Wx + b,并将84个节点连接到10个节点上。 #定义该神经网络的向前传播函数,该函数必须定义,一旦定义成功,向后传播函数也会自动生成(autograd) def forward(self, x): x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) #输入x经过卷积conv1之后,经过激活函数ReLU(原来这个词是激活函数的意思),使用2x2的窗口进行最大池化Max pooling,然后更新到x。 x = F.max_pool2d(F.relu(self.conv2(x)), 2) #输入x经过卷积conv2之后,经过激活函数ReLU,使用2x2的窗口进行最大池化Max pooling,然后更新到x。 x = x.view(-1, self.num_flat_features(x)) #view函数将张量x变形成一维的向量形式,总特征数并不改变,为接下来的全连接作准备。 x = F.relu(self.fc1(x)) #输入x经过全连接fc1,再经过ReLU激活函数,然后更新x x = F.relu(self.fc2(x)) #输入x经过全连接fc2,再经过ReLU激活函数,然后更新x x = self.fc3(x) #输入x经过全连接3,然后更新x return x #使用num_flat_features函数计算张量x的总特征量(把每个数字都看出是一个特征,即特征总量),比如x是4*2*2的张量,那么它的特征总量就是16。 def num_flat_features(self, x): size = x.size()[1:] # 这里为什么要使用[1:],是因为pytorch只接受批输入,也就是说一次性输入好几张图片,那么输入数据张量的维度自然上升到了4维。【1:】让我们把注意力放在后3维上面 num_features = 1 for s in size: num_features *= s return num_features ################ net = Net() # 以下代码是为了看一下我们需要训练的参数的数量 print (net) params = list(net.parameters()) k=0 for i in params: l =1 print "该层的结构:"+str(list(i.size())) for j in i.size(): l *= j print "参数和:"+str(l) k = k+l print "总参数和:"+ str(k)
为了看num_flat_features函数到底起到了什么作用,我单独把这个函数拎出来测试下是什么样的效果,代码如下:
import torch.nn as nn import torch as t x = t.randn(32,3, 5, 4) print('x.shape=',x.shape) def num_flat_features(x): size = x.size()[1:] # 这里为什么要使用[1:],是因为pytorch只接受批输入,也就是说一次性输入好几张图片,那么输入数据张量的维度自然上升到了4维。【1:】让我们把注意力放在后3维上面 num_features = 1 for s in size: num_features *= s return num_features num_fea = num_flat_features(x) # num_fea的值为60,也就是3*4*5 print('num_fea=',num_fea) x = x.view(-1, num_flat_features(x)) print('x.shape=',x.shape)
输出结果:
x.shape= torch.Size([32, 3, 5, 4])
num_fea= 60
x.shape= torch.Size([32, 60])
##############################################
##############################################
科科:
没搞明白为啥叫卷积呢?不就是一个hadamard积吗?
华华:
名字来的
小炮先生:
跟信号与系统里的卷积不一样
土豆:
其实和信号里是一样的~ 只是用了不同的表达方式
科科:
高君宇:
其实是信号与系统里的相关运算
小炮先生:
信号里的那个卷积我只能从傅里叶变换的角度理解
高君宇:
信号与系统里面,卷积是先翻转再平移,相关是直接平移不用翻转
小炮先生:
这里的卷积最初的认识来自于数字图像处理是我才疏学浅
高君宇:
而卷积神经网络里的卷积核在运算的时候不用翻转,所以相当于信号与系统里面的相关运算,名字是个历史遗留问题
小炮先生:
多谢多谢
#####################################################