AI-6卷积神经网络
6.1从全连接层到卷积层
之前的多层感知机,仅仅通过将图像数据展平成一维向量而忽略了每个图像的空间结构信息。
卷积神经网络则改善了这一点,且卷积神经网络需要的参数少于全连接架构的网络同时卷积也很容易用GPU并行计算,因此更适合于高效的进行计算。
练习
1假设卷积层 (6.1.3)覆盖的局部区域Δ=0。在这种情况下,证明卷积内核为每组通道独立地实现一个全连接层。
验证代码
# 代码验证
import torch
import torch.nn as nn
#全连接层
class MyNet1(nn.Module):
def __init__(self, linear1, linear2):
super(MyNet1, self).__init__()
self.linear1 = linear1
self.linear2 = linear2
def forward(self, X):
return self.linear2(self.linear1(nn.Flatten()(X)))
#1x1 的卷积层
class MyNet2(nn.Module):
def __init__(self, linear, conv2d):
super(MyNet2, self).__init__()
self.linear = linear
self.conv2d = conv2d
def forward(self, X):
X = self.linear(nn.Flatten()(X))
X = X.reshape(X.shape[0], -1, 1, 1)
X = nn.Flatten()(self.conv2d(X))
return X
linear1 = nn.Linear(15, 10)
linear2 = nn.Linear(10, 5)
conv2d = nn.Conv2d(10, 5, 1)
linear2.weight = nn.Parameter(conv2d.weight.reshape(linear2.weight.shape))
linear2.bias = nn.Parameter(conv2d.bias)
net1 = MyNet1(linear1, linear2)
net2 = MyNet2(linear1, conv2d)
X = torch.randn(2, 3, 5)
# 两个结果实际存在一定的误差,直接print(net1(X) == net2(X))得到的结果不全是True
print(net1(X))
print(net2(X))
tensor([[ 0.1889, 0.3318, 0.3985, -0.1788, -0.3390],
[-0.2068, 0.2603, -0.5014, 0.7563, -0.4728]],
grad_fn=<AddmmBackward0>)
tensor([[ 0.1889, 0.3318, 0.3985, -0.1788, -0.3390],
[-0.2068, 0.2603, -0.5014, 0.7563, -0.4728]],
grad_fn=<ReshapeAliasBackward0>)
2为什么平移不变性可能也不是好主意呢?
平移不变性可能会降低模型的准确性和泛化能力。对于某些任务,平移不变性并不是必须的特性。例如,对于图像分类任务,我们通常希望模型能够识别物体的位置和姿态,并根据这些信息对其进行分类。
3当从图像边界像素获取隐藏表示时,我们需要思考哪些问题?
需要考虑填充多大的padding
的问题
4描述一个类似的音频卷积层的架构。
卷积神经网络(CNN)是深度学习中常用的网络架构,在智能语音中也不例外,比如语音识别。语音中是按帧来处理的,每一帧处理完就得到了相对应的特征向量,常用的特征向量有MFCC等,通常处理完一帧得到的是一个39维的MFCC特征向量。假设一段语音有N帧,处理完这段语音后得到的是一个39行N列(行表示特征维度,列表示帧数)的矩阵,这个矩阵是一个平面,是CNN的输入。应用在图像问题上的CNN通常是二维卷积(因为图像有RGB三个通道),而语音问题上的CNN输入是一个矩阵平面,可以用一维卷积。所谓一维卷积是指卷积核只在一个方向上移动。具体到语音上,假设一段语音提取特征后是一个M行N列(M表示特征维度,N表示帧数)的矩阵平面,卷积核要在帧的方向上从小到大移动。
原文链接:https://blog.csdn.net/david_tym/article/details/112756785
5卷积层也适合于文本数据吗?为什么?
卷积层也适合于文本数据。 在自然语言处理中,文本数据通常表示为词向量矩阵,其中每行代表一个词的向量表示。卷积层可以在这个矩阵上进行卷积操作。此外,卷积层还可以与循环神经网络结合使用,形成卷积神经网络和循环神经网络的混合模型。这种模型可以同时捕捉文本中的局部特征和全局特征,提高模型的性能。
.2图像卷积
在卷积神经网络中,对于某一层的任意元素x,其感受野(receptive field)是指在前向传播期间可能影响x计算的所有元素(来自所有先前层)。
练习
-
构建一个具有对角线边缘的图像
X
。-
如果将本节中举例的卷积核
K
应用于X
,会发生什么情况? -
如果转置
X
会发生什么? -
如果转置
K
会发生什么?
-
-
在我们创建的
Conv2D
自动求导时,有什么错误消息? -
如何通过改变输入张量和卷积核张量,将互相关运算表示为矩阵乘法?
-
手工设计一些卷积核。
-
二阶导数的核的形式是什么?
-
积分的核的形式是什么?
-
得到d次导数的最小核的大小是多少?
-
1.1结果如图
import torch
from torch import nn
from d2l import torch as d2l
def corr2d(X, K): #@save
"""计算二维互相关运算"""
h, w = K.shape
Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
Y[i, j] = (X[i:i + h, j:j + w] * K).sum()
return Y
# 如果将本节中举例的卷积核K应用于X,会发生什么情况?
X = torch.eye(8)
K = torch.tensor([[1.0, -1.0]])
Y = corr2d(X, K)
print(Y)
tensor([[ 1., 0., 0., 0., 0., 0., 0.],
[-1., 1., 0., 0., 0., 0., 0.],
[ 0., -1., 1., 0., 0., 0., 0.],
[ 0., 0., -1., 1., 0., 0., 0.],
[ 0., 0., 0., -1., 1., 0., 0.],
[ 0., 0., 0., 0., -1., 1., 0.],
[ 0., 0., 0., 0., 0., -1., 1.],
[ 0., 0., 0., 0., 0., 0., -1.]])
1.2 转置不影响结果
1.3 Y发生转置
tensor([[ 1., -1., 0., 0., 0., 0., 0., 0.],
[ 0., 1., -1., 0., 0., 0., 0., 0.],
[ 0., 0., 1., -1., 0., 0., 0., 0.],
[ 0., 0., 0., 1., -1., 0., 0., 0.],
[ 0., 0., 0., 0., 1., -1., 0., 0.],
[ 0., 0., 0., 0., 0., 1., -1., 0.],
[ 0., 0., 0., 0., 0., 0., 1., -1.]])
2 会报错
查看代码
conv2d = Conv2D(kernel_size=(1, 2))
try:
for i in range(10):
Y_hat = conv2d(X)
l = (Y_hat - Y) ** 2
conv2d.zero_grad()
l.sum().backward()
# 迭代卷积核
conv2d.weight.data[:] -= lr * conv2d.weight.grad
if (i + 1) % 2 == 0:
print(f'epoch {i+1}, loss {l.sum():.3f}')
except Exception as e:
print(e)
The size of tensor a (0) must match the size of tensor b (7) at non-singleton dimension 3
需要对输入进行调整
查看代码
conv2d = Conv2D(kernel_size=(1, 2))
X = X.reshape((6, 8))
Y = Y.reshape((6, 7))
lr = 3e-2 # 学习率
try:
for i in range(10):
Y_hat = conv2d(X)
l = (Y_hat - Y) ** 2
conv2d.zero_grad()
l.sum().backward()
# 迭代卷积核
conv2d.weight.data[:] -= lr * conv2d.weight.grad
if (i + 1) % 2 == 0:
print(f'epoch {i+1}, loss {l.sum():.3f}')
except Exception as e:
print(e)
3
查看代码
import torch
from torch import nn
from d2l import torch as d2l
def conv2d_by_mul(X, K):
# 获取卷积核大小
h, w = K.shape
# 计算输出图像大小
outh = X.shape[0] - h + 1
outw = X.shape[1] - w + 1
# 调整卷积核形状以便做乘法
K = K.reshape(-1, 1)
# 将输入图像切成卷积核大小的块,打平成一维,存放在列表 Y 中
Y = []
for i in range(outh):
for j in range(outw):
Y.append(X[i:i + h, j:j + w].reshape(-1))
# 将列表 Y 转为张量,每行代表一块的打平结果
Y = torch.stack(Y, 0)
# 用矩阵乘法表示互相关运算
res = (torch.matmul(Y, K)).reshape(outh, outw)
# 返回输出结果
return res
X = torch.ones((2, 3))
X[:,1]=0
print(X)
K = torch.ones((2, 3))
conv2d_by_mul(X, K)