Kerasが2.0にアップデートされました。

# Kerasが2.0にアップデートされました。

Python向けディープラーニング・フレームワークのKerasが2.0にアップデートしました。
https://blog.keras.io/introducing-keras-2.html

今回は2.0のアップデート情報と、プログラムの書き方の変更箇所をおおまかにまとめていきます。
加えてKeras1.2とKeras2.0の違いをCifar10で比較してみたいと思います。

## アップデートによる変更箇所
変更内容を掻い摘んで訳していきます。
即興で意訳してます、間違いが合ったらご指摘くださいm(_ _)m。

### TensorFlow連携
KerasのバックエンドとしてTensorFlowを2015年12月からサポートしていましたが、TensorFlowのコードベースからKeras APIは隔離していました。
Keras2.0ではTensorFlow1.2ベースで直接呼び出し可能なAPIを提供します。
加えて2つの実装を提供します。
1. internal backendとして、TensorFlowと機能互換なtf.kerasを提供。TensorFlowで書かれている。
2. external backendとして、TheanoやTensorFlowをサポート。
そして将来的にはより多くのバックエンドをサポート。

さらにはScalaやJavaScriptからKeras APIを呼び出す開発も進んでいます。
ScalNet：　https://github.com/deeplearning4j/ScalNet
Keras.js：　https://github.com/transcranial/keras-js

Kerasはディープラーニング・フレームワークのリンガ・フランカ（共通語）になることを目指しているようですね。

### APIの変更
Keras2.0 APIを主流とし、コードベースKerasも同様にサポートしていくため、API仕様を大幅に変更しました。
- Layer APIの変更：Dense、BatchNormalization、Convolution系のAPIに変更を加えました。ただし、Keras1.xのプログラムもKeras2.0で引き続き動作するよう、互換性を持たせています。なお、Keras2.0でKeras1.xプログラムを実行すると、Warningが出ます。
- Training、Evaluation系APIの変更：たとえばfit_generator, predict_generator, evaluate_generatorが変更されていますが、Keras1.xプログラムも引き続きKeras2.0で動作します。
- fitのnb_epochはepochsに変更されました。
- ファイルに保存されたweightのフォーマットの変更：Keras1.xも以下略
- objectivesモジュールはlossesに名称変更

というわけで、Keras1.xプログラムも引き続きKeras2.0で動くようです。ご安心ください。

### 根本的な変更～Breaking Changes～
上記の通りKeras1.xの互換性を保とうとしましたが、どうしても大きく変えなければならない箇所もあったようです。

- MaxoutDense, TimeDistributedDense, Highwayは終焉。
- メトリック、損失関数ファンクションの多くを終焉。
- BatchNormalizationからmodeの削除。
- Kerasの内部実装を変更したため、カスタム・レイヤーも修正する必要があります。比較的少ない変更なので、以下を参考に修正してください。
https://keras.io/layers/writing-your-own-keras-layers/
- Kerasドキュメント未記載（＝未サポート？）のコードは動かなくなる可能性があります。

### 変更の詳細
より詳しい変更は以下リリース・ノートまとまっています。
https://github.com/fchollet/keras/wiki/Keras-2.0-release-notes
Keras1.xモジュールのKeras2.0変更対応一覧になっています。
便利です。

##  Keras2.0の導入方法
pip installでインストールできるKerasは2.0になっています。
既にKerasを使っていて2.0へのアップデートをしたい場合は以下でOKです。

```
pip install keras --upgrade

```


## Cifar10 at Keras2.0
Keras1.2で書いたCifar10のCNNをKeras2.0版に書き換えてみました。

まず、Keras1.2版のCifar10です。

```
# coding: utf-8

import keras
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils


(x_train, y_train), (x_test, y_test) = cifar10.load_data()

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

y_train = np_utils.to_categorical(y_train, 10)
y_test = np_utils.to_categorical(y_test, 10)


model = Sequential()

model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=x_train.shape[1:]))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Convolution2D(64, 3, 3, border_mode='same'))
model.add(Activation('relu'))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(10))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

model.summary()

model.fit(x_train, y_train, batch_size=100, nb_epoch=25, validation_split=0.1)


score = model.evaluate(x_test, y_test)
print('Test loss:', score[0])
print('Test accuracy:', score[1])


```


続いて、Keras2.0版のCifar10です。

```

# coding: utf-8

import keras
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.utils import np_utils


(x_train, y_train), (x_test, y_test) = cifar10.load_data()

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

y_train = np_utils.to_categorical(y_train, 10)
y_test = np_utils.to_categorical(y_test, 10)


model = Sequential()

model.add(Conv2D(32, (3, 3), padding="same", input_shape=x_train.shape[1:]))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(10))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

model.summary()

model.fit(x_train, y_train, batch_size=100, epochs=25, validation_split=0.1)


score = model.evaluate(x_test, y_test)
print('Test loss:', score[0])
print('Test accuracy:', score[1])


```

間違い探しか？ってくらい、ほとんど何も変わっているように見えませんね。
具体的な変更箇所は以下です。

Convolution2D　→　Conv2D


```
# Keras1.x
from keras.layers import Convolution2D, MaxPooling2D

# Keras2.0
from keras.layers import Conv2D, MaxPooling2D

・・・

# Keras1.x
model.add(Convolution2D(32, 3, 3, border_mode='same', input_shape=x_train.shape[1:]))

# Keras2.0
model.add(Conv2D(32, (3, 3), padding="same", input_shape=x_train.shape[1:]))

```

np_epoch →　epochs


```
# Keras1.x
model.fit(x_train, y_train, batch_size=100, nb_epoch=25, validation_split=0.1)

# Keras2.0
model.fit(x_train, y_train, batch_size=100, epochs=25, validation_split=0.1)

```


ほとんど違いはありませんね。
しかもKeras1.x版を修正せずとも、Warningが出るだけで普通に動きます。
修正方法もアドバイスしてくれました（笑）

![2017-03-17.PNG](https://qiita-image-store.s3.amazonaws.com/0/55384/ea306045-2124-1977-5e21-ce889d91a744.png)



ちなみにKeras1.xとKeras2.0の、Cifar10（25エポック）の結果は以下でした。

| バージョン | Loss | Accuracy |
|--------|--------|--------|
|Keras1.x        |0.66        |0.80        |
|Keras2.0        |0.66        |0.79        |


同じネットワークですし、やはり結果に大差ありませんね（笑）