class Model(Chain): def __init__(self): I = self.xp.eyes(size)
ってかんじで、selfからxp呼べるみたいです(しらなかった!)。
chanteraさんありがとうございます!
以下苦しんでた形跡
メモです。
Chainerで学習器を定義するとき、Chainクラスを継承する。
学習器というか、ネットワークのことをモデルと呼ぶことにする。
例えば単位行列を使いたいときとか、モデルの中でnumpyを使いたいことがたまにある。
numpyはGPU環境でcupyになるので、単純にはモデルをnewするときにコンストラクタに引数を渡さないといけない。
慣例として、CPU環境ならxp=numpy、GPU環境ならxp=cupyとしてxpをモデルに渡したりする。
import chainer class Model(chainer.Chain): def __init__(self, xp): super().__init__() self.I = xp.eye(size).astype('f') # 単位行列 def forward(self, x): # 何か単位行列を使う処理 y = x + self.I return y
上の例はネットワークでも何でもない嘘コードだけど、こんな感じにすることが多かった。
入力は正方行列に限定する。
これだと引数が汚くなるのであまり好きじゃない。
これを以下のようにすると、xpを使わずに済む。
import chainer from copy import copy class Model(chainer.Chain): def __init__(self): super().__init__() self.I = None def forward(self, x): # 最初だけself.Iを作る if self.I is None: self.setI(x) # 何か単位行列を使う処理 y = x + self.I return y def setI(self, x): # xと同じサイズの単位行列をxp無しで作る self.I = copy(x.data) chainer.initializers.Identity(1)(self.I)
xはcupy.arrayなので、これをもとに必要な行列を作ってやれば、一回の初期化のためにxpを渡さなくても済む。
前向き計算の処理によっては無理だけど、外から見たクラスがきれいになるので良い。
このへんって皆さんどうしてるんですか。