仮想通貨のお勉強その2 APIから情報を引っ張ってくる
APIからティッカー情報を引っ張ってくる
下記サイトを参考にして(というかそのまま)、さわりだけ勉強、
https://qiita.com/ti-ginkgo/items/7e15bdac6618c07534be
requestsってライブラリは初めて使いました。
何するライブラリなの?
下記サイトを参考にさせてもらいました。
Requests の使い方 (Python Library) - Qiita
httpライブラリらしいですね。使いやすそう。
ティッカー情報をgetします。
import requests import json from pandas import DataFrame URL = 'https://coincheck.com/api/ticker' coincheck = requests.get(URL).json() #json形式のデータから、keyとlistを引っ張ってくる、 #さらにデータ形式を揃えて見やすい形に直します。 for key, item in coincheck.items(): print("%-9s : %-10.9s " % (key, item))
以下別の方法、
http://soy-curd.hatenablog.com/entry/2017/05/06/013515
from coincheck import market m = market.Market() result = m.ticker() print(result)
昔のデータも引っ張ってこれます。
import pandas as pd from datetime import datetime import matplotlib.pyplot as plt import matplotlib df = pd.read_csv("http://api.bitcoincharts.com/v1/trades.csv?symbol=coincheckJPY", header=None, parse_dates=True, date_parser=lambda x: datetime.fromtimestamp(float(x)), index_col='datetime', names=['datetime', 'price', 'amount']) df["price"].plot() plt.show()
ひっぱてきた情報をデータベースに保存できれば、良さげ、
データベースの勉強もしないと
仮想通貨のお勉強
仮想通貨
世の中流行ってますね。
冬休みでまとまった時間があったので勉強してみました。
色んなブログやら書籍やらありますが、主に下記を読みました。
結構ボリュームがあるので、大枠しか読んでませんが、、、
わからないことは、いろいろググりながら読み進めました。
https://www.bitcoinbook.info/translations/ja/book.pdf
ブロックチェーンやらマイニングってなんですかね、
・ブロックチェーンって何?
複数の取引(トランザクション)がまとまって1個のブロックになっており、
複数のブロックが鎖上に繋がっている。
ブロックの中身は下記図の通り、
トランザクション以外にも、前ブロックのハッシュ値やnonceで構成されている。
Bitcoin等の仮想通貨は、ウォレットというものは、このブロックごとの取引情報をかき集めて、合計金額とします。
実際に一つのストレージに個人のお金情報を集めているわけではにです。
なので、個人のお金はブロック毎に分散されて保存されています。
・マイニングって何すること?
ブロックチェーンにおける合意形成(売買の承認)の方法で、
マイナーと呼ばれる人たちが実施しています。
マイナーはマイニングの対価として、仮想通貨を得ます。
流れとしては、
P2Pネットワークを伝わってくるトランザクション情報を、
マイナーはローカルのデータプールにいくつか集め、それらを加工することにより新規ブロックにして、
最後にチェーンにつなげます。
チェーンに繋いだら、繋いだ事を別のマイナー達に伝えます。
別のマイナーは、これを承認します。
尚、トランザクションには優先順位(マイナーに支払われる手数料、取引時間等で決まる)があるので、
優先順位が低いものは次のブロックへ廻されます。
具体的にマイングとは、何をするかというと、
「トランザクション+nonce+前ブロックのハッシュ値」のハッシュ値が、
ある特定の値以下になるように、nonceを決めることです。
このnonceを決める(総当たり的に計算する)のがマイニングです。
「ある特定の値以下」の値は流動的で、
マイニングが10分程度になるように、調整されます。
マイニングは、コンピューターの性能に依存するので、
高性能のコンピュータならすぐ計算できるし、そうでなければ遅くなります。
kaggleに挑戦その5 過学習、学習不足の可視化
学習曲線
データセットに対してモデルが複雑すぎる場合、過学習する傾向があり汎化性能が落ちてしまう。
トレーニングデータをさらに集めると、過学習は抑えることができるが、データをさらに集めることはコストが非常に高い。
また、実はこれ以上データを集めても無駄ということもある。 そんなとき、学習曲線を使うことでデータを集めることに価値があるか、検証できる。
有名な過学習、学習不足の絵ですね。
過学習と、学習不足が丁度良いバランスの場合、
トレーニングデータセットから作成したモデルの精度と、
そのデータを(例えば)K分割交差検証で評価したモデルの精度が同程度になります。
逆にすでに同程度の場合、これ以上サンプル数を増やしても精度は上がらないですね。
精度を上げたい場合は、モデル自体を変えた方が良いことになります。
今回作成したモデルはどうなんでしょう、、、
import matplotlib.pyplot as plt from sklearn.learning_curve import learning_curve train_sizes,train_scores,valid_scores = learning_curve(estimator=forest, X=X_train, y=y_train, train_sizes=np.linspace(0.1,1.0,10), cv=10, n_jobs=1) train_mean = np.mean(train_scores,axis = 1) test_mean = np.mean(valid_scores,axis=1) plt.plot(train_sizes,train_mean) plt.plot(train_sizes,test_mean) plt.show()
過学習してますねー。
データ数増やしていけば、過学習を抑えることができるってことがわかります。
実際は、データ数を増やすことはできないので、
モデルの複雑さを抑えて汎化性能を上げる必要があるかと思います。
kaggleに挑戦その4 k分割交差検証(k-fold cross-validation)及びグリッドサーチ
k分割交差検証
前回までで、ランダムフォレストでモデル予測を実施しました。
今回は、k分割交差検証、グリッドサーチを用いてモデル性能の評価及びハイパーパラメータの修正を行います。
これにより、バイアス高、バリアンス高のバランスをとることができます。
ランダムフォレストで、モデル化してみましたが、これは汎化性能がどの程度あるのか、
k分割交差検証で調べます。
k分割交差検証とは、トレーニングデータをランダムにk個分割して、
そのうちk-1個をモデル予想に使い、残りの1個でそのモデルを予想し、
この手順をk回繰り返すことで、そのモデルの平均性能を評価するものです。
kをどの程度の値にすべきかは、もとのデータセットに依存します。
kの値でどう変わるかというと、、、
・kが大きいと、各トレーニングサブセットの値が似てきて、評価のバリアンス高(性能評価の結果が、テストデータに依存した形となりやすい。)となりやすい。
・kが小さいと、各トレーニングサブセットの値が違いすぎて、バイアス高となりモデルの正確な評価ができない(毎回違う評価結果となる)。
ということです。
今回は、k=5として実施していきます。
from sklearn.model_selection import KFold from sklearn import metrics from sklearn.metrics import accuracy_score K = 5 kf = KFold(n_splits=K, shuffle=True, random_state=1 ) score_train_tmp = 0 score_test_tmp = 0 X = x_train y = np.array(titanic_df_main_random_forest["Survived"]) for train_index,test_index in kf.split(X): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] # トレーニングサブセットでモデル構築 forest.fit(X_train, y_train) # トレーニングサブセットでの予測値 pred_train = forest.predict(X_train) # トレーニングサブセットのaccuracy auccuracy = accuracy_score(pred_train, y_train) #トレーニングサブセットのaccuracyを足していく score_train_tmp+=auccuracy #テストサブセットの予測値 pred_test = forest.predict(X_test) #テストサブセットのaccuracy auccuracy = accuracy_score(pred_test, y_test) #テストサブセットのaccuracyを足していく score_test_tmp+=auccuracy
これで、ランダムフォレストモデル(n_estimators = 100)の平均性能を評価することができます。
続いて、nn_estimators を変えたら、モデル性能はどのように変わるか、グリッドサーチ及びk分割交差検証を実施していきます。
グリッドサーチ
事前に決めるべきパラメータのことをハイパーパラメーターといいます。
今回は、2分木の数(n_estimators)がそれに当たります。
これはいくつにすれば良いのか???ということで今回はグリッドサーチを実施します。
グリッドサーチとは、パラメータを網羅的に変えながら、モデルの良し悪しを評価(例えばk分割交差検証)していき、
何が一番良いのか決める方法のことです。
scikit-learnには、もともとグリッドサーチ用のクラスが準備されているのでそれを使います。
(for文でループ!とかやらなくてもOK)
from sklearn.model_selection import GridSearchCV param_grid = {"n_estimators":[10,20,30,40,50,60,70,80,90,100]} tree_grid = GridSearchCV(estimator=forest, param_grid = param_grid, scoring="accuracy", #metrics cv = K, #cross-validation n_jobs =-1) #number of core tree_grid.fit(X,y) #fit tree_grid_best = tree_grid.best_estimator_ #best estimator print("Best Model Parameter: ",tree_grid.best_params_) print("Best Model Score : ",tree_grid.best_score_)
実行した結果が以下です。n_estimatorsがいくつだと性能が良いかわかりますね。
Best Model Parameter: {'n_estimators': 90} Best Model Score : 0.805836139169
kaggleに挑戦その3 ランダムフォレストを可視化
決定木の可視化
決定木の利点としては、意味解釈可能性があります。
ランダムフォレストで作成された決定木を可視化して、その意味を解釈しようと思います。
scikit-learnには、決定木を.dotファイルとしてエクスポートする機能があります。
その前に、.dotファイルを使うために、自分のパソコンにGraphVizをインストールします。
pip install pydotplus brew install Graphviz
ランダムフォレストで作成された決定木を.dotファイルにエクスポートします。
#ランダムフォレストを作成 from sklearn.ensemble import RandomForestClassifier forest = RandomForestClassifier(criterion="entropy",n_estimators = 100) forest = forest.fit(x_train,y_train) #dotファイルを出力 from sklearn import tree for i,val in enumerate(forest.estimators_): tree.export_graphviz(forest.estimators_[i], out_file='tree_%d.dot'%i)
ファイルが出力されたら、コマンドライン上で.dotファイルを.pngファイルに変換します。
例として、最初の決定木をpngファイルにしてみます。
>dot -Tpng tree_0.dot -o tree.png
実際のファイルは以下です。どういうロジックでTrue or Falseが分岐しているか、一目瞭然ですね。
一番大事な変数は?
scikit-learnのfeature_importancesを使うことにより、重要は変数がわかります。
重要変数は各変数での分岐の際に、情報エントロピーの差分を各決定木で平均させて、求められます。
titanic_df_main_random_forest_df = titanic_df_main_random_forest.drop("Survived",axis = 1).columns importances_df = forest.feature_importances_ random_forest_df = pd.DataFrame({"変数":titanic_df_main_random_forest_df,"corr":importances_df}) random_forest_df= random_forest_df.sort_values(by = "corr",ascending=False) sns.barplot(x = "変数",y = "corr",data = random_forest_df)
一番重要な変数は、Ageのようですね。
kaggleに挑戦 その2 ランダムフォレスト
ランダムフォレストって何?
ランダムフォレストは、複数の決定木を組み合わせて、
各決定木における予想結果の多数決により、結果を得ます。
アルゴリズムとしては、
1.ランダムにn個のデータを抽出、
2.1で取得したデータから決定木を成長、
3.1と2を複数回繰り返す、
4.予想結果を多数決する、
タイタニック号のデータに適用する。
まずは、簡単にするため、
説明変数を"Age"、"Pclass"、"Sex"に絞ろうと思います。
目的変数"Survived"と相関があるか調べます。
#必要なモジュールインポート import pandas as pd import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline #データの読み込み titanic_df = pd.read_csv("train.csv") titanic_df.info() sns.factorplot("Pclass","Survived",data = titanic_df_main, hue = "Sex") sns.lmplot('Age','Survived',data=titanic_df)
データの可視化には、seabornというライブラリを使ってます。
factorplot した歳の、データ点は平均値、誤差棒は標準誤差分です。
男性、3等客室は亡くなった方が多いことがわかります。
近似直線を引くと、右肩下がりになっています。
年齢が高い方が、亡くなった方が多いことがわかります。
"Age"、"Pclass"、"Sex"は説明変数として使えそうですね。
続いて、解析する前にデータを整形します。
"Age"には欠損値が多く、そのままではデータ解析できません。
欠損値を中央値で置き換えることにします。
titanic_df_main["Age"].fillna(titanic_df_main["Age"].median(),inplace = True)
続いて、"Sex"をダミー変数に変えます。
dummy = pd.get_dummies(data = titanic_df_main["Sex"],drop_first=True) titanic_df_main = titanic_df_main.combine_first(dummy)
ダミー変数は、オプションとして、「drop_fisrt = True 」とすると第1項を落としてくれます。
説明変数としてダミー変数を使う場合、多重共線性から上記を実施する必要があります。
続いてscikit-learnのランダムフォレストを利用して、実装していきます。
ランダムフォレストを実装
ランダムフォレストの代表的パラメーターとしては、以下3種類です。
1.ランダムに選ぶデータの数
2.説明変数の数(木の深さ)
3.決定木の数
1と2に関しては、デフォルト値を採用します。
尚、1のデフォルト値はデータ数になります。
データは、復元抽出で選ばれるので、すべてのデータが使われるわけではありません。
2のデフォルト値は、説明変数のルートをとったものです。
3はとりあえずn=100とします。
titanic_df_main_random_forest = titanic_df_main.drop(["PassengerId","Sex"],axis = 1 ) train_data = titanic_df_main_random_forest.values x_train = train_data[:,[0,1,3]] y_train = train_data[:,2] from sklearn.ensemble import RandomForestClassifier forest = RandomForestClassifier(criterion = "entropy", n_estimators = 100)
これでランダムフォレストを実装できました。
決定木の数に関しては、当然数が多いと性能はよくなりますが、計算コストが増えます。
これはグリッドサーチにより決めれば良いと思います。
次はグリッドサーチとランダムフォレストの結果について書こうと思います。