簡體   English   中英

我不明白 conv1d、conv2d 的 pytorch 輸入大小

[英]I don't understand pytorch input sizes of conv1d, conv2d

我有 2 個時間序列的數據,每個序列 18 點。 所以我組織了一個 18 行 2 列的矩陣(180 個樣本分為 2 個類別 - 激活和非激活)。

所以,我想用這些數據做一個 CNN,我的內核沿着線(時間)朝一個方向走。 附圖示例。

我的數據 18x2

在我的代碼中,與具有 3 個通道的 RGB 相比,我不知道我的通道如何。 並且不知道層的輸入大小,以及如何計算才能知道全連接層。

我需要使用 conv1d 嗎? conv2d? conv3d ? 基於理解 conv 1D 2D 3D ,我有 2D 輸入,我想做 1D 卷積(因為我在一個方向上移動我的內核),這是正確的嗎?

例如,我如何傳遞內核大小(3,2)?

我的數據是這種形式,使用 DataLoader 和 batch_size= 4 后:

print(data.shape, label.shape)

火炬大小([4, 2, 18]) 火炬大小([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.Conv1dnn.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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM