bookloveru2
2021年6月14日11 分
最終更新: 2021年11月1日
画像は国内最強の頭脳集団:PFNのchainerチュートリアルより👆
https://tutorials.chainer.org/ja/13_Basics_of_Neural_Networks.html
#@title 多層パーセプトロンで株価予測
import datetime
import fix_yahoo_finance as yf
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
#スタート日を決める
start = "2016-6-14" #@param {type:"string"}
#①株価を取得する
start = start #株価を取得するスタート日を決める
end = datetime.date.today() #現在までの営業日(今日 =today)を取得する最終日とする
codelist = ["^DJI","^N225","^FTSE","000001.SS","IMOEX.ME","^BSESN","^BVSP", "BTC-USD","^TNX","GC=F","CL=F"]
#コードリストに取得したい銘柄を入れる アメリカ 日本 イギリス 中国 ロシア インド ブラジル ビットコ 10年金利 金 原油
#②取得した株価の内、終値をdata2に格納する
data2 = yf.download(codelist, start=start, end=end)["Adj Close"] .dropna()
data2.rename(columns={'^DJI':'ダウ',
'^N225':'日経平均',
'^FTSE':'イギリス',
"000001.SS":'中国',
'IMOEX.ME':'ロシア',
'^BSESN':'インド',
'^BVSP':'ブラジル',
'BTC-USD':'ビットコ',
'^TNX':'10 Year Treasury',
"GC=F":"金",
"CL=F":"原油"},inplace=True)
data2
実行結果👇
スタート日から今日現在までの世界主要株価+指数の終値データが作成されます。
# 前処理開始。分析用のXとyを作成。
import pandas_datareader as pdr
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.linear_model import LogisticRegression
from sklearn.neural_network import MLPClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
ticker = "BAC" #@param {type:"string"}
df = pdr.get_data_yahoo(ticker, start, end)
# data2から説明変数追加
df["金利"] = data2['10 Year Treasury']
df["原油"] = data2['原油']
df["ダウ"] = data2['ダウ']
# 前日との差分をDiffへ格納
df["Diff"] = df["Adj Close"].diff()
# 終値×出来高を"出来高"へ格納
df["出来高"] = df["Adj Close"] * df["Volume"]
実行結果👇
説明変数として作成した【金利・原油価格・ダウ平均価格・Diff(前日との差分)・対象銘柄(今回はバンク・オブ・アメリカの)出来高】データがデータフレームに追加されます。
# 差分[Diff]を1行、上にずらして(.shift(-1))、xが0より大きい(つまり値上がりしていれば1。)
# xが0より大きくない(つまり値下がりしていれば0。)のラムダ式xを作成。.apply()でラムダ式をdf[Diff]へ格納して、df[y]を作成。
# yは未来の値。yが1なら明日の株価終値は上昇。つまりyは正解ラベル。
df["y"] = df["Diff"].apply(lambda x: 1 if x > 0 else 0).shift(-1)
# OpenとかHighとかをdfから削除.drop(["消すindex"],axis=1で列を指定)。.dropna()で欠損値のある行を削除。
df2 = df.drop(["Open", "High", "Low", "Close", "Volume", "Diff", "Adj Close"],axis=1,).dropna()
print('\033[35m'+"dfを表示\n"+'\033[0m', (df))
print('\033[35m'+"df2を表示\n"+'\033[0m', (df2))
# 説明変数
# yを列ごと削除してXを作成。
X = df2.drop(["y"], axis=1)
# 目的変数
# dfのyの値をyへ格納。yは正解ラベル。つまり(値下がりと値上がりの[0,1])だけのデータをyに充当。
y = df2["y"]
y
実行結果👇
前述のデータフレームから不必要な項目を削除。その際、未来の結果[0 or 1]を.shift(-1)で当日に持たせる。
未来の結果を[y]にいれて、それを表示。
つまり、正解・不正解が下図の黄色い枠(赤い丸で囲ったとこ)の中にある(0なら明日の株価下落。1なら明日の株価上昇)。
# デフォルトはtest_size=0.25で25%がテスト用、残りの75%が訓練用。ここでは、テスト用を30%に設定。
# デフォルトでは要素がシャッフルされて分割される。引数shuffle=Falseとするとシャッフルされずに先頭から順番に分割される。
# 機械学習のモデルの性能を比較するような場合、どのように分割されるかによって結果が異なってしまうため、乱数シードを固定して常に同じように分割されるようにする必要がある。
# ここでは使用していないが、要素がシャッフルされる場合、デフォルトでは実行するたびにランダムに分割される。引数random_stateを指定して乱数シードを固定すると常に同じように分割される。
# https://note.nkmk.me/python-sklearn-train-test-split/
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3,shuffle=False,)
# モデルに多層パーセプトロンを適用 [StandardScaler()で標準化] [shuffle=False先頭から順番に分割]
clf = make_pipeline(StandardScaler(), MLPClassifier(random_state=0, shuffle=False))
clf.fit(X_train,y_train)
print("\nX_train.shape", X_train.shape)
print("\ny_train.shape", y_train.shape)
print("\nX_test.shape", X_test.shape)
print("\ny_test.shape", y_test.shape)
print("\n学習用の説明変数 X_train -------------------------\n", X_train)
print("\n学習用の目的変数 y_train -------------------------\n", y_train)
print("\n評価用の説明変数 X_test -------------------------\n", X_test)
print("\n評価用の目的変数 y_test -------------------------\n", y_test)
# 学習させた内容を、テスト用データで確かめる。
predict = clf.predict(X_test)
print("\n予測値 predict --------------------------------------------------\n", predict)
実行結果👇
X_train.shape(679,4)は説明変数が679個の【金利・原油・ダウ・出来高】時系列データ。
4個の説明変数【金利・原油・ダウ・出来高】を表す。
y_tarin(679,)は[0 ore1]の答え。
X_testとかtestは同様のデータ(テスト用:3割に分割されたデータ)。
重要なのは、予測値(predict)。これがモデルで作成した明日の株価の上下予測である。👇
# 正解率(accuracy)、適合率(precision)、再現率(recall)を表示
print('\033[1m'+"\nモデルの正解率 全てのサンプルの正解率 (TP+TN/(TP+TN+FP+FN))--------------------------------------------------\n" + '\033[0m', accuracy_score(y_test, predict) , "\n\n適合率 真陽性/陽性の判定(真陽性+偽陽性)(TP/(TP+FP))\n",precision_score(y_test, predict),"\n\n再現率 真陽性/全ての陽性(真陽性+偽陰性)(TP/(TP+FN))\n", recall_score(y_test, predict))
print("\n教師データを使った正解率--------------------------------------------------\n",clf.score(X_train, y_train))
print("\nテストデータを使った正解率--------------------------------------------------\n",clf.score(X_test, y_test))
実行結果👇
黄色い線の正解率が予測と正解(教師データ)のマッチング率である。
再現率も大事だよ🙉
# 分類問題の評価基準であるprecision(適合率)、recall(再現率)、f1-score(F値)、support(実際のサンプル数)を出力。
import numpy as np
from sklearn.metrics import classification_report
print("\n評価基準--------------------------------------------------\n",classification_report(y_test, predict,target_names=['0 or price down', '1 or price up']))
# 平均二乗誤差を出力。
from sklearn.metrics import mean_squared_error
print("\n平均二乗誤差--------------------------------------------------\n",np.sqrt(mean_squared_error(y_test, predict)))
# 混同行列を生成: confusion_matrix()
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
y_true = y_test
y_pred = predict
cm = confusion_matrix(y_true, y_pred)
print("\n混同行列--------------------------------------------------\n", cm)
#グラフの箱サイズ
plt.figure(figsize=(4,2))
sns.heatmap(cm, annot=True, cmap='Blues')
plt.savefig('sklearn_confusion_matrix.png')
# https://qiita.com/0NE_shoT_/items/b702ab482466df6e5569
# FPR(偽陽性率)、TPR(真陽性率)、閾値。
from sklearn.metrics import roc_curve, auc
Y_score = clf.predict_proba(X_test)[:, 1] # 検証データが陽性(クラス1)に属する確率
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=Y_score)
#グラフの箱サイズ
plt.figure(figsize=(8,6))
plt.plot(fpr, tpr, label='roc curve (area = %0.3f)' % auc(fpr, tpr))
plt.plot([0, 1], [0, 1], linestyle='--', label='random')
plt.plot([0, 0, 1], [0, 1, 1], linestyle='--', label='ideal')
plt.legend()
plt.xlabel('FPR=false positive rate')
plt.ylabel('TPR=true positive rate')
plt.show()
実行結果👇
precision = 適合率
recall = 再現率
F1スコア、support = 個数
混同行列
左上 TN(真陰性)、右上 FP(偽陽性)、左下 FN(偽陰性)、右下 TP(真陽性)
#@title 多層パーセプトロンで株価予測
import datetime
import yfinance as yf
import matplotlib.pyplot as plt
import seaborn as sns
from pandas_datareader import data as pdr
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
import mplfinance as mpf
import requests
import argparse
#スタート日を決める
start = "2020-1-1" #@param {type:"string"}
#①株価を取得する
start = start #株価を取得するスタート日を決める
end = datetime.date.today() #現在までの営業日(今日 =today)を取得する最終日とする
codelist = ["^DJI","^N225","^FTSE","000001.SS","IMOEX.ME","^BSESN","^BVSP", "BTC-USD","^TNX","GC=F","CL=F"]
#コードリストに取得したい銘柄を入れる アメリカ 日本 イギリス 中国 ロシア インド ブラジル ビットコ 10年金利 金 原油
yf.pdr_override() # <== that's all it takes :-)
# download dataframe
data2 = pdr.get_data_yahoo(codelist, start, end)["Adj Close"] .dropna()
data2.rename(columns={'^DJI':'ダウ',
'^N225':'日経平均',
'^FTSE':'イギリス',
"000001.SS":'中国',
'IMOEX.ME':'ロシア',
'^BSESN':'インド',
'^BVSP':'ブラジル',
'BTC-USD':'ビットコ',
'^TNX':'10 Year Treasury',
"GC=F":"金",
"CL=F":"原油"},inplace=True)
# 前処理開始。分析用のXとyを作成。
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.linear_model import LogisticRegression
from sklearn.neural_network import MLPClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
ticker = "MSFT" #@param {type:"string"}
yf.pdr_override()
df = pdr.get_data_yahoo(ticker, start, end)
# data2から説明変数追加
df["金利"] = data2['10 Year Treasury']
df["原油"] = data2['原油']
df["ダウ"] = data2['ダウ']
# 前日との差分をDiffへ格納
df["Diff"] = df["Adj Close"].diff()
# 終値×出来高を"出来高"へ格納
df["出来高"] = df["Adj Close"] * df["Volume"]
# 差分[Diff]を1行、上にずらして(.shift(-1))、xが0より大きい(つまり値上がりしていれば1。)
# xが0より大きくない(つまり値下がりしていれば0。)のラムダ式xを作成。.apply()でラムダ式をdf[Diff]へ格納して、df[y]を作成。
# yは未来の値。yが1なら明日の株価終値は上昇。つまりyは正解ラベル。
df["y"] = df["Diff"].apply(lambda x: 1 if x > 0 else 0).shift(-1)
# OpenとかHighとかをdfから削除.drop(["消すindex"],axis=1で列を指定)。.dropna()で欠損値のある行を削除。
df2 = df.drop(["Open", "High", "Low", "Close", "Volume", "Diff", "Adj Close"],axis=1,).dropna()
# print('\033[35m'+"dfを表示\n"+'\033[0m', (df))
# print('\033[35m'+"df2を表示\n"+'\033[0m', (df2))
# 説明変数
# yを列ごと削除してXを作成。
X = df2.drop(["y"], axis=1)
# 目的変数
# dfのyの値をyへ格納。yは正解ラベル。つまり(値下がりと値上がりの[0,1])だけのデータをyに充当。
y = df2["y"]
# デフォルトはtest_size=0.25で25%がテスト用、残りの75%が訓練用。ここでは、テスト用を30%に設定。
# デフォルトでは要素がシャッフルされて分割される。引数shuffle=Falseとするとシャッフルされずに先頭から順番に分割される。
# 機械学習のモデルの性能を比較するような場合、どのように分割されるかによって結果が異なってしまうため、乱数シードを固定して常に同じように分割されるようにする必要がある。
# ここでは使用していないが、要素がシャッフルされる場合、デフォルトでは実行するたびにランダムに分割される。引数random_stateを指定して乱数シードを固定すると常に同じように分割される。
# https://note.nkmk.me/python-sklearn-train-test-split/
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3,shuffle=False,)
# モデルに多層パーセプトロンを適用
clf = make_pipeline(StandardScaler(), MLPClassifier(random_state=0, shuffle=False))
clf.fit(X_train,y_train)
print("\nX_train.shape", X_train.shape)
print("\ny_train.shape", y_train.shape)
print("\nX_test.shape", X_test.shape)
print("\ny_test.shape", y_test.shape)
print("\n学習用の説明変数 X_train -------------------------\n", X_train)
print("\n学習用の目的変数 y_train -------------------------\n", y_train)
print("\n評価用の説明変数 X_test -------------------------\n", X_test)
print("\n評価用の目的変数 y_test -------------------------\n", y_test)
# 学習させた内容を、テスト用データで確かめる。
predict = clf.predict(X_test)
print("\n予測値 predict --------------------------------------------------\n", predict)
# 正解率(accuracy)、適合率(precision)、再現率(recall)を表示
print('\033[1m'+"\nモデルの正解率 全てのサンプルの正解率 (TP+TN/(TP+TN+FP+FN))--------------------------------------------------\n" + '\033[0m', accuracy_score(y_test, predict) , "\n\n適合率 真陽性/陽性の判定(真陽性+偽陽性)(TP/(TP+FP))\n",precision_score(y_test, predict),"\n\n再現率 真陽性/全ての陽性(真陽性+偽陰性)(TP/(TP+FN))\n", recall_score(y_test, predict))
print("\n教師データを使った正解率--------------------------------------------------\n",clf.score(X_train, y_train))
print("\nテストデータを使った正解率--------------------------------------------------\n",clf.score(X_test, y_test))
# 分類問題の評価基準であるprecision(適合率)、recall(再現率)、f1-score(F値)、support(実際のサンプル数)を出力。
import numpy as np
from sklearn.metrics import classification_report
print("\n評価基準--------------------------------------------------\n",classification_report(y_test, predict,target_names=['0 or price down', '1 or price up']))
# 平均二乗誤差を出力。
from sklearn.metrics import mean_squared_error
print("\n平均二乗誤差--------------------------------------------------\n",np.sqrt(mean_squared_error(y_test, predict)))
# tickerの株価をプロット
plt.figure(figsize=(6,4))
chart = yf.download(ticker, start=start, end=end)
mpf.plot(chart,type='candle',mav=(5,25,60),volume=True,show_nontrading=True)
# 混同行列を生成: confusion_matrix()
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
y_true = y_test
y_pred = predict
cm = confusion_matrix(y_true, y_pred)
print("\n混同行列--------------------------------------------------\n", cm)
#グラフの箱サイズ
plt.figure(figsize=(4,2))
sns.heatmap(cm, annot=True, cmap='Blues')
plt.savefig('sklearn_confusion_matrix.png')
# https://qiita.com/0NE_shoT_/items/b702ab482466df6e5569
# FPR(偽陽性率)、TPR(真陽性率)、閾値。
from sklearn.metrics import roc_curve, auc
Y_score = clf.predict_proba(X_test)[:, 1] # 検証データが陽性(クラス1)に属する確率
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=Y_score)
#グラフの箱サイズ
plt.figure(figsize=(5,4))
plt.plot(fpr, tpr, label='roc curve (area = %0.3f)' % auc(fpr, tpr))
plt.plot([0, 1], [0, 1], linestyle='--', label='random')
plt.plot([0, 0, 1], [0, 1, 1], linestyle='--', label='ideal')
plt.legend()
plt.xlabel('FPR=false positive rate')
plt.ylabel('TPR=true positive rate')
plt.show()
では、ばいちゃ(・ω・)ノ
pythonでプログラミングがしたい!!
pythonを学びたい!という方には、
オンラインプログラミング教室『Aidemy アイデミー』がお勧めです。
ご自身でプログラム環境を用意する必要は無く、サイトへアクセスするだけです。 創業者は東京大学工学部卒の石川聡彦さん。
著書に『人工知能プログラミングのための数学がわかる本』(KADOKAWA/2018年)など。
無料で、お試しもできますので安心です。
お時間ある方は下記リンクを覗いてみてはいかがでしょうか(*'ω'*)。