読者です 読者をやめる 読者になる 読者になる

studylog/北の雲

chainer/python/nlp

chainerメモ5 AttributeError: 'GPUArray' object has no attribute 'T'

chainerをCPU環境でテストしながら実装してて、さあいざ本番のGPUで走らそうとするとこのエラーが出て悩んだ。ちゃんとcuda.init()もmodel.to_gpu()もしてるし、modelに投げるデータもto_gpu()してるはずなのに。

AttributeError: 'GPUArray' object has no attribute 'T'

具体的にはこんなTraceback。

Traceback (most recent call last):
(省略)
File ~~~/src/chainer-master/chainer/function.py", line 201, in forward
return self.forward_cpu(inputs) #←ここがおかしい
File "~~~/src/chainer-master/chainer/functions/linear.py", line 76, in forward_cpu
Wx = x.dot(self.W.T)
AttributeError: 'GPUArray' object has no attribute 'T'

状況

Tracebackをよく見てみるとforward_cpuになってて、つまりCPUモードで動いちゃってる。おかしい。

原因

modelに通すデータのcuda.to_gpu()漏れが発生している。なので丹念に調べる。どこかで漏れてる。

雑感

if args.gpu >= 0:
    prev_char = cuda.to_gpu(prev_char)

ロジックの中でこうやってるとにいつか漏れが発生する可能性が産まれる。全部自分で書いたコードならあんまり漏れは無いけれど、他人が書いたものを弄ってると漏れが発生しやすい気がする。

なのでmodelに通す直前に変換した方がいいのかなあ。

    def forward_one_step(self, x_data, y_data, state, train=True, dropout_ratio=0.5):
        x = Variable(x_data, volatile=not train)
        t = Variable(y_data, volatile=not train)

        h0 = self.embed(x)
        h1_in = self.l1_x(F.dropout(h0, ratio=dropout_ratio, train=train)) + self.l1_h(state['h1'])

        (省略)

こういう感じでmodelに通すと思うので、ここでx_data , y_data , stateをチェックしてGPUArrayになっていなかったらto_gpuする方が確実。その分遅くなるのかな。

今sampleコードを見てみたらptbサンプルはこうなってた

def forward_one_step(x_data, y_data, state, train=True):
    if args.gpu >= 0:
        x_data = cuda.to_gpu(x_data)
        y_data = cuda.to_gpu(y_data)
    x = chainer.Variable(x_data, volatile=not train)
    t = chainer.Variable(y_data, volatile=not train)
    h0 = model.embed(x)

やっぱりこの方がいいね。