CNN

다음과 같이 그래프를 미리 빌드해 놓은 다음,

신경망에 통과시킬 input image를 실행 시점에 ``py sess.run( , feed_dict={})``를 통해 넘긴다.

```python

# 구식 방법

W1 = tf.Variable(tf.random_normal([3, 3, 1, 32], stddev=0.01)) #H, W, C, FN

b1 = tf.Variable(tf.zeros([32]))

 

L1 = tf.nn.conv2d(X_img, W1, strides=[1, 1, 1, 1], padding="SAME")

L1 = tf.nn.relu(L1+b1)

L1 = tf.nn.max_pool(L1, ksize=[1, 2, 2, 1],

                   strides=[1, 2, 2, 1], padding="SAME")

L1 = tf.nn.dropout(L1, keep_prob=keep_prob)

```


위 작업을 ``py tf.layers``를 이용해 더 간단히 처리할 수 있다. 보통 다음과 같은 방법을 사용한다.

channel은 따로 입력받지 않는다. 어차피 ``py filters == input channel`` 수 이니까.

```python

conv1 = tf.layers.conv2d(inputs=X_img, filters=32, kernel_size=[3, 3],

                           padding="SAME", activation=tf.nn.relu)

pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2],

                                  padding="SAME", strides=2)

dropout1 = tf.layers.dropout(inputs=pool1,

                               rate=0.7, training=self.training)

 

.....

 

dense4 = tf.layers.dense(inputs=flat,

                           units=625, activation=tf.nn.relu)

.....

```
``py padding="SAME"``은 stride가 `` 1, 1``일 때 입력 형상이 그대로 출력 형상이 되는 padding을 말한다.

conv layer에서는 stride가 1, 1이고, ``py padding="SAME"``이므로 입력 형상이 그대로 출력 형상이 된다. (?, 28, 28, 32)

pooling layer에서는 stride가 2, 2이고, ``py padding="SAME"``이므로 출력 형상이 입력 형상의 반이 된다. (?, 14, 14, 32)

(stride의 첫 번째와 마지막은 그냥 1로 고정이라고 생각하면 된다)


dropout에서 ``py rate``와 ``py training(boolean)``을 따로 지정한다. 

훈련 시는 `` rate``에 적당한 값을 주고 시험 시는 ``py rate=0``으로 지정하는 것과 결국 같은건데, 그렇게 하지 않는 이유는 각 layer의 dropout에 서로 다른 값이 들어갈 경우 처리가 약간 귀찮기 때문.

그래서 build 시 값을 미리 지정해 두고, dropout을 적용할지 말지는 training flag가 결정한다. 

``py False``인 경우 자동으로 ``py rate=0``이 된다.


학습한 파라미터 저장 / 불러오기

```python

saver = tf.train.Saver(max_to_keep=10)    # default is 5

save_path = saver.save(sess, "./Variables/mnist-en{}-{}".format(ensemble, step+restore_step))

```


```python

if restore_step:

    saver.restore(sess, "./Variables/mnist-en{}-{}".format(ensemble, restore_step))

else:

    sess.run(tf.global_variables_initializer())

```

`` max_to_keep`` default는 5이며 0을 주면 오래된 파일 안지우고 계속 저장하는데 용량이 꽤 큼.

파일 이름이 같으면 계속 덮어 쓰게 된다.

``py restore``를 ``py try-except``로 처리하거나, 파일 존재 유무를 체크해서 파일이 없어도 돌아가도록 만들 수는 있는데, `` save_path``를 명시해서 파라미터를 불러오도록 의도했는데 못불러온다는건 꽤 큰 문제이므로 그냥 프로그램 종료되도록 놔두는게 나은 것 같다.