簡體   English   中英

在 Pytorch 卷積神經網絡中展平張量(大小不匹配錯誤)

[英]Flatten Tensor in Pytorch Convolutional Neural Network (size mismatch error)

我用隨機像素做了一個可重復的例子。 我試圖在卷積層之后展平密集層的張量。 問題出在卷積層和密集層的交叉處。 我不知道如何放置正確數量的神經元。

tl;dr我正在尋找與keras.layers.Flatten()等效的手冊,因為它在pytorch中不存在。

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader

x = np.random.rand(1_00, 3, 100, 100)
y = np.random.randint(0, 2, 1_00)

if torch.cuda.is_available():
    x = torch.from_numpy(x.astype('float32')).cuda()
    y = torch.from_numpy(y.astype('float32')).cuda()

class ConvNet(nn.Module):

    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.conv3 = nn.Conv2d(64, 128, 3)

        self.fc1 = nn.Linear(128, 1024) # 128 is wrong here
        self.fc2 = nn.Linear(1024, 1)

    def forward(self, x):
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))
        x = F.max_pool2d(F.relu(self.conv3(x)), (2, 2))
        x = x.view(x.size(0), -1)
        x = F.relu(self.fc1(x))
        x = torch.sigmoid(self.fc2(x))
        return x

net = ConvNet()
net.cuda()
optimizer = optim.Adam(net.parameters(), lr=0.03)
loss_function = nn.BCELoss()

class Train:

    def __init__(self):
        self.len = x.shape[0]
        self.x_train = x
        self.y_train = y

    def __getitem__(self, index):
        return x[index], y[index].unsqueeze(0)

    def __len__(self):
        return self.len

train = Train()
train_loader = DataLoader(dataset=train, batch_size=64, shuffle=True)

epochs = 1
train_losses = list()
for e in range(epochs):
    running_loss = 0
    for images, labels in train_loader:
        optimizer.zero_grad()
        log_ps = net(images)
        loss = loss_function(log_ps, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    print('It\'s working.')

您一定會遇到尺寸不匹配錯誤,對嗎?

那是因為應用卷積后結果的輸出形狀是[B, 128, 10, 10] ,因此.flatten的結果將是形狀[B, 128*10*10] 所以你需要使用輸入大小為12800的線性層。 那應該可以解決問題。

所以,只要改變

self.fc1 = nn.Linear(128, 1024) # 128 is wrong here

self.fc1 = nn.Linear(12800, 1024)

通常,為了獲得正確尺寸的想法,您可以在紙上計算輸出的形狀,或者僅在正確位置的 forward 函數中使用print(x.shape)調試語句也可以完成這項工作。

這是我制作的一個函數,用於在展平卷積張量的同時自動擬合正確數量的神經元:

def flatten(w, k=3, s=1, p=0, m=True):
    """
    Returns the right size of the flattened tensor after
        convolutional transformation
    :param w: width of image
    :param k: kernel size
    :param s: stride
    :param p: padding
    :param m: max pooling (bool)
    :return: proper shape and params: use x * x * previous_out_channels

    Example:
    r = flatten(*flatten(*flatten(w=100, k=3, s=1, p=0, m=True)))[0]
    self.fc1 = nn.Linear(r*r*128, 1024)
    """
    return int((np.floor((w - k + 2 * p) / s) + 1) / 2 if m else 1), k, s, p, m

在你的情況下:

def __init__(self):
    super().__init__()
    self.conv1 = nn.Conv2d(3, 32, 3)
    self.conv2 = nn.Conv2d(32, 64, 3)
    self.conv3 = nn.Conv2d(64, 128, 3)

    r = flatten(*flatten(*flatten(w=100, k=3, s=1, p=0, m=True)))[0]

    self.fc1 = nn.Linear(r*r*128, 1024)
    self.fc2 = nn.Linear(1024, 1)

    def forward(self, x): ...

暫無
暫無

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

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