TensorFlowで input:100, output:100のネットワークでの学習を検討 v0.6 / v0.4 > とりあえず動いた程度

### TensorFlow

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 14.04 LTS desktop amd64
TensorFlow v0.11
cuDNN v5.1 for Linux
CUDA v8.0
Python 2.7.6
IPython 5.1.0 -- An enhanced Interactive Python.
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
```

TensorFlowを使って、input:100, output:100程度のネットワークの学習をしようかと作業中。

### データ生成コード > v0.6

Jupyterコード。

```py:in100_out100.ipynb
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import os

'''
v0.6 Feb. 14, 2017
  - fix bug > savetxt() was without 'delimiter=','
v0.5 Feb. 06, 2017
  - add [FILENAME_*_CSV],[FILENAME_*_BAK]
  - output to csv with append mode
v0.4 Jan. 21, 2017
  - set size of figures
v0.3 Jan. 21, 2017
  - show 2 images in one figure
v0.2 Jan. 14, 2017
  - calcOutput() return in numpy.array
  - add saveToCsvFile()
v0.1 Jan. 14, 2017
  - add calcOutput()
  - add showIn2D()
  - show 1d in 2d format
'''

'''
codingrule:PEP8
'''

XDIM = 10
YDIM = 10
INDIM = XDIM * YDIM

FILENAME_IN_CSV = 'test_in.csv'
FILENAME_OUT_CSV = 'test_out.csv'
FILENAME_IN_BAK = 'test_in.bak'
FILENAME_OUT_BAK = 'test_out.bak'


def saveToCsvFile(data_1d, filename):
    wrk_1d = data_1d.reshape(1, INDIM)
    # np.savetxt(filename, wrk_1d, delimiter=',')
    with open(filename, 'a') as fd:
        np.savetxt(fd, wrk_1d, delimiter=',')


def calcOutput(in_1d):
    len_1d = XDIM * YDIM
    out_1d = [0.0] * len_1d
    for idx in range(0, in_1d.size):
        out_1d[idx] = in_1d[len_1d - idx - 1]
    return np.array(out_1d)


def showIn2D(data_1d):
    # print(data_1d)
    data_2d = np.reshape(data_1d, (XDIM, YDIM))
    plt.imshow(data_2d, extent=(0, XDIM, 0, YDIM), cmap=cm.gist_rainbow)
    plt.show()


def showIn2D_2image_subplot_each(data1_1d, data2_1d):
    data1_2d = np.reshape(data1_1d, (XDIM, YDIM))
    data2_2d = np.reshape(data2_1d, (XDIM, YDIM))
    fig1 = plt.figure(1)
    fig1.set_size_inches(3.14, 3.14)
    plt.subplot(121)
    plt.title('input node')
    plt.imshow(data1_2d, extent=(0, XDIM, 0, YDIM), cmap=cm.gist_rainbow)
    plt.subplot(122)
    plt.title('output node')
    plt.imshow(data2_2d, extent=(0, XDIM, 0, YDIM), cmap=cm.gist_rainbow)
    plt.show()


def showIn2D_2image_subplot_first(data1_1d, data2_1d):
    data1_2d = np.reshape(data1_1d, (XDIM, YDIM))
    data2_2d = np.reshape(data2_1d, (XDIM, YDIM))
    fig, (axL, axR) = plt.subplots(ncols=2, figsize=(10, 4))
    axL.imshow(data1_2d, extent=(0, XDIM, 0, YDIM), cmap=cm.gist_rainbow)
    axL.grid(True)
    axR.imshow(data2_2d, extent=(0, XDIM, 0, YDIM), cmap=cm.gist_rainbow)
    axR.grid(True)
    fig.show()


if __name__ == '__main__':
    # backup the original csv files
    if os.path.exists(FILENAME_IN_CSV):
        os.rename(FILENAME_IN_CSV, FILENAME_IN_BAK)
    if os.path.exists(FILENAME_OUT_CSV):
        os.rename(FILENAME_OUT_CSV, FILENAME_OUT_BAK)

    # append csv
    NUM_FILEOUT = 100
    NUM_DISPLAY = 5
    for loop in range(NUM_FILEOUT):
        in_1d = np.random.rand(INDIM)
        out_1d = calcOutput(in_1d)
        saveToCsvFile(in_1d, FILENAME_IN_CSV)
        saveToCsvFile(out_1d, FILENAME_OUT_CSV)
        if loop < NUM_DISPLAY:
            showIn2D_2image_subplot_each(in_1d, out_1d)
            showIn2D_2image_subplot_first(in_1d, out_1d)

```

### 学習内容

上記コードで生成されるもの。

- input: 10x10のデータ
- output: 180度回転した結果

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/efa1aafb-72d2-13b0-b2fb-c35e0bdc60bc.png)


### 学習コード > v0.4

```learn_in100out100.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import tensorflow as tf
import tensorflow.contrib.slim as slim
import numpy as np

'''
v0.4 Feb. 15, 2017
    - fix bug > ZeroDivisionError: float division by zero @ shuffle_batch()
v0.3 Feb. 15, 2017
    - tweak [batch_size] for shuffle_batch()
v0.2 Feb. 15, 2017
    - fix bug > different dimensions for placeholder and network
v0.1 Feb. 06, 2017
    - read [test_in.csv],[test_out.csv]
'''

'''
codingrule:PEP8
'''

filename_inp = tf.train.string_input_producer(["test_in.csv"])
filename_out = tf.train.string_input_producer(["test_out.csv"])
NUM_INP_NODE = 100
NUM_OUT_NODE = 100

# parse csv
# a. input node
reader = tf.TextLineReader()
key, value = reader.read(filename_inp)
deflist = [[0.] for idx in range(NUM_INP_NODE)]
input1 = tf.decode_csv(value, record_defaults=deflist)
# b. output node
key, value = reader.read(filename_out)
deflist = [[0.] for idx in range(NUM_OUT_NODE)]
output1 = tf.decode_csv(value, record_defaults=deflist)
# c. pack
# inputs = tf.pack([input1])
inputs = input1
# outputs = tf.pack([output1])
outputs = output1

batch_size = 2
inputs_batch, output_batch = tf.train.shuffle_batch(
    [inputs, outputs], batch_size, capacity=10, min_after_dequeue=batch_size)

input_ph = tf.placeholder("float", [None, 100])
output_ph = tf.placeholder("float", [None, 100])

# network
hiddens = slim.stack(input_ph, slim.fully_connected, [7, 7, 7],
                     activation_fn=tf.nn.sigmoid, scope="hidden")
prediction = slim.fully_connected(
    hiddens, 100, activation_fn=None, scope="output")
loss = tf.contrib.losses.mean_squared_error(prediction, output_ph)

train_op = slim.learning.create_train_op(loss, tf.train.AdamOptimizer(0.001))

init_op = tf.initialize_all_variables()

with tf.Session() as sess:
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    try:
        sess.run(init_op)
        for idx in range(10000):
            inpbt, outbt = sess.run([inputs_batch, output_batch])
            _, t_loss = sess.run(
                [train_op, loss],
                feed_dict={input_ph: inpbt, output_ph: outbt})

            if (idx+1) % 100 == 0:
                print("%d,%f" % (idx+1, t_loss))
    finally:
        coord.request_stop()

    coord.join(threads)
```

### 学習結果

```
$ python learn_in100out100.py > res.learn.170215
```

Jupyterコード

```py:check_result_170215.ipynb
%matplotlib inline

# Feb. 15, 2017

import numpy as np
import matplotlib.pyplot as plt

data1 = np.loadtxt('res.learn.170215', delimiter=',')

input1 = data1[:,0]
output1 = data1[:,1]

fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)

ax1.scatter(input1,output1)

ax1.set_xlabel('step')
ax1.set_ylabel('Error')
ax1.grid(True)

fig.show()
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/e3769ed2-4cc8-7f0d-8576-c45cbcb35281.png)

動いたけど、学習していない。
見事に平らな状態。

TODO 

- パターン数を増やす
- ネットワーク形態を再検討 (7x7x7)はだめ
- dropoutなど試す?

### 間違い
(追記 2017/02/16)

学習コードにおいて以下のようにデバッグ出力してみた。

```
    ipb = sess.run(inputs)
    print(ipb)
```

1セットのデータ(100個)しか読込みしていなかった (本来は100セット)。
値も`test_in.csv`のどの行に対応するものか不明な値になっている。

読込み部分を訂正しないといけない。

### 間違いの間違い
(追記 2017/02/18)

> 1セットのデータ(100個)しか読込みしていなかった (本来は100セット)。
値も`test_in.csv`のどの行に対応するものか不明な値になっている。

sess.run()実行時は「１行単位」のデータを取得していることを思い出した。
http://qiita.com/7of9/items/8ce7b0c26d3f336994bb
> .eval()を実行した時点で次の行に移っている感じ。

1行単位なので１セットのデータ(100個)は正しい。

また、inputs_batchをプリントしてみた。

```py
    ipb = sess.run(inputs_batch)
    print(ipb)
```

```
[[ 0.27378908  0.77832508  0.66996235  0.9936288   0.37003392  0.48302305
   0.91998494  0.47781557  0.84146357  0.87289417  0.59628558  0.31444955
   0.20789994  0.13002349  0.51010031  0.67129123  0.26678562  0.42461532
   0.23077908  0.36953288  0.60923821  0.22428873  0.91484821  0.96400797
   0.82050014  0.19229527  0.33357236  0.27375877  0.672189    0.10478086
   0.3833147   0.51772732  0.57535899  0.45212439  0.86960983  0.46372598
   0.77490646  0.76639509  0.34343696  0.99818504  0.04181263  0.71036136
   0.18994796  0.38545141  0.88715452  0.78941095  0.22124505  0.03441546
   0.64749175  0.83524925  0.42687404  0.94697499  0.52809227  0.8711794
   0.10895945  0.00816056  0.00680686  0.52310741  0.20360599  0.47884497
   0.98351258  0.59743387  0.99637157  0.88777357  0.91498935  0.43188599
   0.55881679  0.60617083  0.67255348  0.67138773  0.80570024  0.85243547
   0.85984218  0.45049888  0.86998856  0.31533426  0.57532537  0.62453246
   0.38949087  0.78828526  0.80525231  0.79273951  0.49979997  0.76873082
   0.20036873  0.90647137  0.758237    0.20328186  0.21196508  0.62333453
   0.89339769  0.81486326  0.28775701  0.25593397  0.06128036  0.93762207
   0.83083159  0.56782335  0.45231211  0.84866965]
 [ 0.07778174  0.41043103  0.34608433  0.51273614  0.88500345  0.71186465
   0.94978476  0.62020504  0.87333673  0.62775117  0.04245559  0.52664864
   0.0528044   0.83136648  0.40310758  0.16103657  0.64057237  0.01316145
   0.11683175  0.55556452  0.78827113  0.35770321  0.15182373  0.40584594
   0.48646879  0.70026076  0.56559467  0.30844554  0.76788306  0.78978932
   0.0050277   0.02185559  0.75613821  0.79734856  0.30024406  0.01432199
   0.86313915  0.08995577  0.26689622  0.78631955  0.43818957  0.79959685
   0.04071518  0.74025762  0.33962905  0.13433631  0.41690096  0.07225868
   0.86578894  0.57572138  0.07017604  0.95596385  0.12751566  0.38668841
   0.71367472  0.28218153  0.50080389  0.60823286  0.43461365  0.01779328
   0.71983147  0.39271042  0.47100115  0.91044843  0.68286359  0.93751448
   0.16222051  0.20191826  0.64682436  0.92627949  0.98703146  0.38289773
   0.01301599  0.17870972  0.87788147  0.25613952  0.09436332  0.76128787
   0.42661723  0.01867126  0.25811395  0.35596904  0.14381361  0.17044938
   0.54219621  0.27092507  0.20158796  0.96859008  0.75240612  0.83702469
   0.85523546  0.70141906  0.07097515  0.50713336  0.51258177  0.98837918
   0.16909966  0.74903727  0.53468341  0.42080453]]
```

batch_size = 2としてshuffle_batch()を使用。
`test_in.csv`からランダムな2セット分のデータを読み込んでいるので、処理としては正しいのだろう。