8
13

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を使ってIoTデータを人工知能してみる - 練習

Last updated at Posted at 2016-11-06

TensorFlowを使ってIoTデータを人工知能してみるの練習用に、学習と判定を繰り返し行えるよう、それぞれ別のportを開けてPOSTできるようにしました。また練習用にFisherのiris data setを使用します。

1. TensorFlowを準備します

  1. BluemixのDockerコンテナ環境にTensorFlowをインストールするを参照し、Bluemix環境にTensorFlowを準備します

  2. 「デプロイ」ステージを構成するステップで、portとして、8888以外に、6006,9000,9001も開けておくようにします
    スクリーンショット 2016-11-07 8.56.54.png

  3. ビルド⇨デプロイが完了すると下記のような画面が表示されます。デプロイの「最終実行の結果」欄に表示される外向け(パブリック)IPアドレスを確認します
    161111_white_page.jpg

  4. Bluemixのダッシュボードから、デプロイされたDockerコンテナーを開き、パブリックIPアドレス(前項と同じ)とプライベートIPアドレスを確認します
    161111_white_page3.jpeg

  5. Chromeなどのブラウザで上記のパブリックIPアドレスの8888ポートへアクセスします。画面右上の「New」プルダウンメニューから「Terminal」でターミナル画面を開きます。
    スクリーンショット 2016-11-11 12.13.18.png

  6. このページでご紹介しているサンプルを実行するため、表示されたターミナル画面でflaskとpandasをインストールします。flaskはpip istall flaskなどで、pandasはpip install pandasなどでインストール可能です
    スクリーンショット 2016-11-11 12.16.17.png

  7. 画面右上の「New」プルダウンメニューから新しいフォルダーを作成し、適当な名前にrenameしておきます
    スクリーンショット 2016-11-11 12.18.30.png

  8. 続いて作成したフォルダー内に入り、同様に画面右上の「New」プルダウンメニューからText Fileを作成し、このページの下記のセクションにあるサンプルのpythonプログラムをコピペしていきます

2. サンプルを準備します

  • 用意したTensorFlow環境に下記のソースを配置します。
  • model.pyでモデルを定義します
    • 隠れ層2でそれぞれ32、16個のReLuで構成しています
    • COLUMN_SIZEに対象にするデータの項目数を指定します。iris data setでは、'Sepal Length', 'Sepal Width', 'Petal Length', 'Petal Width'を対象にしています
    • actual_classに判定に使用する目的変数の項目数を指定します。iris data setでは setosa = 0, versicolor = 1, virginica = 2の3個の値を使用しています
    • ここではGradientDescentOptimizerを使用していますが、AdamOptimizerなど異なるアルゴリズムを使用する事も可能です
    • 学習30回毎に学習とテストの精度を出力します
    • その他詳細はTensorFlowのTutorialをご参照ください
model.py
# -*- coding: utf-8 -*-

import tensorflow as tf
import numpy as np
import os

class Model:
    HIDDEN_UNIT_SIZE  = 32
    HIDDEN_UNIT_SIZE2 = 16
    # 対象データの項目数
    COLUMN_SIZE = 4

    def __init__(self):
        self.__setup_placeholder()
        self.__setup_model()
        self.__setup_ops()

    def __enter__(self):
        self.session = tf.Session()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.session.close()
        return False

    def save(self, path):
        saver = tf.train.Saver()
        saver.save(self.session, path)

    def restore(self, path):
        saver = tf.train.Saver()
        saver.restore(self.session, path)

    def __setup_placeholder(self):
        column_size = Model.COLUMN_SIZE
        self.iot_data   = tf.placeholder("float", [None, column_size])
        # 目的変数が3値
        self.actual_class = tf.placeholder("float", [None, 3])
        self.keep_prob    = tf.placeholder("float")
        self.label        = tf.placeholder("string")

    def __setup_model(self):
        column_size = Model.COLUMN_SIZE
        w1 = tf.Variable(tf.truncated_normal([column_size, Predictor.HIDDEN_UNIT_SIZE], stddev=0.1))
        b1 = tf.Variable(tf.constant(0.1, shape=[Predictor.HIDDEN_UNIT_SIZE]))
        h1 = tf.nn.relu(tf.matmul(self.iot_data, w1) + b1)

        w2 = tf.Variable(tf.truncated_normal([Predictor.HIDDEN_UNIT_SIZE, Predictor.HIDDEN_UNIT_SIZE2], stddev=0.1))
        b2 = tf.Variable(tf.constant(0.1, shape=[Predictor.HIDDEN_UNIT_SIZE2]))
        h2 = tf.nn.relu(tf.matmul(h1, w2) + b2)

        h2_drop = tf.nn.dropout(h2, self.keep_prob)
        # 目的変数が3値
        w2 = tf.Variable(tf.truncated_normal([Predictor.HIDDEN_UNIT_SIZE2, 3], stddev=0.1))
        # 目的変数が3値
        b2 = tf.Variable(tf.constant(0.1, shape=[3]))
        self.output = tf.nn.softmax(tf.matmul(h2_drop, w2) + b2)

    def __setup_ops(self):
        cross_entropy = -tf.reduce_sum(self.actual_class * tf.log(self.output))
        self.summary = tf.scalar_summary(self.label, cross_entropy)
        # 異なるアルゴリズムを使用
        # self.train_op = tf.train.AdamOptimizer(0.0001).minimize(cross_entropy)
        self.train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(cross_entropy)
        self.merge_summaries = tf.merge_summary([self.summary])
        correct_prediction = tf.equal(tf.argmax(self.output,1), tf.argmax(self.actual_class,1))
        self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

class Trainer(Model):

    def train(self, steps, data):
        self.__prepare_train(self.session)
        for i in range(steps):
            self.__do_train(self.session, i, data)
            if i %20 == 0:
                self.__add_summary(self.session, i, data)
                self.__print_status(self.session, i, data)

    def __prepare_train(self, session):
        self.summary_writer = tf.train.SummaryWriter('logs', graph=session.graph)
        if not os.path.exists("./model.ckpt"):
            session.run(tf.initialize_all_variables())
            print 'variables initialized'

    def __do_train(self, session, i, data):
        session.run(self.train_op, feed_dict=self.train_feed_dict(data))

    def __add_summary(self, session, i, data):
        summary_str = session.run(self.merge_summaries, feed_dict=self.train_feed_dict(data))
        summary_str += session.run(self.merge_summaries, feed_dict=self.test_feed_dict(data))
        self.summary_writer.add_summary(summary_str, i)

    def __print_status(self, session, i, data):
        train_accuracy = session.run(self.accuracy, feed_dict=self.train_feed_dict(data))
        test_accuracy  = session.run(self.accuracy, feed_dict=self.test_feed_dict(data))
        print 'step {} ,train_accuracy={} ,test_accuracy={} '.format(i, train_accuracy, test_accuracy)

    def train_feed_dict(self, data):
        return {
            self.iot_data: data.train_data(),
            self.actual_class: data.train_up_down(),
            self.keep_prob: 0.8,
            self.label: "train"
        }

    def test_feed_dict(self, data):
        return {
            self.iot_data: data.test_data(),
            self.actual_class: data.test_up_down(),
            self.keep_prob: 1,
            self.label: "test"
        }


class Predictor(Model):

    def predict( self, data ):
        return self.session.run(tf.argmax(self.output,1), feed_dict=self.predict_feed_dict(data))

    def predict_feed_dict(self, data):
        return {
            self.iot_data: data,
            self.keep_prob: 1,
            self.label: "predict"
        }



  • iot_results_loader.pyで学習用のデータをロードします
    • outcome項で結果を定義しています
    • 全体の2/3を学習データに、1/3をテストデータに使用しています
iot_results_loader.py
# -*- coding: utf-8 -*-

import pandas as pd

class IoTResults:

    def __float__(data):
        return 1.0

    def __init__(self, data):
        self.raw  = data.copy()
        self.data = data

    def predictor_data(self):
        return self.data

    def train_data(self):
        return self.__drop_outcome(self.__train_data())

    def test_data(self):
        return self.__drop_outcome(self.__test_data())

    def train_up_down(self):
        return self.__good_bad(self.__train_data()["outcome"])

    def test_up_down(self):
        return self.__good_bad(self.__test_data()["outcome"])

    def __train_data(self):
        # 全データの 2/3 を訓練データとして使用
        return self.data.loc[lambda df: df.index % 3 != 0, :]

    def __test_data(self):
        # 全データの 1/3 をテストデータとして使用
        return self.data.loc[lambda df: df.index % 3 == 0, :]

    def __drop_outcome(self, data):
        return data.drop("outcome", axis=1)

    def __good_bad(self, outcome):
        return outcome.apply(
            lambda p: pd.Series([
                1 if p <=  0 else 0,
                1 if p ==1  else 0,
                1 if p > 1  else 0
            ], index=['setosa', 'versicolor', 'virginica']))


class IoTResultsLoader:

    def retrieve_iot_data(self, data):
        df = pd.DataFrame(data)
        return df


  • trainer.pyへ学習用データをPOSTします
    • flaskで9000ポートでアクセスします。TenserFlowのDockerコンテナのデプロイによりBluemixから提供されるIPアドレスのうち、パブリックIPを使用してブラウザからアクセスします。flaskサーバーはプライベートIPへ向け9000ポートを開けます
    • 必要に応じ学習回数を変更して試してみます
    • 学習結果が./model.ckptに保存されます
trainer.py
# -*- coding: utf-8 -*-

import os
import pandas as pd
from flask import Flask, jsonify, request
from iot_results_loader import *
from model import *

trainer = Trainer()
trainer.__enter__()
if os.path.exists("./model.ckpt"):
    trainer.restore("./model.ckpt")

loader = IoTResultsLoader()

# webapp
app = Flask(__name__)

@app.route('/api/trainer', methods=['POST'])
def train():
    data2 = pd.DataFrame(eval(request.data))
    data3 = IoTResults(loader.retrieve_iot_data(data2))
    # 学習回数
    trainer.train(60, data3)
    trainer.save("./model.ckpt")
    return 'train done'

if __name__ == '__main__':
    app.run(host='172.xx.xx.xx', port=9000)


  • predictor.pyへ判定用データを送付し結果を確認します
    • flaskで9001ポートでアクセスします。TenserFlowのDockerコンテナのデプロイによりBluemixから提供されるIPアドレスのうち、パブリックIPを使用してブラウザからアクセスします。flaskサーバーはプライベートIPへ向け9000ポートを開けます
predictor.py
# -*- coding: utf-8 -*-

import os
import pandas as pd
from flask import Flask, jsonify, request
from iot_results_loader import *
from model import *

predictor = Predictor()

# webapp
app = Flask(__name__)

@app.route('/api/predictor', methods=['POST'])
def predict():
    predictor.__enter__()
    if os.path.exists("./model.ckpt"):
        predictor.restore("./model.ckpt")
    data = pd.DataFrame(eval(request.data))
    results = predictor.predict(IoTResults(data).predictor_data().iloc[[0]])
    predictor.__exit__(1,1,0)
    return jsonify(result=("2 virginica!" if results[0] == 2 else "1 versicolor!" if results[0] == 1 else "0 setosa!"))
        
if __name__ == '__main__':
    app.run(host='172.xx.xx.xx', port=9001)

  • Node-REDのフローを用意します。フロー中の「trainerへ」と「predictorへ」のhttpノードを開き、前出のパブリックIPアドレスを指定します
TensorFlowへアクセスするフロー
[{"id":"7283e6b5.d9c0b","type":"http request","z":"97be8461.26496","name":"predictorへ","method":"POST","ret":"txt","url":"http://xx.xx.xx.xx:9001/api/predictor","tls":"","x":570,"y":280,"wires":[["8bdeafef.6ac928"]]},{"id":"c306faf.2136088","type":"inject","z":"97be8461.26496","name":"起動","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":110,"y":240,"wires":[["72f86ec9.57bc"]]},{"id":"72f86ec9.57bc","type":"template","z":"97be8461.26496","name":"iris test: 0 setosa","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{'Sepal Length': [4.9], 'Sepal Width':[3.1], 'Petal Length':[1.5], 'Petal Width':[0.1]}","x":330,"y":240,"wires":[["7283e6b5.d9c0b"]]},{"id":"2d37564e.bc98fa","type":"template","z":"97be8461.26496","name":"iris test: 1 versicolor","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{'Sepal Length': [5], 'Sepal Width':[2.3], 'Petal Length':[3.3], 'Petal Width':[1]}","x":340,"y":280,"wires":[["7283e6b5.d9c0b"]]},{"id":"977c9b69.d200d","type":"template","z":"97be8461.26496","name":"iris test: 2 virginica","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{'Sepal Length': [6.4], 'Sepal Width':[2.8], 'Petal Length':[5.6], 'Petal Width':[2.2]}","x":330,"y":320,"wires":[["7283e6b5.d9c0b"]]},{"id":"8f973a5b.a6df7","type":"inject","z":"97be8461.26496","name":"起動","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":110,"y":280,"wires":[["2d37564e.bc98fa"]]},{"id":"9d96a668.46b6a8","type":"inject","z":"97be8461.26496","name":"起動","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":110,"y":320,"wires":[["977c9b69.d200d"]]},{"id":"1e9bc0f2.e7629f","type":"http request","z":"97be8461.26496","name":"trainerへ","method":"POST","ret":"txt","url":"http://xx.xx.xx.xx:9000/api/trainer","tls":"","x":560,"y":120,"wires":[["74e86540.88dde4"]]},{"id":"8bdeafef.6ac928","type":"function","z":"97be8461.26496","name":"取り出し","func":"var data = JSON.parse(msg.payload);\nmsg.payload = data.result;\nreturn msg;\n","outputs":1,"noerr":0,"x":720,"y":280,"wires":[["5305aeb5.15d38"]]},{"id":"5305aeb5.15d38","type":"template","z":"97be8461.26496","name":"出力","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"これは {{payload}} ですね!","x":570,"y":360,"wires":[["a0a1c21a.92fd08"]]},{"id":"a0a1c21a.92fd08","type":"debug","z":"97be8461.26496","name":"","active":true,"console":"false","complete":"false","x":730,"y":360,"wires":[]},{"id":"f1d8f1f3.86eac","type":"template","z":"97be8461.26496","name":"iris training","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"            {'Sepal Length': [6.4,5,4.9,4.9,5.7,4.4,5.4,6.9,6.7,5.1,5.2,6.9,5.8,5.4,7.7,6.3,6.8,7.6,6.4,5.7,6.7,6.4,5.4,6.1,7.2,5.2,5.8,5.9,5.4,6.7,6.3,5.1,6.4,6.8,6.2,6.9,6.5,5.8,5.1,4.8,7.9,5.8,6.7,5.1,4.7,6,4.8,7.7,4.6,7.2,5,6.6,6.1,5,7,6,7.4,5.8,6.2,5,5.6,6.7,6.3,6.4,6.2,7.3,4.4,7.2,6.5,5,4.7,6.6,5.5,7.7,6.1,4.9,5.5,5.7,6,6.4,5.4,6.1,6.5,5.6,6.3,4.9,6.8,5.7,6,5,6.5,6.1,5.1,4.6,6.5,4.6,4.6,7.7,5.9,5.1,4.9,4.9,4.5,5.8,5,5.2,5.3,5,5.6,4.8,6.3,5.7,5,6.3,5,5.5,5.7,4.4,4.8,5.5,5.9,6.9,5.1,6,5.5,6.2,5.5,6.3,5.6,6.7,7.1,4.3,5.6,5.5,6,5.1,5.7,4.8,5.1,5.7,5.4,5.6,6.3,6.3,5.8,6.1,5.2,6.7,6.7,6.4],\n             'Sepal Width': [2.8,2.3,2.5,3.1,3.8,3.2,3.4,3.1,3.1,3.7,2.7,3.1,4,3.9,3.8,3.3,3.2,3,3.2,4.4,3.3,2.8,3.9,2.6,3,3.5,2.6,3,3,3,2.3,2.5,3.2,3,2.8,3.2,3.2,2.8,3.8,3,3.8,2.7,3,3.8,3.2,2.2,3.4,2.6,3.6,3.2,3.3,3,2.8,3.2,3.2,3,2.8,2.7,3.4,2,2.5,3.1,2.5,3.1,2.2,2.9,3,3.6,3,3.4,3.2,2.9,3.5,3,3,3.1,2.4,2.9,2.9,2.7,3.7,2.9,2.8,2.7,3.4,3.1,2.8,2.8,2.7,3.5,3,2.8,3.5,3.1,3,3.4,3.2,2.8,3.2,3.8,3,2.4,2.3,2.7,3.4,3.4,3.7,3.6,2.9,3.1,2.7,2.8,3,3.3,3.5,2.6,3,2.9,3,2.4,3,3.1,3.3,3.4,2.5,2.9,4.2,2.8,3,2.5,3,3,2.8,2.3,2.2,3.5,2.6,3.4,3.4,2.5,3.4,3,2.9,2.5,2.7,3,4.1,3.1,3.3,2.9],\n             'Petal Length': [5.6,3.3,4.5,1.5,1.7,1.3,1.5,5.1,4.4,1.5,3.9,4.9,1.2,1.7,6.7,4.7,5.9,6.6,5.3,1.5,5.7,5.6,1.3,5.6,5.8,1.5,4,5.1,4.5,5,4.4,3,4.5,5.5,4.8,5.7,5.1,5.1,1.5,1.4,6.4,5.1,5.2,1.9,1.6,5,1.6,6.9,1,6,1.4,4.4,4,1.2,4.7,4.8,6.1,5.1,5.4,3.5,3.9,5.6,5,5.5,4.5,6.3,1.3,6.1,5.5,1.5,1.3,4.6,1.3,6.1,4.9,1.5,3.8,4.2,4.5,5.3,1.5,4.7,4.6,4.2,5.6,1.5,4.8,4.5,5.1,1.3,5.2,4.7,1.4,1.5,5.8,1.4,1.4,6.7,4.8,1.6,1.4,3.3,1.3,4.1,1.6,1.4,1.5,1.4,3.6,1.6,4.9,4.1,1.6,6,1.6,4.4,4.2,1.4,1.4,3.7,4.2,5.4,1.7,4.5,4,4.3,1.4,5.1,4.1,5.8,5.9,1.1,4.9,4,4,1.4,3.5,1.9,1.5,5,1.7,4.5,5.6,4.9,3.9,4.6,1.5,4.7,5.7,4.3],\n             'Petal Width': [2.2,1,1.7,0.1,0.3,0.2,0.4,2.3,1.4,0.4,1.4,1.5,0.2,0.4,2.2,1.6,2.3,2.1,2.3,0.4,2.1,2.1,0.4,1.4,1.6,0.2,1.2,1.8,1.5,1.7,1.3,1.1,1.5,2.1,1.8,2.3,2,2.4,0.3,0.3,2,1.9,2.3,0.4,0.2,1.5,0.2,2.3,0.2,1.8,0.2,1.4,1.3,0.2,1.4,1.8,1.9,1.9,2.3,1,1.1,2.4,1.9,1.8,1.5,1.8,0.2,2.5,1.8,0.2,0.2,1.3,0.2,2.3,1.8,0.1,1.1,1.3,1.5,1.9,0.2,1.4,1.5,1.3,2.4,0.1,1.4,1.3,1.6,0.3,2,1.2,0.3,0.2,2.2,0.3,0.2,2,1.8,0.2,0.2,1,0.3,1,0.4,0.2,0.2,0.2,1.3,0.2,1.8,1.3,0.2,2.5,0.6,1.2,1.2,0.2,0.1,1,1.5,2.1,0.5,1.6,1.3,1.3,0.2,1.5,1.3,1.8,2.1,0.1,2,1.3,1,0.2,1,0.2,0.2,2,0.2,1.5,1.8,1.5,1.2,1.4,0.1,1.5,2.5,1.3],\n             'outcome': [2,1,2,0,0,0,0,2,1,0,1,1,0,0,2,1,2,2,2,0,2,2,0,2,2,0,1,2,1,1,1,1,1,2,2,2,2,2,0,0,2,2,2,0,0,2,0,2,0,2,0,1,1,0,1,2,2,2,2,1,1,2,2,2,1,2,0,2,2,0,0,1,0,2,2,0,1,1,1,2,0,1,1,1,2,0,1,1,1,0,2,1,0,0,2,0,0,2,1,0,0,1,0,1,0,0,0,0,1,0,2,1,0,2,0,1,1,0,0,1,1,2,0,1,1,1,0,2,1,2,2,0,2,1,1,0,1,0,0,2,0,1,2,1,1,1,0,1,2,1]}","x":310,"y":120,"wires":[["1e9bc0f2.e7629f"]]},{"id":"6027aa75.7a7a24","type":"inject","z":"97be8461.26496","name":"起動","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":110,"y":120,"wires":[["f1d8f1f3.86eac"]]},{"id":"74e86540.88dde4","type":"debug","z":"97be8461.26496","name":"","active":true,"console":"false","complete":"false","x":730,"y":120,"wires":[]},{"id":"d1575987.34ea48","type":"comment","z":"97be8461.26496","name":"学習用フロー","info":"","x":90,"y":80,"wires":[]},{"id":"bc6ca509.b1321","type":"comment","z":"97be8461.26496","name":"判定用フロー","info":"","x":90,"y":200,"wires":[]}]


スクリーンショット 2016-11-11 12.36.10.png

3. 実行します

  1. Terminalを開き、python trainer.pyで学習用サーバーを起動します
    スクリーンショット 2016-11-11 12.34.36.png

  2. もう一つ別のTerminalを開き、python predictor.pyで判定用サーバーを実行します
    スクリーンショット 2016-11-11 12.35.17.png

  3. 上記のNode-REDフローの「学習用フロー」を起動し、学習状況をtrainer.pyのターミナルから確認します
    スクリーンショット 2016-11-07 8.46.43.png
    スクリーンショット 2016-11-07 8.51.48.png

  4. 学習の進行に応じ、随時「判定用フロー」を起動し、判定結果を確認します
    スクリーンショット 2016-11-07 8.52.49.png

  5. python -m tensorflow.tensorboard --logdir=./logsなどでtensorboardを稼働しブラウザで6006ポートへアクセスして学習の状況などを確認します。IPアドレスはTenserFlowのDockerコンテナのデプロイによりBluemixから提供されるIPアドレスのうち、パブリックIPを使用してブラウザからアクセスします。

スクリーンショット 2016-10-31 15.11.26.png
スクリーンショット 2016-10-31 16.13.53.png

参考

TensorFlowを使った為替(FX)のトレードシステムを作るチュートリアルを大変参考にさせていただきました。どうもありがとうございます。

8
13
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
8
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?