確率的プログラミングライブラリ「Edward」まとめ

Edwardで何ができるのか知らなかったので、忘備録として残しておきます。

目次
・Edwardとは
・Edwardでできること
・参考スライド
・参考文献

Edwardとは

・LDAで有名なコロンビア大のBlei先生の研究室で、2016年より開発されている確率的プログラミング1) プログラミング言語の変数をモデルの構成要素として使うプログラミングのPythonライブラリ。
・積み木のように明快な形で確率的モデリングを行うことができる。(モデル→推論→評価 を一括でできる。)
・ベイズ統計と機械学習、深層学習、確率的プログラミングを融合させている。
・計算の際にTensorFlowを用いている。TensorBoardを可視化の際に用いることもできる。
・計算速度がStanやPyMC3よりも速い。GPUを用いた高速化も可能。2) pip install tensorflow-gpuでGPU版のTensolFlowを入れておく必要がある。
・統計学者のGeorge Edward Pelham Boxから名前を取っている。

Edwardでできること

一般的なベイズ推定は当然ながら、深層学習向けのベイズ適用系の事例が豊富なようです。

・ベイズ線形回帰( Supervised Learning (Regression) )
・バッチトレーニング(巨大なデータセットにおける学習で用いる)( Batch Training )
・Tensorboardを用いた可視化( Tensorboard
・Automated Transformations( Automated Transformations )
・線形混合効果モデル( Linear Mixed Effects Models )
・教師あり学習による分類( Supervised Learning (Classification) )
・教師なし学習( Unsupervised Learning )
・ニューラルネットワークの潜在空間モデル( Latent Space Models for Neural Data )
・混合密度ネットワーク( Mixture Density Networks )
・GAN( Generative Adversarial Networks )
・確率的デコーダー( Probabilistic Decoder )
・ネットワークの推論( Inference Networks )
・ベイジアンニューラルネットワーク( Bayesian Neural Network )
・確率的PCA(主成分分析)( Probabilistic PCA )

jupyterのコードたちはblei-lab/edwardのnotebookに載っています。

2層のニューラルネットワークへのベイズ推定の適用(
Bayesian Deep Learning with Edward (and a trick using Dropout) – Andrew Rowan – PyData London 2017)
Gounosyの方のブログによると、CTR予測などで扱うことができるようです。

参考スライド

参考文献

Edward: A library for probabilistic modeling, inference, and criticism

DEEP PROBABILISTIC PROGRAMMING

EdwardでBayesian DNN+Variational Inferenceをやってみた話

DEEP PROBABILISTIC PROGRAMMING —”深層学習+ベイズ”のライブラリ— Edwardの紹介

【Edward】MCMCの数学的基礎からStochastic Gradient Langevin Dynamicsの実装まで

Hello, world! Stan, PyMC3, and Edward
stanの開発者の方がstanとPyMC3とEdwardを比較しています。

Pythonで体験するベイズ推論 PyMCによるMCMC入門

References   [ + ]

1.  プログラミング言語の変数をモデルの構成要素として使うプログラミング
2.  pip install tensorflow-gpuでGPU版のTensolFlowを入れておく必要がある。

洋楽の歌詞データでDoc2vecを実行してみる

はじめに

仕事で記事間の類似度計算などがあったりするんですが、TF-IDFにしてCOS類似度を計算するなどの方法で行っているのが現状です。そろそろ他の手法にも移行したいので、それに変わる類似度計算の手段としてDoc2vecを試してみたいと思います。

データ

以前より収集している洋楽の歌詞データを用います。Billboardのランキングに登場した楽曲の歌詞データを961曲分集めたものとなります。英語なので、日本語のように形態素解析は不要ですが、ストップワードを除去するなどの処理を施したコーパスを用います。Rのtmパッケージによるストップワードの除去についてはBillboard100位以内の楽曲の歌詞情報にLDAを適用してみたをご覧ください。日本語でのDoc2Vecの適用は参考文献において紹介しています。

類似度計算

TaggedLineDocumentを用いて、doc2vecで扱えるオブジェクトを作成します。TaggedLineDocumentに指定するファイルは主にtxtファイルで、その満たすべき条件は「1行につき1文書」「単語がスペースで区切られている」などです。あとは、doc2vecを実行するだけです。パラメータなどの細かい指定については今後の宿題としたいです。

類似度の算出

早速、気になる楽曲に関して、類似度の高い楽曲を抽出してみたいと思います。

どうやら、Radioactiveという曲はkings of leonというグループも歌っているようですが、私はimagine dragonsの方の楽曲に関心がありますので、インデックスを409にして歌詞情報の近い楽曲を抽出します。

どうやら、toby keithのMade In Americaという楽曲が最も近いようです。類似度は35%程度ですが、全然単語が被っていないので本当に近いのか納得がいかないです。

次に、lady gagaのBorn This Wayに近い楽曲を出してみます。Dancing Queenという非常に懐かしい曲が選ばれていますが、類似度は49%と先ほどよりも高いです。queenやgirlやcanやrightなど共通の単語が含まれているので、先ほどの結果よりは近いのかなぁと思います。

正しく推定できているのか不安だったので、類似度が90%と非常に高かった、Just The Way You Areという楽曲の最も近い楽曲を見てみます。

調べたところ、同じ楽曲のカバー版のようです。近いものは、ちゃんと近いと見なせるようです。近いかどうかの基準をどの水準に置くのかは難しい判断ですね。

参考情報

models.doc2vec – Deep learning with paragraph2vec
Doc2Vecの仕組みとgensimを使った文書類似度算出チュートリアル
Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Billboard100位以内の楽曲の歌詞情報にLDAを適用してみた

目次

・はじめに
・データ収集
・Rによる分析
・LDAの結果
・参考文献

はじめに

前回の投稿でBillboardの週次洋楽ランキングデータをWebスクレイピングで取得し、楽曲の消費サイクルのような順位の挙動を確かめることができました。(某洋楽ヒットチャートの週次ランキングデータをBeautiful Soupで集めてみた)今回は、歌詞の情報を用いて順位データとつなぐことにより、どのような単語の入っている洋楽がBillboardにおいてTop10に入る傾向があるのかをLDAを行うことで確かめたいと思います。

データ収集

残念なことに、Billboardのサイトに歌詞の情報は載っていません。そこで、洋楽の歌詞が取り上げられている某サイトをPython(3系)でWebスクレイピングし、名寄せを頑張って順位データと歌詞データを繋ぎます。

幸いなことに某サイトのURLに規則性があったので、アーティスト名からなるURLを生成し、そのURLをWebスクレイピングして楽曲のリストを集め、今回のBillboardのランキングに入った楽曲のみに絞ります。

楽曲をランキングに含まれるもののみに絞ったら、歌詞詳細ページを取得します。

うまいこと歌詞情報を手に入れることができました。ざっと947曲です。

Rによる分析

ここから、Rにてテキストマイニングを行いたいと思います。まず、tmパッケージを用いて、不要語(stop word)を除去します。具体的にはtheとかyouとかを除外しています。

続いて、LDAを実行できるtopicmodelsパッケージで扱えるようにするために、テキストデータに以下の処理を施します。

あとは以下のコードでLDAを実行するだけです。トピック数はアドホックに20としています。研究者の方、いい加減ですみません。

LDAの結果

まずは推定されたトピックごとの上位10単語をみてみます。トピック1はラブソングとかでしょうか。トピック17にパリピっぽい単語が、トピック18にスラングが含まれていますね。

見ずらいので、行を一つにまとめて、トピックにidを割り振ります。

最後に、BillboardでTop10に入ったかどうかのデータを作っておき、そのデータと各歌詞を繋ぎ、各歌詞ごとに割りふられた確率が最大のトピックで集計をします。

BillboardのTop10ランクイン割合の高いトピックTop3
「one,ooh,call,cause,gettin,born,day,makes,came,stand」
「better,world,whoa,run,light,things,find,show,see,waiting」・・・明るい感じ?
「stop,just,hands,put,party,crazy,live,lights,play,see」・・・パリピぽい

BillboardのTop10ランクイン割合の低いトピックTop3
「wanna,want,take,rock,see,kiss,come,make,body,tonight」・・・欲求系?
「feel,heart,life,away,just,break,real,enough,every,find」・・・癒し系?
「hey,said,old,every,woo,left,told,nothing,daddy,sweet」

あまり洋楽を聴かないので、得られたトピックの解釈が中々できないのがもどかしいです。ただ、スラングの歌詞を含む歌詞はそんなにランクイン割合が悪いわけではなさそうですね。洋楽をもっと聴いて、前処理などもう少し工夫してリベンジしたいですね。

参考文献

トピックモデルによる統計的潜在意味解析 (自然言語処理シリーズ)

Pythonクローリング&スクレイピング -データ収集・解析のための実践開発ガイド-

モダンなRによるテキスト解析topicmodels: An R Package for Fitting Topic Models

某洋楽ヒットチャートの週次ランキングデータをBeautiful Soupで集めてみた

はじめに

知人より、洋楽の流行りに疎いのでキャッチアップしたいという要望があり、某洋楽ヒットチャートの週次ランキングとTop100のデータを大量に集めてみようと思うに至りました。今回は深い考察を行うには至っていませんが、簡単にRにて集計・可視化を行います。

データ収集

Webスクレイピング対象の某洋楽ヒットチャートの週次ランキングは今週の順位・先週の順位・アーティスト名・曲名・詳細ページへのリンクなどが載せられおり、毎週土曜日更新されています。サイト内から導線はありませんが、URLのパラメータに法則があるため、うまく収集できます。今回は2010年8月〜2017年6月の約7年分のデータを集めます。

URLのリストをCSVで読み込み、BeautifulSoupでタグを指定して抽出します。

データ取得後は簡単にpandasのstr.replaceで整形すると、以下のような結果になります。今週の順位と先週の順位が引っ付いてしまっています。

ここから横着してRで整形し、各週の順位データを作成しました。

データ確認

データ構造はこのような形です。

まず、どんな楽曲やアーティストがランキングに入っているのかを簡単に確認してみます。 ほとんど聞いたことない人の名前、曲名ですが。。

続いて、2010年8月〜2017年6月の間に100位以内に入った数を楽曲ごとにヒストグラムにしてみます。べき乗分布な形かと思いきや、20回前後で盛り上がっているのが気になりますね。

中央値が9週間なので、意外と長い期間Top100には入っています。

続いて、100位以内に入った数をアーティストごとにヒストグラムにしてみます。こちらはべき乗分布のような形になっています。

Top10入りの楽曲の実態

Top10に入っている楽曲のみに絞って、ヒストグラムを描いてみます。

Top10に入ったら、10週近くは10位以内に含まれるようです。上位はすぐに取って代わられるのかと思いきや、人気が人気を呼ぶとかなのでしょうか。確か、某ECサイトの方が、生キャラメルは売れるから売れたんだとか言っていた気がします。

順位の推移

100位以内にランクインした回数が最も多かった楽曲のTop10に関して、時系列プロットをしてみます。


初回に上位にランクインして、後は下がるだけの楽曲や、じわじわとランキングを上げていく楽曲などが観察されています。楽曲の消費のサイクルみたいなものがあるのでしょう。

今後について

せっかく面白そうなデータが手に入ったので、リンク先も辿って、どのような楽曲やアーティストの特徴が人気に繋がりうるのか見てみるのも良いですね。あと、もう少し洋楽聴いてみようと思います。私はクラシック音楽とジャズしかウォークマンに入っていないので。

参考文献

Pythonクローリング&スクレイピング -データ収集・解析のための実践開発ガイド-

PythonやRを用いたアルゴリズム取引・株価分析まとめ

はじめに

まわりでシステムトレードや株価の機械学習による予測などに関心が高まってきたので、私も少し調べてみようと思いPythonやRで行われた分析・実装の事例を集めてみました。自分の資産を突っ込む気にはなれないですが、事例を知っておくだけ知っておきたいですね。

調査法

Google検索において以下のクエリで上位に表示されたサイトを中心にまとめました。
「python 機械学習 株価」
「python 機械学習 為替」
「python アルゴリズム取引」
「python machine learning stock price」
(同様にRも調べました。)

アルゴリズムトレードの理論から学ぶ

システムトレードで億万長者になるぞ! coursera で Computational Investing Part I を受けた
こちらはCourseraで開かれていたシステムトレード向けの講座を受けた方のブログです。Active Portfolio Management: A Quantitative Approach for Producing Superior Returns and Selecting Superior Returns and Controlling Riskはもっとも重要なアルゴリズムトレードの本とされているようです。出版年が1999年と結構古いですが。
Active Portfolio Management: A Quantitative Approach for Producing Superior Returns and Selecting Superior Returns and Controlling Risk (McGraw-Hill Library of Investment and Finance)

Rを用いた株価データのモニタリング

Stock Analysis using R
こちらはアルゴリズム取引とかではないですが、Rで株価を簡単に取得できるquantmodライブラリについて紹介されています。

以上のコードを実行しただけで時系列データがボックスプロットで描写されました。非常に便利そうです。複数のグラフを並べてディスプレーで見てみたいですね。図ではテクニカル分析で使われるボリンジャーバンドを一発で出してくれています。傾向を掴むための分析に役立つのではないでしょうか。

MSFT_stockPrice

RSIで株価の連動性を見る

過去のデータからビッグデータ分析で株価を予測する
ここでは、主にpandasを用いて株価の分析を行っています。RSI(Relative Strength Index)という「一定の期間変動幅の中でどれ位株価が上昇しているのか、下落しているのかをはかるもの」を計算して日経平均との相関を見ています。データさえあれば、個別株の市場連動性を見るぶんにはpandasで十分に分析できそうです。

アルゴリズムトレードのシステム構成

自動トレードボット
こちらでは、仮想通貨取引のための自動トレードボットの作成のための手順などが書かれています。
工程としては
・仮想通貨価格データ取得
・バックテストの実施
・明日の価格予想
・学習パラメータの最適化
・結果のメール送信
・APIを使った成行トレード
・ジョブのスケジューリング
などとなっているようです。
完全自動化しようと思うと、作るのは大変そうですね。

WEB屋の自分が機械学習株価予想プログラムを開発した結果
こちらはよりシンプルで
「チャートを見る限り、誰がどうみても今日値上がりする銘柄」を検索して、毎朝Slackに通知してくれるシステム
をPythonで作成されています。最終的に資産を溶かす形になっているようです。

アルゴリズムトレード向けのPythonライブラリ

pythonのアルゴリズムトレードライブラリ
こちらでは
zipline( http://www.zipline.io/
PyAlgoTrade( http://gbeced.github.io/pyalgotrade/ )
pybacktest( https://github.com/ematvey/pybacktest )
backtrader( https://github.com/mementum/backtrader )
というライブラリが紹介されています。

遺伝的アルゴリズムで為替の自動売買

pythonと遺伝的アルゴリズムで作るFX自動売買システム その1
遺伝的アルゴリズムでFX自動売買 その2 進化する売買AIの実装
遺伝的アルゴリズムでFX自動売買 その3 OandaAPIで実際に取引
こちらは、外国為替の取引をPythonで自動化させた試みです。最終的に負けてしまってはいますがシステム構成についても詳しく書かれているので、勉強になりました。データはOANDAというサービスが提供しているAPIを用いて取得し、GA(遺伝的アルゴリズム)を使って為替の売買タイミングを決めているようです。実際の売買にもOandaAPIというものを利用して完全に自動化させています。

決定木による株価リターンの予測

機械学習で未来を予測する – scikit-learn の決定木で未来の株価を予測
こちらはPythonでscikit-learnを用いて、決定木による株価の予測をされています。目的変数としてはリターンインデックスをおいています。前処理においてpandasが使われています。

ランダムフォレストによる株価の予測

Pythonで機械学習を使った株価予測のコードを書こう
こちらでは、ランダムフォレストを用いた機械学習で、ETFなどのデータを特徴量にして個別の株価予測を行っています。

アカデミックサイドでの研究事例

Stock Price Forecasting Using Information from Yahoo Finance and Google Trend
UC Berkeleyの経済学部生の研究です。こちらはR言語で、ヤフーファイナンスとGoogleトレンドの情報を用いて株価を予測している研究です。これまでの時系列手法よりもパフォーマンスが良いそうです。

最後に

事例を集めてみて、どこまでのレベルのものに手を出すべきか悩ましいと思いました。完全自動化は維持するコストがかかりそうですし、ロスが増大しないか心配です。自分としては情報を自動で取得し、リターンが発生する確率の高そうな銘柄をサジェストしてくれるレベルで十分な気がします。

追記

人工知能学会の全国大会2017でAIを用いた株式運用に関する研究がなされていました。深層学習を用いたものが多そうです。
株価変動パターンの類似性を用いた株価予測
深層学習と高頻度データを用いた株式注文状況の推定
LSTM を用いた株価変動予測
深層学習を用いた株価予測の分析

OpenCV&Pythonで画像の類似度を計算させる〜イケメンの顔比較

・動機
・やりたいこと
・準備
・類似度の計算
・実行コード
・実行結果
・おまけ

動機

画像系の技術にあまり関心が無かったのですが、とある知人が福士蒼汰のような雰囲気の男性が好みであると発言されたことを発端に、福士蒼汰に最も顔の近い知人を見つけるというプライベートなミッションを仰せつかりました。
そこで、まずは最も楽だろうと思われる、画像間の類似度を計算する方法について調べてみました。顔のパーツを検知して、パーツ同士で比較するなどのレベルでは無いことをご了承下さい。ちなみに、比較画像は国民的アイドルである嵐のメンバーの画像としました。今回の実践で、与えられた画像の中で、福士蒼汰に最も近そうな嵐のメンバーの写真がわかることになります。

やりたいこと

画像間の類似度の計算

準備

・Python2.7
・OpenCV

OSX環境における準備にあたっては以下の情報が参考になりました。
PythonでOpenCVを使う
Mac OS X で OpenCV 3 + Python 2/3 の開発環境を整備する方法

類似度の計算

こちらのブログにある計算手法とコードを使いました。
How-To: Python Compare Two Images

紹介されているコードで以下の評価指標が計算できます。
・Mean Squared Error (MSE)
・Structural Similarity Index (SSIM)・・・0〜1の値を取ります。

指標について、詳しくはこちらの論文に書かれています。
Image Quality Assessment: From Error Visibility to Structural Similarity

実行コード

紹介されていたコードは画像サイズが同じでないと計算ができなかったので、まずは画像のサイズを整えるためのコードが以下のようになります。コードはこちらのものを使いました。
Python – アンチエイリアスで写真をキレイに縮小

これだけではサイズが同一にならなかったので、追加で以下のコードを実行しました。

以下は、類似度計算の実行用コードとなります。

実行結果

福士蒼汰との比較をしており、画像上部にMSEとSSIMが出ています。嵐の大野くんが一番近いようです。

original

aiba

oono

sakurai

ninomiya

matsumoto

おまけ

イケメンではないですが、出川哲朗でも計算してみました。

degawa

今回最も高い値が出てしまいました。やはり、顔のパーツを識別して、そのパーツ間の類似度の計算ができないといけないような気がします。悔しいので今後も画像認識系の技術について向き合ってみようと思います。

References   [ + ]

1. x, y), Image.ANTIALIAS) else: # アンチエイリアスなしで縮小 resize_img = resize_img.resize((x, y
2. x, y # リサイズ後の画像を保存 resize_img.save(after, 'jpeg', quality=100) print "RESIZED!:{}[{}x{}] --> {}x{}".format(filename, before_x, before_y, x, y) # 実行 main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# -*- coding: utf-8 -*-
import commands
from PIL import Image
import re
 
# 縮小する際の画像の高さピクセル
PHOTO_HEIGHT = 400
 
# 画像があるフォルダのフルパス
BASE_DIR = "/任意のフォルダのパス/"
 
# 画像の正規表現名
PHOTO_REGEX = r"pic00.*.[jpg|jpeg]"
 
# リサイズ後の画像の接頭語
PHOTO_RESIZE_PREFIX = "r_"
 
def main():
    # 画像フルパスを取得
    _cmd = "cd {} && ls".format(BASE_DIR)
    l = commands.getoutput(_cmd)
    l = l.split("\n")
    l = [_l for _l in l if re.match(PHOTO_REGEX, _l)]
 
    # 出力用のフォルダを生成
    commands.getoutput("mkdir {}/output".format(BASE_DIR))
 
    # 既存ファイルを readモードで読み込み
    for _l in l:
        before_path = '{}/{}'.format(BASE_DIR, _l)
        filename = '{}{}'.format(PHOTO_RESIZE_PREFIX, _l)
        after_path = '{}/output/{}'.format(BASE_DIR, filename)
        resize(before_path, after_path, filename=_l)  # 縮小
 
 
def resize(before, after, height=PHOTO_HEIGHT, filename="", aa_enable=True):
    """
    画像をリサイズする
    :param str before: 元画像ファイルパス
    :param str after: リサイズ後の画像ファイルパス
    :param int height: リサイズ後の画像の高さ
    :param bool aa_enable: アンチエイリアスを有効にするか
    :return:
    """
    # 画像をreadonlyで開く
    img = Image.open(before, 'r')
    # リサイズ後の画像ピクセルを計算
    before_x, before_y = img.size[0], img.size[1]
    x = int(round(float(height / float(before_y) * float(before_x))))
    y = height
    resize_img = img
    if aa_enable:
        # アンチエイリアスありで縮小
        resize_img.thumbnail((x, y), Image.ANTIALIAS)
    else:
        # アンチエイリアスなしで縮小
        resize_img = resize_img.resize((x, y))
 
    # リサイズ後の画像を保存
    resize_img.save(after, 'jpeg', quality=100)
    print "RESIZED!:{}[{}x{}] --> {}x{}".format(filename, before_x, before_y, x, y)
 
 
# 実行
main()

これだけではサイズが同一にならなかったので、追加で以下のコードを実行しました。

以下は、類似度計算の実行用コードとなります。

以下は、類似度計算の実行用コードとなります。

教師付き学習編

圧倒的に多いのがSVM(Support Vector Machine)を扱っているSVCモジュールで、続いて定番のロジスティック回帰やRandom Forestが使われているようです。統計解析ではメジャーなはずの線形回帰が5位なのは、初歩的なのであまりコードがアップされていないのかもしれません。GBDTのモジュールももう少し上位にくるかと思ったんですが15位でした。DMLCのXGBoostモジュールを使っているのかもしれませんね。私も実際のところXGBoostを使ってますし。

supervised_module_barplot

教師無し学習編

主成分分析やK-mean法など因子分解などのモジュールが上位を占めています。LDA(Latent Dirichlet Allocation)がもっと上位に来ると思ったんですが、思えばGensimの方が充実しているなぁと思うので、このランキングは妥当なのかもしれません。私もLDAなどはGensimを使っていますし。

unsupervised_module_barplot

収集を終えて

・社内だとデータサイエンティストの方がいないので、scikit-learnのモジュールの利用状況を知れてマニアックな共感をすることができた。
・SVMは実践例が豊富そうなので分析事例を探せば良い発見があるかもしれない。
・scikit-learnのUser Guideは充実していたので、時間を作って向き合ってみたいと思った。

XGBoostのパラメータチューニング実践 with Python

以前の投稿で紹介したXGBoostのパラメータチューニング方法ですが、実際のデータセットに対して実行するためのプログラムを実践してみようと思います。プログラム自体はAnalytics_Vidhya/Articles/Parameter_Tuning_XGBoost_with_Example/XGBoost models.ipynbに載っているのですが、データセットがついていません。そこで、前回の投稿(不均衡なデータの分類問題について with Python)で赤ワインのデータセットを手に入れているので、こちらのデータセットを用います。誤植なのかところどころ、うまく回らなかったところがあったので、手直しをしています。

以下の工程に従って進みます。結構長いですが、辛抱強く実践してみて下さい。
・ライブラリの読み込み
・データの読み込み
・前処理
・学習用データとテスト用データの作成
・XGBoostの予測結果をもとに、AUCの数値を返すための関数の定義
・モデルの実行
・チューニング

ライブラリの読み込み

データの読み込み

前処理

スクリーンショット 2016-05-15 16.54.58

学習用データとテスト用データの作成

XGBoostの予測結果をもとに、AUCの数値を返すための関数の定義

XGBoostの予測結果から、AUCの数値を返し、特徴量に応じた重要度を出力するためのプログラムです。

モデルの実行

feature_importance1

チューニング

max_depthとmin_child_weightの数値をチューニングするためのプログラムです。

より細かい数値で再度最適なパラメータを探します。

max_depthを8、min_child_weightを1として、他のパラメータチューニングに移ります。
続いて、gammaのチューニングを行います。

gammaを0.4と置きます。
ここで、いままでにチューニングしたパラメータを用いて再度推定を行います。先ほどの0.875よりも高くなっています。

feature_importance2

続いて、subsampleとcolsample_bytreeのチューニングを行います。

より細かい範囲で再度パラメータをチューニングします。

続いて、reg_alphaをチューニングします。

範囲が粗かったので、より細かくパラメータをチューニングします。

これまでにチューニングしてきたパラメータを用いて再度推定を行います。

feature_importance3

ブログであるように試行回数を1,000回から5,000回まで増やしてみます。

88.8%まで向上しました。色々と数値いじっても、1%高めるだけにとどまってしまうのですね。

feature_importance4

とにかく、XGBoostをPythonで実行してパラメータチューニングするという一連の試行がこのコードでできそうなので、今後も使いまわしてみようと思います。

References   [ + ]

1. 1236, 13), (363, 13

不均衡なデータの分類問題について with Python

データマイニング界隈で人気のKDnuggetsで紹介されていた、”Dealing with Unbalanced Classes, SVMs, Random Forests, and Decision Trees in Python“のプログラムが残念なことに画像だったので、写経しました。せっかくなので、紹介させていただきます。内容としては不均衡データに対する処方の紹介で、プログラムはPythonで書かれています。ライブラリさえインストールできれば皆さんもすぐに実行できるので、是非チャレンジしてみて下さい。

まずはもろもろライブラリを呼び出します。

CSV形式のデータセットをWebサイトから取得します。ワインの評価と、ワインに関した特徴量からなるデータセットです。

スクリーンショット 2016-05-09 00.24.50

分類のための目的変数を作成します。

スクリーンショット 2016-05-09 00.26.24

ランダムフォレストを実行します。

どんな結果が返ってくるのか、試しに一つだけツリーの数を2にして実行してみます。10回分のクロスバリデーションを行った推定結果が出力されています。これは、いわゆる正解率のことを指します。

ツリーの数に応じた正解率を可視化します。

正解率はツリーの数を増やすことで増すようです。

Classification score for number of trees

しかしながら、正解率は誤解されやすい指標です。不均衡データでは偏りのある方ばかりを当てていても、正解率は増してしまいます。当たりだけを予測できて、ハズレを予測できないというのは分類器として使いみちが限られると思います。そこで、悪いワインの割合を直線で引いてみます。

悪いワインの割合がそもそも多いので、悪いワインと判定しまくっていても、正解率は高いわけです。

Classification score for number of trees2

そこで、機械学習における予測精度の評価指標とされているF値を使います。
ツリーの数を増やしても、F値は良くなっていないようです。

F1 scores as a function of the number of trees

ここでは、0.5よりも大きいとする予測になる特徴量のデータを切り捨てます。その切り捨てる割合がどこが望ましいのかを以下で探していきます。

どうやら、階級値が2~4、つまり割合にして0.3~0.5のカットオフ値が望ましい水準のようです。

custom F scores

以下では、決定境界の可視化を行います。しかしながら、二次元の可視化となると、複数あるデータの中から特徴量を二つだけ選ばなければなりません。その変数を決めるに際して、変数の重要度を用います。変数の重要度はランダムフォレストで計算可能です。

Importance of each feature

こちらで、重要度が上位のものに絞って決定境界を可視化します。ここでは、ランダムフォレストのみならず、SVMや決定木も実行されています。

Decision Tree Classifier

Random Forest Classifier

Support Vector Maachine

sklearnのSVMはデフォルトではクラスごとの重み付けを行わないが、自動で重み付けを行うことが出来る。以下の例では、C=1、gamma=1でクラスごとの重み付けを行う・行わないでの決定境界を描いている。重み付けを行うことで、赤色の少ない方のデータの識別が比較的できていることが伺えるが、他方で、多くの青を誤判定している。さらなる改善にはパラメータチューニングが必要となります。

Svm without class weight

Svm with class weight

不均衡データに対するアプローチや、Pythonによる機械学習を学ぶ良い機会になりました。KDnuggetsは非常に勉強になりますね。

XGBoostやパラメータチューニングの仕方に関する調査

【目次】
・XGBoostとは
・XGBoostで用いるパラメータ一覧
・XGBoostのパラメータチューニング
・参考文献

XGBoostとは

XGBoost (eXtreme Gradient Boosting) は勾配ブースティングアルゴリズムの先進的な実装例で、データサイエンスのコンペであるKaggleで話題となっていた手法です。

ブースティングアルゴリズムとは、弱識別器(weak learners)の集団を直列的に結合することで、予測における正確性を高めようとするアルゴリズムです。任意のt時点において、モデルの予測は以前のt-1時点での結果に基づき重み付けがなされます。正しく予測されたデータに対しては、重みを小さくし、誤って予測されたデータに対しては重みを大きくします。後で学習する識別器ほど、誤ったデータに集中して学習を進めることになります。

以下はブースティングのイメージ図です。
スクリーンショット 2016-04-24 18.40.38

STEP1では全ての学習データに対して、等しい重み付けで学習を行い、決定境界を引きます。これを弱学習器による学習と言います。このケースでは毒キノコを2つ当てており、キノコを5つ当てています。
STEP2ではSTEP1で正しく識別されたデータの重みが下げられ、誤って識別されたデータの重みが上げられています。高く重み付けがなされたデータは決定境界で正しく識別されていますが、他のデータは誤って分類されています。
STEP3においてもSTEP2と同様の傾向があります。このような弱学習器による処理を繰り返すことで識別性能を高めていきます。

最終的にはこのような決定境界を引くことができるような識別器を求めていきます。
スクリーンショット 2016-04-24 18.55.53

勾配ブースティングの勾配とは、ブースティングアルゴリズムにおけるパラメータ推定での最適化手法が勾配降下法に従っているという意味での勾配です。以上が勾配ブースティングモデルの簡素な説明です。

XGBoostで用いるパラメータ一覧

XGBoostで用いるパラメータに関して、大きく分けて3つあります。

    1.全体パラメータ・・・XGBoost全体を司る。
    2.ブースターパラメータ・・・各ステップでツリーなどのブースティングを司る。
    3.学習タスクパラメータ・・・最適化タスクを司る。

以下、3つのパラメータについて、「パラメータ名」・「デフォルトの値」・「役割」・「引数」を表にしています。

1.全体パラメータ

パラメータ名 デフォルトの値 役割 引数
booster gbtree 実行するモデルのタイプをツリーモデルか線形モデルのどちらかを指定できる。 gbtree: ツリーモデル
gblinear: 線形モデル
silent 0 モデルの実行結果を出力するかどうかを決めることができる。モデルを理解する上で、0のままにしておく方が良いとされている。 0:出力結果を表示する。
1:出力結果を表示しない。
nthread not set 並列処理のためのコア数などを指定できる。フルコアで実行したい場合は何も指定しなければ自動的にフルコアになる。

2.ブースターパラメータ

パラメータ名 デフォルトの値 役割 引数
eta 0.3 学習率を調整できる。
小さくすることで、モデルの頑健性を高めることができる。
0.01〜0.2の値になることが多いらしい。
min_child_weigh 1 子ノードにおいて観察されるデータの重み付けの合計値の最小の値で、過学習を避けるために用いられる。
高い値にすることで特定のサンプルに観察されるような傾向を学習することを避けられる。ただし、高くし過ぎるとフィッティングが悪くなる。
max_depth 6 木の深さの最大値
過学習を制御するために用いられる。
高いと過学習しやすくなる。
3〜10の値になることが多いらしい。
max_leaf_nodes 木の終端ノードの最大値
max_depthの代わりに用いる
n本を指定したら、n^2個の枝を生み出す。これが指定された場合は、max_depthは無効化される。
gamma 0 分割が、損失関数の減少に繋がる場合にのみノードの分割を行う。
モデルをより保守的にする。
値は損失関数に応じて大きく変わり、チューニングが必要である。
max_delta_step 0 各木のウェイトの推定に制約をかけることができる。
0の場合は制約なしで、正数値を取るとモデルがより保守的になる。
通常は必要とされないが、不均衡データの分類の際に用いる。
subsample 1 各木においてランダムに抽出される標本の割合
小さくすることで、過学習を避けることができるが保守的なモデルとなる。
0.5〜1の値になることが多いらしい。
colsample_bytree 1 各木においてランダムに抽出される列の割合 0.5〜1の値になることが多いらしい。
colsample_bylevel 1 各レベル単位での、分割における列のsubsample比率
subsampleとcolsample_bytreeで十分なので、あまり使わないが、探索してみるのも良いかもしれない。
lambda 1 重みに関するL2正則化項
多くのデータサイエンティストは使わないが、過学習を避けるためには用いられるべき。
alpha 0 重みに関するL1正則化項
高次元の場合に用いるらしい。
scale_pos_weight 1 不均衡データの際に、0以上の値を取ることで、収束を早めることができる。

3.学習タスクパラメータ