Hello Wor.log

IT系大学生4人による備忘録のようなもの

tensorflowでライフゲーム【python】

CPPXのXです。

tensorflowを使ってライフゲームを実装したお話をします。

GPUを使ってライフゲームを動かしたいなあ って思ったので、畳み込みを使いつつtensorflowで実装を行いました。
ライフゲームのルールとかは、知っている人しかこの記事に流れてこないと思うので省略します。

実装の流れは、
1. 畳み込んでセルの数え上げ
2. 入力と数え上げ結果を使って次世代の状態を計算

だけです。

環境

  • python 3.5.3
  • tensorflow 1.9.0

import

import tensorflow as tf import numpy as np import pylab

この辺り使っていきます。

モデル部分

inputs = tf.placeholder(tf.int8, [None, size, size, 1]) # size = 500

flt = tf.initializers.constant([
[1, 1, 1],
[1, 0, 1],
[1, 1, 1],
])
cnt = tf.contrib.slim.conv2d(tf.cast(inputs, tf.float32), 1, 3, padding="same", activation_fn=None, weights_initializer=flt)
outputs = (tf.equal(inputs, 1) & tf.greater_equal(cnt, 2) & tf.less_equal(cnt, 3)) | (tf.equal(inputs, 0) & tf.equal(cnt, 3))

sizeは整数で、適当な幅を指定してください。

入力に対して、真ん中が0でそれ以外1の3 * 3行列を重みとして畳み込みをします。
周囲のセルを数え上げています。

セルの数え上げ結果と、入力を使って次世代セルの状態を計算します。
ライフゲームのルールに則って、計算します。

周囲のセル数が2以上3以下で既にいるなら維持。
周囲のセル数が3でまだいないなら誕生。
それ以外は死滅です。

テスト

sess = tf.Session()
sess.run(tf.global_variables_initializer())

img = np.random.randint(0, 100, (1, size, size, 1)) < 30 # 初期化:30%の確率で誕生
img = img.astype(np.int8)

with tf.device("/device:GPU:0"): # 自分の環境に応じて
    for _ in range(1000):
        pylab.imshow(np.squeeze(img))
        pylab.show()
        img = sess.run(outputs, feed_dict={inputs: img})

乱数でデータを作って1000世代まで計算しています。

特には言うことないです。

sess.run(... の部分で次世代の計算が行われます。

コード全体

import tensorflow as tf
import numpy as np
import pylab

#%%
size = 50

inputs = tf.placeholder(tf.int8, [None, size, size, 1])

flt = tf.initializers.constant([
[1, 1, 1],
[1, 0, 1],
[1, 1, 1],
])
cnt = tf.contrib.slim.conv2d(tf.cast(inputs, tf.float32), 1, 3, padding="same", activation_fn=None, weights_initializer=flt)
outputs = (tf.equal(inputs, 1) & tf.greater_equal(cnt, 2) & tf.less_equal(cnt, 3)) | (tf.equal(inputs, 0) & tf.equal(cnt, 3))

#%%
sess = tf.Session()
sess.run(tf.global_variables_initializer())

#%%
img = np.random.randint(0, 100, (1, size, size, 1)) < 30
img = img.astype(np.int8)

with tf.device("/device:GPU:0"):
    for _ in range(1000):
        pylab.imshow(np.squeeze(img))
        pylab.show()
        img = sess.run(outputs, feed_dict={inputs: img})

確率の概念とか取り入れて何かしたら面白そうだなあ って漠然と思いました。
outputsに使っている計算も、連続関数で近似したら誤差逆伝播も使えると思うし、何かに使えなかろうか。