こしあん
2019-06-28

PyTorchで複数出力があるモデルの出力の型について

Pocket
LINEで送る


出力が複数あるモデルの訓練というのは少し複雑なモデルだとよく出てきます。PyTorchでは複数出力のモデルの、出力の型はどうなっているでしょうか。それを見ていきます。中間層の値を取りたい場合も使えます。

サンプルコード

import torch
from torch import nn

class TestModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 8, kernel_size=1)
        self.conv2 = nn.Conv2d(8, 16, kernel_size=1)
        self.conv3 = nn.Conv2d(16, 32, kernel_size=1)

    def forward(self, x):
        x1 = self.conv1(x)
        x2 = self.conv2(nn.AvgPool2d(2)(x1))
        x3 = self.conv3(nn.AvgPool2d(2)(x2))
        return [x1, x2, x3] # listで返しているので

def main():
    model = TestModel()
    input = torch.randn(4, 3, 16, 16) # batch_size=4, channel=3, x=y=16
    out = model(input) # 出力はtorch.Tensorのlist
    print(type(out))
    for x in out:
        print(x.size(), type(x))

if __name__ == "__main__":
    main()

ここではconv1, conv2, conv3という複数の畳み込み層があります。各中間層の出力をまとめて返すモデルを試しに作ってみます。

結論からいうと、forwardの返り値の定義に依存します。

出力

上のコードのように、forwardのreturnをlistとして定義すると、出力はtorch.Tensorのlistになります。

<class 'list'>
torch.Size([4, 8, 16, 16]) <class 'torch.Tensor'>
torch.Size([4, 16, 8, 8]) <class 'torch.Tensor'>
torch.Size([4, 32, 4, 4]) <class 'torch.Tensor'>

またforwardの定義を、Tupleにすると、

        return (x1, x2, x3) # Tupleにしてみる

出力もTupleになります。forで取り出せるのは変わりませんね。

<class 'tuple'>
torch.Size([4, 8, 16, 16]) <class 'torch.Tensor'>
torch.Size([4, 16, 8, 8]) <class 'torch.Tensor'>
torch.Size([4, 32, 4, 4]) <class 'torch.Tensor'>

つまりは、モデル側のforwardで定義した通りに帰ってくるということです。わかりやすい。

まとめ

PyTorchで出力が複数あるモデルの出力は、モデルのforward定義に依存

Related Posts

Kerasでメモリ使用量を減らしたかったらmax_queue_sizeを調整しよう... Kerasで大きめの画像を使ったモデルを訓練していると、メモリが足りなくなるということがよくあります。途中処理の変数のデータ型(np.uint8)を変えるのだけではなく、max_queue_sizeの調整をする必要があることがあります。それを見ていきます。 メモリサイズの目安 ニューラルネット...
Kerasで転移学習用にレイヤー名とそのインデックスを調べる方法... Kerasで転移学習をするときに、学習済みモデルのレイヤーの名前と、そのインデックス(何番目にあるかということ)の対応を知りたいことがあります。その方法を解説します。 転移学習とは 転移学習とは、ImageNetなど何百万もの大量の画像で事前学習させたモデルを使い、それを「特徴量検出器」として...
PyTorch/TorchVisionで複数の入力をモデルに渡したいケース... PyTorch/TorchVisionで入力が複数あり、それぞれの入力に対して同じ前処理(transforms)をかけるケースを考えます。デフォルトのtransformsは複数対応していないのでうまくいきません。しかし、ラッパークラスを作り、それで前処理をラップするといい感じにできたのでその方法を...
Kerasで重みを共有しつつ、必要に応じて入力の位置を変える方法... Kerasで訓練させて、途中から新しく入力を作ってそこからの出力までの値を取りたいということがたまにあります。例えば、Variational Auto Encoderのサンプリングなんかそうです。このあまり書かれていないのでざっとですが整理しておきます。 こういうことをやりたい 言葉で書いても...
Kerasのジェネレーターでサンプルが列挙される順番について... Kerasの(カスタム)ジェネレーターでサンプルがどの順番で呼び出されるか、1ループ終わったあとにどういう処理がなされるのか調べてみました。ジェネレーターを自分で定義するとモデルの表現の幅は広がるものの、バグが起きやすくなるので「本当に順番が保証されるのか」や「ハマりどころ」を確認します。 0~...
Pocket
Delicious にシェア

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です