Skip to content

Instantly share code, notes, and snippets.

@awajundesu
Last active March 3, 2017 02:12
Show Gist options
  • Save awajundesu/5d76cddfee4f618eafc05482c534d53b to your computer and use it in GitHub Desktop.
Save awajundesu/5d76cddfee4f618eafc05482c534d53b to your computer and use it in GitHub Desktop.

Hivemallを使ったLeadScoring

Step1) データの前処理

[1]lead_scoring_demo_shape
https://console.treasuredata.com/app/queries/editor?queryId=161457

CVに関係のありそうな変数のみを選択して使用する。

今回使うランダムフォレストというロジックでは、量的変数を前提としているため、選択と同時に整形も行う。

  case
    when LOWER(job_title2) LIKE '%manager%' then 1
    when LOWER(job_title2) LIKE '%director%' then 1
    when LOWER(job_title2) LIKE '%supervisor%' then 1
    else 0
  end as is_manager

職業名は、"manager","director","supervisor"が入っている人は1、そうでない人は0とした変数に変換して使用する。

  case
    when acquisition_channel = 'Cold Call' then 1
    else 0
  end as acquisition_channel_Cold_Call,
  case
    when acquisition_channel = 'Cold Email' then 1
    else 0
  end as acquisition_channel_cold_email,
  case
    when acquisition_channel = 'Paid Leads' then 1
    else 0
  end as acquisition_channel_paid_leads,
  case
    when acquisition_channel = 'Organic Search' then 1
    else 0
  end as acquisition_channel_organic_search,

リードの取得経路を表すacquisition_channelという変数はパターン数が存在するので、ダミー変数を使用する。
ダミー変数とは

No acquisition_channel
01 Cold Call
02 Cold Email
03 Paid Leads
04 Organic Search
05 Paid Search

のような質的データを

No Cold Call Cold Email Paid Leads Organic Search
01 1 0 0 0
02 0 1 0 0
03 0 0 1 0
04 0 0 0 1
05 0 0 0 0

という0と1の量的データで現したものである。
会社規模を表すcompany_size、業界を表すindustryという変数も同様にダミー変数を使用する。

[2]lead_scoring_demo_feature
https://console.treasuredata.com/app/queries/editor?queryId=161511

INSERT OVERWRITE TABLE lead_scoring_featured
SELECT
  rowid,
  converted as label,
  array(days_since_signup, completed_form,visited_pricing,registered_for_webinar,attended_webinar,is_manager,acquisition_channel_cold_call,acquisition_channel_cold_email,acquisition_channel_paid_leads,acquisition_channel_organic_search,company_size_11_50,company_size_51_100,company_size_101_250,company_size_251_1000,company_size_1000_10000,company_size_10001,industry_web_internet,industry_furniture,industry_heavy_manufacturing,industry_scandanavion_design,industry_financial_services
    ) as features
FROM lead_scoring2

hivemallでは、説明変数をarray型にする必要があるためその処理を行う。  

Step2) Random Forest による学習

[3]lead_scoring_demo_train
https://console.treasuredata.com/app/queries/editor?queryId=161576

INSERT OVERWRITE TABLE lead_scoring_trainmodel
SELECT
  train_randomforest_classifier(features,label,'-trees 10') as (model_id,model_type,pred_model,var_importance,oob_errors,oob_tests)
FROM lead_scoring_featured

train_randomforest_classifierという関数を使えばよい。引数'-trees'で決定木の数を指定できる。

Step3) モデルを用いて予測

[4]lead_scoring_demo_predict
https://console.treasuredata.com/app/queries/editor?queryId=161604

WITH t1 AS(
  SELECT
    t.rowid,
    tree_predict(p.model_id,p.model_type,p.pred_model,t.features,true) as predicted
  FROM
    lead_scoring_trainmodel  as p
    LEFT OUTER JOIN lead_scoring_featured as t
),

tree_predict関数を使って予測を行う。   返り値は各レコードに対する全決定木における予測結果。  

t2 AS(
  SELECT
    rowid,
    rf_ensemble(predicted) as predicted
  FROM t1
  GROUP BY
    rowid
)

rf_ensemble関数でアンサンブルという手法を使う。 今回は決定木の数が10個なので、1データに対して10通りの予測結果がある。   それらを集計して多数決で最終的な予測ラベルを決めるのがアンサンブルである。

INSERT OVERWRITE TABLE lead_scoring_predicted
SELECT
  rowid,
  predicted.label, predicted.probability, predicted.probabilities
FROM
  t2;

rf_ensemble関数の返り値は   [予測ラベル,そのラベルである確率,[各ラベルである確率(配列)]]   という形式なので分かりやすくするため分解する。

Step4) モデルの評価

[5]lead_scoring_demo_evaluate
https://console.treasuredata.com/app/queries/editor?queryId=161636

WITH t1 AS(
  SELECT
    t.rowid,
    t.label as actual,
    p.label as predicted
  FROM
    lead_scoring_predicted as p
    LEFT OUTER JOIN lead_scoring_featured as t ON (t.rowid = p.rowid)
)
SELECT
  count(1) / 100000
FROM
  t1
WHERE
  actual = predicted;

ここでは単純に、予測ラベルと実際のラベルを比べて予測成功した確率を出す。

Step5) ユーザーをGRADEに分類

[6]lead_scoring_demo_grade
https://console.treasuredata.com/app/queries/editor?queryId=161651

WITH t1 AS(
  SELECT
    rowid,
    if(label = 0, 1 - probability, probability) as cv_probability
  FROM
    lead_scoring_predicted
),

lead_scoring_predictedのprobabilityというcolumnは、予測ラベルに対する確率なのでラベル1に対する確率に統一する。  

INSERT OVERWRITE TABLE lead_scoring_grade
SELECT
  rowid,
  case
    when (cv_probability < 0.2) then 'F'
    when (cv_probability < 0.4 AND cv_probability >= 0.2) then 'D'
    when (cv_probability < 0.6 AND cv_probability >= 0.4) then 'C'
    when (cv_probability < 0.8 AND cv_probability >= 0.6) then 'B'
    else 'A'
  end as grade
FROM
  t1
)

応じてユーザーをA,B,C,D,Fの5段階に分類した。

[7]lead_scoring_demo_graderate
https://console.treasuredata.com/app/queries/editor?queryId=162490

WITH t1 AS(
  SELECT
    t.rowid,
    t.label,
    p.grade
  FROM
    lead_scoring_grade as p
    LEFT OUTER JOIN lead_scoring_featured as t ON (t.rowid = p.rowid)
)
SELECT
  grade,
  label,
  count(*)
FROM
  t1

各段階のラベルごとの人数をカウントした。    

grade label count
A 0 4
A 1 23
B 0 158
B 1 1594
C 0 627
C 1 5836
D 0 1555
D 1 3323
F 0 74830
F 1 12050

Hivemallを利用したRandomForestによるLeadScoringの手順まとめ

  1. データを整形:質的変数を量的変数に  
  • パターンの多い(決まっていない)変数 → パターンにまとめる
  • パターンの決まっている変数 → ダミー変数を利用する  
  1. データを整形:必要な変数を特徴ベクトルに  
  • array関数を使って配列にする  
  1. Random Forest による学習
  • train_randomforest_classifier関数を使用する
  • -trees で決定木の数 など引数として色々なパラメータを与えることができる
  1. モデルを使った予測
  • tree_predict関数と、rf_ensemble関数を使用
  • 返り値は予測ラベルとその確率、全ラベルに対する確率
  1. リードを予測確率により段階に分類
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment