多項ロジスティック回帰 [TensorFlow2.0でDeep Learning 2]

([目次はこちら](http://qiita.com/kumonkumon/items/6fd05963df92e9eec8c0))

#はじめに
[多項ロジスティック回帰 [TensorFlowでDeep Learning 2]](https://qiita.com/kumonkumon/items/2a659075d55b7b49df5a)をtensorflow2.0で実現するためにはどうしたらいいのかを書く(`tf.keras`)。

# コード
Python: 3.6.8, Tensorflow: 2.0.0a0で動作確認済み

[多項ロジスティック回帰 [TensorFlowでDeep Learning 2]](https://qiita.com/kumonkumon/items/2a659075d55b7b49df5a) ([mnist_softmax.py](https://github.com/kumon/DeepLearningExercise/blob/master/src/tensorflow/mnist_softmax.py))を書き換えると、

[v2/mnist_softmax.py](https://github.com/kumon/DeepLearningExercise/blob/master/src/tensorflow/v2/mnist_softmax.py)

```v2/mnist_softmax.py
from helper import *

IMAGE_SIZE = 28 * 28
CATEGORY_NUM = 10
LEARNING_RATE = 0.1
EPOCHS = 30
BATCH_SIZE = 100
LOG_DIR = 'log_softmax'
EPS = 1e-10

def loss_fn(y_true, y):
    y = tf.clip_by_value(y, EPS, 1.0)
    return -tf.reduce_sum(y_true * tf.math.log(y), axis=1)

class LR(tf.keras.layers.Layer):
    def __init__(self, units, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.units = units

    def build(self, input_shape):
        input_dim = int(input_shape[-1])
        self.W = self.add_weight(
            name='weight',
            shape=(input_dim, self.units),
            initializer=tf.keras.initializers.GlorotUniform()
        )
        self.b = self.add_weight(
            name='bias',
            shape=(self.units,),
            initializer=tf.keras.initializers.Zeros()
        )
        self.built = True

    def call(self, x):
        return tf.nn.softmax(tf.matmul(x, self.W) + self.b)

if __name__ == '__main__':
    (X_train, y_train), (X_test, y_test) = mnist_samples(flatten_image=True)

    model = tf.keras.models.Sequential()
    model.add(LR(CATEGORY_NUM, input_shape=(IMAGE_SIZE,)))
    model.compile(loss=loss_fn, optimizer=tf.keras.optimizers.SGD(LEARNING_RATE), metrics=['accuracy'])

    cb = [tf.keras.callbacks.TensorBoard(log_dir=LOG_DIR)]
    model.fit(X_train, y_train, batch_size=BATCH_SIZE, epochs=EPOCHS, callbacks=cb, validation_data=(X_test, y_test))
    print(model.evaluate(X_test, y_test))
```

と書ける。

ロジスティック回帰との違いは、交差エントロピーの最小化となることと、

```
return -tf.reduce_sum(y_true * tf.math.log(y), axis=1)
```

`sigmoid()`が`softmax()`になるくらい。

```
return tf.nn.softmax(tf.matmul(x, self.W) + self.b)
```

[前回](https://qiita.com/kumonkumon/items/46c1490706115de45a9c)と同様に、シンプルに書ける。

[v2/mnist_softmax_simple.py](https://github.com/kumon/DeepLearningExercise/blob/master/src/tensorflow/v2/mnist_softmax_simple.py)

```v2/mnist_softmax_simple.py
from helper import *

IMAGE_SIZE = 28 * 28
CATEGORY_NUM = 10
LEARNING_RATE = 0.1
EPOCHS = 30
BATCH_SIZE = 100
LOG_DIR = 'log_softmax'


if __name__ == '__main__':
    (X_train, y_train), (X_test, y_test) = mnist_samples(flatten_image=True)

    model = tf.keras.models.Sequential()
    model.add(tf.keras.layers.Dense(CATEGORY_NUM, input_shape=(IMAGE_SIZE,), activation='softmax'))
    model.compile(
            loss='categorical_crossentropy',
            optimizer=tf.keras.optimizers.SGD(LEARNING_RATE), metrics=['accuracy'])

    cb = [tf.keras.callbacks.TensorBoard(log_dir=LOG_DIR)]
    model.fit(X_train, y_train, batch_size=BATCH_SIZE, epochs=EPOCHS, callbacks=cb, validation_data=(X_test, y_test))
    print(model.evaluate(X_test, y_test))
```

めでたしめでたし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127038/cbab2cc0-ad4e-5688-87b8-30e8f92ad9fb.png)