前提
cifar10のデータセットでVGG16を用いて精度を出したいです。
実現したいこと
サイズエラーになってしまうのでそれを改善したい。
発生している問題・エラーメッセージ
RuntimeError: Calculated padded input size per channel: (1 x 1). Kernel size: (3 x 3). Kernel size can't be greater than actual input size
該当のソースコード
python
1ソースコード 2import os 3import numpy as np 4import matplotlib.pyplot as plt 5 6import torch 7import torch.nn as nn 8import torch.nn.functional as F 9import torch.optim as optim 10import torchvision.transforms as transforms 11 12import torchvision 13from torchvision import models 14train_data_dir = './data/' 15 16pytorch_vgg16 = models.vgg16(pretrained=False) 17 18print(pytorch_vgg16) 19 20 21class myVGG(nn.Module): 22 23 def __init__(self): 24 super(myVGG, self).__init__() 25 26 self.conv01 = nn.Conv2d(3, 64, 3) 27 self.conv02 = nn.Conv2d(64, 64, 3) 28 self.pool1 = nn.MaxPool2d(2, 2) 29 30 self.conv03 = nn.Conv2d(64, 128, 3) 31 self.conv04 = nn.Conv2d(128, 128, 3) 32 self.pool2 = nn.MaxPool2d(2, 2) 33 34 self.conv05 = nn.Conv2d(128, 256, 3) 35 self.conv06 = nn.Conv2d(256, 256, 3) 36 self.conv07 = nn.Conv2d(256, 256, 3) 37 self.pool3 = nn.MaxPool2d(2, 2) 38 39 self.conv08 = nn.Conv2d(256, 512, 3) 40 self.conv09 = nn.Conv2d(512, 512, 3) 41 self.conv10 = nn.Conv2d(512, 512, 3) 42 self.pool4 = nn.MaxPool2d(2, 2) 43 44 self.conv11 = nn.Conv2d(512, 512, 3) 45 self.conv12 = nn.Conv2d(512, 512, 3) 46 self.conv13 = nn.Conv2d(512, 512, 3) 47 self.pool5 = nn.MaxPool2d(2, 2) 48 49 self.avepool1 = nn.AdaptiveAvgPool2d((7, 7)) 50 51 self.fc1 = nn.Linear(512 * 7 * 7, 4096) 52 self.fc2 = nn.Linear(4096, 4096) 53 self.fc3 = nn.Linear(4096, 5) 54 55 self.dropout1 = nn.Dropout(0.5) 56 self.dropout2 = nn.Dropout(0.5) 57 58 59 60 def forward(self, x): 61 x = F.relu(self.conv01(x)) 62 x = F.relu(self.conv02(x)) 63 x = self.pool1(x) 64 65 x = F.relu(self.conv03(x)) 66 x = F.relu(self.conv04(x)) 67 x = self.pool2(x) 68 69 x = F.relu(self.conv05(x)) 70 x = F.relu(self.conv06(x)) 71 x = F.relu(self.conv07(x)) 72 x = self.pool3(x) 73 74 x = F.relu(self.conv08(x)) 75 x = F.relu(self.conv09(x)) 76 x = F.relu(self.conv10(x)) 77 x = self.pool4(x) 78 79 x = F.relu(self.conv11(x)) 80 x = F.relu(self.conv12(x)) 81 x = F.relu(self.conv13(x)) 82 x = self.pool5(x) 83 84 x = self.avepool1(x) 85 86 # 行列をベクトルに変換 87 x = x.view(-1, 512 * 7 * 7) 88 89 x = F.relu(self.fc1(x)) 90 x = self.dropout1(x) 91 x = F.relu(self.fc2(x)) 92 x = self.dropout2(x) 93 x = self.fc3(x) 94 95 return x 96 97net = myVGG() 98 99 100transform_train = torchvision.transforms.Compose([ 101 torchvision.transforms.CenterCrop(224), 102 torchvision.transforms.ToTensor(), 103 torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) 104]) 105 106transform_valid = torchvision.transforms.Compose([ 107 torchvision.transforms.CenterCrop(224), 108 torchvision.transforms.ToTensor(), 109 torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) 110]) 111 112trainset = torchvision.datasets.CIFAR10(root=train_data_dir, 113 train=True, 114 transform=transforms.ToTensor(), 115 download=True) 116validset = torchvision.datasets.CIFAR10(root=train_data_dir, 117 train=False, 118 transform=transforms.ToTensor(), 119 download=True) 120 121 122# training set 123 124trainloader = torch.utils.data.DataLoader(trainset, batch_size=16, shuffle=True) 125 126# validation set 127 128validloader = torch.utils.data.DataLoader(validset, batch_size=16, shuffle=False) 129 130 131device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 132net.to(device) 133net.train() 134 135criterion = nn.CrossEntropyLoss() 136optimizer = optim.Adam(net.parameters(), lr=0.00001) 137 138# 同じデータを 50 回学習します 139for epoch in range(50): 140 141 # 今回の学習効果を保存するための変数 142 running_loss = 0.0 143 144 for data in trainloader: 145 # データ整理 146 inputs, labels = data 147 inputs = inputs.to(device) 148 labels = labels.to(device) 149 150 # 前回の勾配情報をリセット 151 optimizer.zero_grad() 152 153 # 予測 154 outputs = net(inputs) 155 156 # 予測結果と教師ラベルを比べて損失を計算 157 loss = criterion(outputs, labels) 158 running_loss += loss.item() 159 160 # 損失に基づいてネットワークのパラメーターを更新 161 loss.backward() 162 optimizer.step() 163 164 # このエポックの学習効果 165 print(running_loss) 166 167 168optimizer = optim.Adam(net.parameters(), lr=0.000001) 169 170for epoch in range(50): 171 running_loss = 0.0 172 for data in trainloader: 173 inputs, labels = data 174 inputs = inputs.to(device) 175 labels = labels.to(device) 176 optimizer.zero_grad() 177 outputs = net(inputs) 178 loss = criterion(outputs, labels) 179 running_loss += loss.item() 180 loss.backward() 181 optimizer.step() 182 print(running_loss) 183 184 185# モデルを評価モードにする 186net.eval() 187 188# 全検証データの正しく分類できた枚数を記録 189n_correct = 0 190n_total = 0 191 192for data in validloader: 193 inputs, labels = data 194 inputs = inputs.to(device) 195 labels = labels.to(device) 196 197 # 予測 198 outputs = net(inputs) 199 200 # 予測結果をクラス番号に変換 201 _, predicted = torch.max(outputs.data, 1) 202 203 # 予測結果と実際のラベルを比較して、正しく予測できた枚数を計算 204 res = (predicted == labels) 205 res = res.sum().item() 206 207 208 # 今までに正しく予測できた枚数に計上 209 n_correct = n_correct + res 210 n_total = n_total + len(labels) 211 212 213print(n_correct / n_total) 214 215### 試したこと 216 217色々調査してみたのですがわかりません 218 219### 補足情報(FW/ツールのバージョンなど) 220 221
> RuntimeError: Calculated padded input size per channel: (1 x 1). Kernel size: (3 x 3). Kernel size can't be greater than actual input size
CIFAR10の画像のサイズ32x32に対して、畳み込み層の層数が多すぎます
畳み込み層を減らすか、入力画像のサイズを大きくするかしたら、質問のエラーは出なくなります
たとえば、下記のようにして画像サイズを256x256にすれば、質問のエラーは出なくなると思います
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, ), (0.5,)),
transforms.Resize(256)
])
trainset = datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)
validset = datasets.CIFAR10(root="./data", train=False, download=True, transform=transform)
画像サイズを変えたくなければ、ネットワーク設計を見直してください
上記を変更したら、それよりも後(下)のところで別のエラーが出ますが、それはこの質問のエラーとは別の内容なので、別の質問にしてください
datasets is not defined
とでました。
trainset = datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)
の部分を
trainset = torchvision.datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)
tとするとこのエラーは出ませんでした。
> datasets is not defined
以前
https://teratail.com/questions/ra3upl68o5eonm
のコードを動かした時に、エラーが全部出なくなるように直したので、それをそのまま書いたためです
> trainset = torchvision.datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)
tとするとこのエラーは出ませんでした。
そのあたり変えてるのですね
そんなに細かいところは見てないので、今のコードに合わせて直してください
以前
https://teratail.com/questions/ra3upl68o5eonm
のコードに合わせて指摘点を変更しました。
TypeError: 'module' object is not callable
というエラーが出ました。
この質問のコードを、私の最初のコメントの通りに変更して、さらに
> trainset = datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)
の部分を
trainset = torchvision.datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)
と変更して、「validset」も同様に変更して、google colab(gpu有り)で実行したら、この質問のエラー
> RuntimeError: Calculated padded input size per channel: (1 x 1). Kernel size: (3 x 3). Kernel size can't be greater than actual input size
は出なくなりました
原因が違う別のエラーが「running_loss += loss.item()」の行で出ますが、そのエラーは
> TypeError: 'module' object is not callable
というエラーが出ました。
とは違うものです
質問者さんの環境で実行したら、上記とは違う結果になるのでしょうか?
【追記】
google colabでgpu無しで実行したら、エラーが出る行が一つ上の「loss = criterion(outputs, labels)」に変わりましたが、そのエラーも
> TypeError: 'module' object is not callable
というエラーが出ました。
とは違うものでした
gpu有り/無しどちらの場合のエラーも原因は同じで、この質問のエラーとは違う内容です
import os
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision.transforms as transforms
import torchvision
from torchvision import models
train_data_dir = './data/'
pytorch_vgg16 = models.vgg16(pretrained=False)
print(pytorch_vgg16)
class myVGG(nn.Module):
def __init__(self):
super(myVGG, self).__init__()
self.conv01 = nn.Conv2d(3, 64, 3)
self.conv02 = nn.Conv2d(64, 64, 3)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv03 = nn.Conv2d(64, 128, 3)
self.conv04 = nn.Conv2d(128, 128, 3)
self.pool2 = nn.MaxPool2d(2, 2)
self.conv05 = nn.Conv2d(128, 256, 3)
self.conv06 = nn.Conv2d(256, 256, 3)
self.conv07 = nn.Conv2d(256, 256, 3)
self.pool3 = nn.MaxPool2d(2, 2)
self.conv08 = nn.Conv2d(256, 512, 3)
self.conv09 = nn.Conv2d(512, 512, 3)
self.conv10 = nn.Conv2d(512, 512, 3)
self.pool4 = nn.MaxPool2d(2, 2)
self.conv11 = nn.Conv2d(512, 512, 3)
self.conv12 = nn.Conv2d(512, 512, 3)
self.conv13 = nn.Conv2d(512, 512, 3)
self.pool5 = nn.MaxPool2d(2, 2)
self.avepool1 = nn.AdaptiveAvgPool2d((7, 7))
self.fc1 = nn.Linear(512 * 7 * 7, 4096)
self.fc2 = nn.Linear(4096, 4096)
self.fc3 = nn.Linear(4096, 5)
self.dropout1 = nn.Dropout(0.5)
self.dropout2 = nn.Dropout(0.5)
def forward(self, x):
x = F.relu(self.conv01(x))
x = F.relu(self.conv02(x))
x = self.pool1(x)
x = F.relu(self.conv03(x))
x = F.relu(self.conv04(x))
x = self.pool2(x)
x = F.relu(self.conv05(x))
x = F.relu(self.conv06(x))
x = F.relu(self.conv07(x))
x = self.pool3(x)
x = F.relu(self.conv08(x))
x = F.relu(self.conv09(x))
x = F.relu(self.conv10(x))
x = self.pool4(x)
x = F.relu(self.conv11(x))
x = F.relu(self.conv12(x))
x = F.relu(self.conv13(x))
x = self.pool5(x)
x = self.avepool1(x)
# 行列をベクトルに変換
x = x.view(-1, 512 * 7 * 7)
x = F.relu(self.fc1(x))
x = self.dropout1(x)
x = F.relu(self.fc2(x))
x = self.dropout2(x)
x = self.fc3(x)
return x
net = myVGG()
transform_train = torchvision.transforms.Compose([
torchvision.transforms.CenterCrop(224),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
transform_valid = torchvision.transforms.Compose([
torchvision.transforms.CenterCrop(224),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, ), (0.5,)),
transforms.Resize(256)
])
trainset = torchvision.datasets.CIFAR10(root=train_data_dir, train=True, transform=transforms.ToTensor(), download=True)
validset = torchvision.datasets.CIFAR10(root=train_data_dir, train=False, transform=transforms.ToTensor(), download=True)
# training set
trainloader = torch.utils.data.DataLoader(trainset, batch_size=16, shuffle=True)
# validation set
validloader = torch.utils.data.DataLoader(validset, batch_size=16, shuffle=False)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
net.train()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.00001)
# 同じデータを 50 回学習します
for epoch in range(50):
# 今回の学習効果を保存するための変数
running_loss = 0.0
for data in trainloader:
# データ整理
inputs, labels = data
inputs = inputs.to(device)
labels = labels.to(device)
# 前回の勾配情報をリセット
optimizer.zero_grad()
# 予測
outputs = net(inputs)
# 予測結果と教師ラベルを比べて損失を計算
loss = criterion(outputs, labels)
running_loss += loss.item()
# 損失に基づいてネットワークのパラメーターを更新
loss.backward()
optimizer.step()
# このエポックの学習効果
print(running_loss)
optimizer = optim.Adam(net.parameters(), lr=0.000001)
for epoch in range(50):
running_loss = 0.0
for data in trainloader:
inputs, labels = data
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, labels)
running_loss += loss.item()
loss.backward()
optimizer.step()
print(running_loss)
# モデルを評価モードにする
net.eval()
# 全検証データの正しく分類できた枚数を記録
n_correct = 0
n_total = 0
for data in validloader:
inputs, labels = data
inputs = inputs.to(device)
labels = labels.to(device)
# 予測
outputs = net(inputs)
# 予測結果をクラス番号に変換
_, predicted = torch.max(outputs.data, 1)
# 予測結果と実際のラベルを比較して、正しく予測できた枚数を計算
res = (predicted == labels)
res = res.sum().item()
# 今までに正しく予測できた枚数に計上
n_correct = n_correct + res
n_total = n_total + len(labels)
print(n_correct / n_total)
色々変更を加えていま自分のコードが回答者様の言うように変えれているか不安です。今このコードでやってみたところ同じようなサイズエラーがでてしまいました。全くわかっていなくてすいません。もしよろしければ教えていただきたいです。
> 色々変更を加えていま自分のコードが回答者様の言うように変えれているか不安
下記のようにやってみてください
・この質問の「該当のソースコード」のコードを、全部そのままコピペ
・先頭の「ソースコード」の行と、最後に近い「色々調査してみたのですがわかりません」の行を削除
・下記を変更
trainset = torchvision.datasets.CIFAR10(root=train_data_dir,
train=True,
transform=transforms.ToTensor(),
download=True)
validset = torchvision.datasets.CIFAR10(root=train_data_dir,
train=False,
transform=transforms.ToTensor(),
download=True)
↓ 変更
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, ), (0.5,)),
transforms.Resize(256)
])
trainset = torchvision.datasets.CIFAR10(root=train_data_dir, train=True, download=True, transform=transform)
validset = torchvision.datasets.CIFAR10(root=train_data_dir, train=False, download=True, transform=transform)
そうすれば、当方でgoogle colabで実行したコードと同じになるので、この質問のエラーは出なくなるはずです
ご丁寧にありがとうございます。この質問のエラーはなくなりました。
RuntimeError: CUDA error: device-side assert triggered
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
新たにこのようなエラーがでてしまいました。
原因としては
ライブラリのVersionが違う
ラベル/クラスの数とネットワークの入出力のshapeが異なる
Loss関数の入力が正確でない
などが挙げられるらしいのですが対処方法がわかりません。
> RuntimeError: CUDA error: device-side assert triggered
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
の原因は
> ラベル/クラスの数とネットワークの入出力のshapeが異なる
です
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
↓ 変更
device = "cpu"
と変えてgpuを使わないようにした時のエラーメッセージの方が原因が分かりやすいので、そうしてみてください
そのエラーメッセージを見ても原因が分からなければ、この質問のエラーとは別の内容なので、別の質問にしてください
IndexError: Target 7 is out of bounds.
というエラーになりました。
> IndexError: Target 7 is out of bounds.
の原因は、先のコメントにも書いたように
> ラベル/クラスの数とネットワークの入出力のshapeが異なる
です
考えても分からなければ、別の質問にしてください
あと、入力画像サイズを256x256にしたのは、ネットワーク構造を変えずにエラーが出なくなるようにした対策ですが、それが望ましい対処方法かどうかは、質問者さんの目的に照らし合わせて判断してください
入力画像サイズを32x32から変えずに実行したいのであれば、私の最初のコメントにも書きましたが、ネットワーク設計を見直してください (畳み込み層の層数を減らす等)
【追記】
上記は、今出てる
> IndexError: Target 7 is out of bounds.
とは関係ありません
もともと出てた
> RuntimeError: Calculated padded input size per channel: (1 x 1). Kernel size: (3 x 3). Kernel size can't be greater than actual input size
の対策の話です
なるほど。全くわからないので別の質問で投稿させていただきます。
どの方法が望ましいのかもわからない状態です。
ネットの記事のコードを参考にしているためどのように書き換えるべきかわかっていません。
何度も教えていただいているのに申し訳ないです。
> どの方法が望ましいのかもわからない状態です。
全部のエラーが消えて学習できるようになってから考えればいいと思いますよ
回答1件
あなたの回答
tips
プレビュー