苦労と試行

python初心者が chainerのエラーに遭遇して、ひたすら苦労しながら解決していった記録。
無慈悲なエラーメッセージと、それがどういう意味で、何を言いたくて、どうしなければいけないのかを記録していきたいと思う。

エラーなんて原因がわかってしまえばなんてことはないんだけど、わかるまでが大変。。。

windowsでcudaを利用する場合インストール時

windowsでcudaを利用する場合に、
pip install chainer でインストールすると、以下のエラーが出る場合がある。

cupy\cuda\cudnn.cpp(3662) : error C3861: 'cudnnAddTensor_v3'

githubにある新しいバージョンで修正されている。2016/12/31にpipで入れようとしたら、このバグ修正がまだpip版に反映されていなくてとても苦労した。
github版では修正されているので、githubからソースコードを持ってきてインストールするとOK。
https://github.com/pfnet/chainer/pull/2031

git clone https://github.com/pfnet/chainer
cd chainer
python setup.py install

正解データは0からの整数で出力数とあっていないといけないらしい。

Traceback (most recent call last):
  File "test.py", line 54, in <module>
    trainer.run()
  File "chainer\training\trainer.py", line 289, in run
    update()
  File "chainer\training\updater.py", line 170, in update
    self.update_core()
  File "chainer\training\updater.py", line 182, in update_core
    optimizer.update(loss_func, *in_vars)
  File "chainer\optimizer.py", line 390, in update
    loss = lossfun(*args, **kwds)
  File "chainer\links\model\classifier.py", line 68, in __call__
    self.loss = self.lossfun(self.y, t)
  File "chainer\functions\loss\softmax_cross_entropy.py", line 223, in softmax_cross_entropy
    use_cudnn, normalize, cache_score, class_weight)(x, t)
  File "chainer\function.py", line 199, in __call__
    outputs = self.forward(in_data)
  File "chainer\function.py", line 319, in forward
    return self.forward_cpu(inputs)
  File "chainer\functions\loss\softmax_cross_entropy.py", line 68, in forward_cpu
    log_p = log_yd[numpy.maximum(t.ravel(), 0), numpy.arange(t.size)]
IndexError: index 3 is out of bounds for axis 0 with size 3

データ(主に正解データ)を0からスタートしていないときや、
出力個数があっていない時にでるらしい。


たとえば、以下のようなモデルがあった場合、正解データは0-3のいづれかでないとダメらしい。

class IrisModel(Chain):
    def __init__(self):
        super(IrisModel, self).__init__(
            l1=L.Linear(4, 100),
            l2=L.Linear(100, 100),
            l3=L.Linear(100, 3),  #正解データ
        )

    def __call__(self, x):
        h1 = F.relu(self.l1(x))
        h2 = F.relu(self.l2(h1))
        y = self.l3(h2)

        return y

l3=L.Linear(100, 正解データの個数)
正解データの個数 = 3 だった場合
正解データは、 [0,1,2] で合計 3つにならないといけないらしい。

それを間違えて、 [1,2,3] で合計 3つにすると、このエラーが発生する。
正解データは、 [0,1,2] で3つにしないといけないらしい。

学習データは、2次元のfloat32データ
np.array([ [1,2,3,4],[5,6,7,8],[9,10,11,12] ]).astype(np.float32)
正解データは、1次元のint32データで0から開始する
np.array([0,1,2]).astype(np.int32)

正解データは、一次元配列でなければならないっぽい

Traceback (most recent call last):
  File "test.py", line 54, in <module>
    trainer.run()
  File "chainer\training\trainer.py", line 289, in run
    update()
  File "chainer\training\updater.py", line 170, in update
    self.update_core()
  File "chainer\training\updater.py", line 182, in update_core
    optimizer.update(loss_func, *in_vars)
  File "chainer\optimizer.py", line 390, in update
    loss = lossfun(*args, **kwds)
  File "chainer\links\model\classifier.py", line 68, in __call__
    self.loss = self.lossfun(self.y, t)
  File "chainer\functions\loss\softmax_cross_entropy.py", line 223, in softmax_cross_entropy
    use_cudnn, normalize, cache_score, class_weight)(x, t)
  File "chainer\function.py", line 189, in __call__
    self._check_data_type_forward(in_data)
  File "chainer\function.py", line 280, in _check_data_type_forward
    type_check.InvalidType(e.expect, e.actual, msg=msg), None)
  File "<string>", line 2, in raise_from
chainer.utils.type_check.InvalidType:
Invalid operation is performed in: SoftmaxCrossEntropy (Forward)

Expect: in_types[1].ndim == in_types[0].ndim - 1
Actual: 2 != 1

正解データを、一次元の配列にしていない時に出る。

入力データは、 [0,1,2] みたいに、2次元配列でなければいけないらしい。
(そしてデータは0から始まるnumpy.int32型でないといけないっぽい)

学習データは、2次元のfloat32データ
np.array([ [1,2,3,4],[5,6,7,8],[9,10,11,12] ]).astype(np.float32)
正解データは、1次元のint32データで0から開始する
np.array([0,1,2]).astype(np.int32)

正解データが numpy.int32の配列になっていないとき

Traceback (most recent call last):
  File "test.py", line 54, in <module>
    trainer.run()
  File "chainer\training\trainer.py", line 289, in run
    update()
  File "chainer\training\updater.py", line 170, in update
    self.update_core()
  File "chainer\training\updater.py", line 182, in update_core
    optimizer.update(loss_func, *in_vars)
  File "chainer\optimizer.py", line 390, in update
    loss = lossfun(*args, **kwds)
  File "chainer\links\model\classifier.py", line 68, in __call__
    self.loss = self.lossfun(self.y, t)
  File "chainer\functions\loss\softmax_cross_entropy.py", line 223, in softmax_cross_entropy
    use_cudnn, normalize, cache_score, class_weight)(x, t)
  File "chainer\function.py", line 189, in __call__
    self._check_data_type_forward(in_data)
  File "chainer\function.py", line 280, in _check_data_type_forward
    type_check.InvalidType(e.expect, e.actual, msg=msg), None)
  File "<string>", line 2, in raise_from
chainer.utils.type_check.InvalidType:
Invalid operation is performed in: SoftmaxCrossEntropy (Forward)

Expect: in_types[1].dtype == <class 'numpy.int32'>
Actual: float32 != <class 'numpy.int32'>

このエラーは、正解データを、一次元の numpy.int32の配列にしていない時に出るっぽい。

入力データは、 [0,1,2] みたいに、1次元配列でなければいけない。
(そしてデータは0から始まるnumpy.int32型でないとダメ)
data.astype(numpy.int32) で型を明示的に指定するといい。

学習データは、2次元のfloat32データ
np.array([ [1,2,3,4],[5,6,7,8],[9,10,11,12] ]).astype(np.float32)
正解データは、1次元のint32データで0から開始する
np.array([0,1,2]).astype(np.int32)

学習データは numpy.float32 でなければならないらしい

Traceback (most recent call last):
  File "test.py", line 54, in <module>
    trainer.run()
  File "chainer\training\trainer.py", line 289, in run
    update()
  File "chainer\training\updater.py", line 170, in update
    self.update_core()
  File "chainer\training\updater.py", line 182, in update_core
    optimizer.update(loss_func, *in_vars)
  File "chainer\optimizer.py", line 390, in update
    loss = lossfun(*args, **kwds)
  File "chainer\links\model\classifier.py", line 67, in __call__
    self.y = self.predictor(*x)
  File "test.py", line 22, in __call__
    h1 = F.relu(self.l1(x))
  File "chainer\links\connection\linear.py", line 92, in __call__
    return linear.linear(x, self.W, self.b)
  File "chainer\functions\connection\linear.py", line 79, in linear
    return LinearFunction()(x, W, b)
  File "chainer\function.py", line 189, in __call__
    self._check_data_type_forward(in_data)
  File "chainer\function.py", line 280, in _check_data_type_forward
    type_check.InvalidType(e.expect, e.actual, msg=msg), None)
  File "<string>", line 2, in raise_from
chainer.utils.type_check.InvalidType:
Invalid operation is performed in: LinearFunction (Forward)

Expect: in_types[2].dtype == in_types[0].dtype
Actual: float32 != float64

このエラーは学習データを numpy.float32 にしていないと出るらしい。
data = data.astype(numpy.float32) として、numpy.float32へ変換すると解決できます。

学習データは、2次元のfloat32データ
np.array([ [1,2,3,4],[5,6,7,8],[9,10,11,12] ]).astype(np.float32)
正解データは、1次元のint32データで0から開始する
np.array([0,1,2]).astype(np.int32)

学習データの個数があっていないときのエラー

Traceback (most recent call last):
  File "test.py", line 54, in <module>
    trainer.run()
  File "chainer\training\trainer.py", line 289, in run
    update()
  File "chainer\training\updater.py", line 170, in update
    self.update_core()
  File "chainer\training\updater.py", line 182, in update_core
    optimizer.update(loss_func, *in_vars)
  File "chainer\optimizer.py", line 390, in update
    loss = lossfun(*args, **kwds)
  File "chainer\links\model\classifier.py", line 67, in __call__
    self.y = self.predictor(*x)
  File "test.py", line 22, in __call__
    h1 = F.relu(self.l1(x))
  File "chainer\links\connection\linear.py", line 92, in __call__
    return linear.linear(x, self.W, self.b)
  File "chainer\functions\connection\linear.py", line 79, in linear
    return LinearFunction()(x, W, b)
  File "chainer\function.py", line 189, in __call__
    self._check_data_type_forward(in_data)
  File "chainer\function.py", line 280, in _check_data_type_forward
    type_check.InvalidType(e.expect, e.actual, msg=msg), None)
  File "<string>", line 2, in raise_from
chainer.utils.type_check.InvalidType:
Invalid operation is performed in: LinearFunction (Forward)

Expect: prod(in_types[0].shape[1:]) == in_types[1].shape[1]
Actual: 5 != 4

このエラーは、学習データの個数があっていなときにでるっぽい。


たとえば、以下のようなモデルがあった場合、学習データは[ [1,2,3,4],[5,6,7,8],[9,10,11,12] ] みたいに、定義した数と個数があっていないといけないらしい。

class IrisModel(Chain):
    def __init__(self):
        super(IrisModel, self).__init__(
            l1=L.Linear(4, 100),  #学習データ
            l2=L.Linear(100, 100),
            l3=L.Linear(100, 3),
        )

    def __call__(self, x):
        h1 = F.relu(self.l1(x))
        h2 = F.relu(self.l2(h1))
        y = self.l3(h2)

        return y

l1=L.Linear(学習データの個数, 100),
学習データの個数 = 4 だった場合
学習データは、 [ [1,2,3,4],[5,6,7,8],[9,10,11,12] ]みたいに、要素が4つの要素を持っていないとダメです。
上の例だと、len(arr[0])==4 len(arr[1])==4 len(arr[2])==4 です。( len(arr) ではなく、 len(arr[0])の方の要素数の話です。 )

それを間違えて、 [ [1,2,3,4,99],[5,6,7,8,99],[9,10,11,12,99] ] みたいに個数を間違えると、このエラーが発生します。

学習データは、2次元のfloat32データ
np.array([ [1,2,3,4],[5,6,7,8],[9,10,11,12] ]).astype(np.float32)
正解データは、1次元のint32データで0から開始する
np.array([0,1,2]).astype(np.int32)