はじめに
先日、機械学習した結果を使って勘定科目を予測するプログラムを作成したのですが、予測結果の応答が異常に遅くて使いものにならないというご意見があったので、少し工夫してみました。
会計データを学習して、仕訳の入力時に摘要の内容から勘定科目を予測してみる - Qiita
応答の仕組み
学習結果をメモリー内に保持し、摘要を送信すると勘定科目を返してくるというものを簡易に実現するため、HTTPを利用することにしました。
そこで、PythonでHTTPサーバーを作成し、HTTPサーバー起動時に学習結果を読み込んでおき、GETで摘要を送信したら勘定科目を予測して返すというものにしてみました。
PythonでHTTPサーバーを構築
以下の記事を参考にしました。
概ねそのまま使用しているのですが、BaseHTTPServerというライブラリが変更になっていることと、日本語の処理でエラーが出たことから少々修正してあります。
ちなみに、Python3です。
CallbackServer.py
#!/usr/local/bin/python
# coding: utf-8
import requests
import http.server
import socketserver
from http.server import BaseHTTPRequestHandler
from urllib.parse import urlparse, unquote
def start(port, callback):
def handler(*args):
CallbackServer(callback, *args)
server = socketserver.TCPServer(('', int(port)), handler)
server.serve_forever()
class CallbackServer(BaseHTTPRequestHandler):
def __init__(self, callback, *args):
self.callback = callback
BaseHTTPRequestHandler.__init__(self, *args)
def do_GET(self):
parsed_path = urlparse(self.path)
query = unquote(parsed_path.query)
self.send_response(200)
self.end_headers()
result = self.callback(query)
self.wfile.write(result.encode('utf-8'))
return
サーバー起動スクリプト
起動時に学習結果を読み込み、GETのコールバックで予測した結果を返します。
server.py
#!/usr/local/bin/python
# coding: utf-8
import sys
import CallbackServer
import pandas as pd
import numpy as np
homedir = "/home/scripts/"
filename = "data/code.csv"
df = pd.read_csv(homedir + filename, header=None)
df.index = df.pop(0)
df_rs = df.pop(1)
from sklearn.externals import joblib
scaler = joblib.load(homedir + 'data/scaler.pkl')
clf = joblib.load(homedir + 'data/clf.pkl')
vect = joblib.load(homedir + 'data/vect.pkl')
from janome.tokenizer import Tokenizer
t = Tokenizer()
def callback_method(query):
texts = [
query,
]
notes = []
for note in texts:
tokens = t.tokenize(note)
words = ""
for token in tokens:
words += " " + token.surface
notes.append(words)
X = vect.transform(notes)
result = clf.predict(X)
ans = ""
for i in range(len(texts)):
ans = df_rs.ix[result[i]]
return ans
if __name__ == '__main__':
port = sys.argv[1]
CallbackServer.start(port, callback_method)
以下のコマンドで起動します。
$ chmod a+x server.py
$ ./server.py 8080 &
動作テスト
Rubyを使って予測結果を取得してみます。
test.rb
require 'net/http'
require 'uri'
puts Net::HTTP.get_print('localhost', URI.escape('/?高速道路利用料'), 8080)
実行します。
$ ruby test.rb
旅費交通
できた(^-^)
LINEボットに組み込んでみる。
いい感じ(^-^)
LINEボットの作り方については以下の記事をご参照下さい。
LINEのMessaging APIで自動応答のBOTを作成する with Ruby
ちなみに、このLINEボットは以下のQRコードでお友達になれます。
さて、次は何しようかな!