pytorchコンテナのnn.Sequential、nn.ModuleList、nn.ModuleDictの紹介

序文

  ディープ ラーニング モデルを作成するとき、特に転移学習のトレーニング中にこれら 3 つのことによく遭遇します。これらは何ですか、どのように使用され、使用時にどのような注意が必要ですか? このブログ投稿をご覧nn.Sequentialくださいnn.ModuleListnn.ModuleDict

1.nn.モジュール

  これら 3 つのコンテナーを紹介する前に、 とは何かを知る必要がありますModuleモデルを作成するとき、ほとんどすべてのモデルがこのクラスを継承します。彼はすべてのネットワークの基本クラスであり、ネットワークのプロパティを管理するために使用されます。nn.Parameterこれには とという 2 つのモジュールが関連付けられていますnn.functionalこれらすべてのモジュールは から来ていますtorch.nn以下にこれらのモジュールを簡単に紹介します。

1.1. nn.パラメータ

  の最初のnn.ParameterPytorchnn.Parameterモデル パラメーターを作成するための特別なクラスです。モデルには多くのパラメーターが存在することが多く、これらのパラメーターを手動で管理するのは簡単な作業ではありません。Pytorch一般に、パラメータは、その構造の下にあるすべてのパラメータを表し、管理するnn.Parameterために使用されますnn.Module

## nn.Parameter 具有 requires_grad = True 属性
w = nn.Parameter(torch.randn(2,2))
print(w)   # tensor([[ 0.3544, -1.1643],[ 1.2302,  1.3952]], requires_grad=True)
print(w.requires_grad)   # True

## nn.ParameterList 可以将多个nn.Parameter组成一个列表
params_list = nn.ParameterList([nn.Parameter(torch.rand(8,i)) for i in range(1,3)])
print(params_list)
print(params_list[0].requires_grad)

## nn.ParameterDict 可以将多个nn.Parameter组成一个字典
params_dict = nn.ParameterDict({
    
    "a":nn.Parameter(torch.rand(2,2)),
                               "b":nn.Parameter(torch.zeros(2))})
print(params_dict)
print(params_dict["a"].requires_grad)

上記で定義されたパラメータは、モジュールを通じて管理できます。

# module.parameters()返回一个生成器,包括其结构下的所有parameters

module = nn.Module()
module.w = w
module.params_list = params_list
module.params_dict = params_dict

num_param = 0
for param in module.parameters():
    print(param,"\n")
    num_param = num_param + 1
print("number of Parameters =",num_param)

  実際の使用では、nn.Moduleモジュールクラスは継承によって構築されるのが一般的で、学習が必要なパラメータを含む部分はすべてコンストラクタ内に配置されます。

#以下范例为Pytorch中nn.Linear的源码的简化版本
#可以看到它将需要学习的参数放在了__init__构造函数中,并在forward中调用F.linear函数来实现计算逻辑。

class Linear(nn.Module):
    __constants__ = ['in_features', 'out_features']

    def __init__(self, in_features, out_features, bias=True):
        super(Linear, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.weight = nn.Parameter(torch.Tensor(out_features, in_features))
        if bias:
            self.bias = nn.Parameter(torch.Tensor(out_features))
        else:
            self.register_parameter('bias', None)

    def forward(self, input):
        return F.linear(input, self.weight, self.bias)

1.2. nn.機能的

nn.functional(導入後は一般に F に名前変更されました) さまざまな機能コンポーネントの機能実装があります。例えば:

  • 活性化関数シリーズ ( F.relu, F.sigmoid, F.tanh, F.softmax)
  • モデル レイヤー シリーズ ( F.linear, F.conv2d, F.max_pool2d, F.dropout2d, F.embedding)
  • 損失関数シリーズ ( F.binary_cross_entropy, F.mse_loss, F.cross_entropy)

  パラメータの管理を容易にするために、パラメータは通常、nn.Module継承を通じてクラス実装形式に変換され、nnモジュールの下に直接カプセル化されます。

  • 活性化関数は ( nn.ReLu, nn.Sigmoid, nn.Tanh, nn.Softmax)になります。
  • モデルレイヤー ( nn.Linear, nn.Conv2d, nn.MaxPool2d, nn.Embedding)
  • 損失関数 ( nn.BCELoss, nn.MSELoss, nn.CrossEntorpyLoss)

  したがって、表面上に確立したnn活性化関数、層、損失関数はすべてfunctional舞台裏で実装されます。nn.Moduleさらに下を見ていくと、このモジュールが非常に強力であることがわかります。このモジュールが参照するさまざまなパラメータを管理することに加えて、このモジュールが参照するサブモジュールも管理できます。

1.3. nn.モジュール

私たちの焦点は、このnn.Moduleモジュールを導入することです。nn.Module以下には重要な辞書属性が多数あります。

     	self.training = True
        self._parameters: Dict[str, Optional[Parameter]] = OrderedDict()
        self._buffers: Dict[str, Optional[Tensor]] = OrderedDict()
        self._non_persistent_buffers_set: Set[str] = set()
        self._backward_hooks: Dict[int, Callable] = OrderedDict()
        self._is_full_backward_hook = None
        self._forward_hooks: Dict[int, Callable] = OrderedDict()
        self._forward_pre_hooks: Dict[int, Callable] = OrderedDict()
        self._state_dict_hooks: Dict[int, Callable] = OrderedDict()
        self._load_state_dict_pre_hooks: Dict[int, Callable] = OrderedDict()
        self._modules: Dict[str, Optional['Module']] = OrderedDict()

_parametersそのうちの 2 つにのみ注目する必要があります。_modules

  • _parameters:nn.Parameterクラスに属する属性 (重みなど) を保存および管理し、これらのパラメータにバイアスをかけます
  • _modules: クラシック ネットワークなどのストレージ管理nn.ModuleクラスはLeNet、サブモジュール、畳み込み層、プーリング層を構築し、_modules に保存されます。

ここで質問があります:nn.Parameternn.Moduleの違いは何ですか_parameters?

  • nn.Parameter: これはtorch.Tensorのサブクラスであり、テンソルをモデルの学習可能なパラメーターとしてマークするために使用されます。モデルを定義するプロセスでは、通常、nn.Parameterモデルの属性として学習可能なパラメーターを作成するために使用します。この利点は、nn.Parameterオブジェクトがモデルのパラメーターとして自動的に登録され、勾配の計算とパラメーターの更新に参加することです。
  • _parameters: これはnn.Moduleクラス内の属性であり、モデルの学習可能なパラメーターを格納するために使用される辞書です。辞書のキーはパラメータの名前であり、値は対応するパラメータ テンソル (nn.Parameterタイプ) です。_parameters属性の値により、モデルの属性から学習可能なパラメーターが自動的に抽出され、辞書に追加されます。

_parametersは、モデルの学習可能なパラメータを格納するためのコンテナと考えることが  でき、nn.Parameterこれらのパラメータを作成してラベルを付けるための特別なクラスです。を使用してパラメータを作成し、モデルの属性として使用すると、これらのパラメータは辞書nn.Parameterに自動的に追加され、一元的な管理と操作が容易になります。_parametersつまり、nn.Parameterモデルパラメータを作成するための特別なクラスであり、_parametersモデルパラメータを格納する辞書属性です。nn.Parameter作成されたパラメータは自動的に_parametersディクショナリに追加されるため、モデルのパラメータの管理とアクセスが容易になります。

nn.Moduleファブリック ネットワークを構築するプロセスはどのようなものですか? 次のネットワークを例に挙げます。

import torch
from torch import nn


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 1, 1, 1)
        self.bn = nn.BatchNorm2d(1)
        self.relu = nn.ReLU()
        self.conv2 = nn.Conv2d(1, 1, 1, 1)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn(x)
        x = self.relu(x)
        x = self.conv2(x)
        return x


if __name__ == "__main__":
    dat = torch.rand(1, 1, 10, 10)
    net = Net().cuda()

ビルドプロセスは次のとおりです。

Moduleまず、この基本クラス(上記のクラスなど) を継承する  大きな(上で作成したNet) を用意し、次にその中に多くのサブモジュールを含めることができ、これらのサブモジュールも から継承されます。これらのメソッドでは、それらは呼び出されます。親クラスの初期化メソッドは、親クラスのプロパティの初期化を実行します。そして、各サブモジュールを構築する際には、実際には初期化を行い、このメソッドで判定した型を対応する属性辞書に保存し、対応するメンバに割り当てるという2つのステップに分かれています。このようなサブモジュールを一つ一つ構築していき、最終的に全体の構築が完了します。特定のプロセスを自分でデバッグできます。nn.ModuleNetNetnn.ModuleModule__init____setattr__valueNet

要約:

  • 1 つにmodule複数のサブクラスを含めることができますmodule(Net畳み込み層、BN層、活性化関数を含む)
  • 1 つmoduleは 1 つの操作に相当し、forward()その関数を実装する必要があります (一部のモジュールの前方は自分で書き直す必要があります。下読みするとわかります)
  • それぞれにはmodule、その属性を管理するための多くの辞書があります (最も一般的に使用されるのは_parameters_modules)

ネットワークの構築プロセスを知ることで、他の人が作成したモデルを分析し、その一部を抽出できます。この部分の導入については、このブログ投稿を参照してください: Pytorch はニューラル ネットワーク層構造、層パラメーター、およびカスタム初期化を  抽出します

二.nn.シーケンシャル

nn.Module上記のモジュール  を導入したら、コンテナの導入を始めましょう。まず、 のモジュールコンテナであるitを見てみましょうnn.Sequential。これは、複数のモジュールを順番に組み合わせるために使用されます。一連のモジュールを接続してシリアルモデル構造を形成できます。でどのように実装されているかを見てみましょう。ここではコンストラクターと順伝播部分のみを見て、他の部分のコードは省略しています。nn.SequentialPyTorchpytorch

class Sequential(Module):
	...
	
    def __init__(self, *args):
        super(Sequential, self).__init__()
        if len(args) == 1 and isinstance(args[0], OrderedDict):
            for key, module in args[0].items():
                self.add_module(key, module)
        else:
            for idx, module in enumerate(args):
                self.add_module(str(idx), module)

	...
	
    def forward(self, input):
        for module in self:
            input = module(input)
        return input

  上記のコードからわかるように、nn.Sequentialこれは から継承されておりModule、説明Sequential自体も 1 であるModuleため、これらの辞書パラメータも持ちます。メソッドnn.Sequentialが実装されていることがわかります。最も一般的に使用される方法は次のとおりです。forwardnn.Sequential

  • forward(input): モデルの順伝播プロセスを定義します。ではnn.Sequential、このメソッドは各モジュールのメソッドをモジュールの順序で順番に呼び出しforward、前のモジュールの出力を入力として次のモジュールに渡して最終出力を計算します。
  • add_module(name, module):nn.Sequentialにサブモジュールを追加します。nameはサブモジュールの名前で、module追加するサブモジュール オブジェクトです。モジュールは、追加された順序で順に順伝播されます。
  • parameters():nn.Sequentialのすべての学習可能なパラメータに対する反復子を返します。モデルの学習可能なパラメーターは、反復子を介してアクセスし、操作できます。
  • zero_grad():nn.Sequentialすべてのモジュールのパラメータ勾配をゼロに設定します。このメソッドは通常、各グラデーション更新の前に呼び出されます。

add_module(name, module)上記のメソッドを列挙してみますが、これらは実際にはまったく正しく、通常、このメソッドはモジュールを追加するために  最もよく使用されます。nn.Sequential使い方を見てみましょう?

class Net(nn.Module):
    def __init__(self, classes):
        super(Net, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 6, 5),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Conv2d(6, 16, 5),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2, stride=2),)

        self.classifier = nn.Sequential(
            nn.Linear(16*5*5, 120),
            nn.ReLU(),
            nn.Linear(120, 84),
            nn.ReLU(),
            nn.Linear(84, classes),)

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size()[0], -1)
        x = self.classifier(x)
        return x

add_module メソッドを使用して作成することもできます。

import torch
import torch.nn as nn

class Net(nn.Module):
    def __init__(self, classes):
        super(Net, self).__init__()

        self.features = nn.Sequential()
        self.features.add_module('conv1', nn.Conv2d(3, 6, 5))
        self.features.add_module('relu1', nn.ReLU())
        self.features.add_module('pool1', nn.MaxPool2d(kernel_size=2, stride=2))
        self.features.add_module('conv2', nn.Conv2d(6, 16, 5))
        self.features.add_module('relu2', nn.ReLU())
        self.features.add_module('pool2', nn.MaxPool2d(kernel_size=2, stride=2))

        self.classifier = nn.Sequential()
        self.classifier.add_module('fc1', nn.Linear(16*5*5, 120))
        self.classifier.add_module('relu3', nn.ReLU())
        self.classifier.add_module('fc2', nn.Linear(120, 84))
        self.classifier.add_module('relu4', nn.ReLU())
        self.classifier.add_module('fc3', nn.Linear(84, classes))

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size()[0], -1)
        x = self.classifier(x)
        return x

forward上記のネットワーク構築により、関数内で 1 つの文だけを使用してself.features(x)6 つの文の実行が完了すること  がわかります。この操作を完了できるのは、プログラムnn.Sequential内の関数によるものですforward。プログラムの実行中に、分析のためにパラメーターが渡されますnn.Sequential。特定の実装プロセスはデバッグおよび観察できます。
概要:
nn.Sequentialこれはnn.module、一連のネットワーク層を順番にパッケージ化するために使用されるコンテナであり、次の 2 つの特徴があります。

  • 順序性: 各ネットワーク層は厳密に順序どおりに構築されますが、このとき、前層と後層のデータの関係に注意する必要があります。
  • 自己完結型forward():forward自己完結型では、for順伝播操作がループを通じて順次実行されます。

3.nn.ModuleList

  nn.ModuleListこれはnn.module、ネットワーク層のグループをラップし、ネットワーク層を繰り返し呼び出すために使用されるコンテナでもあります。一般的に使用されるメソッドは次のとおりで、リストの使用とよく似ています。

  • append():ModuleList後にネットワーク層を追加します
  • extend(): 2 つのスプライスModuleList
  • insert():ModuleListネットワーク層を中間位置に挿入することを指定します

nn.ModuleListネットワークを構築するために使用する方法の例を見てみましょう。

class ModuleListNet(nn.Module):
    def __init__(self):
        super(ModuleListNet, self).__init__()
        self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])

    def forward(self, x):
        for i, linear in enumerate(self.linears):
            x = linear(x)
        return x

  上の例では、nn.Linearリスト内包表記を使用して 10 個のモジュールを作成します。全体的に見て、使い方はまだ非常に簡単で、特定の実装プロセスに興味のある友人は、コードをデバッグすることでそれを見ることができます。

3.nn.ModuleDict

このモジュールをもう一度見てみましょうnn.ModuleDictnn.ModuleDictこれは、ネットワーク層のセットをパッケージ化し、インデックスnn.moduleによってネットワーク層を呼び出すために使用されるコンテナでもあります。一般的に使用されるメソッドは次のとおりで、辞書の操作に似ています。

  • clear(): 空ModuleDict
  • items(): キーと値のペアの反復可能値を返します ( key-value pairs)
  • keys(): 辞書のキーを返します ( key)
  • values(): 辞書の値を返します (value)
  • pop(): キーと値のペアを返し、辞書から削除します。

例を見てみましょう:

import torch
import torch.nn as nn

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()

        self.module_dict = nn.ModuleDict({
    
    
            'conv1': nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
            'relu1': nn.ReLU(),
            'conv2': nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            'relu2': nn.ReLU(),
            'flatten': nn.Flatten(),
            'linear': nn.Linear(128 * 32 * 32, 10)
        })

    def forward(self, x):
        for module in self.module_dict.values():
            x = module(x)
        return x

# 创建模型实例
model = MyModel()

# 随机生成输入
x = torch.randn(1, 3, 32, 32)

# 进行前向传播
output = model(x)
print(output.shape)

nn.ModuleDict上記のネットワークを作成しても、全体としては辞書操作と同様に非常に単純です。
  、 、の基本的な使い方は基本的にワインの紹介です、間違いがあれば修正してnn.Sequentialくださいnn.ModuleListnn.ModuleDict

おすすめ

転載: blog.csdn.net/qq_38683460/article/details/131107291