oikakerublogの日記

知識ゼロから色々しらべてみた話し

Tensorflow 身長・体重・BMIの学習(ソシム本、218ページ)

# 2017-5-21 ソシム スクレイピング本
# 218ページ〜 BMI計算、CSVファイル
# 予め用意したCSVファイルを使って、BMI分類を学習
# 交差エントロピ、ソフトマックス、勾配法

import pandas as pd
import numpy as np
import tensorflow as tf

# 身長,体重,ラベルのCSVデータを読み出す 
# pandas でCSVファイル読み出し
csv = pd.read_csv("bmi.csv")

# データを正規化 、0〜1に
csv["height"] = csv["height"] / 200
csv["weight"] = csv["weight"] / 100

# ラベルを三次元のクラスで表す --- (※3)
# 痩せ、普通、肥満を3つの三次元クラスデータで表す
# thin=(1,0,0) / normal=(0,1,0) / fat=(0,0,1)

bclass = {"thin": [1,0,0], "normal": [0,1,0], "fat": [0,0,1]}
csv["label_pat"] = csv["label"].apply(lambda x : np.array(bclass[x]))

# 正解率を求めるためにテストデータを準備 
# 2万件のうち末尾5000件をテストデータにする

test_csv = csv[15000:20000]
test_pat = test_csv[["weight","height"]]
test_ans = list(test_csv["label_pat"])

# データフローグラフを構築する
# データを入れるプレースホルダを宣言

x  = tf.placeholder(tf.float32, [None, 2]) # 身長,体重のデータを入れる
y_ = tf.placeholder(tf.float32, [None, 3]) # 答えのラベルを入れる

# 変数を宣言 --- (※6)
W = tf.Variable(tf.zeros([2, 3])); # 重み
b = tf.Variable(tf.zeros([3])); # バイアス

# ソフトマックス回帰を定義 
# y=softmax(Wb+b)
y = tf.nn.softmax(tf.matmul(x, W) + b)

# モデルを訓練する
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))

# 降下法でWやbを学習する、tfに用意されているもの
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(cross_entropy)

# 正解率を求める
# 誤差関数:交差エントロピー
# SummaryWriter

predict = tf.equal(tf.argmax(y, 1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(predict, tf.float32))

# セッションを開始
sess = tf.Session()
sess.run(tf.global_variables_initializer()) #変数を初期化

# テストデータを用いて学習させる、100件ずつ3500回学習
# 最初30%くらいの正解率が、95%くらいまで向上

print("- トレーニング中 -")

for step in range(3500):
    i = (step * 100) % 14000
    rows = csv[1 + i : 1 + i + 100]
    x_pat = rows[["weight","height"]]
    y_ans = list(rows["label_pat"])
    fd = {x: x_pat, y_: y_ans}
    sess.run(train, feed_dict=fd)
    if step % 500 == 0:
        cre = sess.run(cross_entropy, feed_dict=fd)
        acc = sess.run(accuracy, feed_dict={x: test_pat, y_: test_ans})
    
        print("step=", step, "cre=", cre, "acc=", acc)

# =>
- トレーニング中 -
step= 0 cre= 109.101 acc= 0.3084
step= 500 cre= 52.4673 acc= 0.8688
step= 1000 cre= 46.4283 acc= 0.9226
step= 1500 cre= 38.8364 acc= 0.9472
step= 2000 cre= 35.4385 acc= 0.9588
step= 2500 cre= 31.0386 acc= 0.9494
step= 3000 cre= 31.2941 acc= 0.9532

# 最終的な正解率を求める

acc = sess.run(accuracy, feed_dict={x: test_pat, y_: test_ans})

print("正解率=", acc)
# =>
正解率= 0.966