実現したいこと
学習を実行させたい。
NoneTypeのオブジェクトを発見しエラーを直したい。
発生している問題・分からないこと
小川雄太郎さんのPyTorchによる発展ディープランニングに習いセマンティックセグメンテーションの学習モデルを実装したが、学習・検証が実行できていない。
エラーメッセージ
error
1TypeError Traceback (most recent call last) 2/home/hatasa/Desktop/vscodepy_11/3_7.ipynb セル 12 line 3 3 1 # 学習・検証を実行する 4 2 num_epochs = 5 5----> 3 train_model(net, dataloaders_dict, criterion, scheduler, optimizer, num_epochs=num_epochs) 6 7/home/hatasa/Desktop/vscodepy_11/3_7.ipynb セル 12 line 6 8 59 # データローダーからminibatchずつ取り出すループ 9 60 count = 0 # multiple minibatch 10---> 61 for imges, anno_class_imges in dataloaders_dict[phase]: 11 62 # ミニバッチがサイズが1だと、バッチノーマライゼーションでエラーになるのでさける 12 63 # issue #186より不要なのでコメントアウト 13 64 # if imges.size()[0] == 1: 14 65 # continue 15 66 16 67 # GPUが使えるならGPUにデータを送る 17 68 imges = imges.to(device) 18 69 anno_class_imges = anno_class_imges.to(device) 19 20File ~/test/lib/python3.10/site-packages/torch/utils/data/dataloader.py:633, in _BaseDataLoaderIter.__next__(self) 21 630 if self._sampler_iter is None: 22 631 # TODO(https://github.com/pytorch/pytorch/issues/76750) 23 632 self._reset() # type: ignore[call-arg] 24--> 633 data = self._next_data() 25... 26-> 1861 data = bytes(data) 27 1862 palette = ImagePalette.raw(rawmode, data) 28 1863 self.mode = "PA" if "A" in self.mode else "P" 29 30TypeError: cannot convert 'NoneType' object to bytes
該当のソースコード
Python
1# モデルを学習させる関数を作成 2def train_model(net, dataloaders_dict, criterion, scheduler, optimizer, num_epochs): 3 4 # GPUが使えるかを確認 5 device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 6 print("使用デバイス:", device) 7 8 # ネットワークをGPUへ 9 net.to(device) 10 11 # ネットワークがある程度固定であれば、高速化させる 12 torch.backends.cudnn.benchmark = True 13 14 # 画像の枚数 15 num_train_imgs = len(dataloaders_dict["train"].dataset) 16 num_val_imgs = len(dataloaders_dict["val"].dataset) 17 batch_size = dataloaders_dict["train"].batch_size 18 19 # イテレーションカウンタをセット 20 iteration = 1 21 logs = [] 22 23 # multiple minibatch 24 batch_multiplier = 3 25 26 # epochのループ 27 for epoch in range(num_epochs): 28 29 # 開始時刻を保存 30 t_epoch_start = time.time() 31 t_iter_start = time.time() 32 epoch_train_loss = 0.0 # epochの損失和 33 epoch_val_loss = 0.0 # epochの損失和 34 35 print('-------------') 36 print('Epoch {}/{}'.format(epoch+1, num_epochs)) 37 print('-------------') 38 39 # epochごとの訓練と検証のループ 40 for phase in ['train', 'val']: 41 if phase == 'train': 42 net.train() # モデルを訓練モードに 43 optimizer.zero_grad() 44 optimizer.step() 45 scheduler.step() # 最適化schedulerの更新 46 print('(train)') 47 48 else: 49 if((epoch+1) % 5 == 0): 50 net.eval() # モデルを検証モードに 51 print('-------------') 52 print('(val)') 53 else: 54 # 検証は5回に1回だけ行う 55 continue 56 57 # データローダーからminibatchずつ取り出すループ 58 count = 0 # multiple minibatch 59 for imges, anno_class_imges in dataloaders_dict[phase]: 60 # ミニバッチがサイズが1だと、バッチノーマライゼーションでエラーになるのでさける 61 # issue #186より不要なのでコメントアウト 62 # if imges.size()[0] == 1: 63 # continue 64 65 # GPUが使えるならGPUにデータを送る 66 imges = imges.to(device) 67 anno_class_imges = anno_class_imges.to(device) 68 69 70 # multiple minibatchでのパラメータの更新 71 if (phase == 'train') and (count == 0): 72 optimizer.step() 73 optimizer.zero_grad() 74 count = batch_multiplier 75 76 # 順伝搬(forward)計算 77 with torch.set_grad_enabled(phase == 'train'): 78 outputs = net(imges) 79 loss = criterion( 80 outputs, anno_class_imges.long()) / batch_multiplier 81 82 # 訓練時はバックプロパゲーション 83 if phase == 'train': 84 loss.backward() # 勾配の計算 85 count -= 1 # multiple minibatch 86 87 if (iteration % 10 == 0): # 10iterに1度、lossを表示 88 t_iter_finish = time.time() 89 duration = t_iter_finish - t_iter_start 90 print('イテレーション {} || Loss: {:.4f} || 10iter: {:.4f} sec.'.format( 91 iteration, loss.item()/batch_size*batch_multiplier, duration)) 92 t_iter_start = time.time() 93 94 epoch_train_loss += loss.item() * batch_multiplier 95 iteration += 1 96 97 # 検証時 98 else: 99 epoch_val_loss += loss.item() * batch_multiplier 100 101 # epochのphaseごとのlossと正解率 102 t_epoch_finish = time.time() 103 print('-------------') 104 print('epoch {} || Epoch_TRAIN_Loss:{:.4f} ||Epoch_VAL_Loss:{:.4f}'.format( 105 epoch+1, epoch_train_loss/num_train_imgs, epoch_val_loss/num_val_imgs)) 106 print('timer: {:.4f} sec.'.format(t_epoch_finish - t_epoch_start)) 107 t_epoch_start = time.time() 108 109 # ログを保存 110 log_epoch = {'epoch': epoch+1, 'train_loss': epoch_train_loss / 111 num_train_imgs, 'val_loss': epoch_val_loss/num_val_imgs} 112 logs.append(log_epoch) 113 df = pd.DataFrame(logs) 114 df.to_csv("log_output.csv") 115 116 # 最後のネットワークを保存する 117 torch.save(net.state_dict(), 'weights/pspnet50_' + 118 str(epoch+1) + '.pth') 119_________________________________________________________ 120# 学習・検証を実行する 121num_epochs = 5 122train_model(net, dataloaders_dict, criterion, scheduler, optimizer, num_epochs=num_epochs)
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
データローダーに問題があると思われるが原因が分からなかった。
補足
class DataTransform():
"""
画像とアノテーションの前処理クラス。訓練時と検証時で異なる動作をする。
画像のサイズをinput_size x input_sizeにする。
訓練時はデータオーギュメンテーションする。
Attributes ---------- input_size : int リサイズ先の画像の大きさ。 color_mean : (R, G, B) 各色チャネルの平均値。 color_std : (R, G, B) 各色チャネルの標準偏差。 """ def __init__(self, input_size, color_mean, color_std): self.data_transform = { 'train': Compose([ Scale(scale=[0.5, 1.5]), # 画像の拡大 RandomRotation(angle=[-10, 10]), # 回転 RandomMirror(), # ランダムミラー Resize(input_size), # リサイズ(input_size) Normalize_Tensor(color_mean, color_std) # 色情報の標準化とテンソル化 ]), 'val': Compose([ Resize(input_size), # リサイズ(input_size) Normalize_Tensor(color_mean, color_std) # 色情報の標準化とテンソル化 ]) } def __call__(self, phase, img, anno_class_img): """ Parameters ---------- phase : 'train' or 'val' 前処理のモードを指定。 """ return self.data_transform[phase](img, anno_class_img)
class VOCDataset(data.Dataset):
"""
VOC2012のDatasetを作成するクラス。PyTorchのDatasetクラスを継承。
Attributes ---------- img_list : リスト 画像のパスを格納したリスト anno_list : リスト アノテーションへのパスを格納したリスト phase : 'train' or 'test' 学習か訓練かを設定する。 transform : object 前処理クラスのインスタンス """ def __init__(self, img_list, anno_list, phase, transform): self.img_list = img_list self.anno_list = anno_list self.phase = phase self.transform = transform def __len__(self): '''画像の枚数を返す''' return len(self.img_list) def __getitem__(self, index): ''' 前処理をした画像のTensor形式のデータとアノテーションを取得 ''' img, anno_class_img = self.pull_item(index) print("Before transformation - img shape:", img.shape) print("Before transformation - anno_class_img shape:", anno_class_img.shape) return img, anno_class_img 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) # [高さ][幅] # 3. 前処理を実施 img, anno_class_img = self.transform(self.phase, img, anno_class_img) print("After transformation - img shape:", img.shape) print("After transformation - anno_class_img shape:", anno_class_img.shape) return img, anno_class_img

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