2019/6/9

誰?

  • Twtter: @0_u0
  • JTMRCのアナリスト(2年目)
    • Japanese Traditional Marketing Research Company
    • 主な業務内容: エクセルのソルバーでクライアントの気持ちに寄り添う
  • 地震コンペに負けました
    • TokyoRチームで参加しました
      • Thanks kumakichi, tsuyupon, kur0cky
    • 悔しくて焼き肉になった
  • 性格: Negative

今日のお話

  • 物を買う回数の話
    • おふざけなしです。
  • 対象者
    • マーケティングが仕事の人でデータサイエンスしたい人
    • そうでない人はツイッター眺めてて大丈夫です
  • 公理的な導出してません
    • 許せとは言うまい……
    • 殴られる覚悟をもって立っている(?)

お断り

  • このLTで出てくる事例は所属組織と無関係です。マジで。

  • でもこの資料は検閲が必要なんだ……
    • すまない
    • 近い内に理論部分はなにかに書く
    • Referenceもまとめるから……許して……

問題設定

  • バレンタインまであと8ヶ月ですね。
    • モテる覚悟してますか?
  • そういえば人間チョコレートを一年に何個買うんだろう
    • きぬいとはほとんど買わないので、お待ちしております……
  • 「データは山ほどあって……」(地獄の釜の蓋)
  • 説明しやすいモデルが欲しいらしい
    • どうモデル化してやろう?

チョコレートの市場よくわかんない

データはつくっている

  • 人間たちが1年で何回チョコレートを買うのかを疑似生成。
    • 132回買う人いるらしい。
summary(Data_Table)
##       Age          Sex         Brand           purchase_count   
##  Min.   :20   Min.   :0.0   Length:20000       Min.   :  0.000  
##  1st Qu.:20   1st Qu.:0.0   Class :character   1st Qu.:  1.000  
##  Median :20   Median :1.0   Mode  :character   Median :  3.000  
##  Mean   :25   Mean   :0.7                      Mean   :  7.623  
##  3rd Qu.:30   3rd Qu.:1.0                      3rd Qu.:  9.000  
##  Max.   :40   Max.   :1.0                      Max.   :132.000
unique(Data_Table$Brand)
## [1] "Lotte" "Meiji" "Grico" "Morin"

「回数」といえばPoisson分布

  • 完全理解者のためのPoisson分布
    • 馬に蹴飛ばされた兵士の人数数えてたら生まれた分布(諸説あり)
  • Poisson分布の確率密度関数(実際は離散なので確率質量関数)
    • \(P(x = k|\lambda) = \frac{\lambda^k}{k!}exp(-\lambda)\)
    • 覚えてない人はぜひStatistician-jaへ来てくれ
  • 平均と分散が同じ(\(\lambda\))
    • この性質があんなことになるなんて……

「回数」といえばPoisson分布

  • 一般化線形モデルのPoisson回帰
    • 手っ取り早い。シンプルだね!
    • 期間Tで全体平均で\(\lambda\)個売れるとしたときに\(\lambda\)を推定する。
    • stats::glm(y ~ ., data = YourData, family = 'poisson')

早速やるかー

mean(Data_Table$purchase_count[Data_Table$Brand == 'Lotte'])
## [1] 4.545625
var(Data_Table$purchase_count[Data_Table$Brand == 'Lotte'])
## [1] 30.44547
  • 平均と分散が同じ(\(\lambda\))
    • 同じ……

きびしい

  • 平均と分散が同じという仮定はキツイ
    • 少なくとも分散がでかい場合が多い(overdispersion)
  • 拡張、したいやないですか……
    • なんか購買個数\(\lambda\)を決める「なにか」が違うと信じたい
    • し、そうなら購入個数の平均と分散はなんか違ったほうがそれっぽい

\(\lambda\)がなんか、分布する

  • 確率分布の「混合」、すなわちMixture
  • poisson分布のパラメータ\(\lambda\)が尺度\(r\)、形状\(\theta = \frac{p}{(1-p)}\)のパラメータをもつGamma分布に従うと願う
    • なんでGamma分布?->それはまた別の機会に……
  • すると何故か負の二項分布に従う

負の二項分布に進化すると

  • こうなる
    • \(P(X = k | r, p) = \frac{\Gamma(r+k)}{k!\Gamma(r)}p^k(1-p)^r\)
    • 平均と分散が違っても大丈夫(\(\mu = \frac{pr}{1-p}\),\(\sigma = \frac{pr}{(1-p)^2}\))
    • 特に\(p = 0\)のとき、\(\lambda = r\)のPoisson分布に従うらしいね(本当か?)
  • ここの\(p\)ってなんなん?
    • \(\lambda\)は個人に紐付くパラメータなので、個人の購買行動に関わる確率っぽそう
    • いろいろな解釈がある
      • ブランドの浸透率だとか個人のカテゴリ購入率とか

まずはPoissonでベンチマーク

  • めんどいんでブランドをLoxxxで固定
model_pois <- glm(purchase_count ~ Sex + Age,
                  data = Data_Table[Data_Table$Brand == 'Lotte',],
                  family = poisson(link = 'log'))
coefficients(model_pois)
## (Intercept)         Sex         Age 
##  0.36594109  2.19362213 -0.02811808
AIC(model_pois)
## [1] 50602.42

一方負の二項回帰は

  • MASS::glm.nbで可能
model_nbin <- glm.nb(purchase_count ~ Sex + Age,
                     data = Data_Table[Data_Table$Brand == 'Lotte',],
                     link = log)
coefficients(model_nbin)
## (Intercept)         Sex         Age 
##  0.36099311  2.19201781 -0.02787068
model_nbin$theta
## [1] 1.468564
AIC(model_nbin)
## [1] 37974.4

どうやら……?

  • 説明力としては負の二項回帰は有能そうではある
    • パラメータ数が多い(\(\theta\)も推定している)のにAICでは負の二項回帰がよさげ
AIC(model_pois)
## [1] 50602.42
AIC(model_nbin)
## [1] 37974.4

しかし

  • 予測精度は
    • 微差
rmse(predict(model_pois, newdata = Data_Table),
     Data_Table$purchase_count)
## [1] 12.74778
rmse(predict(model_nbin, newdata = Data_Table), 
     Data_Table$purchase_count)
## [1] 12.74768

しかし

  • 予測精度は
    • 微差
mae(predict(model_pois, newdata = Data_Table),
    Data_Table$purchase_count)
## [1] 6.728847
mae(predict(model_nbin, newdata = Data_Table),
    Data_Table$purchase_count)
## [1] 6.728866

purchase_countの正体

mu_Brand = (2.2 * Sex - 0.03 * Age + Lotte)
purchase_count = rnegbin(Morin_N, mu = mu_Brand, 
                         theta = (1-Lotte_Share)/Lotte_Share)
  • どうやらパラメータはどちらでもいい感じに推定できているらしい
    • ただ\(\theta\)を予測できていた(今回の場合\(\theta\) = 1.5、推定値は1.47)

予実精度とモデル適合度

  • なんか違うっぽい
  • \(\lambda\)で説明できないOverdispersionにうまく適合できている?
  • あくまでシミュレーテッド☆線型回帰なので、予実の精度という意味では大きく違いが現れなかった?
  • この辺詳しい人Twitterで補足してください……

結局どっちがいいの?

  • Overdispersionの気持ち悪さに耐えられるかどうか

  • 負の二項分布がいい場合
    • チョコレートを買う確率が人によってに違うと信じたい場合は負の二項分布
    • 新規顧客を獲得したいなんてときには便利かもしれない
  • ポアソン分布でもいい場合
    • 世界中の人間が等しい確率でチョコレート買うならポアソン分布でいいかもしれない
    • 既存顧客の分析をしたいときには使えるかもしれない
  • 結局お気持ちドリブン
    • 「データだけドリブン」も「お気持ちのみドリブン」もよろしくない
    • 現実のデータが得られていない(深刻)(お前もか)

ちなみに

  • 4ブランド一気にやりたいならlme4::glmer.nbでRandom-effectモデルを組もう
    • 人類にはGLMMはまだ早いと思う
    • GLMも人類には早いと思う
  • 確率分布の混合も人類には早すぎる
    • コイントスに帰ろう(次回予告)

enjoy!