python - 我不明白 conv1d、conv2d 的 pytorch 输入大小
问题描述
我有 2 个时间序列的数据,每个序列有 18 个点。所以我组织了一个 18 行和 2 列的矩阵(有 180 个样本分为 2 个类 - 激活和非激活)。
所以,我想用这些数据做一个 CNN,我的内核沿着一个方向走,沿着线(时间)。附图示例。
在我的代码中,与具有 3 个通道的 RGB 相比,我不知道我有多少通道。并且不知道层的输入大小,以及如何计算才能知道全连接层。
我需要使用 conv1d 吗?转换?转换3d?基于理解 conv 1D 2D 3D,我有 2D 输入,我想做 1D 卷积(因为我将内核向一个方向移动),是否正确?
例如,我如何传递内核大小(3,2)?
在使用带有 batch_size= 4 的 DataLoader 后,我的数据采用这种形式:
print(data.shape, label.shape)
火炬.Size([4, 2, 18]) 火炬.Size([4, 1])
我的卷积模型是:
OBS:我只是放了任意数量的输入/输出大小。
# Creating our CNN Model -> 1D convolutional with 2D input (HbO, HbR)
class ConvModel(nn.Module):
def __init__(self):
super(ConvModel, self).__init__()
self.conv1 = nn.Conv1d(in_channels=1, out_channels= 18, kernel_size=3, stride = 1)
# I dont know the in/out channels of the first conv
self.maxpool = nn.MaxPool1d(kernel_size=3, stride=3)
self.conv2 = nn.Conv1d(18, 32, kernel_size=3)
self.fc1 = nn.Linear(200, 100) #What I put in/out here ?
self.fc2 = nn.Linear(100, 50)
self.fc3 = nn.Linear(50, 2)
def forward(self, x):
x = F.relu(self.mp(self.conv1(x)))
x = self.maxpool(x)
x = F.relu(self.mp(self.conv2(x)))
x = self.maxpool(x)
x = x.view(-1, ??) # flatten the tensor, which number here ?
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
解决方案
稍后您将希望使用双通道 conv1d 作为第一个卷积。即它将采用形状为 [B, 2, 18] 的张量。具有内核大小为 3 的 2 通道输入将定义形状为 [2, 3] 的内核,其中内核沿输入的最后一个维度滑动。输出特征图中的通道 C1 的数量取决于您。C1 定义了你学习了多少个独立的 [2, 3] 内核。每个带有 [2, 3] 内核的卷积都会产生一个输出通道。
请注意,如果您在 conv1d 期间未定义任何零填充,则大小为 3 的内核的输出将减少 2,即您将得到 [B, C1, 16]。如果包含 1 的填充(在卷积之前有效地用一列零填充输入的两侧),则输出将为 [B, C1, 18]。
最大池不会改变通道数。如果您使用 3 的内核大小、3 的步幅并且没有填充,那么最后一个维度将减少到最大池化层的输入张量floor(x.size(2) / 3)
所在的位置。x
如果输入不是 3 的倍数,则特征图末尾的值x
将被忽略(也称为内核/窗口对齐问题)。
我建议查看文档nn.Conv1d
,nn.MaxPool1d
因为它提供了计算输出形状的方程。
让我们考虑两个例子。您可以随意定义C1, C2, F1, F2
。最佳值将取决于您的数据。
没有填充我们得到
class ConvModel(nn.Module):
def __init__(self):
# input [B, 2, 18]
self.conv1 = nn.Conv1d(in_channels=2, out_channels=C1, kernel_size=3)
# [B, C1, 16]
self.maxpool = nn.MaxPool1d(kernel_size=3, stride=3)
# [B, C1, 5] (WARNING last column of activations in previous layer are ignored b/c of kernel alignment)
self.conv2 = nn.Conv1d(C1, C2, kernel_size=3)
# [B, C2, 3]
self.fc1 = nn.Linear(C2*3, F1)
# [B, F1]
self.fc2 = nn.Linear(F1, F2)
# [B, F2]
self.fc2 = nn.Linear(F2, 2)
# [B, 2]
def forward(x):
x = F.relu(self.mp(self.conv1(x)))
x = self.maxpool(x)
x = F.relu(self.mp(self.conv2(x)))
x = self.maxpool(x)
x = x.flatten(1) # flatten the tensor starting at dimension 1
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
请注意最大池层的内核对齐问题。发生这种情况是因为最大池化的输入不是 3 的倍数。为了避免内核对齐问题并使输出大小更加一致,我建议在两个卷积层中添加 1 的额外填充。那么你会有
class ConvModel(nn.Module):
def __init__(self):
# input [B, 2, 18]
self.conv1 = nn.Conv1d(in_channels=2, out_channels=C1, kernel_size=3, padding=1)
# [B, C1, 18]
self.maxpool = nn.MaxPool1d(kernel_size=3, stride=3)
# [B, C1, 6] (no alignment issue b/c 18 is a multiple of 3)
self.conv2 = nn.Conv1d(C1, C2, kernel_size=3, padding=1)
# [B, C2, 6]
self.fc1 = nn.Linear(C2*6, F1)
# [B, F1]
self.fc2 = nn.Linear(F1, F2)
# [B, F2]
self.fc2 = nn.Linear(F2, 2)
# [B, 2]
def forward(x):
x = F.relu(self.mp(self.conv1(x)))
x = self.maxpool(x)
x = F.relu(self.mp(self.conv2(x)))
x = self.maxpool(x)
x = x.flatten(1) # flatten the tensor starting at dimension 1
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
推荐阅读
- python - 从每一代的已知顶点生成随机树图
- wiki - 使用 GAM 或 admin sdk api 更新成员的显示名称
- javascript - 如何创建一个使用 node 和 mongodb 发送邮件的 api
- jquery - 切换点击最多 4 次可以正常工作,但在第 6 次点击之后效果不佳
- php - JS数组没有被传递给php文件?
- html - 如何在 ion-item 中修改 .item-native 类?
- django - Django创建图像文件的路径
- amazon-web-services - 关于检索 AWS EC2 实例作为快照
- amazon-web-services - 用于授予对 AWS 资源的访问权限的 Amazon STS 与身份池
- openlayers - 如何在打开图层图中的标记单击上设置蜘蛛视图标记?