1
2

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 5 years have passed since last update.

TensorFlow 2.x の Low-level API を使って多項式近似を求める

Posted at

はじめに

中井悦司著の『TensorFlowとKerasで動かしながら学ぶ ディープラーニングの仕組み ~畳み込みニューラルネットワーク徹底解説~』の勉強メモです。

この書籍の第1章では、TensorFlow の Low-level API を使って、最小2乗法による多項式近似曲線を求める内容を扱っています。ただ、そこに掲載されているコードが TensorFlow 1.x 対応版だったので、それを TensorFlow 2.x 対応に書き直してみました(なお、同書籍の第2章以降は、TF 2.x 対応のコードになっています)。

書籍に掲載の TensorFlow 1.x 対応のコードは、著者のGitHub(https://github.com/enakai00/colab_tfbook/tree/tf2.0/Chapter01)から確認できます。

実行環境には、Google Colab. を利用しました。

TF Low-level API を使ってやりたいこと

次のように、月別の平均気温が与えられているとき、月を変数 $x$ とした 4次の多項式近似曲線のパラメータ($w_0,w_1,w_2,w_3,w_4$)を数値的に求めるという内容です。

$$ f(x) = w_0 + w_1x + w_2x^2 + w_3x^3 + w_4x^4 $$

fig.png

temp = [5.2, 5.7, 8.6, 14.9, 18.2, 20.4, 25.5, 26.4, 22.8, 17.5, 11.1, 6.6]

サンプルコードを、そのまま TF 2.x 環境で実行してみる。失敗。

案外、そのままでも動くんじゃないかと思って、上記のコードをコピーして、Google Colab. の TF 2.x 環境で実行してみました。

その結果、次のようなエラーが発生。

x = tf.placeholder(tf.float32, [None, 5])
AttributeError: module 'tensorflow' has no attribute 'placeholder'

上記のエラーをヒントに色々と試行錯誤しましたが、ちょっとした改変では対応できそうもない、という結論になりました。

TF 2.x にあわせて大幅に書き替え

書き替えは、TF公式の こちら のコードを参考にしました。Low-level API を使って・・・がコンセプトなのですが Keras が含まれてしまいました。

GoogleColab.でTF2.xに切り替えるマジックコマンド
%tensorflow_version 2.x
4次の近似曲線のパラメータを求める
import tensorflow as tf
import numpy as np

# f(x) = w0 + w1*x + w2*x^2 + w3*x^3 + w4*x^4 
class Model(tf.keras.Model):
  def __init__(self):
    super(Model, self).__init__()
    self.w = tf.Variable(tf.zeros([5, 1]), name='w') # w0,w1,..,w4
  def call(self, inputs):
    return tf.matmul(inputs, self.w)

# トレーニングデータ(入力)
train_x  = np.array([[mon**n for n in range(0, 5)] for mon in range(1, 13)])
train_x =train_x.astype(np.float32)
# print(train_x.shape) # 実行結果 -> (12,5)

# トレーニングデータ(正解値)
train_t = np.array([5.2, 5.7, 8.6, 14.9, 18.2, 20.4, 25.5, 26.4, 22.8, 17.5, 11.1, 6.6])
train_t =train_t.reshape([12, 1]) 
# print(train_t.shape) # 実行結果 -> (12, 1)

# 損失関数(誤差の2乗和)
loss = lambda model, x, t : tf.reduce_sum(tf.square(model(x)-t))

# 傾きを計算
def grad(model, x, t):
  with tf.GradientTape() as tape:
    loss_value = loss(model, x, t)
  return tape.gradient(loss_value, [model.w])

model = Model()
optimizer = tf.keras.optimizers.Adam()

# 学習ループ
print(f'Initial Loss: {loss(model, train_x, train_t):.5f}')
i = 0
for _ in range(10000):
  i += 1
  grads = grad(model, train_x, train_t)
  optimizer.apply_gradients(zip(grads, [model.w]))
  if i % 1000 == 0:
    print (f'Step: {i}, Loss: {loss(model, train_x, train_t):.5f}')

print(f'Final loss: {loss(model, train_x, train_t):.5f}')
print(f'w = {model.w.numpy()}')
実行結果
Initial Loss: 3442.96973
Step: 1000, Loss: 206.62106
Step: 2000, Loss: 107.81633
Step: 3000, Loss: 53.71612
Step: 4000, Loss: 37.42331
Step: 5000, Loss: 33.97096
Step: 6000, Loss: 33.05221
Step: 7000, Loss: 32.35994
Step: 8000, Loss: 31.79436
Step: 9000, Loss: 31.35630
Step: 10000, Loss: 31.01644
Final loss: 31.01644
w = [[ 1.3081207e+00]
 [ 1.4444064e+00]
 [ 8.0244839e-01]
 [-8.5857309e-02]
 [ 9.1365178e-04]]

求められたパラメータ $w$ を使って近似曲線を描きます。

近似曲線付きのグラフを描く
import japanize_matplotlib
import matplotlib.pyplot as plt

w = model.w.numpy().flatten()
predict = lambda x : np.dot(np.array([x**n for n in range(0, 5)]),w)

plt.figure(dpi=96)
plt.scatter(range(1, 13), train_t)
xs = np.linspace(1, 12, 100)
ys = [ predict(x) for x in xs ]
plt.plot(xs, ys)
plt.xlim(1, 12)
plt.xticks(range(1, 13))
plt.xlabel('Month')
plt.ylabel('気温(℃)')

ダウンロード.png

問題点

  • こちらの TF 1.x 対応のコードよりも、実行速度が遅い。時間がかかる。
1
2
0

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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?