D2C

D2Cでのインターン -未経験からの挑戦-

– プロフィール

こんにちは、2019年卒内定者の遠藤功樹(えんどうあつき)です。 学部時代は生物を専攻、卒業研究ではタンパク質の局在観察を行っていました。学校の授業でプログラミングをしたこともなく、就活中でUnityのC#と数日間のインターンでPythonをいじった程度でほぼ未経験でした。 そんなプログラミング未経験な私がD2Cでデータサイエンティストとして働く前準備として、11月から3月まで週2日程度で内定者インターンとして勉強させて頂きました。その時の内容をまとめてみたので本ブログで紹介します。

– 目次

  1. 環境構築
    ・ AWSでインスタンスの立ち上げ
    ・ 外部サーバーからインスタンスへの接続
  2. 初歩の初歩によるプログラミングの練習
     ・SQL
     ・progate
  3. Pythonの勉強
    ・ インターン資料
    ・ 「機械学習の教科書」
  4. kaggle「Home Credit Default Risk」
  5. 中間まとめ
  6. Uplift Modeling
    ・ 「仕事で始める機械学習」
    ・ class variable transformation(1model approach)
    ・ Criteo
     ―2model approach
     ―1model approach
    ・Uplift Modeling比較
  7. インターンを終えて(まとめ)
  8. 参考文献

1. 環境構築

・AWSでインスタンスの立ち上げ

まず最初にPython勉強するためにjupyter notebookの環境を作るところからのスタートでした。AWSにアカウントを作りEC2のインスタンスを立ち上げるのですが、PCの知識など全くない私は初め「AWSやインスタンスに接続するためのsshなど使ってやるんだよ」と先輩に言われても「AWSやsshって何のことだ?」というくらいさっぱりでした。 とりあえず自力で解決できる能力をつけよう(今後のために)という方針だったので、google先生に何度も聞こうと試みたのですが、まず聞き方も分からないほど知識がない…。説明の中に専門用語があったら取りあえず聞いて自分で調べてと苦労しました。そんなこんなでインスタンスを立ち上げて接続するのに3日間くらいかかり、自分に不安が芽生えたスタートでした。

・外部サーバーからインスタンスへの接続

今度はnotebookをウェブから見れるようにしようという課題が出て壁にぶち当たりました。「え、インスタンス立ち上げれば勝手に見れるんじゃないの?」と現代の技術に頼り切って私がいて、ここでようやくIPアドレスやポート番号、ブラウザ同士のつながりを理解できるようになりました。今思えば立ち上げただけで見れたら「セキュリティくそじゃん」って突っ込みたくなりますよね。

2. 初歩の初歩によるプログラミングの練習

・SQL

会社のデータベースで複数のサーバーを利用したオンプレのHadoopクラスタを利用したサーバーがあります。そのクラスタから知りたいデータを取ってきて加工するという問題を何問か先輩が用意していて、基本的なSQLの書き方が説明されている会社の資料を読みながら自力で解いていきました。 SQL言語を知らなかったですし、何でこんな言語学ばなきゃいけないのかと思いながらも取りあえず指示に従い問題と格闘していました(記事には書いていないですが、後にpysparkというのを使うときにSQLを使いました)。与えられた問題も資料に書かれているやり方を工夫すれば全部解けるようになっており、大学時代に使わなかった頭をフル回転させたので体力を消耗した記憶があります。問題を解いているとプログラミングは数学のように答えにたどり着く過程が1つではなく色々な手法があるのが楽しかったし、この仕事を選んだ要因の1つなので嫌な気持ちもなく取り組めました。

・progate

ようやく私にプログラミングの知識がなさすぎることを知った先輩が、「少し練習させないと話が通じないな」と感じたのかprogateというプログラミングを練習できるサイトでSQL、Linux Command、Pythonを勉強しました。無料でできる範囲でやっていたので、初歩的な問題しかなかったが基礎的なことを知れたのでプログラミング初めての人にはおすすめしたいです。(progate

3. Pythonの練習

・インターン資料

ここに到達するまでに約1か月かかりました。ようやくPythonの実践練習が始まると思うとうきうきでした。初めにインターンで使用された社内資料をもとにコードを写経することから始めました。ここでPythonの基本構文、numpy、pandasを学びました。1つ大きな収穫は資料の内容でリスト内包表記が使われていて、最初何が書かれているか分からなかったが、こんな便利なやり方があったなんてと思いながら今はめちゃめちゃ使っています。

・「機械学習の教科書」

この本ではグラフの描画、行列、微分積分、関数(シグモイドやガウスなど)、教師あり学習の回帰(平均二乗誤差、線形回帰、オーバーフィッティングなど)、分類(最尤推定、勾配法など)を学習しました。 大学の専攻が生物であり、授業で数学もなかったので数式理解を1からやらなければならなく、微分積分以降はすごく苦労しました。ただこの本は丁寧に途中式が書いてあるので理解しやすかったです。関数などを1からコードで書くので写経は嫌になるくらい書かされるので苦手な人は苦手かも…。

4. kaggle「Home Credit Default Risk」

ようやくPythonに慣れてきたところで今まで勉強してきた内容を実践で試すために、先輩がデータの中身を知っていて教えやすいkaggleの過去コンペである「Home Credit Default Risk」に取り組みました。 いきなりコンペをソロでやるのには知識が足りないので、上位のカーネルを真似しながら、どんなやり方があるかを学んびながら実装してみました。データの前処理としてnull値の穴埋めやデータの結合、One-Hot encoding、特徴量エンジニアリングなどをしました。 このコンペは二値分類で評価指標はAUCとなっています。私は3.で勉強したロジスティック回帰をモデルとして選択し、stratified-Kfoldを使い学習・評価データを作りました。今回は前処理の仕方を学ぶ目的だったため、メインデータしか使わなかったですが、最初何も前処理を行わなかったよりもデータ加工してAUCを算出すると精度(ローカル、パブリック、プライベート)がぐんと上がりました。データ分析は前処理が重要なことに気付いたコンペでした。

5. 中間まとめ

4.の「Home Credit」までが一通りの勉強として約2か月間やってきました。Pythonでデータを加工してモデルで評価する一連の流れは自分でできるようになり、少しは成長したのではと感じました。この次から紹介していくUplift Modelingは約3か月かけてじっくり取り込んだ奥の深い内容です。内容や言葉が理解しにくいところもありますが自分なりの解釈で分かりやすく伝えられるように努力しました。

6. Uplift Modeling

・「仕事で始める機械学習」

Uplift Modelingとは?
…「免疫統計ダイレクトマーケティングにおいて活用される機械学習の手法」と書いてあるがよく分かりません。
簡単にいうとA/Bテストに似ているが、A/Bテストと違うのは単に反応を見るだけではなくて、反応したセグメントがどんな特徴量があるかを調べることで、効果が見込めるセグメントを探し出すことができます。 そもそもA/Bテストとは?
…AとBの2つのパターンを用意してどちらがより結果がでるか、というものです。(参照Uplift Modelingを利用する流れ
  1. 母集団を実験したい行為(treatment)を行う実験群(treatment group)と統制群(control group)に隔たりの無いようにランダムで分ける。
  2. CVの結果を付与し、学習データとテストデータに分ける。
  3. 学習データからUplift Modelingのスコアを算出しする。
  4. 予測スコアから求めたいセグメント層を選出する。
Uplift Modelingには四象限のセグメントがあります(CVはconversionの略であり、例にとると商品購入や会員登録といったものがCVにあたります)。
treatmentなしtreatmentありセグメントカテゴリとるべきアクション
CVしないCVしない無関心treatmentにコストがかかる場合、treatmentを控える
CVしないCVする説得可能できる限りここのセグメントにtreatmentする
CVするCVしない天邪鬼絶対にtreatmentしてはいけない
CVするCVする鉄板treatmentにコストがかかる場合、treatmentを控える
Uplift Modelingの評価指標は?
…Upliftの評価指標はAUUC(Area Under the Uplift Curve)を用います。
AUUCの値が大きければ大きいほどUplift Modelingの性能が高いといえます。
→AUCみたく0-1に収まる訳でないのでどの値が本当に性能が高いといえるのが使うデータによって変わるのが難点だと思います。AUUCの算出にはliftを用います。 liftとは?
…あるスコア以上の顧客にはtreatmentを行い、あるスコア未満の顧客にはtreatmentを行わなかった場合、treatmentを行わなかった場合と比較して、どれくらいコンバージョン件数が増えたか、という値です。
$$
lift = ((実験群のCV率) – (統制群のCV率)) * (treatment数)
$$

正直言葉だけでは伝わりにくいので実際にどんなものかを説明していきます。

2つの予測モデルを利用したUplift Modeling(2model approach)

Upliftのscoreを求めるまでの流れ
  1. CVが付与された結果を学習データとテストデータに分ける。
  2. 学習データの中で実験群と統制群の2つに分ける。
  3. それぞれモデルで学習させテストデータを識別する。
  4. CVする予測値2つを利用して以下の通りにしてUplift scoreを算出する。
    Upliftでは以下のセグメントに注目する。
    ・統制群の予測値が低く、実験群の予測値が高い=説得可能なセグメントなので高いスコアになって欲しい。
    ・統制群の予測値が高く、実験群の予測値が低い=天邪鬼なセグメントなので低いスコアになって欲しい。
    以上から、比もしくは差からUpliftのscoreを算出する。

  5. $$
    Uplift_score=\frac{実験群の予測値}{統制群の予測値} or (実験群の予測値) - (統制群の予測値)
    $$
  6. Uplift scoreの高い順に並べてliftを算出する。
  7. ランダムに介入を行った場合の想定コンバージョン上昇数として、liftの原点と終点を結んだ直線をbase_lineとする。
  8. liftとbase_lineに囲まれた範囲をAUUCとする。
・Uplift Modelingの精度が髙ければ高いほど、scoreの上位は実験群においてCVする顧客が集まり、統制群においてはCVしない顧客が集まり、スコアが下位はその反対になる。
・liftの曲線は最初のうちは実験群のCVが集まるため正の傾きを持ち、精度が上がると傾きは急になる。
・逆に最後のほうでは統制群のCVが集まるため負の傾きを持ち、精度が上がると傾きが急になる。
・そのためlift曲線は精度が上がれば上がるほど、より上に凸になり、AUUCの値は大きくなる。
実運用を行う場合は、scoreに従ってtreatmentを実施するかどうかを決定する必要があります。
そのため、横軸をscoreにしたliftグラフを可視化するとどのscore以上でtreatmentを行うかが決定できます。

・class variable transformation(1model approach)

「Uplift modeling for clinical trial data」(参照
「仕事で始める機械学習」では学習データを実験群と統制群の2つに分けて、2つの予測値の比or差でUpliftのscoreを求める2modelでした。今回は1modelで予測値を1つにする方法を紹介していきます。 まず特徴量を$X_1,X_2,…,X_m$、labelを$Y\in{0,1}$、$G\in{T,C}$ とします。
labelは前の説明だとCVにあたり、Y=1はpositive outcome(success)、Y=0はnegative outcome(failure)になります。
G=Tは実験群を、G=Cは統制群を意味しています。また、それぞれの条件付き確率を$P^T$、$P^C$とします。
Upliftのscoreを表すと以下になります。
$$
P(Y=1|X_1,X_2,…,X_m, G=T) \quad – \\quad P(Y=1|X_1,X_2,…,X_m, G=C) \\
= P^T(Y=1|X_1,X_2,…,X_m) \quad – \\quad P(Y=1|X_1,X_2,…,X_m)
$$
1modelにする時には新しいcolumnのzを作ります。条件は以下になります。
$$
Z =
\begin{array}{}
1 \quad if \quad G=T \quad and \quad Y=1 \\
1 \quad if \quad G=C \quad and \quad Y=0 \\
0 \quad otherwise
\end{array}
$$
zの条件をもとにすると以下になります。
$P(Z=1|X_1,X_2,…,X_m, G=T) \\
= P(Z=1|X_1,X_2,…,X_m, G=T)P(G=T|X_1,X_2,…,X_m) \\ + P(Z=1|X_1,X_2,…,X_m, G=C)P(G=C|X_1,X_2,…,X_m) \
\\= P(Y=1|X_1,X_2,…,X_m, G=T)P(G=T|X_1,X_2,…,X_m) \\ + P(Y=1|X_1,X_2,…,X_m, G=C)P(G=C|X_1,X_2,…,X_m)$
Upliftの1modelを考えるときには通常、Gは$X_1,X_2,…,X_m$に独立していると考えます。
独立とは?と思いますが、これは相関していないことであって、$X_1$なら$X_1$で他の影響を受けない(置き換えられない)ことです。
また、実験群と統制群も完全にランダムに選んでなく、偏りが入ると意味がなくなってしまう。
Tも同じようになるので、上の式は以下になります。
$$
P(Z=1|X_1,X_2,…,X_m) \\ = P^T(Y = 1|X_1,X_2,…,X_m)P(G = T) \\ + P^C (Y=0|X_1,X_2,…,X_m)P(G = C) \quad …①
$$
ここで(実験群の数)=(統制群の数)とすると、$P(G=T) = P(G=C) = \frac{1}{2}$ が成り立つので①を変形すると、
$$
\begin{align}
2P(Z=1|X_1,X_2,…,X_m) \\ = P^T(Y=1|X_1,X_2,…,X_m) \\quad + \quad (P^C(Y=0|X_1,X_2,…,X_m)
\\ = P^T(Y=1|X_1,X_2,…,X_m) \quad + \quad 1 \quad – \quad \\P^C(Y=1|X_1,X_2,…,X_m)
\end{align}
$$
になるので、最終的にUpliftのscoreである形に持っていけます。
$$
P^T(Y=1|X_1,X_2,…,X_m) \quad – \\quad P^C(Y=1|X_1,X_2,…,X_m) \\ = 2P(Z=1|X_1,X_2,…,X_m) \quad – \quad 1
$$
以上より、Zで予測した値を2倍して1引いたものがUpliftのscoreになります。 1modelにすることで、学習が早くなったり、2modelのように学習データをさらに分ける必要がないので学習データ数が多くなる利点があるのが特徴なのかなと思います。
ただ、私が2model、1modelをやっている中でAUUCも変わってくるところもあり、2modelの方が良かったりすることもあるので、業務として扱うときには時間は多少かかりますが、両モデル試してどちらかいい方を選択するのがいいのかなと感じました。

Criteo

最後に実践になります。CriteoとはCriteo AI Labが公開している「Criteo Uplift prediction Dataset」を勝手に私がCriteoと略しています。今まで勉強してきたことを踏まえて、自力でCriteoのデータをUplift Modelingしてみようとしました。 Criteoのデータの中身
・f0,f1,,,,f11の12個の特徴量とtreatment、conversionとvisitのbinary label、exposure(treatment effect)の16カラムで構成
・データ数は約2,500万
・Average visit rate=0.4132、Average conversion rate=0.0229
・treatment ratio=0.846(treatment=1が実験群) 今回はCVをvisitとした1modelと2model approachで、モデルにはロジスティックも試しましたが、今回はより精度が髙かったRandomForestを使用したのを紹介していきます。

2model approach

初めにtrain:test=0.8:0.2になるようにデータをランダムに分け、さらにtrainを実験群と統制群に分けました。それぞれをRandomForestで学習させ、学習後にfeature_importancesで各特徴量の重みを見てみると、「f2, f8, f9」の3つの特徴量が重要と思えたので、特徴量エンジニアリングとして3つの中で比を取った新しいカラム3つを作成してみました。 また、1modelと比較するためにtreatment=1とtreatment=0の数を合わせるようにダウンサンプリングをランダムに行いました。新しくできたデータをRandomForestで学習させ、予測した2つの値の差をとってUpliftのscoreにしました。Upliftのscore順に並び変えて、liftとbase_lineのグラフを描いてみました。2modelでのAUUCは50728になりました。

1model approach

2modelの時と同じデータを使い1modelで実装してみました。1modelでやる時は、Zという新しいlabelを作りRandomForestで学習させ、予測値を2倍して1引いたUpliftのscoreにしました。2modelと同じくグラフを描画し、AUUCを求めると、AUUC=41794と2modelよりは精度が低くなってしまいました。

Uplift Modeling 比較

2modelと1modelをAUUCで比較すると2modelの方が精度が髙いモデルができました。またそれぞれのモデルでAUCについて見てみると、2modelのtreatment=1、treatment=0ともにほぼ同じ値になってAUC=0.93になり、1modelはAUC=0.61と差が大きくなりました。 以下に上が2modelと下が1model(左がtreatment=1、右がtreatment=0)の学習させたときの各特徴量の重みをグラフに描いてみました。modelごとの各特徴量の重みを見てみると、重要視されている特徴量が違っています。今回は2modelで顕著に見られる「f2,f8,f9,column1,column2,column3」がよりcriteoのデータで重要な特徴量だったことが考えられます。

7. インターンを終えて(まとめ)

あっという間に時間が過ぎた5か月間でした。インターンの最後に記事という形で何をやってきたかをまとめてみましたが、今思うと最初「AWSって何?sshって何?」と何も知らなかったものが、自力でデータ加工して一つの分析結果を出せるにまで成長できたんだなと実感しています。 ただpysparkといってhadoopを使った分析もcriteoのデータでやったのですが、きれいな結果が出なかったので今回は記事にはしていないことなども多くてもっと自分の中ではやりたいことがたくさんあります。この5か月間、先輩方のサポートによって充実なインターン生活が送れました。今回学んだ知識を入社してからも実務として活かしていきたいと思います。長々とした記事ですが最後まで読んで頂きありがとうございます。

8. 参考文献

伊藤真(2018)『Pythonで動かして学ぶ!あたらしい機械学習の教科書』翔泳社.
今井雄太ほか(2018)『アプリケーションエンジニアのためのApacheSpark入門』秀和システム.
有賀康顕ほか(2017)『仕事で始める機械学習』オライリージャパン.
M Jaskowski, S Jaroszewicz(2012)”Uplift modeling for clinical trial data” (参照)
P Gutierrez, JY Gérardy(2016)”Causal Inference and Uplift Modeling A review of the literature” (参照)
E Diemert et al.(2018)”A Large Scale Benchmark for Uplift Modeling” (参照)


関連タグ