前提
PyTorchでセグメンテーションのタスクをしています。
しかし学習させようとすると
RuntimeError: only batches of spatial targets supported (3D tensors) but got targets of size: : [4, 3, 512, 512]
というエラーが出てうまくいきません。
実現したいこと
ここに実現したいことを箇条書きで書いてください。
学習できるように3Dテンソルで読み込める3次元の形でNNにデータを渡したい。
発生している問題・エラーメッセージ
python
1使用デバイス: cuda:0 2------------- 3Epoch 1/30 4------------- 5(train) 6/usr/local/lib/python3.7/dist-packages/torch/optim/lr_scheduler.py:136: UserWarning: Detected call of `lr_scheduler.step()` before `optimizer.step()`. In PyTorch 1.1.0 and later, you should call them in the opposite order: `optimizer.step()` before `lr_scheduler.step()`. Failure to do this will result in PyTorch skipping the first value of the learning rate schedule. See more details at https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate 7 "https://pytorch.org/docs/stable/optim.html#how-to-adjust-learning-rate", UserWarning) 8--------------------------------------------------------------------------- 9RuntimeError Traceback (most recent call last) 10<ipython-input-12-d290d3cdc9e6> in <module>() 11 1 num_epochs = 30 12----> 2 train_loss_list, val_loss_list = train_model(net, dataloaders_dict, criterion, optimizer, scheduler, num_epochs) 13 143 frames 15<ipython-input-11-4b1cf2875693> in train_model(net, dataloaders_dict, criterion, optimizer, scheduler, num_epochs) 16 69 with torch.set_grad_enabled(phase == 'train'): 17 70 outputs = net(imges) 18---> 71 loss = criterion(outputs, anno_class_imges.long()) / batch_multiplier 19 72 20 73 # 訓練時はバックプロパゲーション 21 22/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs) 23 1128 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks 24 1129 or _global_forward_hooks or _global_forward_pre_hooks): 25-> 1130 return forward_call(*input, **kwargs) 26 1131 # Do not call functions when jit is used 27 1132 full_backward_hooks, non_full_backward_hooks = [], [] 28 29<ipython-input-9-ce874e9e94eb> in forward(self, outputs, targets) 30 24 """ 31 25 32---> 26 loss = F.cross_entropy(outputs[0], targets, reduction='mean') 33 27 loss_aux = F.cross_entropy(outputs[1], targets, reduction='mean') 34 28 35 36/usr/local/lib/python3.7/dist-packages/torch/nn/functional.py in cross_entropy(input, target, weight, size_average, ignore_index, reduce, reduction, label_smoothing) 37 3012 if size_average is not None or reduce is not None: 38 3013 reduction = _Reduction.legacy_get_string(size_average, reduce) 39-> 3014 return torch._C._nn.cross_entropy_loss(input, target, weight, _Reduction.get_enum(reduction), ignore_index, label_smoothing) 40 3015 41 3016 42 43RuntimeError: only batches of spatial targets supported (3D tensors) but got targets of size: : [4, 3, 512, 512]
該当のソースコード
python
1from utils.dataloader import make_datapath_list, DataTransform, Dataset 2makepath = make_datapath_list() 3train_img_list, val_img_list, test_img_list, train_anno_list, val_anno_list, test_anno_list, = makepath.get_list() 4 5train_dataset = Dataset(train_img_list, train_anno_list, phase="train", transform=DataTransform(input_size=512)) 6val_dataset = Dataset(val_img_list, val_anno_list, phase="val", transform=DataTransform(input_size=512)) 7print(train_dataset.__getitem__(0)[0].shape)#torch.Size([3, 512, 512]) 8print(train_dataset.__getitem__(0)[1].shape)#torch.Size([3, 512, 512]) 9 10#ここからdata_augumentation.py 11import os.path as osp 12from PIL import Image 13from pathlib import Path 14import torch.utils.data as data 15import torch 16import torchvision.datasets as datasets 17from torchvision import transforms 18import random 19 20 21from utils.data_augumentation import Compose, Resize, Normalize_Tensor 22 23class make_datapath_list(): 24 25 def get_list(self): 26 27 #事前準備 28 cwd_path = Path.cwd() 29 img_dir = cwd_path / 'images'#検索するファイル 30 label_dir = cwd_path / 'labels'#検索するファイル 31 32 #画像のパスをリストに格納 33 img_dir_g = img_dir.iterdir() 34 img_paths = [ str(x) for x in img_dir_g] 35 img_paths.sort() 36 37 #ラベルのパスをリストに格納 38 label_dir_g = label_dir.iterdir() 39 label_paths = [ str(y) for y in label_dir_g] 40 label_paths.sort() 41 42 p = list(zip(img_paths, label_paths)) 43 random.shuffle(p) 44 img_paths, label_paths = zip(*p) 45 46 train_len = int(len(img_paths)*0.7) 47 val_len = len(img_paths) - train_len 48 49 #画像 50 train_img_list = img_paths[:train_len] 51 val_img_list = img_paths[train_len:train_len+val_len] 52 test_img_list = img_paths[train_len+val_len:] 53 #ラベル 54 train_anno_list = label_paths[:train_len] 55 val_anno_list = label_paths[train_len:train_len+val_len] 56 test_anno_list = label_paths[train_len+val_len:] 57 58 return train_img_list, val_img_list, test_img_list, train_anno_list, val_anno_list, test_anno_list, 59 60class DataTransform(): 61 """ 62 画像のサイズをinput_size x input_sizeにする。 63 64 Attributes 65 ---------- 66 input_size : int 67 リサイズ先の画像の大きさ。 68 """ 69 70 def __init__(self, input_size): 71 self.data_transform = { 72 'train': Compose([ 73 Resize(input_size), 74 Normalize_Tensor([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) 75 ]), 76 'val': Compose([ 77 Resize(input_size), 78 Normalize_Tensor([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) 79 ]) 80 } 81 82 def __call__(self, phase, img, anno_class_img): 83 """ 84 Parameters 85 ---------- 86 phase : 'train' or 'val' 87 前処理のモードを指定。 88 """ 89 return self.data_transform[phase](img, anno_class_img) 90 91 92class Dataset(data.Dataset): 93 """ 94 Datasetを作成するクラス。PyTorchのDatasetクラスを継承。 95 96 Attributes 97 ---------- 98 img_list : リスト 99 画像のパスを格納したリスト 100 anno_list : リスト 101 アノテーションへのパスを格納したリスト 102 phase : 'train' or 'test' 103 学習か訓練かを設定する。 104 transform : object 105 前処理クラスのインスタンス 106 """ 107 108 def __init__(self, img_list, anno_list, phase, transform): 109 self.img_list = img_list 110 self.anno_list = anno_list 111 self.phase = phase 112 self.transform = transform 113 114 def __len__(self): 115 '''画像の枚数を返す''' 116 return len(self.img_list) 117 118 def __getitem__(self, index): 119 ''' 120 前処理をした画像のTensor形式のデータとアノテーションを取得 121 ''' 122 img, anno_class_img = self.pull_item(index) 123 return img, anno_class_img 124 125 def pull_item(self, index): 126 '''画像のTensor形式のデータ、アノテーションを取得する''' 127 128 # 1. 画像読み込み 129 image_file_path = self.img_list[index] 130 img = Image.open(image_file_path) # [高さ][幅][色RGB] 131 132 # 2. アノテーション画像読み込み 133 anno_file_path = self.anno_list[index] 134 anno_class_img = Image.open(anno_file_path) # [高さ][幅] 135 136 # 3. 前処理を実施 137 img, anno_class_img = self.transform(self.phase, img, anno_class_img) 138 139 return img, anno_class_img
補足情報(FW/ツールのバージョンなど)
GoogleColab環境
PyTorch 1.12.0+cu113
動かしたいのはこれでしょうか?
https://github.com/YutaroOgawa/pytorch_advanced/blob/master/3_semantic_segmentation/3-7_PSPNet_training.ipynb
はい!その通りです。
書籍の第3章の通りにVOCデータセットを使っても、質問に記載のエラーになるのでしょうか?
それとも、書籍の通りだと実行できるけど、他のデータセットだとエラーになるのでしょうか?
書籍の通りだと実行できるけど自作データセットだとエラーになります。
自作データセットは
画像:jpg 512*512
ラベル画像:png 512*512 青色でラベリングして背景を黒で塗りつぶしています。
書籍では
print(val_dataset.__getitem__(0)[1].shape)#torch.Size([512, 512])
となっているのですが、自作データでは
print(val_dataset.__getitem__(0)[1].shape)#torch.Size([3, 512, 512])
と3次元になっているようです。
(画像のindex_sizeを457→512に変更しています。)
https://github.com/YutaroOgawa/pytorch_advanced/issues/108
に、似たようなことが書かれてます
外してたらごめんなさい
ありがたい助言です。
リンク先の内容をまとめると
学習に使う画像サイズが(281, 500, 3)ではない場合に次元が増えることがあるため、画像サイズを(281, 500, 3)に変換して学習させる必要があるということでしょうか。ひとまず試してみようと思います。
私のコードでは、データトランスフォームでscaleに関する記述を削除しています。
入力の画像サイズを変えずに学習させる方法はございますでしょうか。
https://github.com/YutaroOgawa/pytorch_advanced/issues/108#issuecomment-667909443
から下のところの話かな? と思ったのですが
誤解しておりました。
class VOCDataset(data.Dataset):内の
def pull_item(self, index):
'''画像のTensor形式のデータ、アノテーションを取得する'''
# 1. 画像読み込み
image_file_path = self.img_list[index]
img = Image.open(image_file_path) # [高さ][幅][色RGB]
# 2. アノテーション画像読み込み
anno_file_path = self.anno_list[index]
anno_class_img = Image.open(anno_file_path) # [高さ][幅]
ここに追記
np.array(anno_class_img)としたら良いでしょうか
# 3. 前処理を実施
img, anno_class_img = self.transform(self.phase, img, anno_class_img)
return img, anno_class_img
anno_class_img = anno_class_img.convert('P')
かな??
参考
https://choshicure.hatenablog.com/entry/png-rgb-to-pallet
ありがとうございます!無事このエラーは出なくなりました。
print(val_dataset.__getitem__(0)[1].shape)#torch.Size([512, 512])
次は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.
のエラーが出たので別に質問しようと思います。
> RuntimeError: CUDA error: device-side assert triggered
https://teratail.com/questions/dcq6kaatbd6192
と同じでしょうか?
「質問への追記・修正依頼」も見てください
ありがとうございます。
同じ問題だと思われます。
アノテーションラベルの色の数が問題でした。

回答1件
あなたの回答
tips
プレビュー