【R】テレビCMの逓減効果(Diminishing Returns)を重回帰分析を使って推定する

f:id:ekanoh:20181021184545p:plain

テレビCMの逓減効果とは

マスメディア広告の中でも最も代表的であるテレビCMは、納得感のある定量的な分析の難易度が高いことが知られています。

テレビCMは顧客認知の形成や企業のブランディングなどを目的として使われることが多いため、認知率などのやや曖昧な指標を使わざるを得ないということや、投資してしばらくしてから効果が出てきたり(ラグ効果)、時間が経つにつれて広告が忘れ去られたり(アドストック)することなど、やや複雑な評価が必要になるからです。

広告の効果測定は、2018年現在でも盛んに研究が行われており、近年では昨年2017年にGoogleが発表した『Bayesian Methods for Media Mix Modeling with Carryover and Shape Effects』(https://ai.google/research/pubs/pub46001)の論文が有名でしょうか。

さて、広告効果の複雑なメカニズムの中でも特に重要なのは、「広告は投下すればするほど効果が出るものではない」という性質です。これを、「逓減効果(Diminishing Returns)」と呼ぶことがあります。

この逓減効果がもし無かったとしたら、「100万円投下すれば認知率が10%あがります。なので、1000万円投下すれば認知率が100%になります」という話になってしまうため、直感的にも理解できるかと思います。

今回はシンプルな分析手法を使って逓減効果を含んだ広告効果のモデリングを行ってみましょう。

cf. アドストック

ちなみに、広告の効果が時間が経つにつれて減衰しながら残存する性質をアドストックと呼ぶことがあり、以下の記事で解説しています: honawork.hatenablog.com

使用するデータ

分析対象として、1984年にWall Street Journalに掲載された、各企業の広告投資とインプレッションを定点観測したデータセットTV Ad Yieldsを利用します。

なお、データセットは2万人の一般人に対して、「印象に残ったテレビCM」を回答させたアンケートと、4000人の消費者に対して、「使用している製品のテレビCMを1週間以内に見たかどうか」を回答させたアンケートに基づいています。

モデリング

1. ナイーブなモデル

まずは、(すべてのパラメータに線形性を仮定して)最もシンプルな回帰分析のモデルを作ってみましょう。モデル式は Y = \beta_1X_1 + \beta_2です。

f:id:ekanoh:20181021181021p:plain

Call:
lm(formula = Impressions ~ TV.Ad.Budget, data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-42.422 -12.623  -8.171   8.832  50.526 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)  22.16269    7.08948   3.126  0.00556 **
TV.Ad.Budget  0.36317    0.09712   3.739  0.00139 **
---
Signif. codes:  
0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.5 on 19 degrees of freedom
Multiple R-squared:  0.424,  Adjusted R-squared:  0.3936 
F-statistic: 13.98 on 1 and 19 DF,  p-value: 0.001389

確かに「広告予算の投下に応じてインプレッションが増える」という基本的(かつ、当たり前)な性質は定量的に説明することが出来ています。 しかしながら、この線形モデルでは逓減効果を表現することはできていません。

2. 2次の項を追加したモデル

次に、先ほどのモデルに2次の項(Quadratic Term)を追加して、 Y = \beta_1 X_1 ^ 2 + \beta_2X_2 + \beta_3の形にして重回帰分析を行ってみましょう。

f:id:ekanoh:20181021181038p:plain

Call:
lm(formula = Impressions ~ TV.Ad.Budget + I(TV.Ad.Budget^2), 
    data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-37.825  -9.128  -2.773   9.560  34.460 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)
(Intercept)        7.059322   9.986180   0.707  0.48867
TV.Ad.Budget       1.084708   0.369944   2.932  0.00891
I(TV.Ad.Budget^2) -0.003990   0.001984  -2.011  0.05954
                    
(Intercept)         
TV.Ad.Budget      **
I(TV.Ad.Budget^2) . 
---
Signif. codes:  
0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.82 on 18 degrees of freedom
Multiple R-squared:  0.5296, Adjusted R-squared:  0.4774 
F-statistic: 10.13 on 2 and 18 DF,  p-value: 0.001127

非線形である二次の項を追加したおかげで、広告の投下量に応じて広告効果が少しずつ逓減していく様子が表現できています。ただし、TV.Ad.Budget = 150であるあたりからインプレッションが減少し始めるため、実際のモデルとしては増加が止まったところからインプレッションが一定になると考えるのが妥当でしょう。

飽和点(Saturation Point)を計算する

さて、飽和点(Saturation Point)=「これ以上投下しても広告の効果が出ない」という投下量を計算してみましょう。先ほどの二次式のモデルを使う場合は、インプレッションが減少を始める点、つまり、傾きが0になる点を探すことになりますので、微分した値が0になればいいはずです。

 \frac{dy}{dx} = 2 \beta_1 X_1 + \beta_2 = 0

なので、回帰分析の結果の係数を代入して飽和点は X = 136だと計算することができました。

f:id:ekanoh:20181021182736p:plain

おわりに

他にも、1未満のべき乗・対数関数・シグモイド型のカーブ・または冒頭で紹介した論文のようにHill関数を利用するなど、さまざまなモデリングの方法が考えられます。広告の改善・最適化などを行う際は、データセットの特徴や、ブランド・商材の特性などを考慮しながら適当なモデルを選び取っていく必要があるでしょう。

本稿では古きよきシンプルな重回帰式を用いて分析を行いましたが、広告の効果分析は日々さまざまな分析モデルが研究されているため、常に分析技術をアップデートをしていく必要があります。データサイエンティストの方々はデータ分析に特化したプログラミング学習サイトであるAidemyなどで無料カウンセリングを受けてみて、一段上の分析へステップアップを図っていくとよいでしょう。

使用したコード

library(tidyverse)
library(ggplot2)

m1 <- lm(Impressions~TV.Ad.Budget, df) 
p1 <- data.frame(x=grid, y=g$coefficients[[2]]*grid+g$coefficients[[1]])

ggplot(df, aes(x=TV.Ad.Budget, y=Impressions)) + 
    geom_point() +
    geom_line(color='#3182bd', data = p1, aes(x=x,y=y)) +
    labs(title="Simple Linear Regression")

m2 <- lm(Impressions~TV.Ad.Budget+I(TV.Ad.Budget**2), df)
p2 <- data.frame(x=grid, y=g$coefficients[[3]]*(grid**2)+g$coefficients[[2]]*grid+g$coefficients[[1]])

ggplot(df, aes(x=TV.Ad.Budget, y=Impressions)) + 
    geom_point() +
    geom_line(color='#3182bd', data = p2, aes(x=x,y=y)) +
    labs(title="Linear Regression with Quadratic Term")