DeepLearning
Keras
TensorFlow

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

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

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

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