前提
拙作の強化学習用ライブラリcpprbの開発の中で遭遇したバグ (issue)
強化学習のExperience Replay用にデータを一時保存しておくためのライブラリであり、そのデータの型はユーザーがコンストラクタで指定し、内部ではNumpyのndarrayとして保存していた。
バグ (失敗)
先日、(厳密には違うが)こんな感じのコードで ndarray に加算を行ったところ、意図せず dtype まで変わってしまい挙動がおかしくなってしまった。
バグ
import numpy as np
def create_buffer(shape,dtype):
return np.zeros(shape=shape,dtype=dtype) + 1
create_buffer(1,np.bool) # array([1]) np.bool ではなくなってる!! np.int64
オペレータ +
の代わりに、numpy.add を利用しても出力される型は変わってしまう。
(仮に出力先 out
に一旦格納した元の変数を指定するとnumpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('int64') to dtype('bool') with casting rule 'same_kind'
と怒られる。)
解決策
以下のように、計算した結果を要素毎に代入すると(あくまで型が変換可能な場合のみだが)元の型を維持した計算ができる。
修正
import numpy as np
def create_buffer(shape,dtype):
a = np.zeros(shape=shape,dtype=dtype)
a[:] = a + 1
return a
create_buffer(1,np.bool) # array([True])
余談
別の目的があって、たまたま加算を実行しただけであって、加算自体には意味はない。
(boolの加算が...ということは、この記事の本題ではない。)
あくまで、ndarray にオブジェクトレベルの演算をしたら、意図せず型を変換されてしまったという失敗談。