TensorflowでCNNを作る際に使いそうな関数を列挙してみた


# はじめに
Googleが作成したDeepLearningフレームワークのTensorflow
いろいろ記事が上がっていて非常に面白いですが、実際にNNを組む際に使用する関数はどれ？というのを備忘としてまとめてみました

なお筆者はDeeplearningを大学で学んだわけではなく自己学習しただけなので、間違いも多々あるかと思いますが、後学のため指摘いただけると幸いです

# 畳込み層で使用
## tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)
畳込みを行う関数
他にはdepthwise_conv2d, separable_conv2dが存在する

### 第1引数: input
インプットデータを、4次元([batch, in_height, in_width, in_channels])のテンソルを渡す
一番最初は画像を読み込んだ後、reshape関数で[-1, in_height, in_width, in_channels]と変換し、渡せばよい

### 第2引数: filter
畳込みでinputテンソルとの積和に使用するweightにあたる
４次元[filter_height, filter_width, in_channels, channel_multiplier] のテンソルを渡す
最後の引数のchannel_multiplierだけchannel数が拡張される

e.g. 3x3x1のフィルタで畳込み、アウトプットを64チャネルにする

```py:フィルタ作成例
weight = tf.random_normal([3, 3, 1, 64]
```

### 第3引数: strides
ストライド（=１画素ずつではなく、数画素ずつフィルタの適用範囲を計算するための値)を指定
ただしstrides[0] = strides[3] = 1. とする必要があるため、指定は[1, stride, stride, 1]と先頭と最後は１固定とする

参考: https://www.tensorflow.org/versions/master/api_docs/python/nn.html#conv2d

#### 第4引数: padding
「'SAME'」か「'VALID'」を利用
ゼロパディングを利用する場合はSAMEを指定

## tf.nn.bias_add(value, bias, name=None)
重みを積和したものにバイアスを加算する際に使用
アウトプットチャネル数に合わせるのが良い（？）

```py:アウトプットチャネルが64の場合にバイアスを加算する
bias = tf.Variable(tf.random_normal([64]))
return tf.nn.bias_add(tf.nn.conv2d(input, weight, strides=[1, 2, 2, 1], padding='SAME'),bias)
```

## tf.nn.relu (features, name=None)
畳込み層のアクティベーション関数としてReLuを使用する
もちろんsoftmaxやsigmoidも用意されている

### 第1引数: features
フィルタやバイアスを足しこんだ結果(Wx + b)のテンソルを利用する

```py:使用例
    return tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(input, weight, strides=[1, 2, 2, 1], padding='SAME'),bias), name='conv1')
```

# プーリング層で使用
## tf.nn.max_pool(value, ksize, strides, padding, name=None)
最大プーリング用の関数
他にも平均プーリングも用意されている

### 第1引数: value
inputデータ
畳込み層からの出力データをそのまま与えれば良い

### 第2引数: ksize
プーリングサイズをしてい
3x3にしたい場合は[1, 3, 3, 1]とすればよい

※第３引数以降はconv2dと同じのため割愛

# その他（ドロップアウト、損失関数、訓練など）
## tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None)
ドロップアウトを行う関数
### 第1引数: x
プーリング層からの出力（を正規化して？）をそのまま与えれば良い

### 第2引数: keep_prob
ドロップアウトする率
公式ドキュメントには「The probability that each element is kept.」とあるから、残す率を指定すればよい（？）

```py:使用例
# 2割をドロップアウトする
tf.nn.dropout(res,0.8)
```


## tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)
交差エントロピー
バックプロパゲーションの損失関数として使用できる

```py:使用例
# res = NNの結果として出力層から返された値
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(res, class))
```

## tf.train.AdamOptimizer
訓練を実施する関数
ここで作ったものをSess.runに引き渡し訓練を実施する

```py:使用例
# res = NNの結果として出力層から返された値
optimizer = tf.train.AdamOptimizer.minimize(cost)
```

# 共通/事前処理などで使用
## tf.reshape(tensor, shape, name=None)
### 第1引数: tensor
inputとなるテンソルを指定

### 第2引数: shape
変えたい形を指定
ただし-1を指定した場合には次元が削減されflattenとなる

与えられた画像をNNで必要なheight, width, channelに変換する
例えば28x28のRGBに変換したい場合は以下のようにする

```py:reshape.py
x = tf.reshape(im, [-1, 28, 28, 3])
```

```py:実行サンプル
>>> import tensorflow as tf
>>> matrix1 = tf.constant([[3, 3],[1, 1],[2,2]])

>>> # 1次元にreshape
>>> r = tf.reshape(matrix1, [-1])
>>> sess = tf.Session()
>>> sess.run(r)
array([3, 3, 1, 1, 2, 2], dtype=int32)

>>> # 2次元にreshape なお[2]とした場合にはエラーが発生する
>>> r = tf.reshape(matrix1, [2, -1])
>>> sess.run(r)
array([[3, 3, 1],
       [1, 2, 2]], dtype=int32)
```

## tf.matmul(a, b, transpose_a=False, transpose_b=False, a_is_sparse=False, b_is_sparse=False, name=None)
テンソル同士の掛け算を行う関数
数値同士の単純な掛け算は tf.mul(x, y, name=None) を使用する

```py:実行サンプル
>>> a = tf.constant([[1,2],[3,4]])
>>> b = tf.constant([[2],[2]])
>>> c = tf.matmul(a, b)
>>> sess = tf.Session()
>>> #計算の結果、[1*2 + 2*2],[3*2 + 4*2]となる
>>> sess.run(c)
array([[ 6],
       [14]], dtype=int32)
```

## tf.reduce_mean(input_tensor, reduction_indices=None, keep_dims=False, name=None)
損失関数などで使用する平均を算出する関数
reduction_indicesで集約する次元を指定する

```py:実行サンプル
>>> a = tf.constant([[1.0,2.0],[3.0,4.0],[5.0,6.0]])

>>> mean = tf.reduce_mean(a)
>>> sess.run(mean)
3.5

>>> mean = tf.reduce_mean(a,0)
>>> sess.run(mean)
array([ 3.,  4.], dtype=float32)

>>> mean = tf.reduce_mean(a,1)
>>> sess.run(mean)
array([ 1.5,  3.5,  5.5], dtype=float32)

```