2016年2月21日日曜日

AWSを使ってみる:Deep-learningのために

このところ、Deep-learningの勉強をしているんですが、サンプルでとにかく処理時間のかかるものがあります。
chainerやTensorFlowは64bit環境が前提(chainerはそうでもないんですが、そっちのほうが望ましい)なので、自宅のLinuxは32bitでアウト。そうなるとMac OSXになるのですが、ノートPCなので電源つなげっぱなしはバッテリーへのタメージから考えると避けたい。
自宅のLinuxを64bitにしてもいいんですが(古いPCですが、Core2なんで一応64bit OSはインストールできます)、せっかくなのでAWSを試してみます。

お試しなので、作れるインスタスは小さな"t2.micro"になります。(64bit redhatですが、メモリが1GBしかありません)それでも、まあchainerは動くだろうと、インストールを始めますが色々問題が出ました。

1.rootのパスワードは何?
まず、pipをインストールしようとしたらエラーがでました。まあ、この手のものはroot権限が必要ですから、sudoコマンドを使おうとすると、passwdを聞かれました。でも、AWSでEC2にインスタンスを作ったばかり、passwdは何?最初、AWSのアカウントのパスワードかと思いましたが、初期状態ではpasswdが設定されていないので、

$ su -
$ passwd

で、rootのパスワードを設定してやるものなんだそうです。

2.chainerのインストールができない(gccが必要)
さて、pipのインストールができたので、それでchainerをインストールしようとすると、エラーがでます。はじめは何が問題なのかわからなく、色々ぐぐってみました。でもどれも見当はずれ。よくよくエラーメッセージをみると、gccコンパイラがないと・・・
そうです、AWS EC2のインスタンスでは最低限のものしか入っていなくて(でもpythonは入っていた)、gccがなかったのです。

$ sudo yum install gcc
$ sudo yum isntall gcc-c++  ←これわかり難い
$ sudo yum install gcc-gfortran ←これも通常の名前と違うみたい
$ sudo yum install python-devel  ←これが一番悩んだ。pipで、Python.hがないと怒られた。

と、いろんな開発用パッケージをインストールしないといけません。AWS内ではyumリポジトリがAmazon専用のものが設けてあるのは知っていましたが、なんかパッケージ名が違うのか?ググったものと”微妙”にパッケージ名が違い困りました。(何かパッケージ名が微妙に違う気がしますが、これは自分が数年間RedHatから遠ざかり、Ubuntuを使い続けたからかもしれません)

3.virtualenv環境でchainerが動かない
これはまだ原因がわかりません。上記、各種パッケージのインストールをしたあと、virtualenv環境下でchainerをインストールしたのですが、なぜかnumpy等のパッケージが見つからないと怒られます。しかたなく、virtualenvの使用をあきらめるとうまくいくので、色々試行錯誤してるうちにどこかで間違ったかもしれません。

と、かなりとまどいました。とりあえず、今回はここで力つきました。AWSでDeep-learningを試してみるのは次にします。

2016年2月20日土曜日

TensorFlowで学習プログラム

TensorFlowで学習するプログラムを作ってみました。
一番単純な、2入力1出力です。(論理積を学習させます)
以前、chainerとかのサンプルも探しましたがどれも学習結果を使う所が見つかりませんでした。TensorFlowだとダイレクトにプログラムしないといけないので、その辺りは楽にできました。

とりあえず、サンプルです。


# -*- coding: utf-8 -*-

import tensorflow as tf
import numpy as np

# 入力データの定義 4行2列(データの定義方法がchainerとは違うようです)
# x_data = [
#   np.array([0., 0.]),
#   np.array([0., 1.]),
#   np.array([1., 0.]),
#   np.array([1., 1.])
# ]
x_data = np.array([
  [0., 0.],
  [0., 1.],
  [1., 0.],
  [1., 1.]
])

# 結果データの定義(4行1列)
# y_data = [
#   np.array([0.]),
#   np.array([0.]),
#   np.array([0.]),
#   np.array([1.])
# ]
y_data = np.array([
  [0.],
  [0.],
  [0.],
  [1.]
])


# 機械学習で最適化するWとbを設定する。Wは4行2列のテンソル。bは4行1列のテンソル。
W = tf.Variable(tf.random_uniform([4, 2], -1.0, 1.0))
b = tf.Variable(tf.zeros([4, 1]))
y = W * x_data + b

loss = tf.reduce_mean(tf.square(y_data - y))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# 学習を始める前にこのプログラムで使っている変数を全てリセットして空っぽにする
init = tf.initialize_all_variables()

# Launch the graph.(おきまりの文句)
sess = tf.Session()
sess.run(init)

# 学習を1000回行い、100回目ごとに画面に学習回数とWとbのその時点の値を表示する
for step in xrange(1001):
    sess.run(train)
    if step % 100 == 0:
        print step, sess.run(W), sess.run(b)

# 学習結果を確認
x_input = np.array([
  [0., 0.],
  [0., 1.],
  [1., 0.],
  [1., 1.]
])

y_res = tf.Variable(tf.zeros([4, 1]))
y_res = W * x_input + b
print sess.run(y_res)
# 4行1列の結果を期待しているのだが、4行2列になってしまう? 
# 学習が十分進めば、どちらの列も同じような結果になるからいいか。
print sess.run(b)

最後に、学習結果を確認しています。結果はこうなります。(一応、期待通りの結果になりました)
[[  0.00000000e+00   0.00000000e+00]
 [ -2.62142518e-23   1.62012971e-23]
 [  7.70256410e-23  -1.24630115e-22]
 [  9.99999881e-01   1.00000012e+00]]
[[  0.00000000e+00]
 [ -2.62142518e-23]
 [ -1.24630115e-22]
 [  6.69862151e-01]]
最後の、変数y_resとbの出力だけを貼り付けました。 どうしてもまだ理解できないのが、y_resの計算結果は4行1列になるはずなんですが、4行2列になってしまいます。(代入する直前でy_resを4行1列で定義しても上書きされてしまいます。bは4行2列でも、4行1列でも構わないようです)ただ結果をみると各行の値はどちらの列をとっても同じような値なのでよさそうです。 まだ深層学習の理論的な本を買って読み始めた所でよくわかっていませんが、TensrFlowの方がPrimitiveにプログラムしなければいけない分、直感的にわかります。(でもなんとなく、chainerの方がこの後進めていくのによさげな気もしますので、しばらく悩みます)