Time: 2019-08-02
视频链接:https://youtu.be/stWU37L91Yc?list=PLZbbT5o_s2xrfNyHZsM6ufI0iZENK9xgG
卷积层的参数
-
kernel_size
: filter的大小,一般filter都是正方形,所以指定一个值即可。注意kernel
和filter
是等价的意思。 -
out_channels
: filters的个数,一个filter输出一个channel.
全连接层的参数
-
out_features
: 设置输出张量的大小,也表示该层神经元的个数
CNN权重
class Network():
def __init__(self):
# super(Network, self).__init__()
# 将层定义为属性
self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)
self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)
self.fc2 = nn.Linear(in_features=120, out_features=60)
self.out = nn.Linear(in_features=60, out_features=10)
# 实现forward函数,即组装网络的过程
def forward(self, t):
# pass
return t
不继承nn.Module
的类,实例化后:
# 实例化网络
network = Network()
network
# <__main__.Network at 0x7febde19b668>
就是一个平平无奇的对象。
继承后:
class Network(nn.Module):
def __init__(self):
super(Network, self).__init__()
# 将层定义为属性
self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)
self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)
self.fc2 = nn.Linear(in_features=120, out_features=60)
self.out = nn.Linear(in_features=60, out_features=10)
# 实现forward函数,即组装网络的过程
def forward(self, t):
# pass
return t
实例化后:
network
'''
Network(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 12, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=192, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=60, bias=True)
(out): Linear(in_features=60, out_features=10, bias=True)
)
'''
刚好今天复习到__repr__
函数的实现,显然在nn.Module
中实现了__repr__
函数,这个可打印出关于对象的信息。
关于卷积层的权重问题思考
network.conv1.weight.shape
# torch.Size([6, 1, 5, 5])
就以这层作为例子好了,可以反映出卷积操作的全部问题。
鼓励的思考卷积操作,我们可以想到几个关键词:
- 权重共享
- 稀疏连接
但我个人觉得在思考CNN问题时,最重要的起点是:想到卷积核是3D张量,每一层的卷积核有多个,所以整体权重是个4D张量。每个卷积核对应着提取一种特征的权重。
卷积层的权重就是卷积核的权重。
另外不要混淆了卷积核输出的特征图的大小。
卷积操作是立体的,是和输入张量形状所匹配的。
这里,在定义卷积操作时,输入通道个数在前,输出通道个数在后,也即该层的卷积核的个数大小。
该层的权重的形状中,第一个轴的大小是本层的输出通道个数,这样方便我们取得单个卷积核的大小。
[6, 1, 5, 5]可以看作是6个卷积核,每个卷积核的形状是[1, 5, 5]。因为输入层就一层,所以这是个平面卷积核。
全连接层就是密集的矩阵乘法,是二维平面。
权重是个平面矩阵。
查看网络的参数
在nn.Module
中,网络中有个默认函数实现,parameters()
,可以按照如下的方式调用:
# 获取所有参数
for param in network.parameters():
print(param.shape)
'''
torch.Size([6, 1, 5, 5])
torch.Size([6])
torch.Size([12, 6, 5, 5])
torch.Size([12])
torch.Size([120, 192])
torch.Size([120])
torch.Size([60, 120])
torch.Size([60])
torch.Size([10, 60])
torch.Size([10])
'''
另外还可以获取命名参数:
for name, param in network.named_parameters():
print(name, '\t\t', param.shape)
'''
conv1.weight torch.Size([6, 1, 5, 5])
conv1.bias torch.Size([6])
conv2.weight torch.Size([12, 6, 5, 5])
conv2.bias torch.Size([12])
fc1.weight torch.Size([120, 192])
fc1.bias torch.Size([120])
fc2.weight torch.Size([60, 120])
fc2.bias torch.Size([60])
out.weight torch.Size([10, 60])
out.bias torch.Size([10])
'''
这些都是可学习参数。
END.
网友评论