スポンサーリンク
はじめに
最近機械学習から離れ気味ですが、何やらTensorFlowのDocumentを覗いたらTensorFlow内部のKerasがすごくいろいろな使い方できることに気が付きました。 (ちなみに、TensorFlowとは別の(いろいろなフレームワークをバックエンドにできる)Kerasの方はどうなっているのか知らないので申し訳ありません。)
ということでそれを簡単にまとめておきたいと思います。本当に簡単に。
これまで通りの使い方
Kerasと言えばコレ:Sequential
最もよく知られている使い方ですね。
model=tf.keras.Sequential()
でインスタンス化して、model.add()
メソッドでひたすら層を積んでいく方式。
とっても直感的で分かりやすいです。
model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(32, input_shape=(500,))) model.add(tf.keras.layers.Dense(32)) model.compile(optimizer=optimizer, loss=loss) model.fit(x, y, batch_size=32, epochs=10)
x
とかy
とかは教師データ・セットです。optimizer
,loss
を決めてやればすぐに学習ができます。便利!
少し発展版:Modelによるfunctional API
少しニューラルネットワークの構成が複雑になったときに使うのがこちら。
枝分かれしたりするネットワークや、ロスが複数あるような場合にも対応可能。
ちなみにtf.keras.kayers.Desne()
などにはactivation
という引数があり、ここで活性化関数を指定することができる。
inputs = tf.keras.Input(shape=(500,)) x = tf.keras.layers.Dense(32, activation=tf.nn.relu)(inputs) outputs = tf.keras.layers.Dense(32, activation=tf.nn.softmax)(x) model = tf.keras.Model(inputs=inputs, outputs=outputs) model.compile(optimizer=optimizer, loss=loss) model.fit(x, y, batch_size=32, epochs=10)
上記ではactivation=tf.nn.relu
だが、activation=tf.keras.activations.relu
でもactivation='relu'
でもいける(ハズ)。
Eagerの登場によって…!
Pythonのclassとしての作り方
これはPyTorchやChainerでのネットワークの作り方とほぼ同じです。
class MyModel(tf.keras.Model): def __init__(self): super(MyModel, self).__init__() self.dense1 = tf.keras.layers.Dense(32, activation=tf.nn.relu) self.dense2 = tf.keras.layers.Dense(32, activation=tf.nn.softmax) def call(self, inputs): x = self.dense1(inputs) return self.dense2(x) model = MyModel() model.compile(optimizer=optimizer, loss=loss) model.fit(x, y, batch_size=32, epochs=10)
という書き方ができるようになりました。call
の部分は自由自在に書けますが、あくまでDefine and Runであることに注意してください。
functional APIの書き方を少し変えて、使う層を__init__()
で準備しておき、call()
で実際にグラフを書くというイメージになります。
正直functional APIに慣れている人はそれで良いような気がしますね。
ちなみにドロップアウトなどのように、training時とevaluation時で振るまいが変わるような処理が入る場合は、
以下のようにcall()
メソッドにtraining引数を与えておけば良いようです。
class MyModel(tf.keras.Model): def __init__(self): super(MyModel, self).__init__() self.dense1 = tf.keras.layers.Dense(32, activation=tf.nn.relu) self.dense2 = tf.keras.layers.Dense(32, activation=tf.nn.softmax) self.dropout = tf.keras.layers.Dropout(0.5) def call(self, inputs, training=False): x = self.dense1(inputs) if training: x = self.dropout(x, training=training) return self.dense2(x) model = MyModel()
Eagerモードとしての書き方
先ほどの書き方はEagerモードを使うときに非常に重要な役割を担います。 というかもはやPyTorch的に書くための物と思って構わないでしょう。
class MyModel(tf.keras.Model): def __init__(self): super(MyModel, self).__init__() self.dense1 = tf.keras.layers.Dense(32, activation=tf.nn.relu) self.dense2 = tf.keras.layers.Dense(32, activation=tf.nn.softmax) def call(self, inputs): x = self.dense1(inputs) return self.dense2(x) model = MyModel() tf.enable_eager_execution()
tf.enable_eager_execution()
はいつ唱えても良いのですが、1つのセッションに対して1回切りです。
コレを唱えた後は、ずっとそのセッションでTensorFlowはDefine by Runとして動きます。
eagerモードで使う場合、ドロップアウトなどのような処理は自分で分岐させねばならないかもしれません。
ただ以下の記事のコードの様に、PyTorchのようにeval()
メソッドやtrain()
メソッドを追加してやれば普通に動きました(ただしこれは、TensorFlow1.5だったとき。tf.contrib.eager.Networkクラスを継承している。多分、正式にEagerモードがcontribから外れて、tf.keras.Modelで書けるようになった際に、何らかの便利機能が入っているはずです…多分)。
確率的なニューラルネットワーク
Edward2がTensorFlow probabiltyとしてTensorFlowの仲間入りしたことはご存知でしょうか。 Edwardは従来のTensorFlowをバックエンドに、確率モデリングとそのニューラルネットワークへの応用を支援するライブラリでした。
例えばGANのように乱数を用いるニューラルネットワークを容易に実装できたり、パラメータを確率変数として扱うようなベイジアンの記述も可能でした。
今回、TF probabilityとして確率推論系が(Edward2)含めTFに正式に加わったことで、どうやら正式にTFの特徴となっているEagerモードへの対応も進んでいる様子です(おそらく…?)
TensorFlow probabilityはまだnightlyとしてインストールができる状態であり、まだまだ正式リリースという段階ではなさそうですが、
以下のように、確率変数としてのパラメータを持つ層を提供するtfp.layers
なるものの存在と、それがEagerモードで動作することが報告されています。
class MNISTModel(tf.keras.Model): def __init__(self): super(MNISTModel, self).__init__() self.dense1 = tfp.layers.DenseFlipout(units=10) self.dense2 = tfp.layers.DenseFlipout(units=10) def call(self, input): """Run the model.""" result = self.dense1(input) result = self.dense2(result) # reuse variables from dense2 layer result = self.dense2(result) return result model = MNISTModel()
完全に、確率推論系もTensorFlowががっちり握り始めそうな雰囲気です。
ちなみにPyMC4もTensorFlowの肩に乗るとかなんとか…!