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

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

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

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

Google Colaboratory

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

PyTorch

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

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

Q&A

解決済

1回答

2769閲覧

[pytorch]でVGG16で画像分類問題をするときのチューニングのやり方がわからない(精度90%を出したい)

oinari03

総合スコア59

深層学習

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

Google Colaboratory

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

PyTorch

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

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

0グッド

1クリップ

投稿2020/09/25 09:45

編集2020/09/25 09:46

やりたいこと

データセット:STL10
ネットワーク定義:vgg16
の画像分類問題に対してTestの精度を90%以上を出したいと考えていて、チューニングをする必要があるが、その方法がわかりません。

ソースコード

transformとnetwork部分、lossと学習部分のソースコードと結果を交互に示します。
googlecorabratolyで実行しているので、形式を合わせました。

学習済みモデルでの精度を出したいのでpretrained= Trueにしています。

#ライブラリimportは省略 transform_train = transforms.Compose( [transforms.ToTensor(), transforms.RandomHorizontalFlip(), transforms.RandomVerticalFlip(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) transform_test = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) #trainデータとtestデータをダウンロードします trainset = torchvision.datasets.STL10(root='./data', split='train', download=True, transform=transform_train) testset = torchvision.datasets.STL10(root='./data', split='test', download=True, transform=transform_test) #クラスIDに対応するラベル名を定義します classes = ('plane', 'bird', 'car', 'cat', 'deer', 'dog', 'horse', 'monkey', 'ship', 'truck') net = torchvision.models.vgg16(pretrained=True).to(device) # print(net) summary(net, (3,96,96))

出力

---------------------------------------------------------------- Layer (type) Output Shape Param # ================================================================ Conv2d-1 [-1, 64, 96, 96] 1,792 ReLU-2 [-1, 64, 96, 96] 0 Conv2d-3 [-1, 64, 96, 96] 36,928 ReLU-4 [-1, 64, 96, 96] 0 MaxPool2d-5 [-1, 64, 48, 48] 0 Conv2d-6 [-1, 128, 48, 48] 73,856 ReLU-7 [-1, 128, 48, 48] 0 Conv2d-8 [-1, 128, 48, 48] 147,584 ReLU-9 [-1, 128, 48, 48] 0 MaxPool2d-10 [-1, 128, 24, 24] 0 Conv2d-11 [-1, 256, 24, 24] 295,168 ReLU-12 [-1, 256, 24, 24] 0 Conv2d-13 [-1, 256, 24, 24] 590,080 ReLU-14 [-1, 256, 24, 24] 0 Conv2d-15 [-1, 256, 24, 24] 590,080 ReLU-16 [-1, 256, 24, 24] 0 MaxPool2d-17 [-1, 256, 12, 12] 0 Conv2d-18 [-1, 512, 12, 12] 1,180,160 ReLU-19 [-1, 512, 12, 12] 0 Conv2d-20 [-1, 512, 12, 12] 2,359,808 ReLU-21 [-1, 512, 12, 12] 0 Conv2d-22 [-1, 512, 12, 12] 2,359,808 ReLU-23 [-1, 512, 12, 12] 0 MaxPool2d-24 [-1, 512, 6, 6] 0 Conv2d-25 [-1, 512, 6, 6] 2,359,808 ReLU-26 [-1, 512, 6, 6] 0 Conv2d-27 [-1, 512, 6, 6] 2,359,808 ReLU-28 [-1, 512, 6, 6] 0 Conv2d-29 [-1, 512, 6, 6] 2,359,808 ReLU-30 [-1, 512, 6, 6] 0 MaxPool2d-31 [-1, 512, 3, 3] 0 AdaptiveAvgPool2d-32 [-1, 512, 7, 7] 0 Linear-33 [-1, 4096] 102,764,544 ReLU-34 [-1, 4096] 0 Dropout-35 [-1, 4096] 0 Linear-36 [-1, 4096] 16,781,312 ReLU-37 [-1, 4096] 0 Dropout-38 [-1, 4096] 0 Linear-39 [-1, 1000] 4,097,000 ================================================================ Total params: 138,357,544 Trainable params: 138,357,544 Non-trainable params: 0 ---------------------------------------------------------------- Input size (MB): 0.11 Forward/backward pass size (MB): 40.50 Params size (MB): 527.79 Estimated Total Size (MB): 568.40 ----------------------------------------------------------------

続きcode

criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9,weight_decay=0.005) train_loss = [] train_acc = [] test_loss = [] test_acc = [] for epoch in range(25): running_loss = 0.0 running_corrects =0.0 img_count=0 for i, data in enumerate(trainloader, 0): # ミニバッチのデータをinputとlabelに分離 inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) #GPUに転送 # 勾配をリセット optimizer.zero_grad() #順伝搬の計算 outputs = net(inputs) _, preds = torch.max(outputs, 1) # 順伝搬の出力と正解ラベルからロスを計算 loss = criterion(outputs, labels) #逆伝搬の計算 loss.backward() #重みを計算 optimizer.step() #LossとAccをミニバッチ分を溜め込む running_loss += loss.item()*inputs.size(0) running_corrects += torch.sum(preds == labels.data).item() #学習画像の枚数をカウント img_count+=inputs.size(0) # lr_scheduler.step() #TrainデータでのLossとAccの計算 train_loss.append(running_loss / img_count) train_acc.append(running_corrects / img_count) #TestデータでのLossとAccの計算 running_loss = 0.0 running_corrects =0.0 img_count=0 with torch.no_grad(): #必要のない計算が走らないように、no_gradを指定 for data in testloader: inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) outputs = net(inputs) _, preds = torch.max(outputs, 1) loss = criterion(outputs, labels) running_loss += loss.item()*inputs.size(0) img_count += inputs.size(0) running_corrects += (preds == labels).sum().item() #このような書き方もできます # lr_scheduler.step() test_loss.append(running_loss / img_count) test_acc.append(running_corrects / img_count) #結果出力 print('[Epoch %d] Train Loss: %.4f, Acc: %.4f, Test Loss: %.4f, Acc: %.4f' %(epoch+1,train_loss[-1], train_acc[-1],test_loss[-1], test_acc[-1]))

出力

[Epoch 1] Train Loss: 3.1006, Acc: 0.2266, Test Loss: 1.4924, Acc: 0.4099 [Epoch 2] Train Loss: 1.3230, Acc: 0.4992, Test Loss: 1.1698, Acc: 0.5547 [Epoch 3] Train Loss: 1.0316, Acc: 0.6164, Test Loss: 1.0681, Acc: 0.6005 [Epoch 4] Train Loss: 0.8659, Acc: 0.6888, Test Loss: 0.8845, Acc: 0.6769 [Epoch 5] Train Loss: 0.7425, Acc: 0.7346, Test Loss: 0.7226, Acc: 0.7444 [Epoch 6] Train Loss: 0.6431, Acc: 0.7714, Test Loss: 0.7063, Acc: 0.7521 [Epoch 7] Train Loss: 0.5773, Acc: 0.7962, Test Loss: 0.6828, Acc: 0.7595 [Epoch 8] Train Loss: 0.4971, Acc: 0.8266, Test Loss: 0.6372, Acc: 0.7776 [Epoch 9] Train Loss: 0.4282, Acc: 0.8490, Test Loss: 0.5830, Acc: 0.8029 [Epoch 10] Train Loss: 0.4151, Acc: 0.8486, Test Loss: 0.5616, Acc: 0.8123 [Epoch 11] Train Loss: 0.3904, Acc: 0.8604, Test Loss: 0.5383, Acc: 0.8144 [Epoch 12] Train Loss: 0.3298, Acc: 0.8832, Test Loss: 0.5308, Acc: 0.8276 [Epoch 13] Train Loss: 0.3127, Acc: 0.8872, Test Loss: 0.5058, Acc: 0.8365 [Epoch 14] Train Loss: 0.2581, Acc: 0.9124, Test Loss: 0.4977, Acc: 0.8370 [Epoch 15] Train Loss: 0.2024, Acc: 0.9268, Test Loss: 0.5344, Acc: 0.8373 [Epoch 16] Train Loss: 0.2112, Acc: 0.9294, Test Loss: 0.5109, Acc: 0.8409 [Epoch 17] Train Loss: 0.1795, Acc: 0.9408, Test Loss: 0.4996, Acc: 0.8509 [Epoch 18] Train Loss: 0.1492, Acc: 0.9490, Test Loss: 0.5890, Acc: 0.8293 [Epoch 19] Train Loss: 0.1402, Acc: 0.9534, Test Loss: 0.5179, Acc: 0.8556 [Epoch 20] Train Loss: 0.1464, Acc: 0.9502, Test Loss: 0.5249, Acc: 0.8521 [Epoch 21] Train Loss: 0.1592, Acc: 0.9436, Test Loss: 0.5376, Acc: 0.8491 [Epoch 22] Train Loss: 0.1126, Acc: 0.9652, Test Loss: 0.5427, Acc: 0.8490 [Epoch 23] Train Loss: 0.0922, Acc: 0.9682, Test Loss: 0.5345, Acc: 0.8470 [Epoch 24] Train Loss: 0.0812, Acc: 0.9744, Test Loss: 0.5323, Acc: 0.8581 [Epoch 25] Train Loss: 0.0727, Acc: 0.9760, Test Loss: 0.4859, Acc: 0.8696

一応、グラフものせときます。
イメージ説明

あと一息なんですよね。どうしても90%にする手法が知りたいです。。。

まとめ

以上のことから90%以上の精度を出す方法、チューニング?の手法、パラメータの決定手法など
何かアドバイスがあればお願いします!!

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

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

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

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

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

guest

回答1

0

ベストアンサー

vgg16(pretrained=True) で ImageNet の学習済みモデルを使うのなら、前処理はそれに合わせて以下のようにするべきではないでしょうか。

学習時

python

1transforms.Compose( 2 [ 3 transforms.RandomResizedCrop(224), 4 transforms.RandomHorizontalFlip(), 5 transforms.ToTensor(), 6 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), 7 ] 8}

推論時

python

1transforms.Compose( 2 [ 3 transforms.Resize(256), 4 transforms.CenterCrop(224), 5 transforms.ToTensor(), 6 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), 7 ] 8)

手元で試したら、20エポックで訓練データの精度が93%、テストデータの精度が96%になりました。

↓コード

snippets/finetuning-vgg16.ipynb

投稿2020/09/25 14:19

編集2020/09/25 14:20
tiitoi

総合スコア21956

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

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

oinari03

2020/10/09 07:08 編集

以前ご回答いただきありがとうございます。 こちらの返答に遅くなって申し訳ないのですが、今頃疑問に思って返信にさせていただきました。 解答していただいた通りに拡張したらかなり精度がよくなりました。 よろしければどうして学習済みモデルを使った際に以上のようなデータ拡張に決まるのでしょうか。ほかのデータ拡張ではだめな理由を教えていただけませんか...? 他のデータ拡張ではなくこちらを採用した理由です。 また、学習時と、推論時でデータ拡張が違う理由も知りたいと思っています。 何かのサンプルurlでも構いませんのでよろしくお願いします
tiitoi

2020/10/10 06:36 編集

> どうして学習済みモデルを使った際に以上のようなデータ拡張に決まるのでしょうか 重要なのは、transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) で標準化することです。 学習済みモデルは一般的に ImageNet を学習して作られたもので、このパラメータは ImageNet データセットの平均と標準偏差です。 学習済みモデルを作ったときにこのパラメータで標準化したので、その重みを使うのであれば、それに合わせる必要があるということです。 もし、そうでない前処理をした場合、学習したときと入力データの分布が異なってしまい学習済みモデルの性能が発揮できません。 上記は学習済みモデルを使う場合の注意点であって、自分で1から学習するのであれば、前処理は好きにしていいです。また学習時の transforms.RandomHorizontalFlip() などオーグメンテーションの部分は、入力サイズが224にできるのであれば、好きに変えて大丈夫です。
oinari03

2020/10/10 14:47 編集

ご返信いただきありがとうございます。 >重要なのは、transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) で標準化することです。 なるほど,ImageNetにおいてこちらが一番大事だったのですね。 今回の場合は学習済みモデルを使う際の注意点というのが知りたい部分でして、normalizeの部分は理解したのですが、以下が気になっています。 >transforms.RandomHorizontalFlip() などオーグメンテーションの部分は、入力サイズが224にできるのであれば、好きに変えて大丈夫です。 どうして、224というサイズなのでしょうか?こちらの理由があればありがたいです。 本当に初心者で申し訳ないのですが また以下も気になる点です。 ・前処理は学習時と推論時に違う理由は何か? どうかよろしくお願いします。
tiitoi

2020/10/10 15:56

> 224というサイズなのでしょうか? モデルの入力サイズは224なので、画像を前処理でモデルの入力サイズに合わせないとエラーになります。224という値は学習済みモデルを作成したときの入力サイズの値です。 > 前処理は学習時と推論時に違う理由は何か? 学習時はオーグメンテーションしたいので、 transforms.RandomResizedCrop(224) transforms.RandomHorizontalFlip() を入れています。推論時はこれらの処理は必要ないので、除いています。 入力サイズが224になっていれば処理は通るので、ここらへんは好きに変えても問題ありません。
tiitoi

2020/10/10 16:03 編集

ImageNet の学習済みモデルというのは、おそらく Caffe で作成した重みを移植しています。ディープラーニングが話題になりだした2015年頃は Pytorch や TensorFlow といった今主流のライブラリがまだなく、Caffe というライブラリを皆使っていました。 上記前処理はそのときに使われていた前処理をそのまま採用しています。例えば、入力サイズが224なのも、当時は GPU が貧弱だったので 500x500 のように大きな入力サイズにすることができなかったからです。歴史的な経緯によるものなので、なぜこの前処理なのかということを追求する必要性はあまりないと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問