卷积笔记

 

天鹅:

 

天鹅:
我想再一次向授课老师核实下,这里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积吗?

华华:
名字来的

小炮先生:
跟信号与系统里的卷积不一样

土豆:
其实和信号里是一样的~ 只是用了不同的表达方式

科科:


高君宇:
其实是信号与系统里的相关运算

小炮先生:
信号里的那个卷积我只能从傅里叶变换的角度理解

高君宇:
信号与系统里面,卷积是先翻转再平移,相关是直接平移不用翻转

小炮先生:
这里的卷积最初的认识来自于数字图像处理是我才疏学浅

高君宇:
而卷积神经网络里的卷积核在运算的时候不用翻转,所以相当于信号与系统里面的相关运算,名字是个历史遗留问题

小炮先生:
多谢多谢

#####################################################

posted @ 2019-01-13 16:31  彩印网  阅读(608)  评论(0编辑  收藏  举报