External Memory

プログラミング周辺知識の備忘録メイン

TensorFlowの機械学習を利用した擬似星の等級の計算

Tensorflowの使い方と深層学習(というより機械学習)の勉強の導入として、
単純モデルを利用したプログラムを作った。
参考にしたのは以下TensorFlowホームページのGET STARTEDページ
Getting Started  |  TensorFlow



今回題材として用いたのは星の等級の計算。
星の明るさはよく一等星、二等星など等級で表されるが、
絶対等級Mと観測者からの距離d(パーセク)から
以下の式で見かけの等級mを見積もることができる。

M = m + 5 - 5 * log10(d) (wikipediaより)

十分なサンプルデータを見つけることができなかったので、
ランダムにデータを生成して、TensorFlowに学習させた。

単純モデルの学習過程は大体以下の通りである。

  • データ値にテンソルで重みをつけ、バイアスと組み合わせて特徴量とする。
  • softmax関数などで特徴量を際立たせる。
  • 正答と予測回答との誤差関数を設定する。(クロスエントロピーなど)
  • 誤差関数を最小にするようにオプティマイズする。(訓練)

プログラム

# -*- coding: utf-8 -*-

import tensorflow as tf
import math
import random

N = 5000
R = 9 #label Range
times = 1000 # times of training         
                 
#absolute magnitude
abmlist = [random.uniform(0,1) for i in range(N)] 

#distance
#d_list = [random.uniform(0.001,1) for i in range(N)] 
d_list = [random.uniform(0.1,1) for i in range(N)]

#factor = [0.1 for i in range(N)] 

#apparent magnitude(答え合わせ用リスト)
apmlist = [ [0 for i in range(R)] for j in range(N)]

for i in range(N):
    #星の等級式 apm = abm + 5 * log(distance)- 5 
    #リストインデクス値を非負整数にするため小数点を丸めて定数を加えてlabel作成
    #apmlist[i][round(abmlist[i] * 15 - 5 + 5 * math.log10(d_list[i] * 100) - 5) + 15] = 1 #R = 31
    apmlist[i][round(abmlist[i] * 3 + 5 * math.log10(d_list[i] * 10))] = 1 #R = 9
    

x = tf.placeholder(tf.float32,[None,2])
W = tf.Variable(tf.zeros([2,R]))

"""
x = tf.placeholder(tf.float32,[None,3])
W = tf.Variable(tf.zeros([3,R]))
"""
b = tf.Variable(tf.zeros([R]))
y = tf.matmul(x,W) + b

y_ = tf.placeholder(tf.float32,[None,R])


cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels = y_,logits = y))
train_step = tf.train.GradientDescentOptimizer(7.0).minimize(cross_entropy) 
#train_step = tf.train.AdagradOptimizer(150).minimize(cross_entropy)

sess = tf.InteractiveSession()
tf.global_variables_initializer().run()

for i in range(times):
    sess.run(train_step,feed_dict={x:[[i,j] for (i,j) in zip(abmlist[:-500],d_list[:-500])],y_:apmlist[:-500]})
    
correct_prediction = tf.equal(tf.arg_max(y,1),tf.arg_max(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
testlist = [[i,j] for (i,j) in zip(abmlist[-500:],d_list[-500:])]
labellist = apmlist[-500:]

"""
for i in range(times):
    sess.run(train_step,feed_dict={x:[[i,j,k] for (i,j,k) in zip(abmlist[:-500],d_list[:-500],factor[:-500])],y_:apmlist[:-500]})
    
correct_prediction = tf.equal(tf.arg_max(y,1),tf.arg_max(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
testlist = [[i,j,k] for (i,j,k) in zip(abmlist[-500:],d_list[-500:],factor[-500:])]
labellist = apmlist[-500:]
"""

print(sess.run(accuracy,feed_dict={x:testlist,y_:labellist}))

結果

大まかな正答率は以下である。

・0.33 ± 0.03  (R=31
・0.75 ± 0.03  (R=9
・0.76 ± 0.01  (R=9 データ種類増 補正値導入
・0.885 ± 0.005 (R=9 optimaizer引数 0.5→7.0
・0.885 ± 0.010  (R=9 optimaizer adamgrad利用 引数150
・0.83 ± 0.02  (R=9 train回数1000→5000変更

単純モデルからか、正答率は最良でも89%程度であり良い結果ではなかったが、
一応学習はされているようではある。

labelの次元数(値域)で正答率がかなり違ってくるようで、
正確さを求めるなら定義域と値域には気を使わないといけない。

単に確率として考えても選択肢の数から
正答率が上がるのは当然ともいえるかもしれない。

いろいろいじってみて、良好な結果を得るには

  • データ数
  • 訓練回数
  • label数

辺りのパラメータををうまくバランスとれるように設定しないといけない。
単に訓練回数やデータ数を多くしてもうまくいかない。

また、今回はランダムデータを用いて学習させたが
この学習が実際のデータではうまくいかない可能性もある。


アルゴリズムやモデルについての知識がまだまだ甘い。
機械学習ならSVCのほうが正答率が良かったかもしれない。
CNNに関しても試してみる。


プログラムを書くにあたってエディタはspyderを利用した。

>conda install -n tensorflow spyder
>activate tensorflow
>spyder