1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Tensorflowの自動微分を使用したfitting

1
Last updated at Posted at 2022-02-27

目的

今更だけどtensorflow2.0あんま使ったことなかったのでお試しにいくつかやっていく予定。1.~と比較してnumpyの値がそのまま使用できたりSessionが無くなったり結構pytorchっぽくなった模様。

本記事では簡単な

y = 2x + 1

回帰の重みw = 2, b = 1を自動微分によってfittingする

事前準備

以下のパッケージが必要

  • tensorflow (2.0以上)
  • matplotlib
  • numpy (多分tensorflowが入れば自動で入る)

データ作成

y = 2x + 1にちょこっとノイズを加えたdataset_y, dataset_yを作成する。

n_sample = 100
dataset_x = np.random.rand(n_sample)
dataset_y = 2 * dataset_x + 1 + np.random.normal(0, 0.05, n_sample) # ちょこっとノイズ加える

plot結果はこんな感じ

dataset.png

目的関数(重みパラメーター)の作成

傾きw, 切片bを定義。初期値はとりあえず0でいい。

w = tf.Variable(np.zeros([1,1])) 
b = tf.Variable(np.zeros([1,1])) 

これで入力xに対して目的関数を

y = w * x * b

で計算できる。pytorchと同じように普通に変数っぽく扱えてtensorの中身を確認できるのはめっちゃ便利になってる。

自動微分の計算

目的関数の傾きと切片を計算するためには計算したy(y = w * x + b)と真の値(datset_y)の誤差が最小になるようなw, bを探せば良いので

w, b = argmin (y_{dataset}- w \times x_{dataset} + b )^2

となれば良い。

loss = (y_{dataset}- w \times x_{dataset} + b )^2 

に対して以下の微分

\frac{\delta loss }{\delta w} \\
\frac{\delta loss }{\delta b} \\

を計算して、lossが小さくなるようにw, bを更新していけば良い。

tensorflowでは自動微分ようにtf.GradientTapeというモジュールがある。
公式のドキュメントはここtf.GradientTape

今回は上記のlossに対しての微分なのでコードは以下のようになる

x = tf.constant(dataset_x)
with tf.GradientTape() as t:
    t.watch(x) # tf.constantはwatachが必要らしい
    y = w * x + b # object function
    loss = tf.reduce_sum(tf.multiply(y - dataset_y, y - dataset_y)) # loss function
# 元の入力テンソル w, b に対する loss の微分
dloss_dparams = t.gradient(loss, [w, b]) # 自動微分
w = tf.Variable(tf.subtract(w, dloss_dparams[0] * 0.001)) # 値の更新
b = tf.Variable(tf.subtract(b, dloss_dparams[1] * 0.001)) # 値の更新

x, bに対する微分は同時にやってくれるっぽい。t.gradientの結果は普通にlistで微分結果のtensorが入っていた。
x = tf.constant(dataset_x)はdataset_xはnumpy.arrayなのでtf.GradientTapeで扱えるようにtf.constantに変換した。

※せっかくtf.Variableはmutableなのにミュータブルっぽくない書き方になってしまっている。そもそもtf.subtractはtf.Tensorを返すので上記のコードのように重みを更新する際は使用しないっぽい。

実際の重みパラメーターの更新はtensorflowでは普通はtf.optimizerを使用するので後述する。

learning_rate = 0.001で100回学習したコードはこちら

w = tf.Variable(np.zeros([1,1])) 
b = tf.Variable(np.zeros([1,1])) 
x = tf.constant(dataset_x)
loss_log = [] # lossの推移記録用
n_step = 100 # 学習回数
for i in range(n_step):
    with tf.GradientTape() as t:
        t.watch(x) # tf.constantはwatachが必要らしい
        y = w * x + b # object function
        loss = tf.reduce_sum(tf.multiply(y - dataset_y, y - dataset_y)) # loss function
    # 元の入力テンソル w, b に対する loss の微分
    dloss_dparams = t.gradient(loss, [w, b]) # 自動微分
    w = tf.Variable(tf.subtract(w, dloss_dparams[0] * 0.001)) # 値の更新
    b = tf.Variable(tf.subtract(b, dloss_dparams[1] * 0.001)) # 値の更新
    loss_log.append(loss)
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?