2021年7月10日土曜日

TensorFlow2(5)3分類ニューラルネットについて

TensorFlowしよう!
機械学習ビギナーの皆さんこんにちは.

「TensorFlow2プログラミング実装ハンドブック」第4章のsample programを眺めているところです.3つの山を認識してRGBに分類するニューラルネットです.
前回の2分類ニューラルネットと似た者ですが、大きく違うのは出力関数です.
出力関数にはいろいろありますが、いずれにも共通した特性は、ー∞~+∞までの入力を受け入れて、出力を0~1に圧縮するところです.
2分類ニューラルの出力関数はシグモイドという奴でした.シグモイドはこんな特性です.出力の0.5を境界に赤か青かの意味を持たせました.
3分類ニューラルネットの出力もシグモイド特性ですが、違うのはRGBの3本出てきます.そいつの出方がミソでして、
  {R,G,B}={0.7, 0.2, 0.1}       ←Rである可能性が高い
このように合計1に正規化されたRGBの確率で出てきます.「合計1に正規化された確率ベクトル」を出す関数をソフトマックスと呼びます.
2分類ニューラルネットと3分類ニューラルネットの違いは以上かな.
つまり、
 1)出力が1本→3本になる
 2)終段の出力関数がシグモイド→ソフトマックスになる
 3)重みWの個数が少し増える

ーーーー
TensorFlow2のsource codeは、キモの部分だけ抜粋するとこんな感じです.それなりに手順を踏んでる様子がわかると思います.
①ニューラルネットの定義
class MLP(tf.keras.Model):
    def __init__(self, hidden_dim, output_dim):
        super().__init__()
        self.l1 = tf.keras.layers.Dense(hidden_dim, activation='sigmoid')
        self.l2 = tf.keras.layers.Dense(output_dim, activation='softmax')
    def call(self, x):
        h = self.l1(x) 
        y = self.l2(h)
        return y
②損失関数の定義
cce = tf.keras.losses.CategoricalCrossentropy()
def loss(t, y):
    return cce(t, y)
③学習ルーチンの定義
def train_step(x, t):
    with tf.GradientTape() as tape:
        outputs = model(x)
        tmp_loss = loss(t, outputs)
    grads = tape.gradient( tmp_loss, model.trainable_variables)
    optimizer.apply_gradients(zip(grads, model.trainable_variables))
    train_loss(tmp_loss)
    return tmp_loss
④メインルーチン
model = MLP(2, 3)
for epoch in range(epochs):
    for step in range(steps):
        tmp_loss = train_step(x_[start:end], t_[start:end])

ところが、Kerasで同じニューラルネットを記述するとこんなに短くて済みます.KerasはTensorFlow2を簡単に使うラッパーです.
①ニューラルネット定義
model = Sequential()
model.add(Dense(2, activation='sigmoid'))
model.add(Dense(3, activation='softmax'))
②損失関数と学習ルーチンの定義
optimizer = optimizers.SGD(learning_rate=0.1)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
③メインルーチン
history = model.fit( x, t, epochs=epoch, batch_size=batch_size, verbose=1, validation_split=0.2 )

なるほどKerasは便利だと評判になるわけですね.ニューラルネットの定義は階層の次数と階層の出力関数で決まる(らしい)ので、この2行で済んでしまうのはさもありなんです.
model.add(Dense(2, activation='sigmoid'))
model.add(Dense(3, activation='softmax'))

というわけで、ここまでで機械学習についてわたしが知り得たことは、、、
・Kerasは便利でいいや
・ニューラルネット構造を定義すればほぼ完了
・自動微分やバックプロパゲーションのprogrammingの必要なし
・教師データを食わせれば学習完了

かしこ

0 件のコメント:

コメントを投稿