思考の本棚

機械学習のことや読んだ本の感想を整理するところ

サッカーを強化学習する

f:id:kutohonn:20201207171940p:plain
 

はじめに

 

この記事は強化学習苦手の会Advent Calenderの12日目の記事です。 私は11月末までKaggle上で開催されていたGoogle Research Football with Manchester City F.C.に参加していました。このコンペはGoogle Researchが用意したサッカーゲーム上でサッカーエージェント(プレイヤー)を作成し、その強さを競うというものです。

私はhigeponさんとチームを組ませていただき、強化学習アプローチでコンペ開催から終了まで取り組みました。そこでサッカーエージェントを強化学習で育成する際に工夫した点や苦労した点を共有できればと思います。

 

 kaggle: Google Research Football competition

www.kaggle.com

GitHub: Google Research Football

github.com

 



コンペの概要


ゲームのルールは通常のサッカーとほとんど同じです。オフサイドやレッドカード、ファールもありです。また今回のコンペではアクティブユーザー(ボールに一番近い)1人のみが操作可能という仕様でした。FIFAウイイレとほぼ同じと考えてもらって大丈夫です。エージェントをkaggle上に提出すると毎日複数の敵と複数回対戦しその勝敗によって順位が変動する仕組みです。

ではゲーム上のエージェントをどのように学習するかというところですが、以下の3つで定義された環境を用いてエージェントを学習させていきます。

①試合の観測状態

②エージェントの行動

③エージェントの行動による報酬(見返り)

この3項目について以下で説明します。


①試合の観測状態(State)

Stateとしては生データとそこからの派生として3種類の表現方法が提供されています。

生データ

試合に関する全ての状態を含む生データ。情報量は一番多い。

(1)Floats

選手やボールの(x,y)座標、アクティブプレイヤーの番号など、ゲーム情報を115次元のベクトル表現として扱う表現方法。

(2)SMM(Simplified spacial minimap)

 72 * 96のミニマップ画像(4ch)を用いた表現方法。シンプルな画像として扱える。

  • 1ch目が自分のチームの選手の位置
  • 2ch目が敵チームの選手の位置
  • 3ch目がボールの位置
  • 4ch目が操作可能なアクティブプレイヤーの位置 

以下SMMの画像例

f:id:kutohonn:20201201215927p:plain

 

(3)Pixels

下記のような実際のゲーム画像を 72 * 96にダウンスケールした表現方法。グレースケールバージョンも用意されている。情報としてはリッチだがノイズも多め。

f:id:kutohonn:20201201214927p:plain


②エージェントの行動(Actions)

方向キーやパス、シュートなど全部で19の行動が設定されている。詳細は以下。

github.com


③エージェントの行動による報酬(Reward)

Google Research Football環境には予め2つの報酬関数が定義されている。

(1)SCORING報酬:

得失点に対応する報酬

得点したら+1で失点したら-1 というシンプルなもの。試合のスコアに対応する。

(2)CHECKPOINTS報酬:

相手フィールド半分を10個のエリアに分割しゴールに近づくにつれて+0.1ずつ与えられる即時報酬のようなもの。 なお敵が自分のフィールドに攻めてきてもCHECKPOINTによるマイナス報酬は発生しない。 上限が設定されており1試合で最大+1.0まで。

またgymのwrapperを使ってカスタム報酬を作成することも可能。

 

 

 学習のアプローチ

本コンペではエージェントの学習方法として以下の3つのアプローチが取られていました。この記事で主に扱うのは強化学習ですがその他の2つの手法もここで簡単に触れておきます。

ルールベースアプローチ

コーディングによってエージェントの行動を決める方法です。人の手でルールを決めてagentの実装を行うため、エージェントの学習コストがなく、またドメイン知識を最も生かすことのできる方法であるため、コンペ開催直後から中盤にかけて多くの方が取り組んでいたアプローチだったのではないかと思います。

www.kaggle.com

機械学習アプローチ

こちらはコンペ中盤から目立ち始めたアプローチです。どういうものかというと過去の対戦データを使ってエージェントを学習させるというものです。本コンペは作成したエージェントをkaggle上にアップロードして複数の相手と毎日対戦させることで暫定順位を出す設計になっており、各エージェントの対戦結果はデータとして取得できるものになっていました。

そこで機械学習モデルで過去のエージェントの行動を教師ラベルとして学習(模倣)するアプローチが中盤から終盤にかけて取り組まれていたと思います。学習器としてはRandom ForestやGBDTなどの決定木ベースのアルゴリズムが私が観測した範囲では使用されていました。コンペ上位の方も使用されている非常に有効なアプローチであったようです。

 

s_toppo's solution(6th)

www.kaggle.com

強化学習アプローチ

こちらが今回の本題である強化学習アプローチです。機械学習アプローチと異なる点としては教師ラベルは利用せず、試合の結果(報酬)をもとにして各状態でのとるべき行動をエージェント自身が学習していく方法になります。コンペ上位の方で強化学習アプローチを取られている方が複数いたことからも本コンペでは強化学習アプローチは有効な手法であったと思われます。

 


取り組みの概要

以下、行った取組みの概要を示します。

  • 強化学習アルゴリズムとしてSEED RL(V-trace)による分散型強化学習を採用
  • 観測状態としてSMM(ミニマップ)を使用
  • 学習序盤で対戦botの難易度を段階的に増加
  • 学習序盤でCHECKPOINT報酬の減衰
  • 複数の対戦相手による過学習の抑制
  • カスタム報酬はノイズになりうるのであえて加えない
  • 1620M steps(541,666試合)の学習

いくつかのポイントについて説明します。

SEED RL

今回はSEED RLという計算資源の拡張性に優れた分散型強化学習フレームワークを使用しました。こちらはGoogle Researchから2020年に出されたものでSEED RL内でIMPALA(V-trace),R2D2,soft-Actor-Criticの3つの強化学習アルゴリズムが利用可能となっています。本論文内でGoogle Research Football環境での性能評価を行っており、実装及びGCPによる計算環境も整っていたことからSEED RL内で扱えるIMPALA(V-trace)を強化学習アルゴリズムとして採用しました。また本論文では3つの観測状態(floats, SMM, Pixels)の比較も行なっており、SMMが良い結果を示していたことからSMMを利用することにしました。

github.com

序盤での対戦相手の難易度(difficulty)増加

Google Research Football環境にはあらかじめBot(NPCのようなもの)が用意されており、difficultyを変更することが可能であったため、easyモードに該当するdifficuly=0.05から最難易度であるdifficuly=1.0まで徐々に上げていきました。difficultyは学習時の平均得失点差が1を越した(勝ち越した)時に0.05ずつ上げていく方式を取りました。

CHECKPOINT報酬の減衰

CHECKPOINT報酬はエージェントをうまくゴール近くに誘導するために良い効果を発揮します。これは学習序盤では効果的なのですが、学習が進行してくると得点することよりもゴールの方向へ進むことに意味を見出してしまい、学習のノイズになってしまうことが考えられました。そこでCHECKPOINTの割合を徐々に減らしていき、最終的には0にすることで、試合に勝つことのみに報酬(SCORING報酬のみ)を与えるようにしました。CHECKPOINTの減衰はdifficultyの増加に合わせて行い、difficultyが最高難易度に達した時にCHECKPOINTがゼロになるように設定しました。

 

計算資源

GCPのAI Platformを利用しました。

SEED RLはactor(試合をplayしてデータを取得する役割) とlearner(データから学習をする役割)に分かれており、GPUがlearner、CPUがactorに対応します。

  • GPU:  p100*1
  • CPU: n1-standard-4*96(合計384個のvCPU)

合計534体のactorを同時に並列で試合をさせて学習を行いました。

 

学習過程

今回作成したエージェントは最終的には1620Msteps(約54万試合分)の過程を経て学習されました。ここではその過程について説明していきます。

こちらは1620Mstepsまでの1試合ごとに返される報酬結果を示したものです。縦軸が対戦相手との得失点差を示していると考えてもらえればいいです。

f:id:kutohonn:20201207173618p:plain

0M ~ 160M steps

この期間は対戦botの難易度の増加とCHECKPOINT報酬の減衰を行なっていました。

LBスコア*: 700 

(*kaggle上で公開されているLeader Boardのスコアのこと600が平均値)

160M ~ 900M steps

160Mあたりから性能が急激に落ちてしまいました。難易度とCHECKPOINT減衰のスピードが早すぎたのかもしれません。しかし200Mあたりから右肩上がりで学習していき、bot相手には圧勝できるようになりました。試合の様子はこんな感じです。

drive.google.com

drive.google.com

ところがkaggle上でのスコアは思うように伸びませんでした。

LBスコア: 800~900

 

900M~1400M steps

対戦相手のBotには大差で勝ち越せるようになっているにも関わらず、LB Scoreが思うように上がらないことからBot過学習していると考え、対戦相手を追加することにしました。相手はkaggle上で公開されておりLBスコアが1100(当時上位5-10%の順位)とかなり高いルールベースのBotを利用しました。学習比率はBot : ルールベースBot=1 : 3の比で学習させました。

これにより停滞していたLBスコアの向上が見られました。

LB スコア:900-1100

1400M - 1620M steps

上記Botを追加し手元ではどちらもBotにも勝ち越せるようになりましたがLBスコアは期待以上には伸びませんでした。そこで新たに新たに機械学習ベースのBotを対戦相手として追加し学習させました。ここで時間(資金)切れとなり終了となりました。

LB Score 1100-1200

 

最終のエージェントの試合の様子

drive.google.com

 

終結

本日(12/12)コンペが終了し、最終成績は以下のようになりました。

最終LBスコア 1174 (58th /1141)

f:id:kutohonn:20201212091410j:plain

ギリギリの銅メダル。。金銀目指していたので悔しさはもちろんありますが上位の方の手法を見る限り力不足だったなと思いました。

 

私たちの解法をまとめたDiscussion

www.kaggle.com


難しかった点

① 学習の推移が予想できない

 特に学習序盤ですが、推移の変動が大きく、学習がどのように進むのか予想できませんでした。今回はひとまずそれなりの時間放置して経過を見守るというスタンスを取りましたが、③で書いているようにコストがかなりかかるのでどの時点で学習を止めるべきかの判断が難しいように感じました。

② 思っていた以上に過学習する

 最初はBot相手に強くなれば性能・スコアも右肩上がりで上がっていくと思っていたのですが今思うと過学習気味だったので、序盤から複数の相手と戦わせたり自己対戦をしていたらもう少しスコアが上がったのかなと思いました。

③ 学習コストが大きい

1620M stepsの学習を行うのにGCPのAI platformを利用しました。

この学習にざっくり20万円近くのコストがかかっています

私たちは本コンペ用に抽選で配布された1人$1000(約10万4千円分)のGCPクーポンを運よく2人ともゲットすることができたので計算資金はそれなりにあったと言えますが、それでも強化学習にはかなりの学習コストを要することがわかりました。

④試行錯誤の数が限られる

強化学習は答えを与えない分データ効率が悪いので学習するまでに多くの時間を要します。そのためいろいろ試して比較するということがなかなかできず、どのように学習を進めていくべきかの判断が難しい印象を受けました。行動の探索空間を限定したり補助的な報酬を与えるなどのデータ効率を上げる工夫、試行の良し悪しをどの時点のどの基準で判断するかの意思決定が重要のように感じました。

 

試したけどうまくいかなかったこと

  • アンサンブル学習

機械学習のように複数のRL エージェントを用意し選択行動を投票で決めるアンサンブルを行いましたがうまくいきませんでした。

  • カスタムシナリオによる部分学習

通常の試合だけではなくゴール前での得失点に関わる状況に限定したシナリオを作成し学習をすることに取り組みましたが、単一で行うとこれまでの戦略を忘却したかのように全く異なる行動をとるようになり、それを避けようと通常の試合と混ぜながら行なっても性能の向上が見込めなかったのでボツとなりました。

 

上位解法の良さそうな取り組み

  • 自己対戦学習

3位解法6位解法はどちらも自己対戦を取り入れた自己対戦学習を行なっていました。自己対戦の場合、データ効率が倍になりかつ過学習にもある程度対策ができていたようで一つの良いアプローチだったのかなと思いました。ちなみに上位の方は自己対戦とは別に複数の敵との対戦も同時に行なっており過学習対策をしっかりされている印象でした。

  • 階層的な行動空間

行動の選択肢はidle状態を除くと全部で17こありますが、全てが重要というわけではありません。6位解法では8つの方向移動行動を1つの移動行動としてまとめて、移動行動が選ばれた時にのみ方向を選択するという取り組みを行なっていました。これにより探索する行動空間を小さくすることができるのでデータ効率を上げる狙いがあったようです。非常に面白い取り組みだと感じました。

  • 模倣学習

本コンペでは機械学習アプローチ(教師あり)も有効であったことから模倣学習も有効だったのではないかと考えました。模倣学習によりエージェントをある程度高いレベルまで学習させた後、自己対戦による強化学習などで学習を継続すれば効率よく、比較的少ないコストで学習ができたのではないかと考えました。

 

感想

今年の8月くらいから、強化学習の勉強を本格的にしたいと思い論文や書籍などで勉強していたところに、このような面白いコンペが開催されたので私としては非常に幸運でした。書籍では知っていた強化学習を行う上での難しさ(報酬設計、データ効率、過学習)を身をもって学ぶことができました。難しさを感じるコンペであったものの、学習初期はボールを素通りしたりオウンゴールをしていたエージェントがちゃんとパスをして相手のゴールに向かっていく姿にはちょっぴり感動しました。

 

本コンペを通して改めて強化学習は非常に興味深い分野だなと思ったので今後も勉強していき、このような面白いコンペがあったら積極的に参加していきたいと思います。

ここまで読んでいただき、ありがとうございました。

  

その他参考文献

Google Research Footballの論文

arxiv.org

Google Research Football環境で強化学習に取り組んだかなり質の高いブログ

sites.google.com

 

効果検証入門が良かったのでまとめてみた③

はじめに

 効果検証入門のまとめの続きです。前回はセレクションバイアスを軽減する基本的な方法である回帰分析についてまとめました。本記事ではセレクションバイアスを軽減する手段の1つである傾向スコアを用いた分析について説明していきます。 kutohonn.hatenablog.com

参考文献

効果検証入門


傾向スコア分析の仕組み

 傾向スコアとは各サンプルにおいて介入が行われる確率のことです。傾向スコアを用いた分析は、介入が行われた仕組みに着目しています。介入グループと非介入グループのデータの性質を近くする操作を行うことで、セレクションバイアスを軽減します。この操作は以下の仮定に基づいて行われます。 以下は回帰分析の仮定(CIA)と傾向スコア分析の仮定の比較をしたものです。

f:id:kutohonn:20200424183848j:plain

 セレクションバイアスを取り除くためには、目的関数Yに対して介入Zが独立している必要があることを前回説明しました。この独立性を満たすために回帰分析で考えられている仮定はCIAというものでした。これは共変量の値が同一のユーザの中で、目的関数Yに対して介入変数Zが独立しているという仮定です。一方、傾向スコアでは、傾向スコアP(X_i)が同一となるサンプルの中で、目的関数Yに対して介入変数Zが独立しているという仮定です。つまり回帰分析との違いは、介入が目的関数に対して独立であることを、共変量で条件づけるのではなく、傾向スコアで条件付ける点にあります。そのためには各データの傾向スコアP(X)を求めてあげる必要があります。


傾向スコアの推定方法

 傾向スコアを用いた分析では、上記で説明したように傾向スコアP(X)を求める必要があります。しかしながら傾向スコアP(X)を直接観測できる状況はほとんどないため、何かしらのモデルを用いて手持ちのデータから傾向スコアP(X)を推定する必要があります。この時多くの場合でロジスティック回帰が用いられます。(共変量数が多い場合は、勾配ブースティングも有効のようです。)ロジスティック回帰は介入変数Zの値を目的変数とし、以下のような回帰式となっています。

Z_i =\sigma(\beta X_i + u_i)
\sigma(x) = 1 / (1 + e^{-x})
\hat{P}(X_i) = \hat{Z}_i = \sigma(\hat{\beta}\ X_i)
u_i:誤差項, \beta:推定されるパラメータ, \sigma(X):シグモイド関数

 ここでのロジスティック回帰は、仮に変数Xと、0か1の値をとるYを与えると、Y=1となる確率を推定するモデルを得る方法と言えます。 ロジスティック回帰によって得られたモデルを利用することで傾向スコアの推定値\hat{P}(X_i)を得ることができます。ここで重要なのは傾向スコアの推定値\hat{P}(X_i)のみでモデルのパラメータ自体は特に分析する必要はありません。機械学習をやっている方だとモデルの妥当性や精度を考慮する必要があるように感じるかもしれません。しかしながら効果の分析において、傾向スコアの推定に用いたモデルの解釈は質の保証にはなりえません。そのため傾向スコアの推定を行ったモデルやそのパラメータに関しては特に解釈を行う必要はありません。


傾向スコアを用いた分析方法

ここでは傾向スコアを用いた2つの分析手法について説明します。

傾向スコアマッチング

 こちらはとてもシンプルなアイデアです。傾向スコアマッチングでは、介入ありグループから取り出したサンプルと傾向スコアの値が近いものを介入なしグループから取り出してペアにします。そしてペアの中で目的変数の差を算出し、これを全てのデータで行いその平均を効果の推定値とします。先ほど説明したように傾向スコアが同じ値を持つサンプルの中では介入変数ZY^{(0)}と独立して決定されていると考えられます。そのためこの中でグループ間の比較を行ってもセレクションバイアスの影響を受けることなく効果を推定することができます。

f:id:kutohonn:20200424184312j:plain

  マッチングにおいては傾向スコアごとにグループ間を比較し、それらの結果をグループに属しているサンプルの数を重みとした重み付きの平均を算出することで、効果を推定しています。マッチングによって推定される効果は以下のようになります。

\hat{\tau}_{match} = E\{E[Y|P(X), Z=1] - E[Y|P(X),Z=0]|Z=1\}

これは介入を受けたサンプルにおける介入効果の期待値で、ATT(Averaged Treatment effect on Treated)と呼ばれます。ATTは介入を受けたサンプルにおける効果なので、ATTの推定を行った値は平均的な効果を推定した値ATE(Average Treatment Effect)と結果が異なる場合があります。  

マッチングは実際の計算時間が長くなってしまう傾向にあります。また傾向スコアのモデルに含まれる変数が多くなると、傾向スコアが完全に一致しないため、傾向スコアの値が似ているサンプルをペアにする必要があります。


逆確率重み付き推定(IPW)

 逆確率重み付き推定(Inverse Probability Weighting;IPW)では、傾向スコアをサンプルの重みとして利用し、データ全体の介入を受けた場合の結果の期待値E[Y^{(1)}] と、介入を受けなかった場合の結果の期待値(E[Y^{(0)}])を推定します。そしてその後にこれらの差分を取ることで効果を推定します。 式を用いて説明します。

\bar{Y}^{(1)} = \sum_{i=1}^{N}{Z_i Y_i} / \sum_{i=1}^{N}{Z_i}

\bar{Y}^{(0)} = \sum_{i=1}^{N}{(1-Z_i) Y_i} / \sum_{i=1}^{N}{(1-Z_i)}

上記は単純にZ=1の時のY(1)、Z=0の時のY(0)の平均の推定値を示しています。これらの差から効果の推定を行うとセレクションバイアスの影響を受けてしまいます。そこで傾向スコアの推定値\hat{P}(X_i)を用いて以下のように変形します。

\bar{Y}^{(1)} = \sum_{i=1}^{N}\frac{Z_i Y_i}{\hat{P}(X_i)}/\sum_{i=1}^{N}\frac{Z_i}{\hat{P}(X_i)}

\bar{Y}^{(0)} = \sum_{i=1}^{N}\frac{(1-Z_i) Y_i}{1-\hat{P}(X_i)}/\sum_{i=1}^{N}\frac{(1-Z_i)}{1-\hat{P}(X_i)}

こちらがIPWで用いる重み付きの平均です。傾向スコアの推定値\hat{P}(X_i)の逆数を重みとして平均を取っています。詳細は省きますがこうすることによりセレクションバイアスの影響を低減することができます。あとはこれらの差分を取ることで効果を推定することができます。

\hat{\tau}_{IPW} = \bar{Y}^{(1)} - \bar{Y}^{(0)}

IPWでは先にE[Y^{(1)}]とE[Y^{(0)}]を推定し,その推定結果の差分を取ることで効果を推定しました。これはつまりデータ全体での平均的な効果を推定したことになります。これはATEの推定を行っていることになり、介入の効果がサンプルによって異なるような場合でもそれを考慮した平均的な効果が推定されることになります。


より良い傾向スコアとは

傾向スコアは回帰分析と同様、どのように推定してもセレクションバイアスを消し去ってくれるような便利な道具ではありません。 ここではより良い傾向スコアを得るためには何をする必要があるかについて説明します。 傾向スコアを用いた分析では、マッチングもしくは重み付けを行ったあとのデータにおいて、共変量のバランスが取れているかが重要です。


傾向スコアと回帰分析の比較

介入の効果の分析において、傾向スコアは共変量の影響を取り除くという点で回帰分析と役割はほぼ同じです。ではどのように使い分ける必要があるのでしょうか。以下に回帰分析と傾向スコアのメリットデメリットを整理してみます。

回帰分析 傾向スコア
メリット 手軽で取り組みやすい
モデリングが正しくできる場合、効果の標準誤差が小さくなる(検証結果の質が上がる)
Yに対するモデリングを行わなくて良い
情報を入手しやすいZの決定方法に関する調査を行うだけで良い
デメリット 目的関数と共変量の関係について入念にモデリングを行わないといけない マッチングは計算に時間を要するため大量のデータには不向き

よってYの値がどのような仕組みで決まるかに関して豊富な情報を持つ場合には、回帰分析を行うメリットが大きく、Yに関する情報があまりない場合には傾向スコアを用いるほうが望ましいです。


おわりに

今回は傾向スコアについてまとめてみました。傾向スコアのアイデアはシンプルながら個人的に非常に面白いなと思いました。

【Kaggleで役立つ】計算過程およびエラーをslackに通知する

f:id:kutohonn:20200423223709j:plain


はじめに

KaggleのNotebookやGoogle Colab, GCPなどのクラウド環境で計算を回していると、途中でエラーが発生していて計算が止まってしまったり, 処理がどう進んでいるかが気になってしまうことが多々あったので, 欲しい情報をslackに通知するようにしてみました。

f:id:kutohonn:20200423214153p:plain

この記事ではプログラムの処理過程をslackに通知するための方法について説明していきます。


参考にしたサイト

tech.bita.jp amalog.hateblo.jp


slackの設定

まずはslackの設定を行なっていきます。slackに登録していない方はこちらからサインインしてください。 それでは初めにワークスペースを作成します。私は1人で使う個人開発用のワークスペースを作成しました。 その後作成したワークスペースに入り、以下の図に示すように左側のappというタグを選択し、その後中央の画面で『Incoming Webhook』というアプリを検索してslackに追加します。

f:id:kutohonn:20200423220229p:plain


追加したら『Incoming Webhook』をクリックするとweb上の設定画面にリンクします。 設定画面で大事なのは主にこちらの2項目です。

f:id:kutohonn:20200423221713p:plain

1つ目に通知を送りたいチャンネルを選択します。もともとあるgenralなどでもいいですし新しいチャンネルを作成しそちらに通知を送るようにしてもいいです。 2つ目にWebhook URLのコピーです。Webhook URLというものが割り当てられますのでそれをコピーしておいてください。後ほど使います。そのほかの設定はお好みで大丈夫です。 これでslackでの設定は完了です。


関数の定義

次にslackに通知を送るためのコードを書いていきます。 動かしたいプログラムの中に以下のコードを貼り付けます。 コード中の<自分のWEBHOOK_URL>の部分は先ほど取得したWebhook URLに書き換えてください。

import json
import requests

# 任意のメッセージを通知する関数
def send_slack_message_notification(message):
    webhook_url = '<自分のWEBHOOK_URL>'  
    data = json.dumps({'text': message})
    headers = {'content-type': 'application/json'}
    requests.post(webhook_url, data=data, headers=headers)

# errorを通知する関数
def send_slack_error_notification(message):
    webhook_url = '<自分のWEBHOOK_URL>' 
    # no_entry_signは行き止まりの絵文字を出力
    data = json.dumps({"text":":no_entry_sign:" + message})  
    headers = {'content-type': 'application/json'}
    requests.post(webhook_url, data=data, headers=headers)

これで準備は整いました。次に実際の使い方を説明していきます。

使い方

まず任意のメッセージを通知する方法ですが以下のように先ほど定義した関数の引数に通知したい文章を与えることで通知することが可能です。 str型であれば基本、なんでも大丈夫です。

message1 = "[START] training phase"

val_score = 0.89
message2 = "valid score:{}".format(val_score)

send_slack_message_notification(message1)
send_slack_message_notification(message2)

f:id:kutohonn:20200423213002p:plain

通知結果はこのようになりました。kaggleの場合だと現在の処理フェーズであったり、算出したスコアであったりを通知すると便利そうです。


次にerrorが起きたときに通知する方法です。
今回はmainという関数内でエラーがあった場合を想定して説明していきます。ここは別に関数でなくても大丈夫です。 try構文を用いて例外処理を記述し、例外(エラー)が発生した場合にexcept以下を実行します。 通知されるのはsend_slack_error_notificationの引数に与えられた文章です。今回はtraceback.format_exc()によってerror内容を通知しています。

import traceback
def main():
    prin("試しにわざとエラーを出してみます。")

try:
    main()
except:
    send_slack_error_notification("[ERROR]\n" + traceback.format_exc())  

f:id:kutohonn:20200423213854p:plain

このような形でエラー内容を通知することができました。「クラウド上でプログラムを回してたらいつの間にかerrorで止まっていた、」なんてことはよくあるので、そういったときに役立ちそうです。例外処理を部分部分でいちいち書くのは面倒なので、全ての処理をmainの関数に集約して、その関数に対して上記のように実行すると楽だと思います。


おわりに

kaggleなどの機械学習タスクでは、処理時間がかなり長いため処理がうまくいってるか気になってしまう人は多いと思います。なのでこのように通知を送ることによって、計算の過程やエラーを確認し効率よく計算を回していければと思います。

【効果検証入門】が良かったのでまとめてみた②

前回に引き続き、効果検証入門の内容をまとめていこうと思います。本記事では2章の介入効果を測るための回帰分析について説明していきます。なお本記事ではRによる実装部分は割愛いたします。


はじめに

前回の記事では、効果検証を行う上で引き起こりやすいセレクションバイアスについての説明とその理想的な対応策であるRCT(無作為化比較実験)について説明しました。RCTは分析を行う上で、非常に都合の良い反面、ビジネスとしては大きなコストになってしまう可能性があります。

kutohonn.hatenablog.com

そこで本記事ではセレクションバイアスが存在している状態でもその影響を少なくすることのできる回帰分析について説明していきます。回帰分析は最も基本的なセレクションバイアスの削減方法です。


効果分析のための回帰分析

セレクションバイアスの入ったデータで効果検証を行う場合、何も対処せず分析を行うとセレクションバイアスを含んだ介入効果を導出することになってしまい、真の効果がわかりません。効果分析のための回帰分析では、データに存在するセレクションバイアスの影響をなるべく減らして\tau = E[Y(1) ] - E[Y(0) ] (介入の有無による期待値の差←真の効果値)の推定が行われます。効果分析のための回帰分析では以下の3種類の変数が登場します。

・被説明変数 Y: 介入による効果を確認したい変数
・介入変数 Z: 施策の有無を示すバイナリ変数
・共変量 X: セレクションバイアスを発生させていると分析者が想定する変数

X,Z統計学では説明変数、機械学習の分野では特徴量と呼ばれたりもします。効果を検証する際の回帰分析においては、説明変数が複数あることが一般的です。このように複数の種類の変数をモデルに含む回帰分析を重回帰分析と言います。今回はX,Zを説明変数とした重回帰分析について説明していきます。以下にX,Zを説明変数としたYに対する回帰式を示します。

E[Y|X, Z] = \beta_0 + \beta_1 X + \beta_2 Z

左辺はX,Zの場合のYの期待値(条件つき期待値)を示しています。これはX,Zが与えられたときにYがどのような値を取りうるかを表したもので、これが今回の回帰分析で対象となる回帰式です。なお回帰式の係数\beta_0, \beta_1,\beta_2は未知のため、後ほど説明する最小2乗法によってこれらのパラメータを推定する必要があります。

Y = E[Y|X, Z]+u = \beta_0 + \beta_1 X + \beta_2 Z+u

こちらは上記の式を少しだけ変形したものです。Yは実際のデータを示しており、uは実際のデータYと回帰式との間の誤差を示しています。
(図)回帰(図簡単のためX,Zは1次元にまとめ疑似的な単回帰で説明) f:id:kutohonn:20200409230910j:plain 上記で示した誤差は以下の式のように表すことができます。

u_i =Y_i - (\beta_0 + \beta_1 X_i + \beta_2 Z_i)

回帰式を求めるにはこの誤差を最小化するように計算をする必要があります。このとき使われるのが最小2乗法です。最小2乗法は誤差の2乗を最小にすることで、誤差がプラスの値であろうがマイナスの値であろうが関係なく全ての誤差の和が最小となるパラメータ\beta_0,\beta_1,\beta_2を求めることができます。

min_{\beta_0,\beta_1,\beta_2} \sum_{i=1}^N(Y_i-(\beta_0 + \beta_1 X_i + \beta_2 Z_i))^2


ここで本題である介入効果の分析において調べたいのは、介入した場合としなかった場合の期待値の差E[Y|X,Z=1 ] - E[Y|X,Z=0 ]です。それぞれの期待値は以下のように表せます。

E[Y|X,Z=1 ] =\beta_0 + \beta_1 X + \beta_2 1
E[Y|X,Z=0 ] =\beta_0 + \beta_1 X + \beta_2 0

介入の効果はこれらの差分であるので 

E[Y|X,Z=1 ] -E[Y|X,Z=0 ] = (\beta_0 + \beta_1 X + \beta_2 1) - (\beta_0 + \beta_1 X + \beta_2 0)=\beta_2

となります。これは回帰分析において介入の効果は\beta_2であることを示しています。つまり回帰分析では介入変数Zの係数のみが介入の効果を表すということになります。よって最小2乗法によって\hat{\beta_2}を求めれば、回帰分析によって介入の効果を推定することができます。仮に\hat{\beta_2}=0.4と導出された場合、介入したグループのYの平均は介入していないグループの平均より40%高いであろうということを意味しています。ただ求めた値はあくまで推定値であるため、それが偶然得られたものであるかどうかを有意差検定を用いて検証する必要もあります。なおプログラムでパラメータの推定を行うと今回の場合、\hat{\beta_0}, \hat{\beta_1}も同時に推定されますが、効果検証のための回帰分析で興味があるのはあくまで介入変数の係数だけであるため、それ以外の値に対して何らかの解釈を行うことはありません。


回帰分析におけるバイアス

上記で示したのはあくまで回帰分析による平均的な効果の比較になります。そのため得られた推定値はセレクションバイアスと実際の効果の和となります。回帰分析でセレクションバイアスが小さくなるような推定を行うためには、共変量を正しく選択する必要があります。セレクションバイアスが発生しているデータにおいて、新たな共変量を加えて回帰分析を行うことで、セレクションバイアスの影響がより少ない分析結果を得ることができます。


脱落変数バイアス(OVB)

ではセレクションバイアスの影響をより小さくするためにはどのような共変量をモデルに追加するべきか。結論から述べると「目的関数Yと介入関数Zに対して相関のある変数を与えるべき」ということになります。以下に2つのモデルを示します。

Y_i =\alpha_0 + \alpha_1 Z_i + u_i(モデルA)
Y_i =\alpha_0 + \alpha_1 Z_i + \beta_2 X_{omit,i\\} + e_i(モデルB)

この2つのモデルの差は共変量X_{omit,i}が追加されているか否かです。モデルBはセレクションバイアスの影響を軽減した結果が得られるとします。
このことからこの変数を加えたことによってモデルBのセレクションバイアスが軽減されたことが伺えます。このような本来は必要であるがモデルから抜け落ちている変数を脱落変数と呼びます。Xommit,iを無視したモデルAにおいて介入効果を示すパラメータ\alpha_1

\alpha_1 = \beta+\gamma_1\beta_2

となることが知られています。*1

上式に示すようにモデルAの介入効果\alpha_1はセレクションバイアスの影響を取り除けているモデルBの介入効果\beta_1に加えて、余分なバイアス\gamma_1\beta_2が存在していることが分かります。この\gamma_1\beta_2のように必要な共変量がモデルから抜け落ちていることによって起こるバイアスを脱落変数バイアス(Omitted Variable Bias: OVB)と言います。このモデルA,Bの比較は必要な共変量がモデルに含まれない場合には推定される効果にはOVBが含まれていることを示すとともに、一方ではそのような変数をモデルに加えることでOVBの影響を取り除くことが可能であるという回帰分析の基本的な仕組みを説明しています。
f:id:kutohonn:20200410180819j:plain なお詳細な説明は省きますが、OVBは介入量Zにも目的変数Yにも相関のある共変量が抜け落ちることによって生じます。このようなZ,Yの両方に関係のあるような変数のことを交絡因子といいます。目的変数Yとの相関が0でない変数は、Yを予測する上では含まれるべき重要な存在といえます。しかしながらその変数とZとの相関が0であるような場合はその変数を加えてもZの効果には変化がない、つまりはOVBの減少にはつながらないということになります。よってYZどちらに対してもある程度相関のある変数を加えることにより、バイアスの少ない効果推定を行うことができます。 f:id:kutohonn:20200410180837j:plain

Conditional Independence Assumption(CIA)

効果検証のための回帰分析における共変量の選択は、理想的にはOVBが0になるような状態を目指します。この状況を、CIA(Conditional Independence Assumption)といいます。直感的な解釈としては、共変量の値が同一のサンプルにおいて、介入量Zはランダムに割り振られているのに等しい状態というものです。
CIAは以下の式で表されます。

(Y_i^{(1)}, Y_i^{(0)}) \perp Z_i|X_i

回帰分析で推定した効果の値が本当に正しいのかを考える場合、CIAが満たされているかどうかを考える必要があります。


変数の選び方とモデルの評価

回帰分析において分析者は以下のような手順でモデルを作ることになります。

1.介入の割り当てがどのように決定されるのかを考える
2.想定される決定方法を表現できるような共変量を選択する
3.選択した共変量とYとの関係性を考慮してを決める

このとき推定された効果の妥当性を主張するには作ったモデルの共変量がCIAを満たしているかと考える必要があります。しかしこれを主張する上で2つの問題点があります。

①バイアスの評価ができないという問題
この場合、基本的に分析者がセレクションバイアスの発生原因、どの変数が有効かを仮定する必要があります。
②必要な共変量がデータにはないという問題
この場合、基本的には回帰分析ではセレクションバイアスの影響を取り除いて効果を推定するのは不可能になります。


Post Treatment Bias

介入によって影響を受けた変数を分析に入れることによって起こるバイアスのことをPost Treatment Biasと呼びます。Post Treatment Biasは、元々の介入自体がどのような方法で割り当てられていたとしても発生してしまう問題です。よって仮にRCTによって介入をランダムに選んだユーザに配信したとしても、介入によって影響を受けた変数を投入して作成されたモデルはPost Treatment Biasを含んだ状態となってしまいます。この問題を避けるためには介入よりも後のタイミングで値が決まるような変数を分析から除外する必要があります。


回帰分析に関する様々な議論

分析の現場では、しばしば目的変数に対する予測能力の低いモデルは効果の検証として利用価値がないといった議論が発生します。これは機械学習のような予測を目的として捉える分野においては重要な視点であり、また多くの場合モデルの予測能力の計測が直感的なモデルの評価になると考えられています。一方、今回のような回帰分析のプロセスでは、予測能力や手元のデータに対する説明能力は一切考慮しません。この理由は「モデルのデータに対する説明能力や未知のサンプルに対する予測能力を高めることが効果検証において有用であるという保証にはならない」という点にあります。
脱落変数バイアスの式に注目すると介入変数と目的関数に相関するような変数を含めればより正確なZに関する効果を得ることができる一方で単にYの予測を改善するような変数を追加してもその変数がZと相関がないようであれば効果の推定は改善しないということになります。このような事情からYに対する予測能力が一定以上なければ効果検証としてもモデルの価値がないという批判は、本質をついたものではないことが分かります。


おわりに

次回は3章の傾向スコアを用いた分析についてまとめたいと思います。

*1:OVBの詳細はこちら: www.amazon.co.jp

【効果検証入門】が良かったのでまとめてみた①

          f:id:kutohonn:20200403151037j:plain

はじめに

先日効果検証入門という本を読みました。こちらの内容が非常に素晴らしかったので、内容を整理するために本記事を書いています。


現在身の回りで『効果』という言葉を様々な場所で目にするようになっています。「ある食品はダイエットに効果がある」「広告は売上を増加させる効果がある」など。 効果は私たちが意思決定をする上で非常に重要なものですが、その多くは、測り方を間違っていたり思い込み(バイアス)が入っていたりと正しく検証するのは難しいものでもあります。効果検証を行う上で問題となるのは、比較が正しくできていないために、因果関係を示すことができていないという点です。この本では比較を正しく行うためにどのようにしてバイアスを取り除くか、その手法をまとめたものです。

この記事では本著1章に該当するセレクションバイアスとRCT(無作為化比較実験)について自分なりに重要だと思ったところを簡潔にまとめます。なお本著ではRによる検定手法の実装なども含まれていますが、本記事では割愛します。


セレクションバイアス

セレクションバイアスとは、比較実験を行う際に、観察対象のグループ分けによって引き起こされるバイアスのことを言います。 メールマーケティングの例をもとに説明していきます。 Amazonがユーザに、Amazon内の商品を宣伝するメールを送信することで、購買を促すマーケティング施策を行うとします。Amazonは売上を伸ばすために、メールに割引クーポンを添付するという施策を行います。クーポンをメールにて受け取ったユーザは普段より安い価格に反応し、本来より多くの購買に至る可能性があると考えられます。よってメールを配信することで、潜在的な購買量(何も施策を行わない場合の購買量)に加えて、メールの効果によって増えた購買量が得られると想定しています。この効果検証は「クーポン付きのメールを送信するという介入が、ユーザ1人あたりの売上をどう変化させるか」を知りたいものとします。

(図) メールマーケティングの例 f:id:kutohonn:20200403181336j:plain

既にメールは送付済みのものとする場合、単純に、①メールを受け取ったユーザ と ②受け取らなかったユーザ の売上の傾向を比較すれば、メールの効果を検証できそうですが、これがセレクションバイアスの罠です。その理由として多くの場合ではメールマーケティングをより効率的に実施する目的から、ある程度購買の見込みのあるユーザにメールを送信していることが考えられます。つまりそもそも①メールを受け取ったユーザ と ②受け取らなかったユーザの選択には恣意性が含まれており、これによってセレクションバイアスを招いている可能性があるのです。

(図) メール割り振りの仕組み f:id:kutohonn:20200403184907j:plain セレクションバイアスが引き起こされているとどうなるか。①メールを受け取ったユーザはもともと購買量の多い傾向のグループであり②受け取らなかったユーザはもともと購買量の少ない傾向のグループであると言えます。よってメールの介入による効果がなくても潜在的な購買量の差によってあたかもメールマーケティングに絶大な効果があるように思える状況が発生してしまいます。

(図) グループ間のセレクションバイアス f:id:kutohonn:20200403191441j:plain

このセレクションバイアスに対して何らかの対処を施した上でデータ分析を行わなければ、得られた効果はバイアスを含んでしまい、本来取るべき意思決定とは異なる決定を下してしまう可能性があります。たまに「分析のバイアスはデータ数の増加によって解決される」と誤解されていることがあるそうです。比較対象にセレクションバイアスが含まれている場合、推定している値がそもそも興味のない値(バイアスを含んだ値)であるため、データ数を増やしたところで興味のない値をより正確に推定するようになるだけであることに注意する必要があります。


RCT (Randomized Controlled Trial)

バイアスを取り除くために実行可能で最も信頼のおける効果の検証方法が、介入を無作為にすることです。つまり、介入を実施する対象をランダムに選択して実験し、その結果得られたデータを分析することです。先程の例で言うと、メールを送る対象をランダムに選択することで①メールを受け取ったユーザ と ②受け取らなかったユーザ間のセレクションバイアスを取り除き正しい効果検証を行うことが可能となります。

(図)RCTのイメージ
f:id:kutohonn:20200403192317j:plain

なぜこれだけでバイアスを取り除くことができるかと言うと、介入が行われる対象と行われない対象におけるその他の要因も平均的に同一となるからです。メールの例で言うと、送る対象をランダムに選別することで、先程問題となった購買量の差も平均的には無くなりますし、その他の属性(性別、年齢など)も平均的には同一となることが期待されます。よってバイアスを気にすることなく効果を検証することが可能となるのです。このように効果を知りたい施策をランダムに割り振り、その結果として得られたデータを分析して比較することをRCT(無作為化比較試験、Randomized Controlled Trial)と言います。


有意差検定の注意点 

統計学では有意差検定というものが存在します。詳細な説明は省きますが、推定結果が偶然得られた可能性について検証するものです。 ここでは本著で記載されていた有意差検定の注意点についてまとめます。


p値

有意差検定では最終的な評価を下すためにp値と呼ばれる値に変換します。p値は得られた推定結果が偶然得られてしまう確率を示します。 有意差検定ではデータから得られたp値が有意水準(5%や1%)より低い場合は、得られた推定結果が偶然である可能性は十分に低いとして統計的に有意な値であると評価します。一方で、有意水準を上回るようなp値が得られた場合は、推定結果が得られたのは偶然であるということを否定しきれないという解釈になります。これは推定結果が偶然得られたとみなしているわけではないことに注意する必要があります。


信頼区間

p値以外に、信頼区間を利用した意思決定が行われていることもあります。95%の信頼区間と言ったとき、95%の意味合いは100回データを変えて同じ推定を行ったとき、母集団におけるパラメータの真の値が95%ほどはその区間に含まれるということを示します。加えて95%の信頼区間内に0を含む場合には, p値が5%よりも高い状態と同じ意味を持つことになります。


有意差検定について

有意差検定とは不確実性に関する評価を簡略化して考えるためにのルールであり、絶対的な判断基準というわけではありません。また有意差検定はあらゆる分析の結果に保証を与えるものではなく、例えばRCTを行っていないデータで有意差検定を行う場合、セレクションバイアスが大きいと有意差検定の結果は有意になりやすいことがあります。これらのことから、有意差検定は何でもかんでも効果を保証するような道具ではないことが分かります。


ビジネスにおける因果推論の必要性

RCTはバイアスを取り除く上で非常に有効な方法ですが、RCTは効果を検証するために介入がランダムに割り当てられるという状況を作る必要があります。これは分析の都合を最優先した介入の割り当てを行うことになるため、ビジネスの面を度外視したものになります。メールの例で言うと、購買量が少ない人にもメールを送ることになり、その施策はビジネスの観点からは非合理的で、短期的には売上が下がってしまうことも考えられます。つまりRCTは分析を行う上で、非常に都合の良い反面、ビジネスとしては大きなコストになってしまう可能性があります。 計量経済学や因果推論は、このように理想的にはRCTでデータをデザインして分析したいがそれが不可能という状態においてRCTの結果を近似するような方法論を提供してくれます。


おわりに

本記事では効果検証入門の1章部分を簡潔にまとめてみました。次は2章の回帰分析についてまとめたいと思います。

kutohonn.hatenablog.com

GCPとdockerによるkaggle環境の構築手順

はじめに

画像データを扱うkaggleコンペに参加しようと思い、クラウドGPU環境を構築しようと考えて以下のサイトを見つけました。

qiita.com

非常に丁寧で分かりやすい記事で参考にさせていただいたのですが、いくつかつまずくポイントもあったため、記録として残しておこうと思います。 今回はGCPGoogle Cloud Pratform)上でdockerとkaggleAPIを用いて行うkaggle環境の構築手順についてまとめたいと思います。

GCEインスタンスの作成

まずはクラウド上にインスタンスを作成します。この手順は非常に簡単です。

GCPの公式サイトにログイン(登録が済んでいない方はサインイン)します。 console.cloud.google.com

次にGPUの割り当て設定を確認します。 ナビゲーションメニュー → 「IAMと管理」 → 「割り当て」を選択し、指標のところでGPUs(all regions)を選択する f:id:kutohonn:20200301161905p:plain この時一番右側に表示される上限の値が使えるGPU数を示しています。 何も設定していない段階ではおそらく0になっているためCompute Engine API GPUs(all regions)の項目にチェックを入れ「割り当ての編集」を選択し,手順に従って割り当て数を1以上に変更します。これでGPUをGCEインスタンス上に加えることが可能になります。

ナビゲーションメニュー → Marketplace → 「deep learning VM」という環境を選択しLAUNCHボタンをクリック
すると以下の画面が出てきます。 f:id:kutohonn:20200301165111p:plain Deployment name: 任意の環境名
Zone: 特に変更なし
Machine type: CPUの数とメモリをカスタマイズする。
この時カスタマイズをするとGPUs aren’t available for the selected Machine Type という警告が出る場合があります。GPUと選択できるMachine typeには制限があるようなので、もし選択したMachine typeがGPUを利用できない場合はそれに近い別のものを選択する必要があります。今回はvCPU×4 メモリ26GBのものを選択しました。
GPUs: 使いたいGPUを選択
Framework: 今回はdockerで環境を作るためフレームワークのインストールは不要です。そこでIntel(R)のCUDA10.1のものを選択することにします。
GPU: 両方にチェック
Boot disk: 特に変更なし
Networking: 特に変更なし
設定が終わったら「デプロイ」をクリック

f:id:kutohonn:20200301171650p:plain

デプロイされていればGCEインスタンスの作成は完了です。 私の場合、警告が表示されていますが、そのまま続行しました。今のところ問題は起きていませんがもし解決方法がわかる方がいらっしゃればご教授いただけると幸いです。

gcloudのインストール

qiita.com この記事に従ってgcloudコマンドをインストールするとローカルのターミナルから作成したインスタンスに簡単にssh接続できるようになります。
(gcloudを入れなくてもブラウザ上のターミナルから作成したインスタンスに接続することはできます。その方法については他記事を参照ください。)

インスタンスssh接続

ナビゲーションメニュー → Compute Engine → 「VMインスタンス」で先ほど作成したインスタンスを開始 f:id:kutohonn:20200301173530p:plain

インスタンスが開始したらssh → gcloudコマンドを表示を選択 f:id:kutohonn:20200301174037p:plain

出てきたポップアップのscriptをローカルのターミナルにコピペして実行しパスワードを入力することでインスタンス内に接続することができます。

dockerによる環境構築

次にdockerによる環境構築を行なっていきます。 まずは接続したディレクトリでDockerfileとrequirements.txtを作成します。 以下をインスタンス内に入ったターミナルで実行します。

$ touch Dockerfile
$ touch requirements.txt

Dockerfileは環境構築のための仕様書のようなもので、requirements.txtにはインストールするモジュールを記載します。 vimがデフォルトで入っているのでvimを用いて以下のようにDockerfileとrequirements.txtをターミナル上で書きます。内容は冒頭で紹介した記事を参考にしています。

Dockerfile

FROM nvidia/cuda:10.0-cudnn7-devel-ubuntu16.04

# install basic dependencies
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
    sudo git wget cmake nano vim gcc g++ build-essential ca-certificates software-properties-common \
    && rm -rf /var/lib/apt/lists/*

# install python
RUN add-apt-repository ppa:deadsnakes/ppa \
&& apt-get update \
&& apt-get install -y python3.6 \
&& wget -O ./get-pip.py https://bootstrap.pypa.io/get-pip.py \
&& python3.6 ./get-pip.py \
&& ln -s /usr/bin/python3.6 /usr/local/bin/python3 \
&& ln -s /usr/bin/python3.6 /usr/local/bin/python

# install common python packages
ADD ./requirements.txt /tmp
RUN pip install pip setuptools -U && pip install -r /tmp/requirements.txt

# set working directory
WORKDIR /root/user

# config and clean up
RUN ldconfig \
&& apt-get clean \
&& apt-get autoremove

requirements.txt

pip==20.0.2
setuptools==39.1.0
wheel==0.30.0
jupyter==1.0.0
matplotlib==2.2.2
seaborn==0.8.1
scikit_learn==0.20.0
scipy==1.1.0
numpy==1.15.2
pandas==0.23.4
gensim==3.6.0
kaggle==1.5.6
torch==1.4.0
torchvision==0.5.0

今回はフレームワークにPyTorchを選択しています。 PyTorchとCUDAの対応バージョンが一致していないと環境構築でつまずきます。 今回はインスタンスの作成時にCUDA 10.1をインストールしたのでそれに対応するバージョンのPyTorchモジュール(torch, torchvision)をインストールします。

今いるディレクトリ内にここで作成した2つのファイルが存在していればOKです。 ではDockerfileに従ってdockerイメージをbuildします。イメージ名は任意の名前をつけることができます。

$ docker build ./ -t {イメージ名}

上記のスクリプトを実行するとbuildが始まります。完了にはしばらくかかります。 終了時にSuccessfully built ~とかかれていればdockerイメージのbuildは成功です。

ではprojectというフォルダを作成しその後イメージからコンテナを作成します。 コードの意味については冒頭の記事を参照ください。

$ mkdir project
$ docker run --runtime=nvidia -p 8888:8888 -d -v ~/project:/root/user/project --name {コンテナ名} {イメージ名} /sbin/init

上記で任意の名前のコンテナができたので下記のスクリプトでコンテナ内に入ります。

$ docker exec -it {コンテナ名} /bin/bash

これでdockerの設定はおしまいです。コンテナを抜けたいときはexitを入力するとコンテナを抜けれます。 またコンテナに入り直したいときは dicker exec~ を再び実行すれば同じコンテナに入ることができます。

Kaggle APIの導入

kaggle APIを利用してデータセットをターミナル上で取得することが可能です。
ただしkaggle APIの導入作業をする必要があります。

まずkaggleの公式サイトからMy accountに移動します。APIという項目の部分のCreate New API Tokenというボタンをクリックするとkaggle.jsonというファイルがダウンロードされます。 f:id:kutohonn:20200301191739p:plain このファイルの中身をコピーしておきます。

次にインスタンスと接続しているターミナルからコンテナ内に入ります。 root直下に.kaggleというフォルダが既に作成されていると思うので

$ touch ~/.kaggle/kaggle.json

を実行しkaggle.jsonという空のファイルを作成します。 この空のファイルにさきほどダウンロードしコピーしたものを貼り付けます。vimとかでターミナル上で開いてコピペするのが早いと思います。 その後以下のコマンドを入力し実行権限を付与します。

$ chmod 600 ~/.kaggle/kaggle.json

この設定をすることでdocker内でkaggleコマンドが使えるようになります。
kaggleコマンドを用いることでデータセットのダウンロードを簡単にできます。

以下使いそうなコマンドをメモしておきます。

特定のコンペのデータをダウンロード

$  kaggle competitions download -c [コンペ名]

特定のkeywordでdatasetを検索

$ kaggle datasets list -s [KEYWORD]

データセットをダウンロード

$ kaggle datasets download -d [DATASET_NAME]

ダウンロードされたデータセットはzipファイルになっているので解凍します。 zip, unzipコマンドのインストール

$ sudo apt-get install zip unzip

zipファイルの解凍

$ unzip {zipファイル名}

Jupyter Notebookの設定

jupyterを起動するにはインスタンス内でコンテナに入った状態で以下を実行します。

$ jupyter notebook --ip=0.0.0.0 --allow-root

すると~ token= ~と書かれた文が出力されると思うので,tokenをコピーしておきます。

その後インスタンスに入っていないローカルのターミナルを開き以下を実行します。

$ gcloud compute ssh "{インスタンス名}" -- -N -f -L 7777:localhost:8888

その後localhost:7777をURLとしてブラウザに入力するとパスワードもしくはtokenが求められるので、先程のtokenを入力すると jupyterへの接続が完了します。

以上で環境構築は終了です。

おわりに

web上でGCPでの環境構築に関する有益な記事は存在しているものの、つまずきポイントが多かったので自分なりにまとめてみました。 環境構築に関してはdockerを使わない方法も試してみたんですけど、結果的にはdockerを用いての環境構築の方がいろいろと楽な気がしました。

2019年の振り返り

2019年も残りわずかとなったので、今年の学びと2020年の目標を記録として残しておこうと思います。

 

純粋な興味から機械学習を勉強し始めたのが昨年の11月で、そこから非常に多くのことを学んできました。1年の振り返りなので時系列で整理していきたいと思います。

 

1月

Couseraの機械学習コースを受講しました。

 

ja.coursera.org

スタンフォード大学のAndrew Ng氏が講師を務めるオンライン講義で機械学習の入門として評判が高い+無料ということで受講しました。講義は英語でしたが、有志の方のおかげで日本語字幕もあったため、言語による障害はほとんどありませんでした。

Andrew氏の講義は非常に分かりやすく、動画学習の良さというのをここで初めて感じました。ただ使用するプログラミング言語Octaveという言語で進行していたため、実装をそれほど重要視せずあくまで理論の方を理解するというスタンスで受講しました。

今考えると理論だけでなく、別の教材やコンペ等で実装を試しつつ、理解を深めた方が良かったのかなとも思いました。

 

2月

日本ディープラーニング協会が主催するG検定を受験しました。

www.jdla.org

機械学習分野に関して全くの無知であったため、分野に関する概要を浅くはあるものの幅広く知るという意味でいい動機づけになると思い、受験しました。

公式の問題集とStudy-Alというサイトにある模試を基本的には行なっていました。

その他にもQiitaのまとめ記事やAI白書等を読み、検定に臨んだ結果無事合格することができました。資格自体が役に立っているとは言い難いですが、画像認識、自然言語処理強化学習、生成モデル、ベイズ学習など、非常に幅広い機械学習分野にどういう技術があるのか、その大枠を知ることができたのは良かったと思っています。

 

3月

機械学習の世界的コンペKaggleに初めて参加しました。

1-2月でどちらかというと知識のインプットばかりを行なっているように感じていたので思い切って参加してみました。当時開催されていたコンペの中で最も規模の大きかった『Santander Customer Transaction Prediction』というコンペに参加しました。

www.kaggle.com

このコンペは銀行のユーザーが商品あるいはローン等に対して契約をするか否かを、200個もの匿名の特徴量から判定するというものでした。初めてのKaggleであったので公開されているKernel(現Notebook)を辿ることしかできませんでしたが、EDA探索的データ分析)の重要性をこのコンペから学びました。

 

4月

就職活動が終了した解放感から新しいことを学びたいと思い、以下の書籍を購入し勉強しました。

ベイズ推論による機械学習入門

機械学習のエッセンス

 

機械学習のエッセンスは数学的な機械学習の基礎部分を丁寧に解説されていてPython実装もある良書でした。個人的にはCouseraの機械学習コースよりもこちらの本の方が基礎を学ぶ目的であれば取り組みやすいかなと思いました。

ベイズ本は途中まで読んでいたのですが、挫折してしまい半分までしか読めていないので2020年に改めて読み返してみようと思っています。

 

5月

Kaggleのコンペ『Freesound Audio Tagging 2019』に参加しました。

www.kaggle.com

内容は与えられた音声データのラベルを予測するというものでした。このコンペでも正直Kernelを参考に少し変更を加える程度しかできなかったのですが、そのKerneがPyTorchで書かれており、そこで初めてPyTorchに触れました。もともとはKerasしか使ったことがなかったのですが、KaggleではPyTorchを利用する人が多い印象を受けたのでここらへんからPyTorchを使うようになりました。

 

6月

研究で機械学習を使うことになりました。

私の所属する研究室は鉄鋼材料の研究をメインに行なっているところで機械学習とは無縁のところでした。しかし縁あって機械学習を用いた研究に参加できることになり、そこから4ヶ月ほど研究でも機械学習を使いました。当時プログラミングによる機械学習の実装技術はそれほどなかったのですが、研究で用いたのを機にステップアップできたように感じています。やはり勉強のための勉強ではなく、目的がありそれを達成するために学んでいくことが一番学習効率が良いことを肌で感じました。

 

7-8月

Kaggleコンペ 『Generative Dog Images』に参加

www.kaggle.com

今年参加した機械学習コンペの中で個人的に最も楽しかったコンペです。

GAN(敵対的生成ネットワーク)を使用して与えられた犬のデータセットをもとに犬の画像を生成し、その生成画像の精巧さと多様性の観点から競い合うというものです。ただしKaggle内のKernel環境(Google Colabのようなもの)でのみ学習可能という条件付きであったため制限時間のある中でより良い画像を生成するというのがこのコンペの肝でした。このコンペが自分の中で最もコミットしたもので、DiscussionやKernelは毎日追い、GANの論文も1日1本ペースで読んでいました。結果は残念ながら203/927位とメダル獲得はできませんでしたが、KaggleそしてGANという技術の面白さを体感することができました。反省としては、当時比較的新しいGANのモデルであったBigGANやSAGANが上位入賞者に使われていたのですが、私は検討すらしていませんでした。Kaggleではある技術を取り入れるだけでメダル入賞も十分ありうるので、日本語の記事だけでなく新しい文献の調査も今後コンペに参加する際は取り組んでいこうと思いました。

 

9月

ベイズに挫折した私ですが再び挑戦してみようと思い、当時話題となっていた以下の新著を購入し勉強しまたもや挫折しました。

ガウス過程と機械学習

この本も2020年度に持ち越したいと思います。

 

10月

SIGNATEで学生限定の家賃予測コンペに参加

kutohonn.hatenablog.com


学生限定コンペがあるという情報を聞き、初めてSIGNATEに参加しました。内容は東京23区内に存在する家の家賃を予測するというものでした。初めて真剣に取り組んだテーブルデータのコンペで学びが非常に多かったのと同時に、コンペ終了後の上位者の解法を見て、同年代の人と現在の自分との差を痛感したコンペでもありました。

 

12月

初めてAdventCalender投稿しました。

qiita.com

KaggleのGANコンペに参加し興味を持ったのと、発信する機会を強制的に作りたいという理由からDeep learning 論文紹介AdventCalenderにてGANの論文まとめを投稿することに決めました。内容は当時ちょうど開催されていたICCV2019でSinGANというGANが話題となっていたのでその論文についてまとめることにしました。投稿後自分が思っていた以上に反応があって、アウトプットすることのモチベーションになりました。私はもともと情報系の専門ではないので、GitHubやQiita、Arxivなどのように情報を共有する環境・雰囲気が整っており、それに対して反応がくるという文化がすごく羨ましく感じました。

2020年の展望

現在考えている私の来年度の目標はこんな感じです。

[勉強面]

[Kaggle]

  • Kaggle expertになる
  • Kaggleにチームを組んで参加する

[実績作り]

  • 機械学習を使った成果物を作る
  • 勉強会等の外部のイベントに参加してみる
  • ブログ等での発信の頻度を増やす

 

まず勉強面に関してです。強化学習は以前から興味があったのですが、取り組めていなかったので見識を広げるという意味でも勉強していこうと思っています。また統計の知識が圧倒的に不足していると感じているので統計学を基礎から学びつつ、今年挫折してしまったベイズガウス過程への理解を深めれればと思っています。

Kaggleに関しては実績としてまだ何も残せていないので、次の称号であるexpertをまずは目標として取り組みたいと思います。また複数人でのコンペ参加を体験したことがないので来年度はチームを組んでの参加にも挑戦します。ただKaggle等のコンペというのはあくまで与えられた課題に対しての取り組みであることに留意する必要があるとも考えています。

そこでコンペ以外での実績づくりも行なっていきたいと考えています。最近以下のような記事を拝見しました。この取り組みは非常に面白いなと思います。

hampen2929.hatenablog.com

このように自分で一から問題を設定して、〇〇×AlというようにAlを別の分野に応用する形で面白い成果物を作りたいなと考えています。この方のように自分の興味のある分野に応用するのが一番熱中して取り組めると思うので、今思いつくあたりだと、私はもともと野球をやっていたので投手の癖をAlで見抜いたり、投球フォームからボールの軌道を予測するというようなことができたら非常に面白いのかなと思っています。そういう取り組みの過程をブログやイベントで発信することで、実績を積み重ねていきたいと思っています。

 

以上が今年の振り返りと来年の展望です。

1年後の今頃、自分がどのような振り返りをしているのかとても楽しみです。