読者です 読者をやめる 読者になる 読者になる

MATHGRAM

主に数学とプログラミング、時々趣味について。

[Keras] backend functionを使いこなそう!

みなさん, keraってますか.

今回はloss関数やlayerの実装に欠かせない, backend functionをまとめていきます.

ただし自分が主に使ってる関数のみ紹介するので, 絶対Document読む方がいいですよ. これ以外にも色々ありますからね.

こいつを使いこなして, どんどんオリジナルのlayerなどを実装していきましょう!

インポート

まずバックエンド関数をインポートしましょう.

from keras import backend as K

# arrayを使うので, numpyもimportします.
import numpy as np

今回はこれだけしか使いません.
Kを使って自由にテンソルを扱っていきましょう!

numpy.arrayからテンソルを作る: K.variable

そもそもテンソルを用意しないと演算もくそもありません.

A = np.asarray([
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ])

B = np.asarray([
        [9, 8, 7],
        [6, 5, 4],
        [3, 2, 1]
    ])

こいつらをバックエンドで扱えるテンソルに変えるにはK.variableを使います.

A = K.variable(A)
B = K.variable(B)

これで準備オッケー. 今回Aくん, Bくんにはかなり働いてもらうよ.

テンソルの中身を見る: K.get_value, K.eval

テンソルの中身を確認したい. そんな時はK.get_value.

K.get_value(A)

出力

array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.],
       [ 7.,  8.,  9.]], dtype=float32)

K.evalも同じです.

和: +

要素ごとの足し算. 要素の合計ではないです. 気をつけて.
これは + 演算子オーバーロードされています.

K.get_value(A + B)

出力

array([[ 10.,  10.,  10.],
       [ 10.,  10.,  10.],
       [ 10.,  10.,  10.]], dtype=float32)

intやfloatも足せます.

K.get_value(A + 1)

出力

array([[  2.,   3.,   4.],
       [  5.,   6.,   7.],
       [  8.,   9.,  10.]], dtype=float32)

差: -

引き算も同じ, もちろんint, floatいけます.

K.get_value(A - B)

出力

array([[-8., -6., -4.],
       [-2.,  0.,  2.],
       [ 4.,  6.,  8.]], dtype=float32)

積: *

要素ごとに掛け算, 行列の積ではないので注意. int, floatもいけますよ.

K.get_value(A * B)

出力

array([[  9.,  16.,  21.],
       [ 24.,  25.,  24.],
       [ 21.,  16.,   9.]], dtype=float32)

商: /

要素ごとに割り算. int, floatもいけます.

K.get_value(A / B)

出力

array([[ 0.11111111,  0.25      ,  0.42857143],
       [ 0.66666669,  1.        ,  1.5       ],
       [ 2.33333325,  4.        ,  9.        ]], dtype=float32)

合計: K.sum

こっちが要素の合計.

K.get_value(K.sum(A))

出力

45.0

K.sumはテンソルを返すので, 合計をlossに足したい!なんて時はlossもテンソルとして扱うためK.sumだけで問題ないです.

※ intを足しても問題ないんですけどね

結構大事なのが, 軸を指定できる点.

画像を扱っていると, RGBのチャネルごとに何らかの操作をしたいときがありますしね.

行ごとの和

K.get_value(K.sum(A, axis=0))
array([ 12.,  15.,  18.], dtype=float32)

列ごとの和

K.get_value(K.sum(A, axis=1))
array([  6.,  15.,  24.], dtype=float32)

平均: K.mean

要素の平均. lossの実装でめっちゃ使う. まじでめっちゃ使う.

K.get_value(K.mean(A))

出力

5.0

こっちもテンソルを返す. またmeanもsum同様にaxisを設定できます.

行列積: K.dot

こっちが行列積

K.get_value(K.dot(A, B))

出力

array([[  30.,   24.,   18.],
       [  84.,   69.,   54.],
       [ 138.,  114.,   90.]], dtype=float32)

型の取得: K.int_shape

これは画像のshapeとって割る時とかに結構使う. ちなみにtensorflowでのみ動作します.
(つか悪いことは言わないからバックエンドはtensorfowを使え)

K.int_shape(A)

出力

(3, 3)

tuppleで返ってくるので注意.

要素の数を数える: K.count_params

明示的にint_shapeで受け取らなくても, 単に要素数を取ってくることもできる.

K.count_params(A)

出力

9

次元数の取得: K.ndim

次元の間違いがないよう, assertでエラー吐かせるために使ったりする.

K.ndim(A)

出力

2

np.zeros的なやつ: K.zeros

正直使ったことはないw 同様にK.onesK.eye(単位行列)もあるよ.

K.zeros((3,3))

出力

array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]], dtype=float32)

転置行列: K.transpose

K.transpose(A)

出力

array([[ 1.,  4.,  7.],
       [ 2.,  5.,  8.],
       [ 3.,  6.,  9.]], dtype=float32)

テンソルの欲しいところだけ集める: K.gataher

ここだけ欲しいって時に使う. 列指定はできないんじゃないかな. ちょっと確かなことわかってません.

K.get_value(K.gather(A, [0,2]))

出力

array([[ 1.,  2.,  3.],
       [ 7.,  8.,  9.]], dtype=float32)

reshape: K.reshape

np.reshapeはほんとよく使いますよね. Kでも一緒です.

K.get_value(K.reshape(A, (1,9)))

出力

array([[ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.]], dtype=float32)

要素のクリップ: K.clip

画像を扱う時はクリップも結構使うんじゃないでしょうか.
全ての値を設定した最小値と最大値以内に書き換えます.

K.get_value(K.clip(A, 2, 5))

出力

array([[ 2.,  2.,  3.],
       [ 4.,  5.,  5.],
       [ 5.,  5.,  5.]], dtype=float32)

要素を逆順に並べる: K.reverse

(追記: 2017/2/14)

K.reverse(x, axes=-1)

(batch, h, w, ch)のテンソルのRGBをBGRに変える時に使いました.

テンソルのslice

バックエンドとは関係ないですが, sliceは重要なので紹介しときます.

2行目のみ抽出する.

K.get_value(A[:,1])

出力

array([ 2.,  5.,  8.], dtype=float32)

(1,1)を指定する.

K.get_value(A[1,1])

出力

5.0

このように, 特に難しい操作は入らずにテンソルのsliceは可能です.

ほかの基本演算たち

sin, cos, exp, abs, logとか, まぁ有名な演算はもちろん全部あります. めんどいんで, 書きませんがこいつらは全部要素ごとです.

まとめ

今回はバックエンドの演算を中身を確認しながらまとめてみました.

lossの実装で必要なのは, 多分sumとmeanが主に使う関数じゃないでしょうか. あとはint_shapeとか結構使うかな.

これさえ扱えれば, Kerasの実装の幅は跳ね上がるので, Document見ながらbackendの使い方に慣れていきましょう. 僕も勉強中です!

以上です.