前提・実現したいこと
PytorchをColabで使用して、自動的に機械学習のモデルを作成するプログラムを実装しようと思っています。自動的にモデルを作成するコードは完成したのですが、自動生成したモデルをCIFAR10で評価する際にエラーコードが出てしまいます。
発生している問題・エラーメッセージ
RuntimeError: 1only batches of spatial targets supported (3D tensors) but got targets of size: : [64]
該当のソースコード
・MakeModel関数で自動的にモデルを作成し、nn.modules.container.Sequentialをreturnする。
・net = MakeModel([] , True , 12)で各層3つの要素を持つ4つの層のモデルを作成する。
・train_dataset , val_dataset = Make_CIFAR10_Dataset(1000)で訓練データセットが1000個と49000個の評価セットに分ける。
import torch import torch.nn as nn import torch.nn.functional as F import sys import random import os import numpy as np import matplotlib.pyplot as plt import torch.optim as optim import torchvision from torchvision import models import torchvision.transforms as transforms from torchvision import datasets # リストの要素は全てint型に変更する事ができるか否か。数値は0 ~ 4の範囲内に収まっているか.int型のリストを変換する。 def CheckList(LIST): Objlis = [] for List_Element in LIST: T_F_str = isinstance(List_Element, str) if (T_F_str == False): if (0 <= List_Element <= 4): Objlis.append(List_Element) else: sys.exit("Invalid Number was Enterd") else: try: List_Element = int(List_Element) if (0 <= List_Element <= 4): Objlis.append(List_Element) else: sys.exit("Invalid Number was Enterd") except ValueError: sys.exit("Invalid Element was Enterd") return Objlis # 3つ要素を収納して、nnシーケンシャルをReturnする。 def Make_Layer(ORDER_LIS , INPUT_CHANNEL , OUTPUT_CHANNEL): if (ORDER_LIS.count(0) == 0): Del_Insert_Idx = random.randrange(0,3) ORDER_LIS[Del_Insert_Idx] = 0 Layer = [] for Number in (ORDER_LIS): if Number == 0: Layer.append(nn.Conv2d(INPUT_CHANNEL , OUTPUT_CHANNEL , kernel_size=3, padding=1)) elif Number == 1: Layer.append(nn.BatchNorm2d(OUTPUT_CHANNEL)) elif Number == 2: Layer.append(nn.ReLU(inplace=True)) elif Number == 3: Layer.append(nn.Sigmoid()) elif Number == 4: # probability of an element to be zeroed. Default: 0.5 Layer.append(nn.Dropout(0.5)) Pytorch_Layer = nn.Sequential(*Layer) return Pytorch_Layer def MakeModel(OBJLIS , TF_RANDOM , RANDOM_MODELSIZE): # ObjLisに問題のある数字 / 文字は無いか ObjLis = CheckList(OBJLIS) # ランダムにモデルを作成するための処理 if TF_RANDOM == True: random.seed(0) Criteria_List = [0,1,2,3,4] ObjLis = random.choices(Criteria_List, k = int(RANDOM_MODELSIZE)) Model = [] InputChannel = 3 OutPutChannel = 64 Counter = 0 tmplis = [] for OP_Number in ObjLis: # 3つで一つの層なので、3の倍数ごとにモデルに層を追加する if (Counter % 3 == 0) and (Counter != 0): OP_Layer = Make_Layer(tmplis , InputChannel , OutPutChannel) Model.append(OP_Layer) tmplis = [] tmplis.append(OP_Number) InputChannel = OutPutChannel OutPutChannel = OutPutChannel * 2 else: tmplis.append(OP_Number) Counter = Counter + 1 #3の倍数で割り切れないリストサイズの場合の処理 if 0< len(tmplis) < 3: InputChannel = OutPutChannel OutPutChannel = OutPutChannel * 2 OP_Layer = (tmplis,InputChannel,OutPutChannel) Model.append(OP_Layer) Model = nn.Sequential(*Model) return Model def Make_CIFAR10_Dataset(TrainSize): transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) trainval_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) n_samples = len(trainval_dataset) Train_Per = (TrainSize) / n_samples train_size = int(len(trainval_dataset) * Train_Per) val_size = n_samples - train_size train_dataset, val_dataset = torch.utils.data.random_split(trainval_dataset, [train_size, val_size])` print("TrainSize is " + str(train_size)) print("ValSize is " + str(val_size)) return train_dataset , val_dataset
# GPUの使えるか? !nvidia-smi device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") train_dataset , val_dataset = Make_CIFAR10_Dataset(1000) net = MakeModel([] , True , 12) net.to(device) import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) List_Answer = [] EpochList = [10] BatchList = [64] for Epoch in EpochList: for Batch in BatchList: train_loader = torch.utils.data.DataLoader(train_dataset, Batch, shuffle =True) testloader = torch.utils.data.DataLoader(val_dataset, Batch,shuffle=False, num_workers=2) for i in range(int(Epoch)): running_loss = 0.0 for i, data in enumerate(train_loader, 0): # get the inputs; data is a list of [inputs, labels] inputs, labels = data[0].to(device), data[1].to(device) # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # print statistics running_loss += loss.item() if i % 2000 == 1999: # print every 2000 mini-batches print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 correct = 0 total = 0 with torch.no_grad(): for (images, labels) in testloader: outputs = net(images.to(device)) #for gpu _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels.to(device)).sum().item() print('Accuracy: {:.2f} % TestData'.format(100 * float(correct/total))) List_Answer.append([Epoch , Batch , (100 * correct / total)]) running_loss = 0.0 correct = 0 total = 0 with torch.no_grad(): for (images, labels) in train_loader: outputs = net(images.to(device)) #for gpu _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels.to(device)).sum().item() print('Accuracy: {:.2f} % TrainData'.format(100 * float(correct/total))) List_Answer.append([Epoch , Batch , (100 * correct / total)])
試したこと
エラーコードを検索してみる等はしてみたのですが、解決できませんでした。
補足情報(FW/ツールのバージョンなど)
Pytorch : 1.9.0+cu102
GoogleColab
Python:3.7.10
あなたの回答
tips
プレビュー