質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Q&A

解決済

1回答

2114閲覧

MobileNet学習中にepoch終了時にValidate関数内で発生したエラーが解決できない。

Otom_jp

総合スコア4

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

Google Colaboratory

Google Colaboratoryとは、無償のJupyterノートブック環境。教育や研究機関の機械学習の普及のためのGoogleの研究プロジェクトです。PythonやNumpyといった機械学習で要する大方の環境がすでに構築されており、コードの記述・実行、解析の保存・共有などが可能です。

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

0グッド

0クリップ

投稿2020/06/09 09:52

編集2020/06/09 09:56

前提・実現したいこと

現在Google ColabにてPyTorchを用いてMobileNet V1を実装。
学習データはImageNetのスモールデータセットであるImageNetteを用いる。
このデータセットは

!wget https://s3.amazonaws.com/fast-ai-imageclas/imagenette-320.tgz !tar xzf imagenette-320.tgz

コマンドで取得しColab上から対象のGoogleドライブ内のフォルダにアクセスし読み込んでいる。

ベースとなる学習コードはGitHub上の

https://github.com/Z0m6ie/CIFAR-10_PyTorch

を参考にしている。

このデータセットを用いて学習を行いたい。

発生している問題・エラーメッセージ

99%まで訓練が終わりvalidationを行う際にエラーが発生している模様。

Error

1Requirement already satisfied: tensorboardX in /usr/local/lib/python3.6/dist-packages (2.0) 2Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from tensorboardX) (1.12.0) 3Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from tensorboardX) (1.18.4) 4Requirement already satisfied: protobuf>=3.8.0 in /usr/local/lib/python3.6/dist-packages (from tensorboardX) (3.10.0) 5Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from protobuf>=3.8.0->tensorboardX) (47.1.1) 6--------------------------------------------------------------------------- 7IndexError Traceback (most recent call last) 8<ipython-input-57-8e253ac717c8> in <module>() 9 9 for epoch in range(1): 10 10 train(epoch) 11---> 11 loss, accuracy = validate(epoch) 12 12 best_loss, best_acc = save_best(loss, accuracy, best_loss, best_acc) 13 13 14 155 frames 16/usr/local/lib/python3.6/dist-packages/torchvision/datasets/folder.py in __getitem__(self, index) 17 132 tuple: (sample, target) where target is class_index of the target class. 18 133 """ 19--> 134 path, target = self.samples[index] 20 135 sample = self.loader(path) 21 136 if self.transform is not None: 22 23IndexError: list index out of range

該当のソースコード

以下にノートブック上で学習データの読み込み等を行っている箇所、また、train関数とvalidate関数とそれらの実行を行うソースコードを記す。
なにが原因でこのエラーが起きているのかわからないので原因と解決方法をご教授頂ければ幸いです。

Dataload

1normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], 2 std=[0.229, 0.224, 0.225]) 3 4valid_size=0.1 5 6traindir = 'imagenette-320/train' 7valdir = 'imagenette-320/val' 8 9train_transform = transforms.Compose([ 10 transforms.RandomResizedCrop(224), 11 transforms.RandomHorizontalFlip(), 12 transforms.ToTensor(), 13 normalize 14]) 15 16valid_transform = transforms.Compose([ 17 transforms.Resize(256), 18 transforms.CenterCrop(224), 19 transforms.ToTensor(), 20 normalize 21]) 22train_dataset = datasets.ImageFolder(traindir,transform=train_transform) 23valid_dataset = datasets.ImageFolder(valdir,transform=valid_transform) 24 25num_train = len(train_dataset) 26indices = list(range(num_train)) 27split = int(np.floor(valid_size * num_train)) 28 29 30np.random.seed(42) 31np.random.shuffle(indices) 32 33train_idx, valid_idx = indices[split:], indices[:split] 34 35 36train_sampler = SubsetRandomSampler(train_idx) 37valid_sampler = SubsetRandomSampler(valid_idx) 38 39 40train_loader = torch.utils.data.DataLoader(train_dataset, 41 batch_size=128, sampler=train_sampler) 42 43valid_loader = torch.utils.data.DataLoader(valid_dataset, 44 batch_size=128, sampler=valid_sampler)

Train

1def train(epoch): 2 model.train() 3 writer = SummaryWriter() 4 for batch_idx, (data, target) in enumerate(train_loader): 5 if use_cuda: 6 data, target = data.cuda(), target.cuda() 7 data, target = Variable(data), Variable(target) 8 optimizer.zero_grad() 9 output = model(data) 10 correct = 0 11 pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability 12 #print('pred=',pred) 13 correct += pred.eq(target.data.view_as(pred)).sum() 14 loss = criterion(output, target) 15 loss.backward() 16 accuracy = 100 * (int(correct)/ int(len(output))) 17 #print('correct=',correct) 18 #print('len=',len(output)) 19 #print(accuracy) 20 optimizer.step() 21 if batch_idx % 1 == 0: 22 #print('correct=',correct) 23 #print('len=',len(output)) 24 #print(accuracy) 25 print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}, Accuracy: {:.2f}'.format(epoch, batch_idx * len(data), len(train_loader.dataset),100. * batch_idx / len(train_loader), loss.data.item(), accuracy)) 26 writer.add_scalar('Loss/Loss', loss.data.item(), epoch) 27 writer.add_scalar('Accuracy/Accuracy', accuracy, epoch) 28 scheduler.step()

Validate

1def validate(epoch): 2 valid_loss=0.0 3 accuracy=0.0 4 model.eval() 5 6 writer = SummaryWriter() 7 8 valid_loss = 0 9 correct = 0 10 11 for data, target in valid_loader: 12 if use_cuda: 13 data, target = data.cuda(), target.cuda() 14 15 data, target = Variable(data, volatile=True), Variable(target) 16 output = model(data) 17 valid_loss += F.cross_entropy(output, target, size_average=False).data.item() # sum up batch loss 18 pred = output.data.max(1, keepdim=True)[1] # get the index of the max log-probability 19 correct += pred.eq(target.data.view_as(pred)).sum() 20 21 22 valid_loss /= len(valid_idx) 23 accuracy = 100. * correct / len(valid_idx) 24 print('\nValidation set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format( 25 valid_loss, correct, len(valid_idx), 26 100. * correct / len(valid_idx))) 27 writer.add_scalar('Loss/Validation_Loss', valid_loss, epoch) 28 writer.add_scalar('Accuracy/Validation_Accuracy', accuracy, epoch) 29 30 return valid_loss, accuracy
!pip install tensorboardX from tensorboardX import SummaryWriter best_loss = None best_acc = None for epoch in range(1): train(epoch) loss, accuracy = validate(epoch) best_loss, best_acc = save_best(loss, accuracy, best_loss, best_acc)

試したこと

そもそものデータセットの異常を考えましたが、このデータセットを紹介していた

https://qiita.com/sakaia/items/a8d7b08ebce92da1fc14

こちらのページでは問題なく学習が出来ており、私自身もResNetですが同じ手順を踏み学習できました。
どなたかお力添え頂ければ幸いです

補足情報(FW/ツールのバージョンなど)

PyTorchのバージョンは確認したところ

Name: torch Version: 1.5.0+cu101 Summary: Tensors and Dynamic neural networks in Python with strong GPU acceleration Home-page: https://pytorch.org/ Author: PyTorch Team Author-email: packages@pytorch.org License: BSD-3 Location: /usr/local/lib/python3.6/dist-packages Requires: numpy, future Required-by: torchvision, torchtext, fastai

でした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

python

1valid_loader = data.DataLoader(valid_dataset, batch_size=128, sampler=valid_sampler)

ここの valid_sampler ですが、

python

1train_idx, valid_idx = indices[split:], indices[:split] 2train_sampler = data.SubsetRandomSampler(train_idx) 3valid_sampler = data.SubsetRandomSampler(valid_idx)

で train_dataset のインデックスを元に作成したものですよね。
それを valid_dataset を参照する際に使用したら、train_dataset と val_dataset はサンプル数が異なるので、out of range になります。

今回、train と val はディレクトリ構成として別れているので、1つのデータセットを2つに分割するのに使用する sampler を使う必要がそもそもないのではないでしょうか

python

1import torch.utils.data as data 2import torchvision.datasets as datasets 3import torchvision.transforms as transforms 4 5train_transform = transforms.Compose( 6 [ 7 transforms.RandomResizedCrop(224), 8 transforms.RandomHorizontalFlip(), 9 transforms.ToTensor(), 10 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), 11 ] 12) 13 14valid_transform = transforms.Compose( 15 [ 16 transforms.Resize(256), 17 transforms.CenterCrop(224), 18 transforms.ToTensor(), 19 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), 20 ] 21) 22train_dataset = datasets.ImageFolder("imagenette-320/train", transform=train_transform) 23valid_dataset = datasets.ImageFolder("imagenette-320/val", transform=valid_transform) 24train_loader = data.DataLoader(train_dataset, batch_size=128, shuffle=True) 25valid_loader = data.DataLoader(valid_dataset, batch_size=128)

追記

Accuracyが100%か0%としか出力されなくなってしました。
これはデータアクセスの方法に問題があるのでしょうか。

データのアクセス方法は問題なさそうに見えます。
100%や0%になるとのことですが、Accuracy や Loss はバッチ単位で表示しても激しく変動するので、あまり参考になりません。1エポックが終了したときにそのエポックの平均を算出して表示するようにしてみてはどうでしょうか。

また、学習が上手くいくかどうかは学習率やバッチサイズなどハイパーパラメータに左右されるので、あるデータセットやモデルで上手くいったものをそのまま別のものに使いまわしても同様に上手くいくとは限らないので、ハイパーパラメータを調整して、上手くいく値を見つける必要があります。

mobilenetv2 (v1 は torchvision になかった) で imagenette-320 を学習するサンプルコードを作成したので、一応載せておきます。

↓ こちらで試したコード
transfer-learning-mobilenetv2-imagenette320.ipynb

参考
Pytorch - 事前学習モデルを使ってクラス分類モデルを学習する方法

投稿2020/06/09 10:26

編集2020/06/09 14:40
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Otom_jp

2020/06/09 11:56

丁寧な回答ありがとうございます。 ご提案頂いたようにコードを書き換えた結果、先のようなエラーは出なくなったのですが、どうやら学習がうまくいかなくなりました。Accuracyが100%か0%としか出力されなくなってしました。 これはデータアクセスの方法に問題があるのでしょうか。
tiitoi

2020/06/09 12:11 編集

学習がうまくいかなくなったのではなく、精度を計算するところあたりに問題があるのでは? len(valid_idx) のように valid_idx が使われている場所も適宜 len(valid_loader.dataset) のように変える必要があるのではないでしょうか
Otom_jp

2020/06/09 12:51 編集

ご回答ありがとうございます。 validate関数内は仰る通りだと思います。 しかしながら出力がおかしくなっているのは、train関数内の出力なのです。 train関数内ではtrain_idxは参照されていないのですがどこに原因があるのでしょうか。accuracyの計算には作成したmodelにdataを入力して得られた値を格納する変数outputを参照しているので問題なさそうなのですが...。
tiitoi

2020/06/09 14:20

拝見しましたが、とくに問題はあるようには見えません。 一応、こちらで imagenette-320 で動かして試したコードを載せておきました
Otom_jp

2020/06/09 14:36

わざわざありがとうございます。 デバッグに大いに参考にさせて頂きます。 今のところValidate関数の方はご指摘いただいた方法で実装して問題はありませんでした。 Train関数の方はtrain_idx,Train_samplerを元のソースコードと同様に定義してやると学習が問題なく進み始めました。epoch内の精度も平均的に上昇し、損失関数も平均的に減少しております。 tiitoi様のご指摘通り、samplerを使用しない方法を私としては実装したいのですが、その方法をとるとやはりTrain関数の方で精度を正しく計算できていない問題(?)に直面します。 ご提供いただいたコードを参考にしてデバッグしてみようと思います。
tiitoi

2020/06/09 14:38 編集

dataloader の引数に shuffle=True を入れる必要はありますね。 これを入れないと、dataloader が返すラベルが 1, 1, ..., 1, 2, 2, ..., 2 のように連番になってしまうので学習に影響がでそうです 今までは sampler のほうでシャッフルされてたので、問題にならなかったのかも
Otom_jp

2020/06/09 14:52

ご回答ありがとうございます。 ご提示いただいた方法で、先の正常に学習が進んでいる状態と同じように学習が進み始めました。仰る通りでした。 私自身、PyTorchを用いた深層学習に関しては初学者で正直泥沼にハマった感じがありあきらめていたのですが、本当に助かりました。ありがとうございました。
tiitoi

2020/06/09 14:56

ディープラーニングは、1つ手順が違うだけで全く上手くいかなくなるということがあるので、ややこしいですよね。解決したようでよかったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問