開発のヒホ

iOSとかAndroidとかのアプリを開発するのに四苦八苦するブログ

TheanoのAutoEncoder実装例のcaglar/autoencodersを動かす四苦八苦

 Theanoを使った機械学習の勉強に励む中、とりあえず実装例を見たいと思いAutoEncoderをTheanoで実装したらしい一連のリポジトリを見つけて喜んでいました。
 caglar/autoencoders · GitHub

 このプログラムを動かす中で行った四苦八苦をメモに残しておこうと思います。
 とりあえずこちらの環境ではPython3.4.3で、caglar/autoencodersのcommitは16a65a0fd4c2b61917ae60432011f1702ce0d8f8です。

Python3に対応させる

 いつものxrange(->range(print hoge->print(hoge)の他、ae.pyなどの下記一行を修正します。

# n_batches = data.shape[0] / batch_size
n_batches = data.shape[0] // batch_size

 これでn_batchesが整数になり、range(n_batches)でエラーを出さなくなります。

ae.pyを実行可能にする

 ae.pyを実行しようとすると下記エラーに阻まれました。

ValueError: Input dimension mis-match. (input[0].shape[1] = 784, input[1].shape[1] = 30)
Apply node that caused the error: Elemwise{Composite{tanh((i0 + i1))}}[(0, 0)](Dot22.0, InplaceDimShuffle{x,0}.0)
Inputs types: [TensorType(float64, matrix), TensorType(float64, row)]
Inputs shapes: [(10000, 784), (1, 30)]
Inputs strides: [(6272, 8), (240, 8)]
Inputs values: ['not shown', 'not shown']

HINT: Re-running with most Theano optimization disabled could give you a back-trace of when this node was created. This can be done with by setting the Theano flag 'optimizer=fast_compile'. If that does not work, Theano optimizations can be disabled with 'optimizer=None'.
HINT: Use the Theano flag 'exception_verbosity=high' for a debugprint and storage map footprint of this apply node.

 どうやらdecode()内で、入力値のshapeと隠れ層出力値のshapeが合ってないようです。ということでlayer.pyファイル内の132行目あたりを以下のように修正。 layer.py

        if bhid is not None:
            self.b_prime = bhid
        else:
            if n_in_dec is not None:
                b_values = numpy.zeros((n_out_dec), dtype=theano.config.floatX)
            else:
#                b_values = numpy.zeros((self.n_out/num_pieces), dtype=theano.config.floatX)
                b_values = numpy.zeros((self.n_in/num_pieces), dtype=theano.config.floatX)

            self.b_prime = theano.shared(value=b_values, name='b_prime')

sa.pyを修正する

 sa.pyもこのままでは正常に動作しません。最初の方のcost_typeのデフォルト値がクロスエントロピーになっているせいです。MeanSquaredに変更します。

# cost_type=CostType.CrossEntropy,
cost_type=CostType.MeanSquared,

 更に、updates部分でdict型を与えてしまっているのでOrderedDictに変更し、最初の方でimportします。

from collections import OrderedDict

# updates = {}
updates = OrderedDict({})

 あと、KL値を計算する際にlogを用いますが、負の数が入ると計算結果がNaNになるので小さい値を足すようにします。

# def kl_divergence(self, p, p_hat):
def kl_divergence(self, p, p_hat, epsilon=1e-6):
    term1 = p * T.log(p)
#     term2 = p * T.log(p_hat)
    term2 = p * T.log(p_hat+epsilon)
    term3 = (1-p) * T.log(1 - p)
    term4 = (1-p) * T.log(1 - p_hat)
    return term1 - term2 + term3 - term4

 encode関数の出力値からスパース項を計算するが、デフォルトでは出力値を正規化するようになっていてスパース項の計算値が狂うので変更。

def get_sa_sgd_updates(self, learning_rate, sparsity_level, sparse_reg, x_in=None):
#         h = self.encode(x_in)
        h = self.encode(x_in, center=False)

 また四苦八苦した部分があれば書き足します。

(未完)python3でcaffeを使用可能にする

 最近流行りのchainerを使用して機械学習の挙動を勉強しており、そろそろDeepDreamに手を付けるべくその方法を調査した所、どうやらcaffeが必要だとわかりました。
 しかし問題があります。caffeはpython3を公式サポートしておりません。そのためか、普通にcaffeを使おうと思うとエラーが出ます。

 動作環境はMacOS10.10、Python 3.4.3です。
 今回は先人様のコードをお借りします。
 Chainerで入力画像の最適化 - mktozkの日記

Traceback (most recent call last):
  File "TestDeepGoggle.py", line 14, in <module>
    func = caffe.CaffeFunction('bvlc_reference_caffenet.caffemodel')
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_function.py", line 104, in __init__
    raise RuntimeError('CaffeFunction is not supported on Python 3')
RuntimeError: CaffeFunction is not supported on Python 3

 chainerコード内のエラーです。python3を使用しているとこの先に進めなくなります。
 とりあえずここのコードをいじって無理やり先に進みます。

# in chainer/functions/caffe/caffe_function.py

# caffe_pb2 does not support Py3
# if sys.version_info < (3, 0, 0):
if sys.version_info < (4, 0, 0):

 続いてprotobuf内にエラーが出ました。

Traceback (most recent call last):
  File "TestDeepGoggle.py", line 9, in <module>
    from chainer.functions import caffe
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/__init__.py", line 1, in <module>
    from chainer.functions.caffe import caffe_function
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_function.py", line 13, in <module>
    from chainer.functions.caffe import caffe_pb2
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_pb2.py", line 7, in <module>
    from google.protobuf import reflection as _reflection
  File "/usr/local/Cellar/python3/3.4.3_2/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/google/protobuf/reflection.py", line 68, in <module>
    from google.protobuf.internal import python_message
  File "/usr/local/Cellar/python3/3.4.3_2/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/google/protobuf/internal/python_message.py", line 848
    except struct.error, e:

 なんか途中でpip経由のものを抜けて偉いところにあるpythonファイルを使ってそうです・・・
 python3版のprotobufがあるらしいのでこちらを使います。

pip3 install python3-protobuf

 続くエラーはこちら。

Traceback (most recent call last):
  File "TestDeepGoggle.py", line 9, in <module>
    from chainer.functions import caffe
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/__init__.py", line 1, in <module>
    from chainer.functions.caffe import caffe_function
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_function.py", line 13, in <module>
    from chainer.functions.caffe import caffe_pb2
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_pb2.py", line 905, in <module>
    has_default_value=True, default_value=unicode("constant", "utf-8"),
NameError: name 'unicode' is not defined

 protobufからは抜けられました。caffe内はPython3に対応していないらしく、python2にあったunicode関数が使われています。ちょろっと書きなおして先に進みます。

# in chainer/functions/caffe/caffe_pb2.py

unicode("", "utf-8") -> ""
unicode("warp", "utf-8") -> "warp"
unicode("constant", "utf-8") -> "constant"
unicode("L2", "utf-8") -> "L2"

 えーっと次なるエラーは・・・

Traceback (most recent call last):
  File "TestDeepGoggle.py", line 9, in <module>
    from chainer.functions import caffe
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/__init__.py", line 1, in <module>
    from chainer.functions.caffe import caffe_function
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_function.py", line 37, in <module>
    class CaffeFunction(function.Function):
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_function.py", line 207, in CaffeFunction
    @_layer('Concat', 'CONCAT')
  File "/usr/local/lib/python3.4/site-packages/chainer/functions/caffe/caffe_function.py", line 22, in decorator
    typevalue = getattr(caffe_pb2.V1LayerParameter, oldname)
AttributeError: type object 'V1LayerParameter' has no attribute 'CONCAT'

 だめだ、なんでこのエラーが出るのか、どう対処すれば良いのかわからない・・・

MacでIkaLogとStatInkを連携する

 Splatoonのガチマッチに篭っていますが、いまいち自分の特性が分かりません。
 StatInkという対戦結果を記録しつつ統計計算もしてくれるサービスがあるらしいので早速使ってみます。

このサイトは、スプラトゥーンの勝敗データを自動的に収集して統計として後で解析できるように蓄積するサイトです。
stat.ink | このサイトについて

IkaLogをインストールする

 動画像から対戦結果を解析してくれるサービスIkaLogがあり、StatInkの利用はIkaLogを介して行います。
 MacでIkaLogを使ってみる - 開発のヒホ

連携する

 まずは登録です。
 stat.ink | ユーザ登録

 登録後のプロフィールページAPIキーをコピーして、設定ファイルIkaConfig.pyに書き加えます。

outputs.StatInk(api_key='YOUR_API_KEY_HERE'), # このYOUR_API_KEY_HERE内にコピー

 python IkaLog.pyで実行します。解析が終わるとイカのようなログが出てきます。

<ikalog.outputs.statink.StatInk object at 0x103d6afd0> (enabled = True)
<ikalog.outputs.statink.StatInk object at 0x103d6afd0>: No lobby information.
ranked scores = None
<ikalog.outputs.statink.StatInk object at 0x103d6afd0>: Using temporary file _image_for_statink.png
<ikalog.outputs.statink.StatInk object at 0x103d6afd0>: Encoded screenshot (1280x720 948876 bytes)
<ikalog.outputs.statink.StatInk object at 0x103d6afd0>: Using temporary file _image_for_statink.png
<ikalog.outputs.statink.StatInk object at 0x103d6afd0>: Encoded screenshot (1280x720 1250705 bytes)
{'agent': 'IkaLog',
 'agent_version': 'f575d51',
 'cash_after': 9041235,
 'death': 3,
 'end_at': 1445154924,
 'his_team_color': {'hue': 10, 'rgb': [170, 45, 20]},
 'image_judge': '(PNG Data)',
 'image_result': '(PNG Data)',
 'kill': 2,
 'knock_out': 'yes',
 'level': 49,
 'map': 'hakofugu',
 'my_team_color': {'hue': 160, 'rgb': [32, 130, 96]},
 'rank': 's+',
 'rank_after': 's+',
 'rank_exp_after': 35,
 'rank_in_team': 4,
 'result': 'win',
 'rule': 'yagura',
 'start_at': 1445154827,
 'weapon': 'nzap85'}

 StatInkのユーザーページに結果が反映されていることを確かめます。
 stat.ink | ヒホ(テスト用)さんのバトル結果

 おお・・・これはすごい・・・