
一応のゴール達成
以前に作ったソースコードを元に、プロらしいソースコードへ改造しました。
そして、時系列データのCSVから、時間情報を取り除き、数値だけで次の数値を予測するソースコードが出来ました。
もちろん、PythonをインストールしていないPCで動作しました。
これで、既存のシステムでもPythonのライブラリーを作るための基礎が出来たと思います。
既存のシステム→得意な言語で制御プログラム→Pythonコードで予測
目標だったことが、精度は不明ですが出来ました。
python predicted.py in.csv out.csv のようにすれば動きます。
#ロギングを行う
import logging
#異常終了する
import sys
#csvをデータフレームとして利用するために読み込みます
import pandas as pd
#機械学習用のライブラリ
from sklearn.linear_model import LinearRegression
#Matplotlibは 、科学技術計算向けのグラフを描いてくれるライブラリ。
#from matplotlib import pyplot as plt
#学習用データと予測用数列を作成する関数
#内容 1次元配列のStringOfNumbersとIntervalを元に、学習用データと正解データを作る
# この関数は、学習データと正解データの生成の他に
# 予測のための、学習データを生成する
# 予測のための、学習データを作成するとき、StringOfNumbersの最後にはダミーの数値を入れること
#制限 StringOfNumbersの配列は、Intervalの数より多くないと、戻り値を生成しない
#引数 StringOfNumbers[] 1元配列で、予測のための数値を格納する
# Interval 学習に利用する配列の数
#戻値 Retrun True=正常終了 False=例外発生
# DataForLearning[[]] 2次元配列で、Intervalの数だけ予測データをまとめる
# AnswerData[] 1次元配列で、学習用の正解データが入る
#
#解説 1,2,3,4,5,6と3を指定して起動 => [[1,2,3],[2,3,4],[3,4,5]]と[4,5,6]に変換する
def make_data(StringOfNumbers,Interval):
#関数のオプションを記録する
logging.debug('%s %i','StringOfNumbers=',len(StringOfNumbers))
logging.debug('%s %i','Interval=',Interval)
try:
#interval前のデータを学習させるための配列
DataForLearning = []
#答えとなる配列
AnswerData = []
#NumberOfArraysは0からStringOfNumbersの数だけ処理を繰り返す
#指定された数列全部を処理する
for NumberOfArrays in range(len(StringOfNumbers)):
#繰り返しの数 、Intervalより小さい場合、以降の処理を省略する
if NumberOfArrays < Interval:
continue
#配列AnswerDataに現在の数値を追記する
#Intervalの数以上の数列が対象となる
AnswerData.append(StringOfNumbers[NumberOfArrays])
#配列Lumpの作成 、DataForLearningへの2次元配列を作るために作業用として使う
Lump = []
#NumberForLearningは0からintervalの数まで繰り返される
#今日よりinterval日前のデータを揃える
for NumberForLearning in range(Interval):
#NumberOfArraysはinterval以上になるので 、TemporaryPositionの値がマイナスになることはない
TemporaryPosition = NumberOfArrays + NumberForLearning - Interval
#配列Lumpに指定された数値を格納
Lump.append(StringOfNumbers[TemporaryPosition])
#interval日前のデータが揃ったので 、2次元配列に追加
DataForLearning.append(Lump)
except Exception as err:
#例外が発生したのでログファイルに記録して 、異常終了します。
logging.critical('%s %s','Exception handling occurs=',err)
#戻り値を返すが 、例外が発生したので値は使わないこと
return (False,DataForLearning,AnswerData)
#戻り値の指定
return (True,DataForLearning, AnswerData)
# main関数
#内容 与えられた数列から、次に来る数値を予測する
#制限 起動オプションが指定通りでない場合、異常終了する
#引数 StringOfNumbers[] 1元配列で、予測のための数値を格納する
# Interval 学習に利用する配列の数
#戻値 Retrun 0=正常終了 0以外=例外発生
#
#解説 1,2,3,4,5,6と3を指定して起動 => [[1,2,3],[2,3,4],[3,4,5]]と[4,5,6]に変換する
def main():
#ロギングの設定
LogFormat = "%(asctime)s:%(pathname)s:%(funcName)s:%(lineno)s:%(message)s"
logging.basicConfig(filename='Python_log.log', level=logging.DEBUG,format=LogFormat)
try:
#起動オプションが3つ以外か?
if len(sys.argv)!= 3 :
#エラーであることを残す
logging.warning('Other than 3 startup options')
#画面への表示
print('Other than 3 startup options')
#異常終了させる
sys.exit(1)
else:
#オプションが3つなので、入力ファイル名を記録する
logging.debug('%s %s','input=',sys.argv[1])
#オプションが3つなので、出力ファイルを記録する
logging.debug('%s %s','output=',sys.argv[2])
#計算用のCSVをロードする
df = pd.read_csv(sys.argv[1], names=('ds', 'y'),dtype = {'ds':'object', 'y':'float64' })
#読み込んだCSVのデータを日時順にソートする
df=df.sort_values('ds')
#過去interval回数分を学習するデータを作成
#過去10回分からの学習とする
interval = 10
#受け渡された構造体から、数値の部分のみ利用する
#時間のことは計算に含めない
only_y = list(df["y"])
#学習用データを作成する
#1次元配列と学習用過去の回数を指定
#2次元配列の学習用データと、1次元配列の正解データに分ける
RetVal,train_x, train_y = make_data(only_y,interval)
#異常が発生したか確認する
if RetVal == False:
#異常が発生しているので 、異常終了する
sys.exit(1)
#グラフ表示のために0から配列の数だけ数列を作る
ReferenceNumbers=[]
for i in range(len(train_y)):
ReferenceNumbers.append(i)
#グラフの表示
#X軸は順番 、Y軸は正解データの表示
#plt .plot(ReferenceNumbers,train_y)
#こちらはグラフに表示するタイトルや軸名など 。
#plt .title('Graph')
#plt .ylabel('weight')
#plt .xlabel('Number ')
#グラフ表示 (の前に表示している気がする)
#plt .show()
#学習開始
#線形回帰を使うことを宣言
regressor = LinearRegression()
#学習用データと正解データを与えて 、予測の元となる計算方法を考えさせる
regressor.fit(train_x, train_y)
#未来の数値を予測 (今日の時点で)
#予測のための数値を作る
SourceOfPrediction = []
#数列の数を調べる
PositionOfPredictionData=len(only_y)
#数列の数から 、インターバル分を取る
PositionOfPredictionData=PositionOfPredictionData-interval
#予測のための数値を数列の末端部分を加える
for point in range(interval):
SourceOfPrediction.append(only_y[PositionOfPredictionData+point])
#ダミーデータを取り付ける
#ダミーデータは予測のための材料には含まれない
#また 、正解データにダミーデータが入るが、使わない
SourceOfPrediction.append(0)
#予測のためのデータを作成する
RetVal,train_x2, train_y2 = make_data(SourceOfPrediction,interval)
#異常が発生したか確認する
if RetVal == False:
#異常が発生しているので 、異常終了する
sys.exit(1)
#予測値を計算する
ThePredictedValue = regressor.predict(train_x2)
#予測値を記録に残す
logging.debug('%s %f','ThePredictedValue=',ThePredictedValue)
#予測値の保存
with open(sys.argv[2],mode='w') as fileP:
#数値を文字列にして保存
fileP.write(str(ThePredictedValue[0]))
#画面にも表示する
print(ThePredictedValue[0])
except Exception as err:
#例外が発生したのでログファイルに記録して 、異常終了します。
logging.critical('%s %s','Exception handling occurs=',err)
sys.exit(1)
#main関数終了
return
#最後にmainを呼び出す
main()