Pythonと機械学習

Pythonも機械学習も初心者ですが、頑張ってこのブログで勉強してこうと思います。

決定木アルゴリズムで明日のBitcoin価格を予想

下記のブログ記事に影響を受けて、私なりに調べてみました。
サイト名にも惹かれました。非常にナイスなネーミングだと思います。


決定木アルゴリズム機械学習アルゴリズムの一種ですが、正直詳しいことはよく分かりません。
仕組みよりも結果の方が重要なので、取りあえずやってみる事が重要ではないかと思います。

大まかには、Pythonというマシーンに、過去のBitcoinデータを学習させて明日のBitcoinが上昇するか、下降するかを予測させます。

過去のBitcoin価格変動パターンを、トレーニングデータと教師データのセットとしてPythonに入力してやります。

例えば昨日以前の過去3日のBitcoin価格データから今日の価格を学習させたい場合は、以下のトレーニングデータと教師データを用意してやります。

  • 昨日以前3日のトレーニングデータ:["昨日のBTC価格"、"一昨日のBTC価格"、"一昨々日のBTC価格"]
  • 教師データ:["今日のBTC価格"]

過去3日ではなくもっと多くのトレーニングデータを用意した方が予測精度は上がりますし、もちろんトレーニングデータと教師データのセットを多く作ってやった方が予想精度はさらに上がります。

説明が長いと分かり難くなると思うので、取りあえず以下を実行してみてください。


このスクリプトを実行すると、以下の様に明日のBTC価格予想が出力されます。

-----------------------------------------
BTC価格データダウンロード
-----------------------------------------
今日は2016-08-02です。PoloniexからBTC価格データをダウンロードします。
取得データファイル中にある最新の日付は2016-08-02でその時のBTCオープン価格は$605.01000519です。
-----------------------------------------
明日のBTC価格予想
-----------------------------------------
2016-08-02までのBTCオープン価格データから2016-08-03のBTCオープン価格を予測します。
・トレーニングデータ数: 29
・トレーニングデータと教師データのセット数: 30

明日のBTC価格は100.0%の確率で上昇します。

コードの説明

それぞれの関数を説明していきます。

getDataPoloniex

これはPoloniexからBTC価格データをダウンロードする関数です。
main関数内でこの関数を呼んだ直後に、取得したBTC価格データのリスト内の順序をreverse関数で逆にしている事に注意してください。

dateBTC, dataBTC = getDataPoloniex()
dateBTC.reverse()
dataBTC.reverse()

※dateBTCが日付で、dataBTCがopen価格です。
データの順序を逆にするのは、データを扱いやすくするためです。というのも、学習ではより新しいデータから順に扱いたいためdataBTC[0]に一番新しいデータが入ってくれた方が都合がいいです。dataBTC[1]、dataBTC[2]、dataBTC[3] .... の様に取り出せるので楽です。

changeData

この関数内では、BTC価格を上昇・下降率に変換しています。BTC価格そのままよりも、ある程度規格化されたデータの方が学習精度が上がります。
この関数の出力であるdataには、前日に比べてどのくらいの割合で上がった、または下がったかのデータが入っています。上がった場合は+値、下がった場合は−値になります。

preparationTrainAndKyoushiSets

この関数は、トレーニングデータと教師データのセットを作る関数です。
train_Xがトレーニングデータのセットで、train_yが教師データのセットです。

theNumberOfTrainData個のトレーニングデータ、[data[1],data[2],data[3],.....data[theNumberOfTrainData]に対し、1個の教師データ[int(0 < data[0])]が対応します。

つまり昨日までのBTC価格data[1]~をトレーニングデータとするのに対し、今日のBTC価格が上がったか、または下がったかint(0 < data[0])が教師データになります。

int(0 < data[0])はBool値(True,False)をint型で返します。つまり上がっていれば1になり、下がっていれば0になります。

これらを1日ずつ過去にずらし、theNumberOfTrainAndKyoushiSet個のトレーニングデータと教師データのセットを作っています。

トレーニングデータ、[data[1],data[2],data[3],.....data[theNumberOfTrainData]に対し、教師データ[int(0 < data[0])]
トレーニングデータ、[data[2],data[3],data[4],.....data[theNumberOfTrainData+1]に対し、教師データ[int(0 < data[1])]
...
...
...
トレーニングデータ、[data[theNumberOfTrainAndKyoushiSet],data[theNumberOfTrainAndKyoushiSet+1],data[theNumberOfTrainAndKyoushiSet+1],.....data[theNumberOfTrainData+theNumberOfTrainAndKyoushiSet]に対し、教師データ[int(0 < data[theNumberOfTrainAndKyoushiSet-1])]
predictionTommorowBTC

明日のBTC価格を予想する関数です。

以下for文中のtree.DecisionTreeClassifier()で決定木インスタンスclfを定義しています。

for i in range(0, studyTrialTimes):
   clf = tree.DecisionTreeClassifier()
   clf.fit(train_X, train_y)
   y_PredictionTommorow.append(clf.predict([X])[0])

学習部分は、clf.fit(train_X, train_y)です。トレーニングデータと教師データのセットを入力し、トレーニングデータに対する教師データのパターンを学習しています。

予想部分は、clf.predict([X])です。過去のトレーニングデータで学習した決定木インスタンスに、教師データが存在しないX、つまり[data[0],data[1],data[2],.....data[theNumberOfTrainData-1]を入力して、未知の教師データを予想します。

tree.DecisionTreeClassifier()関数中に乱数のパラメータがあるため、同じトレーニングデータで学習しても予測値が異なる場合があります。
for文でstudyTrialTimes回(ここでは200回に設定しています)回すことで、予想結果の確率を算出しています