import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from torch.autograd import Variable
from sklearn import preprocessing
batch_size = 32
num_classes = 8
epochs = 10
img_rows, img_cols = 256, 256
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
print('x_train shape:', x_train.shape)
print("Training samples: {}".format(x_train.shape[0]))
print("Test samples: {}".format
(x_test.shape[0]))
x_train = torch.Tensor(x_train).float()
x_test = torch.Tensor(x_test).float()
y_train = torch.LongTensor(y_train)
y_test = torch.LongTensor(y_test)
#Define model
model = nn.Sequential(
nn.Conv2d(256,80,1, stride=1),
nn.ReLU(),
nn.Conv2d(80,40,1, stride=1),
nn.ReLU(),
nn.MaxPool2d(4,stride=1),
nn.Conv2d(40,30,1, stride=1),
nn.ReLU(),
nn.Conv2d(30,15,1, stride=1),
nn.ReLU(),
nn.Dropout(0.2),
nn.Flatten(),
nn.Linear(32, 32),
nn.Dropout(0.1),
nn.Linear(num_classes, 256),
nn.ReLU()
)
criterion = nn.CrossEntropyLoss()# cross entropy loss
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
for epoch in range(100):
optimizer.zero_grad()
out = model(x_train)
loss = criterion(out, y_train)
loss.backward()
optimizer.step()
print(f"Epoch {epoch+1}, loss: {loss.item()}")
RuntimeError Traceback (most recent call last)
<ipython-input-10-96fa8b09f1ec> in <module>
63 for epoch in range(100):
64 optimizer.zero_grad()
---> 65 out = model(x_train)
66 loss = criterion(out, y_train)
67 loss.backward()
带有以下错误信息
运行时错误:给定输入大小:(40x256x1)。计算出的输出尺寸:(40x253x-2)。输出尺寸太小
我不确定如何解决这个问题,因为我是 pytorch 的新手,而原始模型确实在 tensorflow 中工作。 任何帮助将不胜感激
答案 0 :(得分:1)
我假设您正在处理图像。在这种情况下,您的代码存在多个问题。同时阅读评论,我需要澄清一些事情。
我认为最重要的是您已经将输入形状的轴调高了。与 Tensorflow 不同,PyTorch 多通道地图的形状为 (b, c, h, w)
(b
:批量大小;c
:通道数;h
xw
:高度和特征图的宽度。
您还将第一层定义为 nn.Conv2d(256, 80, 1, stride=1)
,这意味着它具有 80 个过滤器,并期望有 256 通道输入!假设您遵循我的第一点(即提供 (1,256,256)
图像)到您的模型,这不是您应该想要的。过滤器的数量可以保持在 80,这取决于您和您的神经网络设计。
稍后在您的模型中,您使用 nn.MaxPool2d(4, stride=1)
定义一个最大池。只是要指出您在这里使用的内核大小为 4 像素。这意味着,此时,生成的张量将具有 (b, 40, 253, 253)
的形状。从 256x256 到 253x253 的变化是由于内核大小为 4。
在最终卷积为 (b, 960135)
后,您变平了。那是 253*253*15
(特征图尺寸乘以特征图数量)。最终,下一个密集层需要将该数字作为输入大小。相反,您将 nn.Linear(32, 32)
后跟 nn.Linear(num_classes, 256)
。它应该类似于 nn.Linear(253*253*15, n)
后跟 nn.Linear(n, num_classes)
。其中 n
是任意设置的,我假设您想要在末尾带有 num_classes
logits 的输出。
另外,我看了评论
<块引用>如果你组织正确,我认为你必须将 Sequential() 中的第一层从 nn.Conv2d(256,80,1, stride=1) 更改为 nn.Conv2d(32,80,1, stride= 1)
批量大小与层的大小参数没有任何关系。不要考虑批处理轴,它是第一个轴。您的模型不取决于您的批量大小!
我建议增加内核大小,这将允许您的特征图在通过网络时缩小尺寸,同时增加通道数,直到达到平坦层并完全已连接。
这是您的模型进行了一些重要的修正,足以让它运行:
batch_size = 32
num_classes = 8
img_rows, img_cols = 256, 256
input_shape = (img_rows, img_cols, 1)
# dummy data, would broadcast your data with these shapes
x_train = torch.rand(batch_size, 1, img_rows, img_cols)
y_train = torch.rand(batch_size, 256)
model = nn.Sequential(
nn.Conv2d(1, 80, 1, stride=1),
nn.ReLU(),
nn.Conv2d(80, 40, 1, stride=1),
nn.ReLU(),
nn.MaxPool2d(4, stride=1),
nn.Conv2d(40, 30, 1, stride=1),
nn.ReLU(),
nn.Conv2d(30, 15, 1, stride=1),
nn.ReLU(),
nn.Dropout(0.2),
nn.Flatten(),
nn.Linear(253*253*15, 256),
nn.Dropout(0.1),
nn.Linear(256, num_classes),
nn.ReLU()
)