言語処理100本ノック 2020 (Rev2)の「第8章: ニューラルネット」の72本目「損失と勾配の計算」記録です。勾配計算はいつもkeras
に任せていたので、勾配の取得などしようと思ったこともなく、調べるのに時間がかかりました。本当は**keras
を使わずに、自分でコーディングすることこそが良い学習なのでしょうが、取り急ぎkeras
を使い続けます**。
記事「まとめ: 言語処理100本ノックで学べることと成果」に言語処理100本ノック 2015についてはまとめていますが、追加で差分の言語処理100本ノック 2020 (Rev2)についても更新します。
参考リンク
リンク | 備考 |
---|---|
72_損失と勾配の計算.ipynb | 回答プログラムのGitHubリンク |
言語処理100本ノック 2020 第8章: ニューラルネット | (PyTorchだけど)解き方の参考 |
【言語処理100本ノック 2020】第8章: ニューラルネット | (PyTorchだけど)解き方の参考 |
まとめ: 言語処理100本ノックで学べることと成果 | 言語処理100本ノックまとめ記事 |
公式ガイド: モデルに関する勾配 | 勾配取得の公式ガイド |
環境
後々GPUを使わないと厳しいので、Goolge Colaboratory使いました。Pythonやそのパッケージでより新しいバージョンありますが、新機能使っていないので、プリインストールされているものをそのまま使っています。
種類 | バージョン | 内容 |
---|---|---|
Python | 3.7.12 | Google Colaboratoryのバージョン |
2.0.3 | Google Driveのマウントに使用 | |
tensorflow | 2.6.0 | ディープラーニングの主要処理 |
第8章: ニューラルネット
学習内容
深層学習フレームワークの使い方を学び,ニューラルネットワークに基づくカテゴリ分類を実装します.
ノック内容
第6章で取り組んだニュース記事のカテゴリ分類を題材として,ニューラルネットワークでカテゴリ分類モデルを実装する.なお,この章ではPyTorch, TensorFlow, Chainerなどの機械学習プラットフォームを活用せよ.
72. 損失と勾配の計算
学習データの事例$x_1$と事例集合$x_1$,$x_2$,$x_3$,$x_4$に対して,クロスエントロピー損失と,行列$W$に対する勾配を計算せよ.なお,ある事例$x_i$に対して損失は次式で計算される.
$$l_i=−log[事例x_iがy_iに分類される確率]$$
ただし,事例集合に対するクロスエントロピー損失は,その集合に含まれる各事例の損失の平均とする.
回答
回答結果
これ見ても何も判断できないですが、一応回答結果です。1行目がLossで、行列部分が勾配。
1.3719598
dense_1/kernel:0, shape: (300, 4)
[[-0.06244335 0.02067989 0.02176488 0.01999857]
[-0.00420518 0.00139266 0.00146573 0.00134678]
[-0.00508651 0.00168454 0.00177292 0.00162904]
...
[-0.05607251 0.01857001 0.0195443 0.0179582 ]
[-0.03232378 0.01070494 0.01126659 0.01035225]
[ 0.06478423 -0.02145514 -0.02258081 -0.02074828]]
1.3873249
dense_1/kernel:0, shape: (300, 4)
[[-0.05536687 0.00082223 0.08464365 -0.03009901]
[ 0.01126796 -0.01080388 -0.03230093 0.03183684]
[-0.03271427 0.06947812 -0.0883422 0.05157837]
...
[-0.09661584 0.08457799 -0.00822031 0.02025817]
[-0.00410734 0.08742411 0.00315564 -0.08647241]
[ 0.07903252 0.00211453 0.01354344 -0.09469048]]
回答プログラム 72_損失と勾配の計算.ipynb
GitHubには確認用コードも含めていますが、ここには必要なものだけ載せています。
import tensorflow as tf
from google.colab import drive
drive.mount('/content/drive')
BASE_PATH = '/content/drive/MyDrive/ColabNotebooks/ML/NLP100_2020/08.NeuralNetworks/'
train_raw = tf.data.TFRecordDataset(BASE_PATH+'train.tfrecord')
def _parse_function(example_proto):
# 特徴の記述
feature_description = {
'title': tf.io.FixedLenFeature([], tf.string),
'category': tf.io.FixedLenFeature([], tf.string)}
# 上記の記述を使って入力の tf.Example を処理
features = tf.io.parse_single_example(example_proto, feature_description)
X = tf.io.decode_raw(features['title'], tf.float32)
y = tf.io.decode_raw(features['category'], tf.int32)
return X, y
dense_layer = tf.keras.layers.Dense(
4,
activation='softmax',
input_dim=300,
use_bias=False,
kernel_initializer='random_uniform')
def print_loss_gradients(batch_size):
for X, y_true in train_raw.map(_parse_function).batch(batch_size).take(1):
print('---y_true---')
print(y_true.numpy())
with tf.GradientTape() as tape:
y_pred = dense_layer(X)
print('---y_pred---')
print(y_pred.numpy())
loss = tf.keras.losses.categorical_crossentropy(y_true, y_pred)
print('---loss---')
print(tf.math.reduce_sum((loss.numpy()/batch_size)).numpy())
grad = tape.gradient(loss, dense_layer.trainable_variables)
for var, g in zip(dense_layer.trainable_variables, grad):
print(f'{var.name}, shape: {g.shape}')
print(g.numpy())
print_loss_gradients(1)
print_loss_gradients(4)
回答解説
勾配の記録
GradientTape
を使って勾配を記録します。with
内で記録するための計算を書きます。
with tf.GradientTape() as tape:
y_pred = dense_layer(X)
print('---y_pred---')
print(y_pred.numpy())
loss = tf.keras.losses.categorical_crossentropy(y_true, y_pred)
print('---loss---')
print(tf.math.reduce_sum((loss.numpy()/batch_size)).numpy())
gradient
関数で勾配を入出力を渡して取得します。
grad = tape.gradient(loss, dense_layer.trainable_variables)
今回はバイアス項がないのでfor
でまわしても1件しか取得出来ませんが、バイアス項があると複数回ループして取得できます。
for var, g in zip(dense_layer.trainable_variables, grad):
print(f'{var.name}, shape: {g.shape}')
print(g.numpy())
1件のみ取得するとこんな出力です。
---y_true---
[[1 0 0 0]]
---y_pred---
[[0.25360948 0.24718848 0.2601575 0.23904456]]
---loss---
1.3719598
dense_1/kernel:0, shape: (300, 4)
[[-0.06244335 0.02067989 0.02176488 0.01999857]
[-0.00420518 0.00139266 0.00146573 0.00134678]
[-0.00508651 0.00168454 0.00177292 0.00162904]
...
[-0.05607251 0.01857001 0.0195443 0.0179582 ]
[-0.03232378 0.01070494 0.01126659 0.01035225]
[ 0.06478423 -0.02145514 -0.02258081 -0.02074828]]