(2018-02-19 初稿 - 2021-05-21 転記・修正)
はじめに
Raspberry Pi 3(以下、ラズパイ)を購入してから、python や tensorflow を使って、ディープラーニングのことを学んでいる。
ちなみに、筆者は、ディープラーニングのことも、pythonのことも、まったくの素人なので、以下の記述は参考までに。
なお、tensorflowのラズパイへのインストールは以下のページを参照のこと。
さて、tensorflowをgoogleから頂いて来て、MNIST dataでmnist_softmax.pyを実行して、文字認識のテストをしたまでは良かったが、実際何をやっているのか筆者にはまったく理解できなかった。とほほ。(^_^;)
まずは、理解しやすい内容を実行しようと思い、回帰分析を実行してみた。
このページでは、tensorflowを用いた回帰分析について記述する。
なお、このページを記述するにあたり、以下のサイトを参照させていただいた。多謝
1次回帰
まずは、上記サイトの1次回帰のスクリプトを実行してみる。
# coding:utf-8 import tensorflow as tf # y = 2x + 1 input_x = [[0.],[1.]] input_y = [[1.],[3.]] x = tf.placeholder("float", [None, 1]) y_ = tf.placeholder("float", [None, 1]) a = tf.Variable([1.], name="slope") # 初期値 a = 1 b = tf.Variable([0.], name="y-intercept") # 初期値 b = 0 y = tf.multiply(a,x) + b init = tf.global_variables_initializer() # 誤差関数 loss = tf.reduce_sum(tf.square(y_ - y)) # トレーニング方法は、勾配降下法を選択 train_step = tf.train.GradientDescentOptimizer(0.03).minimize(loss) with tf.Session() as sess: sess.run(init) print("初期状態") print('誤差' + str(sess.run(loss, feed_dict={x: input_x, y_: input_y}))) print("slope: %f, y-intercept: %f" % (sess.run(a), sess.run(b))) for step in range(200): sess.run(train_step, feed_dict={x: input_x, y_: input_y}) if (step+1) % 20 == 0: print('\nStep: %s' % (step+1)) print('誤差' + str(sess.run(loss, feed_dict={x: input_x, y_: input_y}))) print("slope: %f, y-intercept: %f" % (sess.run(a), sess.run(b)))
実行結果は以下のとおり。
(tflow) $ python 1kaiki.py 初期状態 誤差5.0 slope: 1.000000, y-intercept: 0.000000 Step: 20 誤差0.02128378 slope: 1.802436, y-intercept: 1.069051 (中略) Step: 200 誤差3.7843301e-06 slope: 1.997323, y-intercept: 1.001655
正解は、y=2x+1 の式だが、200回のステップで、正解の値までかなり近づくことがわかった。
2次回帰
1次回帰については、なんとかできるようになったので、2次回帰に挑戦してみる。前回のリストから、値の部分と、計算式の部分が異なるだけ。
【List 2-1】
# coding:utf-8 import tensorflow as tf input_x = [[-1.],[0.],[2]] input_y = [[3.],[1.],[9]] x = tf.placeholder("float", [None, 1]) y_ = tf.placeholder("float", [None, 1]) a = tf.Variable([1.], name="slope") b = tf.Variable([0.], name="y-intercept") y = tf.multiply(a,x**2) + b # y = 2 x^2 + 1 init = tf.global_variables_initializer() # 誤差関数 loss = tf.reduce_sum(tf.square(y_ - y)) # トレーニング方法は、勾配降下法を選択 train_step = tf.train.GradientDescentOptimizer(0.03).minimize(loss) with tf.Session() as sess: sess.run(init) print("初期状態") print('誤差' + str(sess.run(loss, feed_dict={x: input_x, y_: input_y}))) print("slope: %f, y-intercept: %f" % (sess.run(a), sess.run(b))) for step in range(200): sess.run(train_step, feed_dict={x: input_x, y_: input_y}) if (step+1) % 20 == 0: print('\nStep: %s' % (step+1)) print('誤差' + str(sess.run(loss, feed_dict={x: input_x, y_: input_y}))) print("slope: %f, y-intercept: %f" % (sess.run(a), sess.run(b)))
実行結果は以下のとおり。
(tflow) @ ~/tflow$ python 2kaiki_list2-1.py 初期状態 誤差30.0 slope: 1.000000, y-intercept: 0.000000 Step: 20 誤差0.017613236 slope: 2.034258, y-intercept: 0.893097 (中略) Step: 160 誤差1.1404211e-12 slope: 2.000000, y-intercept: 1.000000
なんと、160ステップでほぼ正解に辿りついた。
もう少し実用的な回帰分析ができないと、tensorflowを使う意味がないね。
そこで、ネットで検索して、年と総農家個数の表を見つけたので、以下のとおりデータファイルを作成した。 毎回、データを打ち込むのって大変だからね。
# test data 年(年-1900/10)と総農家戸数(1/1000) 6.0,2.078 6.5,1.219 7.0,0.831 7.5,0.616 8.0,0.623 8.5,0.626 9.0,0.498 9.5,0.473
注意点としては、あまり大きな数字だと、nanとエラーが出るので、年については (年 - 1900)/10、総農家戸数は1/1000に値を小さくしている。
さっそく、データファイルから読み込むスクリプトを作成。
【List 2-2】
# coding:utf-8 import tensorflow as tf import sys args = sys.argv # コマンドライン引数を取得 if len(args) == 1: # 引数がなかったら fname = "./data.csv" # data.csv を読む else: # 引数があったら fname = args[1] # ファイルを指定 input_x = [] input_y = [] f = open(fname) for line in f.readlines(): if line[0] == '#': # データファイルのコメントスキップ continue line = line.split(',') # カンマで分けて読み込む input_x.append([float(line[0])]) input_y.append([float(line[1])]) x = tf.placeholder("float", [None, 1]) y_ = tf.placeholder("float", [None, 1]) a = tf.Variable([1.], name="slope") b = tf.Variable([0.], name="y-intercept") y = tf.multiply(a,1/tf.sqrt(x)) + b # y = a / sqrt(x) + b に近い init = tf.global_variables_initializer() # 誤差関数 loss = tf.reduce_sum(tf.square(y_ - y)) # トレーニング方法は、勾配降下法を選択 train_step = tf.train.GradientDescentOptimizer(0.03).minimize(loss) with tf.Session() as sess: sess.run(init) print("初期状態") print('誤差' + str(sess.run(loss, feed_dict={x: input_x, y_: input_y}))) print("slope: %f, y-intercept: %f" % (sess.run(a), sess.run(b))) for step in range(400): sess.run(train_step, feed_dict={x: input_x, y_: input_y}) if (step+1) % 20 == 0: print('\nStep: %s' % (step+1)) print('誤差' + str(sess.run(loss, feed_dict={x: input_x, y_: input_y}))) print("slope: %f, y-intercept: %f" % (sess.run(a), sess.run(b)))
実行結果は以下のとおり。
(tflow) @ ~/tflow$ python 2kaiki_list2-2.py 初期状態 誤差3.94166 slope: 1.000000, y-intercept: 0.000000 Step: 20 誤差1.8281436 slope: 1.259537, y-intercept: 0.417840 (中略) Step: 400 誤差1.5395262 slope: 2.963965, y-intercept: -0.199980
400ステップで、誤差は大分小さくなったが、y = a / sqrt(x) + b の式に適合しているかは、検定しないとわからないが、近いような気もする。(^_^;)
おわりに
今回は、2次回帰までのスクリプトを作ったが、本来ならばディープラーニングで、入力した式も自ら推定しながら解析して欲しいよね。
自ら解析しながら、式を作っていく方法については、以下に示すので参考に。^^;
また、何かわかったら、追記するね。