1
この資料はラボ内自主勉強会に向けて書いたものです。間違い等ありましたら教えてください。

nn.Moduleとは?

PyTorchでカスタムモデルを作成する際にクラスで継承するやつ

1
2
3
4
5
6
7
8
9
10
11
12
class SimpleModel(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(10, 100)
self.act = nn.sigmoid()
self.fc2 = nn.Linear(100, 10)

def forward(self, x):
y = self.fc1(x)
y = self.act(y)
y = self.fc2(y)
return y

【事前知識】pythonの外部ファイルのクラスを実行可能にする方法

カレントディレクトリのhogeファイルのfugaクラスを読み込む場合

main.py
1
from .hoge import fuga 

カレントディレクトリのhogeファイルの全てのクラスを読み込む場合

main.py
1
from .hoge import *

カレントディレクトリのhogeディレクトリのFuga1,Fuga2クラスを読み込む場合

main.py
1
from .hoge import *
/hoge/__init__.py
1
2
3
from . import *
__all__=["Fuga","Fuga2"]

/hoge/fuga.py
1
2
3
class Fuga

class Fuga2

どこに継承元のModuleクラスが書いてある?

外部ファイルが存在?
torch/nn/Module.pyは存在しない

書き方的に、torch/nnディレクトリに存在
Pythonは外部ディレクトリを読み込み時に__init__.pyを先に読む。
nn.Module→nnディレクトリの__init__.pyを読む
👉source

しかし、ここにも書いていない

1
from .modules import *  # noqa: F403

つまり、nn/module/を全て読み込んでいる。
nn/module/__init__.pyを見る
👉source

Moduleクラスを読み込んでいる部分を発見!

1
2
3
4
5
6
7
from .module import Module
.
.
.

__all__ = [
'Module', 'Identity', 'Linear', 'Conv1d', 'Conv2d', 'Conv3d', 'ConvTranspose1d',

nn/module/module.pyにModuleクラスが存在しているはず。

👉nn/module.py

1
2
3
4
5
class Module:
r"""Base class for all neural network modules.
.
.
.

インスタンス生成時に実行されるもの

インスタンス生成例

1
model=SimpleModel()

👉source

__setattr__

__setattr__: インスタンスで代入操作実行時に呼び出されるコンストラクタ

(代入された変数,代入された値)
→ex.

1
super().__setattr__('_parameters', OrderedDict())

_parametersに代入された時、辞書順にソートする。

Callable

  • Callable 関数の型のようなもの。

  • 関数名 Callable([引数型], 返り値型)
    ...→Ellipsisという、Noneだけど、bool(…)でTrueを返すオブジェクト。今は無いけど、そのうちあることを示唆するような感じ。
    つまり、forward: Callable[..., Any]→…はforwardの引数の型、Anyがforwardの出力の型

  • _forward_unimplementedはそのまま呼び出すとNotImplementedErrorを吐く関数。
    →forward関数を、何か実装する雛形として宣言する。

つまりこのセクションで言いたいのは・・・
Moduleクラスの継承はインスタンス作成時にforwardを絶対に実装する必要がある!

インスタンス呼び出し時に実行されるもの

def __call__はどこに?

これも同様に、Callableで宣言はして、_call_implで置き換えている。
__call__ : Callable[..., Any] = _call_impl

_call_implは何をしている?

*hook系のものは、そのhookがTrueの時実行するもの。(ex.forward pass, backward passで__call__の処理を変える。)
→一旦self.forwardが実行されていると考えていい。
nn.Module継承先から呼び出す場合、継承先のself.forwardが実行される。

つまりこのセクションで言いたいのは・・・
クラスや型の機能を使ってfoward/backwardで処理を変更可能なモデル実行の雛形を作っている。