まずは蝋の翼から。

学んだことを書きながら確認・整理するためのメモブログ。こういうことなのかな?といったことをふわっと書いたりしていますが、理解が浅いゆえに的はずれなことも多々あると思うのでツッコミ歓迎

BUSINESS DATA SCIENCE 2章 Regression① 回帰の解釈

BUSINESS DATA SCIENCEという本を最近読んでいるので内容を自分なりにまとめる。
データなどは作者のgitにある。

最近「ビジネスデータサイエンスの教科書」という邦題で日本語版も出たみたいです

ビジネスデータサイエンスの教科書

ビジネスデータサイエンスの教科書

今回は2章 Regression(回帰)。回帰モデルの一番初歩の部分は省略する。

過去分は以下。

knknkn.hatenablog.com

knknkn.hatenablog.com

この章はなにか

多くのDataScienceの問題に回帰モデルが用いられているからわかるように、回帰モデルはDataScienceの基本となるので紹介されている。

回帰モデルの解釈

以前同様のことをおこなったが改めてちゃんとしたデータでおこなう。

knknkn.hatenablog.com

オレンジジュース市場についてのデータを用いる。

oj = read_csv('BDS-master/examples/oj.csv')
# A tibble: 28,947 x 4
# sales price brand      feat
# <dbl> <dbl> <chr>     <dbl>
#   1  8256.  3.87 tropicana     0
# 2  6144.  3.87 tropicana     0
# 3  3840.  3.87 tropicana     0
# 4  8000.  3.87 tropicana     0
# 5  8896.  3.87 tropicana     0
# 6  7168.  3.87 tropicana     0
# 7 10880.  3.29 tropicana     0
# 8  7744.  3.29 tropicana     0
# 9  8512.  3.29 tropicana     0
# 10  5504.  3.29 tropicana     0
# # … with 28,937 more rows

切片のみブランドダミー

このデータに対して、 log(sales) ~ brand + log(price) を考えると以下のような結果となる。

reg = glm(log(sales) ~ brand + log(price), data = oj)
coef(reg)
# (Intercept) brandminute.maid   brandtropicana       log(price) 
# 10.8288216        0.8701747        1.5299428       -3.1386914 

oj %>% 
  ggplot(aes(log(price), log(sales))) +
  geom_point(size = 0.1, alpha = 0.1) +
  geom_abline(slope = -3.1386914, intercept = 10.8288216, color = 'red') + # dominics
  geom_abline(slope = -3.1386914, intercept = 10.8288216 + 0.8701747, color = 'blue') + # minutemaid
  geom_abline(slope = -3.1386914, intercept = 10.8288216 + 1.5299428, color = 'green') # tropicana

f:id:chito_ng:20200102031835p:plain

これは、図からわかるように 各ブランド毎に切片が異なるが傾き(priceが増えたときのsalesへの影響が同じ)は同じ というモデルとなる。また、結果より **同じpriceのときにtropicanaが最もsalesが良いということがわかる。

brand交互作用

ここで、 dominics愛好家はtropicana愛好家よりお金がない という情報を得たとする。つまり、**salesにおいて、dominics愛好家はtropicana愛好家よりもpriceの影響があるのでは?」という仮定が生まれることとなりその仮定をモデルに組み込むとlog(sales) ~ brand * log(price) となる。

reg_interact = glm(log(sales) ~ brand * log(price), data = oj)
coef(reg_interact)
# (Intercept)            brandminute.maid              brandtropicana 
# 10.95468173                  0.88825363                  0.96238960 
# log(price) brandminute.maid:log(price)   brandtropicana:log(price) 
# -3.37752963                  0.05679476                  0.66576088 

oj %>% 
  ggplot(aes(log(price), log(sales))) +
  geom_point(size = 0.1, alpha = 0.1) +
  geom_smooth(aes(color = brand), method = 'glm', formula = y ~ x)

f:id:chito_ng:20200102033234p:plain

ここで得られた結果より、モデル式は
 log(sales) = -3.37752963 log(price) + 0.05679476 log(price) \times minute.maid dummy + 0.66576088 \times tropicana dummy + 10.95468173 + 0.05679476 \times minute.maid dummy + 0.66576088 \times tropicana dummy
となる。このとき、各brand dummyはそのbrandのモデルを考えるときに1、それ以外の場合は0となる。
そのため、例えばtropicana を考えるときはtropicana_dummy = 1, minute.maid_dummy = 0dominics を考えるときはtropicana_dummy = 0, minute.maid_dummy = 0 を代入した結果となる。

この結果のbrand毎の回帰線の傾きは以下のようになる(ここでこの表を表1とする)。

Dominick's Minute Maid Tropicana
-3.4 -3.3 -2.7

ここから更に、広告露出(feature)の有無を加える。brand毎に広告露出の効果は異なると考えられるのでlog(sales) ~ brand * log(price) * featとしてモデルを考える。

ojreg = glm(log(sales) ~ brand * log(price) * feat, data = oj)
coef(ojreg)
# (Intercept)                 brandminute.maid 
# 10.40657579                       0.04720317 
# brandtropicana                       log(price) 
# 0.70794089                      -2.77415436 
# feat      brandminute.maid:log(price) 
# 1.09440665                       0.78293210 
# brandtropicana:log(price)            brandminute.maid:feat 
# 0.73579299                       1.17294361 
# brandtropicana:feat                  log(price):feat 
# 0.78525237                      -0.47055331 
# brandminute.maid:log(price):feat   brandtropicana:log(price):feat 
# -1.10922376                      -0.98614093 

oj %>% 
  ggplot(aes(log(price), log(sales), group = interaction(feat,brand))) +
  geom_point(size = 0.1, alpha = 0.1) +
  geom_smooth(aes(color = interaction(feat,brand)), method = 'glm', formula = y ~ x)

f:id:chito_ng:20200102035811p:plain

この結果より、各傾きは以下のようにまとめられる(ここでこの表を表2とする)。

Dominick's Minute Maid Tropicana
広告無し -2.8 -2.0 -2.0
広告あり -3.2 -3.6 -3.5

この結果の解釈をおこなう。Dominick'sは広告の有無で0.4の差分しかないが、他の2つは約1.5も差分が出てしまう。これは、Minute Maid Tropicanaは広告を打つことによって価格を気にする人が新規として多く入ってきたのではないか?といった仮説が考えられる。実際に、Marketing 101 dictaesでは「広告打ちと値下げは連動させろ」という話もあるので仮説として的外れではない可能性が高い。また、需要供給曲線は非線形であり、低価格帯の消費者は価格に敏感に反応することが知られている。

別の解釈を考えるために、表1(広告をモデルに入れていないモデルの傾き)を再掲する。

Dominick's Minute Maid Tropicana
-3.4 -3.3 -2.7

表1ではDominick'sMinute Maidはほぼ同様の傾きだったが、表2では広告有無に関わらず大きく異なる結果となっている。

広告の有無それぞれのときのデータ割合は以下のようになっている。

oj %>%
  group_by(brand, feat) %>% 
  summarise(n = n()) %>% 
  group_by(feat) %>% 
  mutate(all = sum(n),
         rate = n/all) %>% 
  ungroup() %>% 
  ggplot(aes(feat, rate, fill = brand))+
  geom_bar(stat = "identity", position = "stack") 

f:id:chito_ng:20200102042047p:plain

広告無しのときはDominick'sMinute Maidは同じくらいの割合だが、広告ありではMinute Maidの方が割合が多い。そのため、前述のように価格に過敏に反応する消費者の数が広告ありでは Minute Maidに多く存在することになる。その結果として、 Minute Maidではpricesalesへの影響が多く出ているのではないかと思われる(仮説)。