Lecture 4 前半:異質性のある需要と合併分析

計量経済学II

作者

Kei Ikegami

このノートはLecture 4の前半である。続きは後半:需要と供給を同時に推定するを参照。

重要この講義で押さえたいこと
  • 属性への評価や価格への反応を消費者ごとに変えると、商品の代替関係がどう変わるかを理解する。同じ販売数を再現していても、好みの構造が違えば値上げ後の需要は異なり得る。
  • random coefficient logit の選択確率を人々について平均し、市場全体の需要を計算する。この平均を数値積分で求める。
  • 第3回の「Berry反転とIV」を、係数に異質性のあるモデルへ拡張する。小さな数値例で、BLPによる需要推定の手順を追う。
  • 推定した需要に企業の価格設定行動を加え、合併後の価格と消費者余剰を予測する。需要の推定と合併分析を、一つの例でつなげる。
  • 購入者の所得や第二希望を使う micro BLP を学ぶ。販売数だけでなく「誰が買ったか」「ほかに何を買いたかったか」を使うと、好みの違いについて何が分かるだろうか。

前回とのつながり・今回のゴール

第3回では、第2回で学んだ logit を使って需要を推定する際の、2つの問題を扱った。一つは、どの商品からどの商品へ需要が移るかをモデルが強く制約してしまうこと。もう一つは、価格が分析者には見えない需要ショックに反応して決まる、価格の内生性である。今回は、この両方の話を引き継ぐ。

まず、代替関係の問題を振り返ろう。plain logit には IIA(無関係な選択肢からの独立性)があり、他の価格や属性を固定して財3だけを値上げすると、財1と財2の需要の増加分の比は、両者の元のシェア比で決まる。財1の方が財3に似ているとしても、その近さを別に反映できない。前回の nested logit では、同じネストに属する財の効用ショックに相関を許すことで、この制約を緩めた。ただし、どの財を同じネストに入れるかは分析者が事前に決める必要があり、同じネスト内の2財のシェア比にはIIAが残る。

今回は、ネストを指定する代わりに、属性への評価や価格への反応を表す係数を、消費者ごとに変える。これまでも、効用ショックを通じて人による好みの違いを表していた。新しく加えるのは、例えば甘さを評価する係数そのものが人によって違い、甘いコーヒーを好む人は複数の甘い商品を高く評価する、という関係である。価格への反応にも人による違いを認める。こうしたモデルを random coefficient logit と呼ぶ。

次に、価格の内生性である。前回は、Berry反転でシェアから平均効用を取り出し、その式にIVを使うことで対処した。反転は需要ショックを取り出せる形を作るための操作であり、価格と需要ショックの相関に対処するには、妥当な操作変数が必要だった。係数を消費者ごとに変えても、この内生性の問題は残る。

そこで今回は、random coefficient logit でも同じ推定の考え方を使いたい。ただし、消費者ごとの選択確率を平均してシェアを求めるため、前回の logit のようにシェアの対数差だけで平均効用を取り出すことはできない。係数の分布を表すパラメータを仮に決め、観測シェアを再現する平均効用を数値計算で逆算する。その上で、取り出した需要ショックと操作変数が無相関になる条件を使って推定する。これが、今回学ぶBLPの推定方法につながる。

Lecture 4は二つのノートに分ける。この前半では、まず係数の異質性が代替関係をどう変えるかを確かめ、BLPで需要を推定する。次に、その需要を企業の価格設定のモデルに入れ、合併したら価格がどれだけ上がるかを計算する。最後に、個票データを追加するmicro BLPを取り上げる。合併予測に必要な代替関係を、「誰がどの商品を買ったか」という情報からも調べるためである。

ここでは、需要を推定した後に企業の価格設定行動を使う。では、その行動についての仮定を、需要を推定する段階から使うことはできないだろうか。後半では、この問いから需要と供給の同時推定に進む。どちらも、第5回のゲスト講義で扱う合併審査を理解するための準備になる。

計算の手順は少し長いが、「需要を推定する」「推定した需要で合併後を予測する」「需要の推定に使う情報を増やす」という順に追っていこう。

1. なぜ係数を消費者ごとに変えるのか

コンビニにブラック、微糖、カフェオレの3種類が並んでいるとする。消費者はどれかを買うか、「買わない」(outside option)を選ぶ。ここで微糖が10円値上げされたらどうなるだろうか。plain logit では、微糖からブラックとカフェオレへ移る需要の比率は、両者の市場シェアの比で決まる。

しかし、微糖を選ぶ人の多くが甘さを好むなら、値上げ後の候補としてブラックよりカフェオレを高く評価するかもしれない。このような代替を表す一つの方法が、人によって甘さの好みが違うことをモデルに入れることである。第2回の \(x_j'\beta\) の \(\beta\) を、人ごとの \(\beta_i\) に変える。以下では、その意味を3人の買い物で確かめる。どの属性の係数をどう分布させるかが代替パターンを決めるので、係数を動かせば任意の「近さ」が自動的に再現されるわけではない。

価格への反応も、人によって違う。例えば、所得の高い管理職は10円の値上げをあまり気にしない(\(\alpha_i\) が小さい)が、学生は気にする(\(\alpha_i\) が大きい)、と考えてみよう。この異質性を入れると、もともと価格をあまり気にしない人ほど高い財を買いやすくなる。こうした選択(セレクション)によって、高価格帯の弾力性も plain logit の予測とは変わってくる。

ノートビジネスの現場で:自社ラインナップのカニバリゼーション

新商品を出すときには、自社のどの既存商品から客が移るかも知りたい。これがカニバリゼーション(cannibalization)の問題である。plain logit では、どの商品から移るかはシェアの比率で決まってしまう。しかし「濃いめのカフェオレ」を発売したなら、ブラックよりも微糖や既存のカフェオレから客が移りやすいと考えられる。random coefficient logit では、属性への好みの違いを使って、どの自社製品の需要がどれだけ減るかを予測する。この予測は、価格改定や品揃え(assortment)の最適化にも使われる。

品質の順位と好みの違いを3人の例で比べる

製品の違いを、価格を同じにそろえたとき、消費者の製品順位が一致するかという観点から整理しよう。同じ価格なら全員が同じ品質順位で評価する場合を垂直的差別化、好みによって製品の順位が異なる場合を水平的差別化と呼ぶ。

ここでは、両者からどんな需要が生まれるかを、3人の買い物の例で確かめよう。いずれも説明用の架空の市場であり、効用を「評価額−価格」として円単位で測る。買わない効用は0とし、ランダム項は一旦省く。後でこの例を random coefficient logit につなげる。

垂直的差別化:同じ価格なら全員が高品質を好む

Aは品質1、Bは品質2のコーヒーとする。品質1単位に払ってよいと思う金額が、3人それぞれ120円、160円、220円だとしよう。BはAの2倍の品質なので、それぞれの評価額も2倍になる。

消費者 Aの評価額 Bの評価額 Aが100円、Bが250円のときの効用と選択 Bだけ300円にしたときの効用と選択
1人目 120円 240円 A:20、B:−10 → A A:20、B:−60 → A
2人目 160円 320円 A:60、B:70 → B A:60、B:20 → A
3人目 220円 440円 A:120、B:190 → B A:120、B:140 → B

例えば2人目は、値上げ前には \(320-250=70\) が \(160-100=60\) より大きいのでBを買う。値上げ後にはBの効用が \(320-300=20\) に下がるのでAに移る。3人の選択を数えると、需要はAが1本・Bが2本から、Aが2本・Bが1本へ変わる。

AもBも100円だったら、3人ともBを選ぶ。同じ価格なら、全員が同じ品質順位で製品を評価するのが、この垂直的差別化の例である。好みが完全に同じという意味ではなく、追加の品質にいくら払うかは人によって異なる。品質を \(z_j\)、人 \(i\) の品質1単位への評価を \(w_i>0\) とすれば、効用は \(u_{ij}=w_i z_j-p_j\) と書ける。すでにこのモデルにも、品質への支払意思額の異質性がある。

水平的差別化:同じ価格でも好きな製品が違う

今度はAを「苦いコーヒー」、Bを「甘いコーヒー」と考える。苦い方が好きな人も、甘い方が好きな人もいる。次の評価額を持つ3人を考えよう。

消費者 Aの評価額 Bの評価額 Aが100円、Bが250円のときの効用と選択 Bだけ300円にしたときの効用と選択
1人目 160円 80円 A:60、B:−170 → A A:60、B:−220 → A
2人目 120円 360円 A:20、B:110 → B A:20、B:60 → B
3人目 160円 400円 A:60、B:150 → B A:60、B:100 → B

同じ100円にそろえても、1人目はA、2・3人目はBを選ぶ。同じ価格でも、人によって製品の好ましさの順位が違うのが、この水平的差別化の例である。

値上げ前の需要は、先ほどと同じAが1本・Bが2本である。しかし、この例ではBを300円にしても2・3人目はBを選び続け、需要は変わらない。同じ現在の販売数を説明できても、好みのモデルが違えば、値上げ後の需要予測は違う。水平的差別化なら必ず価格に反応しにくいという意味ではなく、現在のシェアだけでは代替関係は決まらない、という例である。

共通の \(\beta\) から \(\beta_i\) へ:特性への評価を変える

第2回で学んだ特性アプローチ(characteristics approach)では、製品を特徴の束として表した。Aの特徴を「苦味2・甘さ0」、Bを「苦味0・甘さ2」とし、苦味と甘さ1単位への評価額を次のように置くと、上の水平的差別化の表を作れる。

消費者 苦味1単位への評価 甘さ1単位への評価 Aの評価額 Bの評価額
1人目 80円 40円 \(80\times2+40\times0=160\)円 \(80\times0+40\times2=80\)円
2人目 60円 180円 \(60\times2+180\times0=120\)円 \(60\times0+180\times2=360\)円
3人目 80円 200円 \(80\times2+200\times0=160\)円 \(80\times0+200\times2=400\)円

製品属性を \(x_j\)、人ごとの評価を \(\beta_i\) とすれば、評価額は \(x_j'\beta_i\)、効用は \(u_{ij}=x_j'\beta_i-p_j\) である。第2回から変えたのは、属性への係数そのものを人ごとに変えた点だ。第2回の共通 \(\beta\) の logit でも、\(\varepsilon_{ij}\) によって同価格で人ごとの製品順位は異なり得た。したがって、random coefficient を入れて初めて水平的な好みの違いを扱える、ということではない。

では、\(\beta_i\) にする利点は何か。例えば、Bと同じく甘さを持つ製品Cも並べたとする。甘さへの評価が高い人では、同じ甘さの係数がBとCの効用をともに押し上げる。これにより、観測された属性・価格を固定して人々を比べたとき、製品間の効用に属性を通じた相関が生まれる。独立な \(\varepsilon_{ij}\) だけに選択の違いを任せる場合と違い、「甘い製品を好んだ人が、どの別の製品を次の候補として好みやすいか」をモデル化できる。これが、ネストを事前に区切らずに代替関係を柔軟にする仕組みである。Train (2009), Chapter 6 は、random coefficient とこの効用の相関の関係を説明している。

ここまでは3人の評価額をすべて既知とし、円単位の効用に価格係数1を置いた手計算だった。次節では、\(\beta_i\) や価格係数 \(\alpha_i\) に分布を仮定し、さらに Gumbel の \(\varepsilon_{ijt}\) を加える。人ごとには logit の選択確率を計算し、それを人々について平均して市場需要を作る。上の円単位の評価額を、そのまま後の標準化された logit の係数として用いるわけではない。

ノート第1回のBresnahanと、今回のBLPのつながり

第1回の Bresnahan (1987) も、共通の品質軸と消費者ごとの支払意思額から選択を集計して需要を作っていた。最初の垂直的差別化の表は、その考え方を小さくした説明例であり、論文の推定結果ではない。Berry, Levinsohn and Pakes (1995) はこの系譜を引き継ぎ、複数の属性とより豊かな好みの分布を使い、観測できない製品属性による価格の内生性も扱う需要推定を発展させた。

したがって、ここでの発展は「Bresnahanの需要関数を捨てて離散選択へ移る」ことではない。属性から効用を作り、選択を集計して需要を作るという発想を共有した上で、どの属性を誰がどれだけ評価するかの制約を緩めるのである。垂直・水平という製品の評価の仕方と、logit・nested logit・random coefficient logit というモデルの仕様は、別の区別だと整理しておこう。

2. モデル:random coefficient logit

記法は第2回・第3回と同じである。消費者を \(i\)、財を \(j\)(\(j=0\) は「買わない」という outside option)、市場を \(t\) と書く。効用は次のようになる。

\[ u_{ijt} = x_{jt}'\beta_i - \alpha_i\, p_{jt} + \xi_{jt} + \varepsilon_{ijt}. \]

これまでの logit との違いは、係数に \(i\) の添字が付いたことである。\(\varepsilon_{ijt}\) はこれまで通り Type I 極値分布(Gumbel)に従う。\(\xi_{jt}\) は分析者には観測できない製品・市場の魅力であり、第3回で価格の内生性を考えるときに使った項である。

属性への評価が人によって違うことを、次の式で表す。

\[ \beta_i = \beta + \Sigma^{1/2}\nu_i, \qquad \nu_i \sim N(0, I). \]

\(\beta\) は平均的な好み、\(\Sigma\) は好みのばらつきを表し、その対角成分が異質性の大きさに対応する。\(\nu_i\) は消費者ごとの違いを表す乱数である。

価格係数には対数正規分布を使う

価格係数 \(\alpha_i\) に正規分布を仮定すると、分布の裾では \(\alpha_i < 0\) となる人も出てくる。効用の式には価格がマイナスで入っているので、この人は価格が上がるほど効用が高くなってしまう。そこで、実務でも使われる対数正規分布を使い、価格係数が常に正になるようにする。

\[ \alpha_i = \exp(\bar\alpha + \sigma\, \nu_i^{p}), \qquad \nu_i^{p} \sim N(0,1). \]

\(\bar\alpha\) は log価格係数の平均、\(\sigma\) はlog価格係数の標準偏差である。元の水準では

\[ \operatorname{median}(\alpha_i)=e^{\bar\alpha},\qquad E[\alpha_i]=e^{\bar\alpha+\sigma^2/2}. \]

したがって、\(e^{\bar\alpha}\) は一般には平均価格係数ではない。平均と一致するのは \(\sigma=0\) のときだけである。この区別に注意しよう。Nevo (2000) は、こうした符号制約や所得との相互作用など、実装上の論点を整理している。次節では属性と価格の両方の係数を動かして比較するが、第5節の需要推定では、計算を簡単にするため価格係数だけに異質性を入れる。

\(\nu_i\) を1つ固定すると、その人の係数 \((\beta_i, \alpha_i)\) が決まる。したがって、その人の選択確率には、第2回と同じ logit の公式を使える。

\[ s_{ijt}(\nu_i) = \frac{\exp(\delta_{jt} + \mu_{ijt})}{1 + \sum_{k=1}^{J}\exp(\delta_{kt} + \mu_{ikt})}. \]

ここで \(\alpha_0=E[\alpha_i]=e^{\bar\alpha+\sigma^2/2}\) と置けば、平均効用と個人偏差を

\[ \delta_{jt}=x_{jt}'\beta-\alpha_0p_{jt}+\xi_{jt},\qquad \mu_{ijt}=-(\alpha_i-\alpha_0)p_{jt}+x_{jt}'(\Sigma^{1/2}\nu_i) \]

と分けられる。2式を足せば元の効用の確定部分 \(x_{jt}'\beta_i-\alpha_i p_{jt}+\xi_{jt}\) に戻る。\(\delta\) には \(i\) が入らず、\(\mu\) が平均ゼロの係数偏差を表す、という対応を確認しておこう。

市場全体のシェアは、この選択確率を \(\nu\) の分布で積分して求める。人々について平均するということである。

\[ s_{jt}(\delta_{\cdot t}, \sigma) = \int s_{ijt}(\nu)\, dF(\nu). \]

選択確率は \(\nu\) の非線形な関数なので、この積分は閉じた形では書けない。そこで第2回と同じように、シミュレーションを使う。乱数を \(ns\) 人分引き、それぞれの選択確率を計算して平均すれば、積分を近似できる。この方法がモンテカルロ積分である。

具体的には、シェアを次のように近似する。

\[ s_{jt}(\delta_{\cdot t}, \sigma) \approx \frac{1}{ns}\sum_{r=1}^{ns} \frac{\exp(\delta_{jt} + \mu_{jt}(\nu_r))}{1 + \sum_{k}\exp(\delta_{kt} + \mu_{kt}(\nu_r))} \]

第2回では選択確率をシミュレーションで求めた。ここでは、消費者ごとの選択確率を平均して、市場全体のシェアを計算している。

3. シミュレーション1:異質性が代替性を変える

以下の図表でいう「同質」「異質」は、属性・価格への係数が全員共通か、人によって違うかを指す。どちらのモデルにも \(\varepsilon_{ij}\) はある。

まず「\(\sigma=0\)(= plain logit)」と「\(\sigma>0\)」で、集計需要曲線と交差弾力性がどう変わるかを、コードで作ったデータで見比べる。3財+outside の1市場を考える。財1と財2は属性が近い(\(x\) が近い)ペア、財3は離れた財、という設計にする。価格係数の異質性を変える際は \(E[\alpha_i]\) を固定し、平均反応の変化とばらつきの変化を混同しない。

# --- モンテカルロ積分でシェアを計算する関数 ---
# nu_x: 個人の属性選好ショック (ns), nu_p: 価格選好ショック (ns)
# 属性 x への好み beta_i = beta_x + sigma_x * nu_x
# 価格係数 alpha_i = exp(abar + sigma_p * nu_p)  (対数正規で正値保証)
sim_shares <- function(x, p, beta0, beta_x, sigma_x, abar, sigma_p, nu_x, nu_p) {
  ns <- length(nu_x)
  J  <- length(x)
  beta_i  <- beta_x + sigma_x * nu_x          # (ns) 属性選好
  alpha_i <- exp(abar + sigma_p * nu_p)       # (ns) 価格係数(正)
  # 効用 v[i,j] = beta0 + beta_i * x_j - alpha_i * p_j
  V <- outer(beta_i, x) - outer(alpha_i, p)   # (ns x J)
  V <- sweep(V, 2, rep(beta0, J), "+")        # 定数項を各財に足す
  eV <- exp(V)
  denom <- 1 + rowSums(eV)                     # outside の効用は 0 -> exp(0)=1
  s_ij <- eV / denom                           # (ns x J) 個人選択確率
  colMeans(s_ij)                               # 集計シェア (J)
}

# 属性: 財1と財2は近い(1.0, 0.9)、財3は離れている(-0.8)
x_char <- c(1.0, 0.9, -0.8)
beta0  <- -1.0
beta_x <- 1.2
alpha_mean_target <- exp(0.2)  # 比較を通じてE[alpha_i]を約1.22に固定
abar_for_sigma <- function(sigma_p) log(alpha_mean_target) - sigma_p^2 / 2
p_base <- c(2.0, 2.1, 1.8)

ns <- 200
nu_x <- rnorm(ns)
nu_p <- rnorm(ns)

# sigma_x = 0 (plain logit) と sigma_x = 1.2 (異質性あり) を比較
s_homog <- sim_shares(x_char, p_base, beta0, beta_x, 0.0, abar_for_sigma(0.0), 0.0, nu_x, nu_p)
s_heter <- sim_shares(x_char, p_base, beta0, beta_x, 1.2, abar_for_sigma(0.6), 0.6, nu_x, nu_p)

data.frame(
  product = c("財1", "財2", "財3"),
  x       = x_char,
  share_homog = round(s_homog, 4),
  share_heter = round(s_heter, 4)
) |> kable(caption = "同質(sigma=0) vs 異質(sigma>0) の集計シェア")
同質(sigma=0) vs 異質(sigma>0) の集計シェア
product x share_homog share_heter
財1 1.0 0.0881 0.1502
財2 0.9 0.0691 0.1144
財3 -0.8 0.0130 0.0291

交差弾力性行列:IIA が破れる様子

弾力性を数値微分で計算する。plain logit(同質)では、財 \(k\) の値上げに対する財1・財2・財3の反応は「シェア比例」でしか決まらない(\(\eta_{jk}=\alpha p_k s_k\)、\(j\) に依存しない)。random coefficient 版では、属性の近い財1↔︎財2の交差弾力性が大きくなるはずだ。

cross_elast <- function(sigma_x, sigma_p) {
  eps <- 1e-5
  abar_use <- abar_for_sigma(sigma_p)  # 平均価格感応度を固定して分散だけ変える
  s0 <- sim_shares(x_char, p_base, beta0, beta_x, sigma_x, abar_use, sigma_p, nu_x, nu_p)
  E  <- matrix(0, 3, 3)
  for (k in 1:3) {
    p_up <- p_base; p_up[k] <- p_up[k] + eps
    s1 <- sim_shares(x_char, p_up, beta0, beta_x, sigma_x, abar_use, sigma_p, nu_x, nu_p)
    # eta[j,k] = (ds_j/dp_k) * p_k / s_j
    E[, k] <- (s1 - s0) / eps * p_base[k] / s0
  }
  dimnames(E) <- list(paste0("財", 1:3), paste0("値上げ:財", 1:3))
  round(E, 3)
}

E_homog <- cross_elast(0.0, 0.0)
E_heter <- cross_elast(1.2, 0.6)
kable(E_homog, caption = "plain logit の弾力性行列(列=どの財を値上げしたか)")
plain logit の弾力性行列(列=どの財を値上げしたか)
値上げ:財1 値上げ:財2 値上げ:財3
財1 -2.228 0.177 0.029
財2 0.215 -2.388 0.029
財3 0.215 0.177 -2.170

同質モデルでは、各列の非対角成分がすべて同じ値になっている。例えば、財1を値上げしたときの財2の交差弾力性と、財3の交差弾力性が等しい。財1に似ているかどうかにかかわらず同じ反応になるところに、IIAの制約が表れている。

kable(E_heter, caption = "random coefficient logit の弾力性行列")
random coefficient logit の弾力性行列
値上げ:財1 値上げ:財2 値上げ:財3
財1 -1.191 0.286 0.019
財2 0.357 -1.325 0.021
財3 0.108 0.097 -1.307

異質モデルでは、財1を値上げしたとき、属性の近い財2の交差弾力性が財3より大きい(列1の中で財2の行 > 財3の行)。ネストを指定しなくても、属性の近い財どうしが代替しやすいという関係を表現できている。

df_plot <- data.frame(
  responder = rep(c("財2 (財1と属性近い)", "財3 (財1と属性遠い)"), 2),
  model     = rep(c("plain logit", "random coef."), each = 2),
  elasticity = c(E_homog[2, 1], E_homog[3, 1], E_heter[2, 1], E_heter[3, 1])
)
ggplot(df_plot, aes(model, elasticity, fill = responder)) +
  geom_col(position = position_dodge(width = 0.7), width = 0.6) +
  scale_fill_brewer(palette = "Set2") +
  labs(title = "財1値上げに対する交差弾力性",
       x = NULL, y = "交差弾力性", fill = "反応する財") +
  theme(legend.position = "top")

財1を値上げしたときの他財の反応。plain logit では財2・財3が同率、RC では属性の近い財2が強く反応する。

集計需要曲線の曲がり方も変わる

異質性は需要曲線の形にも影響する。価格への反応が人によって違うと、値上げしたときにまず価格に敏感な人が買わなくなり、価格をあまり気にしない人が買い続ける。そのため、集計した需要曲線の曲がり方も単純な logit とは変わってくる。財1の価格を動かして、需要曲線を描いてみよう。

p_grid <- seq(1.0, 4.0, length.out = 40)
demand_curve <- function(sigma_x, sigma_p) {
  abar_use <- abar_for_sigma(sigma_p)
  sapply(p_grid, function(pp) {
    p_try <- p_base; p_try[1] <- pp
    sim_shares(x_char, p_try, beta0, beta_x, sigma_x, abar_use, sigma_p, nu_x, nu_p)[1]
  })
}
dc <- data.frame(
  price = rep(p_grid, 2),
  share = c(demand_curve(0.0, 0.0), demand_curve(1.2, 0.6)),
  model = rep(c("plain logit", "random coef."), each = length(p_grid))
)
ggplot(dc, aes(price, share, color = model)) +
  geom_line(linewidth = 1) +
  scale_color_manual(values = c("plain logit" = "grey50", "random coef." = "#1f77b4")) +
  labs(title = "財1の自己需要曲線", x = "財1の価格", y = "財1のシェア", color = NULL) +
  theme(legend.position = "top")

財1の自己需要曲線。異質性を入れると曲率が変わる。

4. 識別の直感:\(\sigma\) はどこから分かるのか

ここまでは異質性の大きさをこちらで決めていた。では、データから異質性パラメータ \(\sigma\)(好みのばらつき)を知るには、どのような情報が必要だろうか。主に次の3つを考える。

(1) 価格変化への反応の「曲がり方」。 均質な logit なら、価格を下げていくとシェアはロジスティック曲線に沿って増える。一方、価格感応度がばらついていると、価格に敏感な人とそうでない人とで反応する価格帯が違う。そのため、需要曲線の曲率が均質モデルとは変わる。価格の外生的変動、または妥当なIVで取り出した変動が十分にあれば、この違いが \(\sigma\) の識別に役立つ。内生的な価格が単にばらついているだけでは、識別にはつながらない。

(2) 市場間の選択集合・属性分布の変動。 ある市場では属性の近い財ばかり、別の市場では散らばっている、という変動は代替パターンの情報を増やす。ただし、それを「自然実験」と呼べるのは、品揃え・属性が未観測需要ショックに反応して選ばれていない等の外生性があるときだけである。そうでなければ操作変数や参入モデルが必要になる。

(3) 購入者の属性や第二希望。 同じシェアでも、どのような人が買っているかは異なり得る。個票データやアンケートがあれば、購入者の平均所得や、別の商品への乗り換え先もモデルと比べられる。この情報を使う方法が、第7節で扱うmicro BLPである。まずは集計データを使って需要を推定し、合併分析まで進もう。

5. BLPによる需要の推定

ここからは、市場シェア・価格・商品属性のデータを使って、需要のパラメータを推定する。価格係数だけに異質性を入れた小さな例で、BLPの計算を実装してみよう。後の合併分析にも、この推定結果をそのまま使う。

ここでは、価格係数を \(\alpha_i=\exp(a+\sigma\nu_i)\) と書く。\(a\) はこれまで \(\bar\alpha\) と書いていた価格係数の対数の平均であり、水準の平均ではない。水準の平均は \(m(a,\sigma)=\exp(a+\sigma^2/2)\) となる。\(a\) と \(\sigma\) の両方を推定することで、どの候補でもすべての消費者の価格係数が正になる仕様を保つ。

計算は、次の3つの段階に分かれる。

  1. シェア反転:\((a,\sigma)\) を仮に決め、予測シェアが観測シェアに一致する平均効用 \(\delta\) を求める。
  2. 線形係数の推定:\(\delta\) を使い、IVの条件から属性の係数 \(\beta\) と需要残差 \(\hat\xi\) を求める。
  3. 異質性パラメータの選択:\(\hat\xi\) と操作変数の標本モーメントがゼロに近くなるように、\((a,\sigma)\) を選ぶ。

5.1 同じ市場で推定と合併分析を行うためのデータ

財は3つ、市場は120個とする。各市場で、3社が1財ずつ販売している。消費者の効用は

\[ u_{ijt}=\beta_0+\beta_x x_{jt}-\exp(a+\sigma\nu_i)p_{jt} +\xi_{jt}+\varepsilon_{ijt} \]

である。属性 \(x\) と投入価格の対数 \(w\) は、需要ショック \(\xi\) と費用ショック \(\omega\) から独立に発生させる。限界費用を \(mc_{jt}=\exp(\gamma_0+\gamma_xx_{jt}+\gamma_ww_{jt}+\omega_{jt})\) で作り、企業が利潤を最大化する価格を計算する。価格設定の式は次の合併分析の節で詳しく説明する。

ここで費用関数を使うのは、観測される価格とシェアを生成するためである。この節の推定には、需要側のモーメントだけを使う。 分析者が見るのは \(x,w,p,s\) と所有関係であり、生成に使った \(\xi,\omega,mc\) は見えないものとして扱う。

前のシミュレーションでは個人を乱数で発生させたが、ここでは標準正規分布の分位点を120個並べて積分を近似する。反復のたびに個人を引き直すと目的関数自体が変わってしまうので、どのパラメータ候補でも同じ点を使う。価格の反復計算には、更新を半分ずつ進める方法を使い、収束しなかった場合には停止するようにしている。

# 個人の価格係数は正。nu はどの計算でも同じ積分点を使う。
rc_probs <- function(p, quality, a, sigma, nu) {
  alpha <- exp(a + sigma * nu)
  v <- sweep(-outer(alpha, p), 2, quality, "+")
  vmax <- pmax(0, apply(v, 1, max))
  ev <- exp(v - vmax)
  ev / (exp(-vmax) + rowSums(ev))
}
rc_market <- function(p, quality, a, sigma, nu) {
  prob <- rc_probs(p, quality, a, sigma, nu)
  alpha <- exp(a + sigma * nu)
  jac <- crossprod(prob, prob * alpha) / length(nu)
  diag(jac) <- diag(jac) - colMeans(prob * alpha)
  list(s = colMeans(prob), jac = jac)
}
owner_matrix <- function(groups) outer(groups, groups, "==") * 1
markup_at <- function(p, groups, quality, a, sigma, nu) {
  demand <- rc_market(p, quality, a, sigma, nu)
  Delta <- -owner_matrix(groups) * t(demand$jac)
  as.vector(solve(Delta, demand$s))
}
solve_prices <- function(mc, groups, quality, a, sigma, nu,
                         p_init = mc + 1, tol = 1e-10, maxit = 2000) {
  p <- p_init
  for (it in seq_len(maxit)) {
    target <- mc + markup_at(p, groups, quality, a, sigma, nu)
    err <- max(abs(target - p))
    if (err < tol) return(list(p = p, iterations = it, error = err))
    p <- 0.5 * p + 0.5 * target
  }
  stop("価格の反復が収束しなかった")
}
# 複数市場の確率をまとめて計算。各積分点について市場を並べ、列は商品。
rc_all <- function(delta, price, a, sigma, nu, slopes = TRUE) {
  nt <- nrow(price); nj <- ncol(price); nr <- length(nu)
  mean_alpha <- exp(a + sigma^2 / 2)
  deviation <- exp(a + sigma * nu) - mean_alpha
  v <- matrix(0, nt * nr, nj)
  for (j in seq_len(nj)) {
    v[, j] <- rep(delta[, j], nr) -
      rep(price[, j], nr) * rep(deviation, each = nt)
  }
  vmax <- pmax(0, v[, 1])
  for (j in 2:nj) vmax <- pmax(vmax, v[, j])
  ev <- exp(v - vmax)
  prob <- ev / (exp(-vmax) + rowSums(ev))
  share <- matrix(0, nt, nj)
  own_slope <- matrix(0, nt, nj)
  alpha <- rep(exp(a + sigma * nu), each = nt)
  for (j in seq_len(nj)) {
    share[, j] <- rowMeans(matrix(prob[, j], nt, nr))
    if (slopes) own_slope[, j] <- -rowMeans(matrix(
      alpha * prob[, j] * (1 - prob[, j]), nt, nr))
  }
  list(share = share, own_slope = own_slope)
}
invert_shares <- function(S_obs, price, a, sigma, nu,
                          tol = 1e-9, maxit = 2000) {
  delta <- log(S_obs) - log(1 - rowSums(S_obs))
  for (it in seq_len(maxit)) {
    predicted <- rc_all(delta, price, a, sigma, nu, slopes = FALSE)$share
    correction <- log(S_obs) - log(predicted)
    delta <- delta + correction
    if (max(abs(correction)) < tol) {
      return(list(delta = delta, iterations = it,
                  error = max(abs(correction))))
    }
  }
  stop("シェアの反転が収束しなかった")
}
vec <- function(m) as.vector(t(m))
# その市場の需要を固定したときの1人あたり消費者余剰。
cs_value <- function(p, quality, a, sigma, nu) {
  alpha <- exp(a + sigma * nu)
  v <- sweep(-outer(alpha, p), 2, quality, "+")
  vmax <- pmax(0, apply(v, 1, max))
  inclusive <- vmax + log(exp(-vmax) + rowSums(exp(v - vmax)))
  mean(inclusive / alpha)
}
market_outcomes <- function(p, mc, quality, a, sigma, nu, market_size = 10000) {
  s <- rc_market(p, quality, a, sigma, nu)$s
  c(quantity = market_size * sum(s),
    profit = market_size * sum((p - mc) * s),
    consumer_surplus = market_size * cs_value(p, quality, a, sigma, nu))
}
set.seed(202604)
J <- 3
Tn <- 120
ns <- 120
# 等間隔の確率に対応する標準正規分布の分位点。毎回引き直さない。
nu <- qnorm((seq_len(ns) - 0.5) / ns)
theta_true <- c(beta0 = 3.5, beta_x = 1.2, a = 0.2, sigma = 0.7,
                gamma0 = -0.1, gamma_x = 0.15, gamma_w = 0.6)
x <- matrix(runif(Tn * J, -1, 1), Tn, J)
w <- matrix(runif(Tn * J, -1.2, 1.2), Tn, J)
xi_true <- matrix(rnorm(Tn * J, 0, 0.18), Tn, J)
omega_true <- matrix(rnorm(Tn * J, 0, 0.08), Tn, J)
quality_true <- theta_true["beta0"] + theta_true["beta_x"] * x + xi_true
mc_true <- exp(theta_true["gamma0"] + theta_true["gamma_x"] * x +
                 theta_true["gamma_w"] * w + omega_true)
groups_pre <- seq_len(J)
price <- S_obs <- matrix(0, Tn, J)
for (tt in seq_len(Tn)) {
  eq <- solve_prices(mc_true[tt, ], groups_pre, quality_true[tt, ],
                     theta_true["a"], theta_true["sigma"], nu)
  price[tt, ] <- eq$p
  S_obs[tt, ] <- rc_market(eq$p, quality_true[tt, ],
                          theta_true["a"], theta_true["sigma"], nu)$s
}

需要ショックが高い商品では企業が高い価格を付けやすくなる。費用が外生的に動く部分もあるが、価格全体が外生になるわけではない。第3回で扱った価格の内生性が、企業の価格設定を通じて生じるデータになっている。

data_summary <- data.frame(
  variable = c("価格", "商品シェア", "外部選択肢シェア"),
  minimum = c(min(price), min(S_obs), min(1 - rowSums(S_obs))),
  maximum = c(max(price), max(S_obs), max(1 - rowSums(S_obs))))
knitr::kable(data_summary, digits = 3,
             col.names = c("変数", "最小値", "最大値"))
変数 最小値 最大値
価格 1.314 3.824
商品シェア 0.044 0.464
外部選択肢シェア 0.149 0.487

5.2 内側:縮小写像で平均効用を取り出す

平均効用と個人偏差を

\[ \delta_{jt}=\beta_0+\beta_x x_{jt}-m(a,\sigma)p_{jt}+\xi_{jt}, \qquad \mu_{ijt}=-\{\exp(a+\sigma\nu_i)-m(a,\sigma)\}p_{jt} \]

と分ける。\((a,\sigma)\) を固定したとき、次の更新で観測シェアを再現する \(\delta\) を求める。

\[ \delta_{jt}^{\mathrm{new}} =\delta_{jt}+\log s_{jt}^{\mathrm{obs}} -\log s_{jt}(\delta;a,\sigma). \]

予測したシェアが小さすぎる財では平均効用を上げ、大きすぎる財では下げる、という更新である。前回のBerry反転 \(\log s_{jt}-\log s_{0t}\) を初期値にして、更新幅が十分小さくなるまで繰り返す。

truth_inversion <- invert_shares(S_obs, price,
  theta_true["a"], theta_true["sigma"], nu)
delta_true <- quality_true - exp(theta_true["a"] + theta_true["sigma"]^2 / 2) * price
inversion_check <- data.frame(
  check = c("平均効用の回収誤差", "シェアの再現誤差"),
  error = c(max(abs(truth_inversion$delta - delta_true)),
    max(abs(rc_all(truth_inversion$delta, price,
      theta_true["a"], theta_true["sigma"], nu)$share - S_obs))))
knitr::kable(inversion_check, digits = 10,
             col.names = c("確認項目", "最大絶対誤差"))
確認項目 最大絶対誤差
平均効用の回収誤差 0.0000000118
シェアの再現誤差 0.0000000003
stopifnot(all(inversion_check$error < 1e-6))

真のパラメータを与えたときに、元の平均効用を取り戻せることを確認できる。ただし、シェアを再現できただけでは、異質性を推定したことにはならない。別の \((a,\sigma)\) を与えても、それに合わせて \(\delta\) を調整できる。そこで、次に需要ショックと操作変数の関係を使う。

5.3 中間:IVの条件から属性の係数を求める

\((a,\sigma)\) を仮に決めると、平均価格係数 \(m(a,\sigma)\) も決まる。価格の項を左辺に移すと、

\[ \delta_{jt}(a,\sigma)+m(a,\sigma)p_{jt} =\beta_0+\beta_x x_{jt}+\xi_{jt} \]

となる。この線形の式に、第3回のIVの考え方を使う。

需要側の操作変数には、定数、自財の属性 \(x\)、投入価格の対数 \(w\)、その2乗、他財の属性和、他財の投入価格の対数の和を使う。\(w\) は効用に直接入らず、費用を通じて価格を動かす。他財の属性や費用も、競争相手の価格設定を通じて自財の価格に影響する。

この例では、これらの変数をすべての需要ショックから独立に生成しているため、IVの外生性が成り立つ。実際の市場で同じ変数が妥当かどうかは、別に考える必要がある。例えば、競合の品質と自財の未観測品質が同じ地域の需要を反映しているなら、他財の属性和をそのまま使うことはできない。

第3回の2SLSは、複数の操作変数を使って回帰係数を求める方法だった。ここでも、需要残差と操作変数の積の平均をゼロに近づける。\(N=JT\) として

\[ \bar g_D(a,\sigma,\beta)=\frac{1}{N}\sum_{j,t}Z^D_{jt} \{\delta_{jt}(a,\sigma)+m(a,\sigma)p_{jt}-\beta_0-\beta_xx_{jt}\} \]

と書こう。このベクトルをまとめて小さくする目的関数が

\[ Q_D=\bar g_D'W_D\bar g_D, \qquad W_D=(Z_D'Z_D/N)^{-1} \]

である。こうしたモーメントのずれを最小化する推定方法がGMMであり、2SLSもその一例である。\((a,\sigma)\) を固定すれば、\(Q_D\) を最小にする \(\beta\) は線形IVの式で求められる。

# 自財の費用変数と競合財の属性・費用変数を需要側のIVに使う。
rival_x <- rowSums(x) - x
rival_w <- rowSums(w) - w
X_d <- cbind(constant = 1, x = vec(x))
Z_d <- cbind(X_d, w = vec(w), w2 = vec(w)^2,
              rival_x = vec(rival_x), rival_w = vec(rival_w))
N <- nrow(X_d)
W_d <- solve(crossprod(Z_d) / N)
# 固定した非線形パラメータの下で線形係数を解く。
linear_gmm <- function(y, X, Z, W) {
  ZX <- crossprod(Z, X) / N
  Zy <- crossprod(Z, y) / N
  coef <- as.vector(solve(t(ZX) %*% W %*% ZX, t(ZX) %*% W %*% Zy))
  residual <- as.vector(y - X %*% coef)
  g <- crossprod(Z, residual) / N
  list(coef = coef, residual = residual,
       Q = as.numeric(t(g) %*% W %*% g))
}
scale_d <- 1

vec() は、市場1の財1・2・3、市場2の財1・2・3、という順に行列を並べ直す関数である。説明変数とシェアから取り出した平均効用の順序をそろえないと、別の市場の商品どうしを対応させることになる。行列計算ではこの点に注意しよう。

5.4 外側:価格係数の分布を選ぶ

最後に、\((a,\sigma)\) を動かしながら、シェア反転と線形IVを繰り返す。各候補で \(\beta\) を求め直した後の \(Q_D\) が最も小さくなる場所を探す。

以下では optim() を使い、2つの初期値から計算する。探索する範囲は \(-0.4\leq a\leq1\)、\(0.05\leq\sigma\leq1.3\) とする。これは今回の計算用の範囲であり、一般にこの範囲でよいわけではない。推定値が端に張り付いた場合には、範囲や仕様を見直す必要がある。

gmm_fit <- function(par) {
  a <- par[1]; sigma <- par[2]
  inverted <- invert_shares(S_obs, price, a, sigma, nu)
  delta <- inverted$delta
  mean_alpha <- exp(a + sigma^2 / 2)
  # delta + E[alpha]*p = beta0 + beta_x*x + xi
  demand <- linear_gmm(vec(delta + mean_alpha * price), X_d, Z_d, W_d)
  fit <- list(par = setNames(par, c("a", "sigma")), beta = demand$coef,
              delta = delta, xi = demand$residual, Qd = demand$Q,
              Q = demand$Q / scale_d, inversion_error = inverted$error)
  fit
}
# 開始点を複数試し、目的関数が最も小さい結果を使う。
estimate_model <- function() {
  starts <- list(c(0.1, 0.4), c(0.4, 0.9))
  runs <- lapply(starts, function(initial) {
    optim(initial, function(par) gmm_fit(par)$Q,
          method = "L-BFGS-B", lower = c(-0.4, 0.05), upper = c(1, 1.3),
          control = list(factr = 1e7, pgtol = 1e-7))
  })
  best <- runs[[which.min(sapply(runs, function(z) z$value))]]
  result <- gmm_fit(best$par)
  result$convergence <- best$convergence
  result
}
fit_d <- estimate_model()
point_estimates <- data.frame(
  parameter = c("beta0", "beta_x", "a", "sigma", "mean_alpha"),
  truth = c(theta_true[c("beta0", "beta_x", "a", "sigma")],
    exp(theta_true["a"] + theta_true["sigma"]^2 / 2)),
  estimated = c(fit_d$beta, fit_d$par, exp(fit_d$par[1] + fit_d$par[2]^2 / 2)))
knitr::kable(point_estimates, digits = 3,
             col.names = c("パラメータ", "真値", "推定値"))
パラメータ 真値 推定値
beta0 3.50 3.439
beta_x 1.20 1.168
a 0.20 0.191
sigma 0.70 0.677
mean_alpha 1.56 1.522
stopifnot(fit_d$convergence == 0)

生成に使った真値と推定値を比べてみよう。推定では真の \(a\) を固定せず、価格係数の平均とばらつきを両方求めている。標本は有限なので、推定値が真値とぴったり一致するわけではない。

目的関数の形も見てみよう。次の図では \(a\) を推定値に固定し、各 \(\sigma\) で \(\delta\) と \(\beta\) を求め直している。2つのパラメータを同時に最適化した後の、一方向の断面である。図の幅自体を信頼区間として読むものではない。

sigma_grid <- seq(0.35, 1.05, length.out = 15)
objective_slice <- data.frame(sigma = sigma_grid,
  Q = sapply(sigma_grid, function(s) gmm_fit(c(fit_d$par[1], s))$Q))
ggplot(objective_slice, aes(sigma, Q)) +
  geom_line(color = "#1f77b4", linewidth = 0.9) +
  geom_point(color = "#1f77b4") +
  geom_vline(xintercept = fit_d$par[2], color = "#d62728", linetype = "dashed") +
  labs(x = expression(sigma), y = "需要側のGMM目的関数",
       title = "aを推定値に固定した目的関数の断面")

破線は推定したσ。各点でシェア反転と線形係数の推定を行っている。

推定値だけでなく、標準誤差も確認しておこう。市場ごとに同じ企業や競合関係を共有するため、ここでは市場内の残差の相関を許す、市場単位のクラスタ標準誤差を計算する。独立な市場が十分に多いという近似に基づく。GMMのモーメントがパラメータを動かしたときにどれくらい変わるかと、市場間でどれくらいばらつくかを組み合わせる計算である。

cluster_se <- function(fit) {
  qd <- ncol(Z_d)
  G <- matrix(0, qd, 4)
  G[, 1:2] <- -crossprod(Z_d, X_d) / N
  h <- 1e-4
  for (k in 1:2) {
    upper <- lower <- fit$par
    upper[k] <- upper[k] + h; lower[k] <- lower[k] - h
    fit_upper <- gmm_fit(upper); fit_lower <- gmm_fit(lower)
    y_upper <- fit_upper$delta + exp(upper[1] + upper[2]^2 / 2) * price
    y_lower <- fit_lower$delta + exp(lower[1] + lower[2]^2 / 2) * price
    G[, k + 2] <- crossprod(Z_d, vec(y_upper - y_lower)) / (2 * h * N)
  }
  moments <- Z_d * fit$xi
  clustered <- rowsum(moments, rep(seq_len(Tn), each = J))
  clustered <- sweep(clustered, 2, colMeans(clustered), "-")
  Vg <- crossprod(clustered) / N^2 * Tn / (Tn - 1)
  bread <- solve(t(G) %*% W_d %*% G)
  V <- bread %*% t(G) %*% W_d %*% Vg %*% W_d %*% G %*% bread
  list(se = sqrt(diag(V)), vcov = V)
}
inference_d <- cluster_se(fit_d)
mean_alpha_d <- exp(fit_d$par[1] + fit_d$par[2]^2 / 2)
gradient_mean <- c(0, 0, mean_alpha_d, mean_alpha_d * fit_d$par[2])
se_mean_alpha <- sqrt(as.numeric(t(gradient_mean) %*% inference_d$vcov %*% gradient_mean))
demand_parameters <- data.frame(
  parameter = c("beta0", "beta_x", "a", "sigma", "mean_alpha"),
  truth = c(theta_true[c("beta0", "beta_x", "a", "sigma")],
              exp(theta_true["a"] + theta_true["sigma"]^2 / 2)),
  estimated = c(fit_d$beta, fit_d$par, mean_alpha_d),
  std_error = c(inference_d$se, se_mean_alpha))
knitr::kable(demand_parameters, digits = 3,
             col.names = c("パラメータ", "真値", "推定値", "標準誤差"),
             caption = "需要パラメータと市場クラスタ標準誤差")
需要パラメータと市場クラスタ標準誤差
パラメータ 真値 推定値 標準誤差
beta0 3.50 3.439 0.116
beta_x 1.20 1.168 0.030
a 0.20 0.191 0.029
sigma 0.70 0.677 0.015
mean_alpha 1.56 1.522 0.049

この標準誤差は、積分点を固定した数値近似のもとでの推定の不確実性を表す。モデルの誤りや、合併後に企業行動そのものが変わる可能性まで含んでいるわけではない。

重要推定で何を合わせたのか

シェア反転では、候補となる価格係数の分布ごとに市場シェアを合わせた。IVとGMMでは、その結果取り出される需要ショックが操作変数と無相関になる条件を使った。この2つは役割が異なる。シェアへの当てはまりだけで、価格内生性に対処できたと考えないようにしよう。

6. 合併分析:推定した需要から価格を予測する

需要が推定できたので、財1と財2を販売する企業が合併した場合を考えよう。合併後の企業は、財1の値上げで財2へ移る顧客からも利益を得る。需要が同じでも、この所有関係の変化によって価格設定が変わる。

この節では、商品属性と需要ショックを固定し、限界費用も合併前と同じにする。参入や退出は考えず、各企業が自社の利潤を最大化する価格を同時に選ぶ、Bertrand-Nash均衡を仮定する。

6.1 価格設定の条件から、限界費用を逆算する

1企業が1財を販売するとき、市場規模を除いた利潤は \((p_j-mc_j)s_j(p)\) である。限界費用は販売数量によらず一定とする。価格で微分した一階条件は

\[ s_j+(p_j-mc_j)\frac{\partial s_j}{\partial p_j}=0 \]

となる。つまり、値上げによる1個あたり利益の増加と、需要減少による利益の損失が釣り合う価格を選ぶ。

多製品企業は、自社の他商品への波及も考える。同じ企業が財 \(j,k\) を持つときに1となる所有行列 \(\Omega\) を使うと、条件をまとめて

\[ s-\Delta(p-mc)=0, \qquad \Delta_{jk}=-\Omega_{jk}\frac{\partial s_k}{\partial p_j} \]

と書ける。これを解けば、

\[ p=mc+\underbrace{\Delta^{-1}s}_{\text{マークアップ}}, \qquad mc=p-\Delta^{-1}s \]

である。価格とシェアは観測されており、需要の微分は推定したモデルから計算できる。企業の価格設定について仮定を置くことで、観測されていない限界費用を逆算できる。

企業 \(f\) の製品集合を \(\mathcal F_f\) とすると、利潤は \(\pi_f=\sum_{k\in\mathcal F_f}(p_k-mc_k)s_k(p)\) である。自社製品 \(j\) の価格で微分すると、

\[ s_j+\sum_{k\in\mathcal F_f}(p_k-mc_k)\frac{\partial s_k}{\partial p_j}=0. \]

\(\Omega_{jk}\) を掛ければ、和を全財について書いても自社製品だけが残る。\(\Delta\) の行 \(j\) は微分する価格、列 \(k\) は利潤に入る商品に対応する。

消費者 \(i\) の選択確率を \(s_{ij}\) とすると、需要の微分は

\[ \frac{\partial s_k}{\partial p_j} =\begin{cases} -E_i[\alpha_i s_{ij}(1-s_{ij})] & k=j,\\ E_i[\alpha_i s_{ik}s_{ij}] & k\neq j. \end{cases} \]

コードの rc_market() は、行 \(k\)・列 \(j\) に \(\partial s_k/\partial p_j\) を置いた行列を返す。このため markup_at() では転置してから所有行列を掛けている。

6.2 推定に使った市場で合併を計算する

120市場のうち第1市場を取り出す。推定で得た \(\hat a,\hat\sigma\) と、この市場の \(\hat\delta\) を使う。価格を変えたときには、\(\hat\delta\) そのものを固定してはいけない。\(\delta\) には基準時点の価格が含まれているからである。固定するのは、価格を除いた効用 \(\hat\delta+m(\hat a,\hat\sigma)p^{\mathrm{base}}\) である。

まず基準時点の費用を逆算し、次に財1・2を同じ企業が持つように所有行列を変える。その費用と新しい所有行列のもとで、価格設定の一階条件を解き直す。

# 第一市場の観測価格と、推定で反転した効用を使う。
p_pre <- price[1, ]
a_d <- fit_d$par[1]; sigma_d <- fit_d$par[2]
quality_d <- fit_d$delta[1, ] + exp(a_d + sigma_d^2 / 2) * p_pre
mc_d <- p_pre - markup_at(p_pre, groups_pre, quality_d, a_d, sigma_d, nu)
groups_post <- c(1, 1, 3)
eq_merger <- solve_prices(mc_d, groups_post, quality_d, a_d, sigma_d, nu, p_pre)
p_merger <- eq_merger$p
s_pre <- rc_market(p_pre, quality_d, a_d, sigma_d, nu)$s
s_merger <- rc_market(p_merger, quality_d, a_d, sigma_d, nu)$s
merger_tbl <- data.frame(product = paste0("財", seq_len(J)),
  cost = mc_d, price_pre = p_pre, price_post = p_merger,
  price_change_pct = 100 * (p_merger / p_pre - 1),
  quantity_pre = 10000 * s_pre, quantity_post = 10000 * s_merger,
  profit_pre = 10000 * (p_pre - mc_d) * s_pre,
  profit_post = 10000 * (p_merger - mc_d) * s_merger)
outcomes_merger <- data.frame(
  outcome = c("販売数量の合計", "企業利潤の合計", "消費者余剰"),
  before = market_outcomes(p_pre, mc_d, quality_d, a_d, sigma_d, nu),
  after = market_outcomes(p_merger, mc_d, quality_d, a_d, sigma_d, nu))
outcomes_merger$change <- outcomes_merger$after - outcomes_merger$before
jac_pre <- rc_market(p_pre, quality_d, a_d, sigma_d, nu)$jac
diversion12 <- -jac_pre[2, 1] / jac_pre[1, 1]
upp1 <- diversion12 * (p_pre[2] - mc_d[2])
cost_check <- data.frame(product = merger_tbl$product,
  truth = mc_true[1, ], recovered = mc_d)
knitr::kable(cost_check, digits = 3,
             col.names = c("商品", "限界費用の真値", "需要推定から逆算"))
商品 限界費用の真値 需要推定から逆算
財1 1.060 1.060
財2 0.548 0.544
財3 2.143 2.161
knitr::kable(merger_tbl[, c("product", "price_pre", "price_post", "price_change_pct")],
  digits = 3, col.names = c("商品", "合併前価格", "合併後価格", "変化率(%)"))
商品 合併前価格 合併後価格 変化率(%)
財1 2.371 3.292 38.856
財2 1.862 2.500 34.217
財3 3.681 3.702 0.564
stopifnot(all(mc_d > 0), eq_merger$error < 1e-6)

真の費用も横に置いて、需要推定の誤差が限界費用の逆算にどれくらい伝わったかを確認しよう。ここで使う費用は推定した需要から逆算した値であり、データ生成に使った真の費用に置き換えてはいない。

ggplot(merger_tbl, aes(product, price_change_pct,
                        fill = product %in% c("財1", "財2"))) +
  geom_col(width = 0.6, show.legend = FALSE) +
  scale_fill_manual(values = c("FALSE" = "grey60", "TRUE" = "#d62728")) +
  labs(title = "財1・財2の合併による価格変化", x = NULL, y = "価格変化率(%)")

赤が合併当事者。限界費用は固定している。

この例では、合併する財1・2の価格が大きく上がり、非当事者の財3も少し値上げする。財1から財2へ移る需要を合併後の企業が取り込めるため、値上げの誘因が強まったのである。このような影響を単独効果(unilateral effect)と呼ぶ。ここでの値上げ率は、あくまで今回のデータとモデルから計算した結果である。

6.3 数量・利潤・消費者余剰も見る

市場の人数を \(M=10{,}000\) 人とすると、販売数量は \(q_j=Ms_j\)、利潤は \((p_j-mc_j)q_j\) となる。固定費は含めない。合併で利益が増えても、消費者にとって望ましいとは限らないので、消費者余剰も見ておこう。

消費者余剰の変化にはlogsumを使う。価格を除いた効用を \(b_j=\hat\delta_j+m(\hat a,\hat\sigma)p_j^{\mathrm{base}}\) とすると、1人あたりの変化は

\[ \Delta CS=E_i\left[ \frac{\log\{1+\sum_j\exp(b_j-\alpha_i p_j^{\mathrm{new}})\} -\log\{1+\sum_j\exp(b_j-\alpha_i p_j^{\mathrm{base}})\}} {\alpha_i}\right]. \]

効用の差を各消費者の価格係数 \(\alpha_i\) で割って、金額の単位に直している。価格に対して効用が線形で、反実仮想でも各人の \(\alpha_i\) が変わらない仕様を使っている。次の表では、1人あたりの値に \(M\) を掛けた市場全体の値を示す。

knitr::kable(merger_tbl[, c("product", "quantity_pre", "quantity_post", "profit_pre", "profit_post")],
  digits = 1, col.names = c("商品", "合併前数量", "合併後数量", "合併前利潤", "合併後利潤"))
商品 合併前数量 合併後数量 合併前利潤 合併後利潤
財1 2714.1 1741.4 3557.2 3886.7
財2 3598.5 2851.2 4745.3 5576.6
財3 1264.2 1884.4 1921.8 2903.6
knitr::kable(outcomes_merger, row.names = FALSE, digits = 1,
  col.names = c("指標", "合併前", "合併後", "変化"))
指標 合併前 合併後 変化
販売数量の合計 7576.9 6476.9 -1099.9
企業利潤の合計 10224.3 12367.0 2142.7
消費者余剰 31360.4 27236.9 -4123.5

この例では企業利潤の合計が増える一方、販売数量と消費者余剰は減る。価格・費用・余剰の金額単位は、シミュレーションで設定した価格の単位である。

6.4 補足:diversion ratio と UPP

合併後の均衡をすべて計算する前に、値上げ圧力を簡単に調べる指標もある。diversion ratio は、財 \(j\) の小さな値上げで離れた顧客のうち、財 \(k\) に移る割合である。

\[ D_{j\to k}=-\frac{\partial s_k/\partial p_j}{\partial s_j/\partial p_j}. \]

財1の値上げによって財2へ多く移り、財2のマージンも大きいなら、合併後にその移動を取り込める価値は大きい。費用削減を考えない簡便な UPP(upward pricing pressure) は

\[ \mathrm{UPP}_1=D_{1\to2}(p_2-mc_2) \]

で表される。UPPは値上げの誘因を測る指標であり、合併後の価格変化そのものではない。価格変化を知るには、他社の反応も含めて均衡を計算する必要がある。

knitr::kable(data.frame(
  indicator = c("財1から財2へのdiversion ratio", "財1のUPP(費用削減なし)"),
  value = c(diversion12, upp1)), digits = 3,
  col.names = c("指標", "値"))
指標 値
財1から財2へのdiversion ratio 0.576
財1のUPP(費用削減なし) 0.759
ノートビジネスの現場で:需要予測と価格の均衡

自社が値上げしたときの販売数量を知りたいなら、価格を与えて需要を計算すればよい。競合も値付けを変える状況まで予測したいなら、その企業の行動についても仮定が必要になる。今回の合併分析では、需要とBertrandの価格設定を組み合わせて、全社の価格を一緒に求めた。実務の価格シミュレータを見るときも、どの価格を固定し、どの企業の反応を計算しているかを確認しよう。

ヒント実証研究コーナー:Nevo (2001) — 高マージンは共謀か、ブランド力か

問い:朝食シリアル業界は、価格が限界費用よりずっと高い(高マージン)。これは企業が裏で協調(共謀)しているからか、それとも製品差別化とブランド力の結果か。

データ:米国の朝食シリアル市場について、都市×四半期のスキャンパネル(POS)データを使う。ブランドごとの価格・シェア・製品特性が記録されている。

識別戦略・モデル:random coefficient logitで需要を推定し、供給側の行動仮説(単独最大化 vs 協調)のもとでマークアップを比べた。ブランド固定効果などで平均品質を制御するだけでなく、価格の内生性には他都市の同一ブランド平均価格(Hausman型IV)や流通費用のproxyなど複数のIVを用い、その仮定と頑健性を検討している。

主要な発見:観測される高マージンは、共謀を仮定しなくても、製品差別化とブランド力(強い選好)で説明できるという結果を得た。price-cost マージンはおおむね4〜5割と推定されたが、これは単独価格設定と矛盾しなかった。

なぜこの回と繋がるか:需要推定(random coefficient logit)と供給側モデル(Bertrand-Nash)を組み合わせて、観測できない限界費用や企業の行動を分析する例である。合併審査でも、現在の競争がどれくらい激しいかを調べるために、同じ枠組みを使う。

ヒント実証研究コーナー:Miller and Weinberg (2017) — 合併後に協調的値上げは起きたか

問い:2008年の MillerCoors 合弁(Miller と Coors のビール事業統合)の後、ビール業界で価格が上がったか。上がったとすれば、それは単独効果か、それとも残った大手(Anheuser-Busch と MillerCoors)の協調的な値上げか。

データ:合弁前後の米国ビール市場のスキャンデータを使う。ブランド×地域×時点の価格・シェアが記録されている。

識別戦略・モデル:random coefficient logit で需要を推定し、合弁前のデータで供給側モデルを較正する。その上で、単独 Nash による合弁後の価格予測を、実際の価格と比べる。実際の値上げが単独効果の予測を上回る分を、協調の強まりと解釈した。

主要な発見:合弁後、単独 Nash が予測する以上の価格上昇が観測され、協調的価格上昇(部分的協調)の証拠と解釈された。とくに Miller と Coors の主要ブランドで、合弁後に価格が数%上昇した。

なぜこの回と繋がるか:今回の合併シミュレーションで計算した単独効果は、合併後の結果を検証する際の比較基準にもなる。予測と実際の価格の差を調べることで、単独効果だけでは説明できない協調の可能性を検討する。第5回の合併審査の実務にも関わる分析である。

ヒント実証研究コーナー:Adam, He and Zheng (2023, Management Science) — ロングテール市場の需要推定と機械学習

問い:オンライン小売のように「売れる商品はごく一部、大半は販売数ゼロか極少(ロングテール)」という市場では、従来の random coefficient logit(BLP)はうまく推定できるか。

データ・設定:多数の商品を扱うオンラインマーケットプレイスで、販売数が0の商品が大量にある状況を分析する。BLPは販売数が正の商品しか扱えず、ゼロ販売をどう扱うかによってセレクションバイアスが生じる。

識別戦略・モデル:2段階推定を提案する。第1段階で、random coefficient logit のデータ生成過程を模した構造を持つニューラルネットワーク(深層学習)で全商品の市場シェアを予測する。第2段階で、その予測を使って観測シェアを再重み付けし、セレクションバイアスを補正しつつ構造モデルの因果的解釈を保つ。市場数について推定量の一致性を示した。

主要な発見:ロングテールのシミュレーションデータと実データの両方で、素朴なBLPより正確に消費者行動を推定できた。得られた推定値は、価格設定や品揃え(assortment)の意思決定に使える。

なぜこの回と繋がるか:この論文では、今回学んだBLPの枠組みに機械学習を組み合わせ、ECに多い、販売数がゼロまたは少数の商品に対応する。需要推定に使う情報を広げるために、機械学習の方法も組み合わせられる例である。

7. 個票データを使った需要推定:micro BLP

合併の予測では、当事者の商品どうしがどのくらい代替するかが重要だった。ところが、現在の市場シェアがよく合っているだけでは、その代替関係までうまく捉えられているとは限らない。第1節の3人の例でも、同じ販売数を再現する好みの構造が複数あり、値上げ後の需要は異なっていた。

ここまでは、市場ごとの価格・シェア・商品属性と、その外生的な変動を使って需要を推定してきた。これに「誰が買ったか」という情報を加えられないだろうか。例えば、同じ高価格帯の車でも、主に高所得世帯が買っているのか、それとも所得にあまり関係なく選ばれているのかで、所得と価格への反応の関係について得られる情報は違う。また、その車の購入者が第二希望としてどの車を挙げるかも、代替関係を考える手がかりになる。

このような消費者ごとの情報を、集計データと組み合わせてBLPの推定に使う方法を、ここではmicro BLPと呼ぶ。ここでいうmicroは、消費者ごとのデータを指す。Berry, Levinsohn and Pakes (2004) は、自動車の第一希望と第二希望、購入者の属性などの情報を組み合わせて需要を推定した。

7.1 所得をモデルに入れる

購入者の所得を観測できても、その所得が選択とどう関係するかをモデルに書かなければ、推定には使えない。そこで、この節では価格係数の式を少し拡張してみよう。所得を \(y_i>0\)、比較の基準となる所得を \(y_{\mathrm{ref}}>0\) として、

\[ \alpha_i =\exp\left(a+\pi\log\frac{y_i}{y_{\mathrm{ref}}}+\sigma\nu_i\right), \qquad \nu_i\sim N(0,1) \]

とする。ここでは \(\nu_i\) は所得と独立と仮定する。\(a\) は基準所得 \(y_{\mathrm{ref}}\) の人のlog価格係数の平均である。これまでの対数正規の価格係数に、所得との関係を表す \(\pi\) を加えただけである。例えば \(\pi<0\) なら、同じ \(\nu_i\) を持つ人を比べたとき、高所得の人ほど \(\alpha_i\) が小さく、価格に反応しにくい。\(\sigma\nu_i\) は、所得だけでは説明できない価格感応度の違いを表す。

このモデルなら、「高所得の人ほど高い商品を買う」というデータの特徴を、\(\pi\) や \(\sigma\) を選ぶ際の情報にできる。所得以外にも、家族の人数と車の大きさ、年齢と商品属性などの組み合わせが考えられる。どの個人属性をどの係数と結びつけるかは、知りたい代替関係と利用できるデータに応じて決める。

7.2 「購入者の平均所得」をモデルと比べる

一つの市場に注目し、市場を表す添字 \(t\) は省略する。需要のパラメータをまとめて \(\theta\) と書こう。所得や \(\nu_i\) を与えたとき、消費者 \(i\) が商品 \(j\) を選ぶ確率を \(s_{ij}(\theta)\) とする。これは、これまで計算してきた個人ごとのlogit確率である。

アンケートから、商品 \(j\) の購入者の平均所得 \(\bar y_j^{\mathrm{obs}}\) が分かったとする。モデルでは、この平均をどう計算すればよいだろうか。人口全体の所得をただ平均するだけではいけない。商品 \(j\) を買いやすい人ほど、購入者の中では大きな割合を占めるからである。そこで、各人の所得をその人の購入確率で重み付けする。

\[ m_j^y(\theta) =\frac{E[y_i s_{ij}(\theta)]}{E[s_{ij}(\theta)]}. \]

分子は所得と購入確率の積の平均、分母は商品 \(j\) の市場シェアである。この比が、モデルの予測する「商品 \(j\) の購入者の平均所得」になる。期待値は、その市場にいる消費者の所得や \(\nu_i\) の分布について取る。

具体的に、所得が300万円、600万円、900万円の人が同じ人数ずついる市場を考えよう。ある商品を買う確率がそれぞれ0.1、0.3、0.6なら、購入者の平均所得は、

\[ \frac{300\times0.1+600\times0.3+900\times0.6}{0.1+0.3+0.6} =750\text{万円} \]

となる。人口全体の平均所得は600万円だが、この商品を買う人は高所得層に偏っているため、購入者の平均はそれより高くなる。

この計算をパラメータの候補ごとに行い、観測値とのずれ、

\[ g_j^y(\theta)=\bar y_j^{\mathrm{obs}}-m_j^y(\theta) \]

を小さくしたい。市場シェアは合っていても、実際には平均750万円の購入者を、モデルが平均600万円と予測しているなら、購入者の構成を捉えられていない。このずれが、所得と好みの関係を見直すための追加の情報になる。

なお、モデルが平均を取るときに必要なのは、購入者だけでなくその市場の消費者全体の所得分布である。購入者のアンケートと人口全体のデータは、役割が違う。調査で特定の層が多く抽出されている場合には、その抽出方法に合わせた重みも必要になる。

ヒント実証研究コーナー:Petrin (2002) — ミニバンを買ったのはどんな世帯か

1984年に登場したミニバンは、消費者にどれだけの便益をもたらしたのだろうか。Petrin (2002) は、自動車の価格・シェアなどに加え、Consumer Expenditure Surveyから得られる購入世帯の属性を使って、この問いを調べた。

同論文のTable 2では、1987–1992年の新車購入世帯の平均人数が2.87人なのに対し、ミニバン購入世帯では3.86人である。ミニバンのシェアだけでは分からない、「家族の多い世帯に選ばれている」という情報が加わる。こうした購入者属性と車種の関係をモデルにも再現させることで、家族構成と車への好みの関係を推定する。

その結果、個票の情報を使わないモデルと比べて、代替関係や新製品の便益の推定が変わった。ミニバンの販売数だけでなく、誰が買っていたかを説明することが、ミニバンのない世界の予測にも効いているのである。

7.3 「その商品がなければ何を選ぶか」も使う

購入者の属性に加え、第二希望を尋ねたデータがあるとしよう。例えば商品 \(j\) の購入者に、「価格やほかの商品が同じで、\(j\) だけ買えなかったら、何を選びますか」と聞く。商品 \(k\) を選ぶと答えた人の割合を \(q_{jk}^{\mathrm{obs}}\) とする。「何も買わない」も選択肢に含める。

この割合もモデルから計算できる。消費者 \(i\) のタイプを固定するとlogitなので、\(j\) を除いたときに \(k\) を選ぶ確率は、

\[ s_{ik}^{(-j)}(\theta) =\frac{s_{ik}(\theta)}{1-s_{ij}(\theta)},\qquad k\ne j \]

となる。分母から \(j\) の分を取り除き、残った選択肢の確率の合計を1に直している。Gumbelの効用ショックから得られる順位のモデルでは、タイプ \(i\) の人が「第一希望 \(j\)、第二希望 \(k\)」となる確率は \(s_{ij}(\theta)s_{ik}^{(-j)}(\theta)\) である。したがって、商品 \(j\) の購入者に限った第二希望の割合は、

\[ q_{jk}(\theta) =\frac{E[s_{ij}(\theta)s_{ik}^{(-j)}(\theta)]}{E[s_{ij}(\theta)]}. \]

購入者の平均所得と同じく、\(j\) を買いやすいタイプほど大きな重みを付けている。例えば「Aの購入者のうち、AがなければBを選ぶ人は60%」という観測値があれば、モデルにもその割合を再現させる。ここで使っているのは人口全体でのBの人気ではなく、Aを選んだ人にとってのBの位置づけである。第一希望と第二希望を組み合わせる方法は、Berry, Levinsohn and Pakes (2004) の中心的な考え方の一つであり、上の確率の計算はPyBLPの解説でも確認できる。

7.4 追加した情報を推定に使う

購入者の平均所得や第二希望の割合のように、個票データから作った統計量を micro moments と呼ぶ。すべての個人の記録をそのまま推定に入れる代わりに、モデルと比べたい特徴を平均や比率として取り出している。

これまで使った需要のモーメントを、商品×市場の観測数 \(N\) に対して、

\[ g_D(\theta)=\frac{1}{N}\sum_{j,t}z_{jt}\xi_{jt}(\theta) \]

と書こう。micro momentsについても、観測値と予測値のずれを縦に並べたベクトル \(g_M(\theta)\) を作る。例えば、

\[ g_M(\theta)= \begin{pmatrix} \bar y_1^{\mathrm{obs}}-m_1^y(\theta)\\ q_{12}^{\mathrm{obs}}-q_{12}(\theta)\\ \vdots \end{pmatrix} \]

である。両方をまとめて、

\[ g(\theta)= \begin{pmatrix}g_D(\theta)\\g_M(\theta)\end{pmatrix}, \qquad \widehat\theta=\arg\min_\theta g(\theta)'Wg(\theta) \]

を解けばよい。\(W\) は、それぞれのずれにどれだけ重みを付けるかを決める行列である。所得と選択割合では単位も推定の精度も違うので、その違いを考慮して重みを付ける。

計算の流れはBLPのままである。パラメータの候補を与えたら、まず市場シェアに合う平均効用を反転で求める。その上でIVの条件をどれだけ満たすかを調べ、さらに購入者の所得や第二希望もデータと比べる。同じシェアを再現する候補でも、どんな人が買うかの予測が違えば、micro momentsとのずれに差がつくのである。条件付き平均や比率を使う場合の目的関数は、厳密には最小距離推定の形だが、BLPの実装ではこれも含めてGMMと呼ぶことが多い(PyBLPの解説)。

7.5 合併予測へのつながりと、残る内生性の問題

micro momentsを加えて好みの分布の推定が変われば、価格を変えたときの需要の反応も変わる。すると、第6節で使った需要の価格微分、マークアップ、合併後の均衡価格も変わってくる。個票データを使う目的は、合併後の価格を直接尋ねることではない。その予測の土台となる需要について、観測データで確かめられることを増やすことである。

ただし、第二希望の割合を、そのまま第6節のdiversion ratioに置き換えてはいけない。第二希望は商品がなくなったときの選択であり、diversion ratioは価格を少し上げたときの需要の移り方だった。価格に敏感な人ほど小さな値上げで動きやすいため、両者で重みの付く消費者が違う。第二希望を使ってモデルを推定した後、そのモデルから価格微分を計算する必要がある。

もう一つ、個票データがあっても、価格の内生性はなくならない。消費者の所得を詳しく観測していても、人気の高い商品ほど高く売られているなら、価格と未観測の需要ショック \(\xi_{jt}\) は相関し得る。micro momentsを加えたからといって、IVの条件を捨ててよいわけではない。個票は好みの違いについて情報を足し、IVは価格と需要ショックを区別するための変動を与える。どちらの情報を何に使っているかを分けて考えよう。

ここでは正規分布や対数正規分布を仮定して需要を推定した。では、特定の関数形を置かずに考えたとき、個票データから何が分かるのだろうか。Berry and Haile (2024) は、消費者の選択と属性を観測できる状況で、差別化財需要の識別を分析している。

同じ市場の消費者を比べれば、商品ごとの需要ショック \(\xi_{jt}\) は共通のまま、消費者の属性による選択の違いを調べられる。この情報を市場間の変動や価格の操作変数と組み合わせることで、識別に必要な操作変数の条件を緩められる場合がある。ただし、その結果には効用の構造、消費者属性の十分な変動、妥当な操作変数などの仮定が必要であり、個票があれば自動的に需要が分かるという話ではない。詳しくは著者のワーキングペーパーを参照。

まとめ

重要この回のポイント
  • 共通係数のlogitにも、効用ショックによる選択の違いはあった。random coefficient logitでは、さらに属性への評価や価格への反応を人ごとに変える。これにより、属性と結びついた代替関係を表せる。
  • 個人の係数を固定すれば選択確率はlogitになる。その確率を人々について積分すると、市場シェアが得られる。同じ現在のシェアでも、好みの構造が違えば値上げ後の需要は異なり得る。
  • BLPは、第3回の反転とIVを異質性のある需要へ拡張する。非線形パラメータの候補ごとに、シェアに合う平均効用を逆算し、需要ショックと操作変数の無相関条件を使ってパラメータを選ぶ。
  • 推定した需要に企業の価格設定行動を加えると、限界費用を逆算し、所有関係を変えた合併後の価格を予測できる。前半では、需要を推定してから供給側の条件を使った。
  • micro BLPでは、購入者の属性や第二希望もデータと比べる。誰が買うか、何と何が代替するかについての追加情報が、異質性の推定と合併予測に役立つ。ただし、価格の内生性に対処する条件は引き続き必要である。

宿題

  1. 第3節の交差弾力性のコードで、財1と財2の属性 x_char を「近い」から「遠い」に変えてみよう(例:c(1.0, -0.9, -0.8))。財1と財2の代替関係がどう変わるかを、好みの異質性から説明してみよう。
  2. 第6節の合併分析で、需要の推定値、合併前の価格、所有関係が、それぞれどの計算に使われているかを追ってみよう。合併後も固定しているものは何だろうか。
  3. 第7節の3つの所得層の例で、購入確率をそれぞれ0.3、0.3、0.3に変えると、購入者の平均所得はいくらになるだろうか。元の例との違いを、「誰が買いやすいか」という言葉を使って説明してみよう。
  4. 自分が知っている商品について、需要推定に使えそうなmicro momentを一つ考えよう。どんな個票データが必要で、モデルのどの好みの違いについて情報を与えるだろうか。

ブラウザで数値を変えてみたい人は、ブラウザ実験室も使ってみよう。coding課題は 課題4を参照。

後半・次回予告

Lecture 4 後半:費用関数の推定と費用変化の反実仮想では、企業の価格設定行動を推定の段階でも使う。前半では、需要を推定した後に価格設定の条件から限界費用を逆算した。後半では、その限界費用に費用関数を仮定し、費用ショックと操作変数の無相関条件も使う。需要だけの推定に比べて何が分かるようになり、どんな仮定が増えるのかを考える。その推定結果を使い、投入価格が20%下がったときの費用・価格・数量・余剰を計算することが後半のゴールである。

第5回は、公正取引委員会の方をお招きするゲスト講義である。今回の需要推定や合併シミュレーションが、実際の企業結合審査でどのように使われるのかを伺う。企業や経済コンサルが提出する分析を、当局はどのように評価するのか。どんな代替関係を仮定し、何をデータで確かめているかを意識しながら聞いてみよう。

その後の第6回では、今回推定したような好みの分布を、個人の購買履歴からその人について学ぶために使う。市場全体のシェアを計算する場合と、個人の次の選択を予測する場合を比べてみよう。第7回では、好みを測るための選択課題を設計するコンジョイント分析に進む。

参考文献

  • Bresnahan, T. F. (1987). “Competition and Collusion in the American Automobile Industry: The 1955 Price War.” The Journal of Industrial Economics, 35(4), 457–482. 論文
  • Train, K. E. (2009). Discrete Choice Methods with Simulation, 2nd ed., Cambridge University Press, Chapters 3 and 6. Chapter 6
  • 上武康亮・遠山祐太・若森直樹・渡辺安虎『実証ビジネス・エコノミクス』日本評論社(第4章)。
  • Nevo, A. (2000). “A Practitioner’s Guide to Estimation of Random-Coefficients Logit Models of Demand.” Journal of Economics & Management Strategy, 9(4), 513–548.
  • Nevo, A. (2001). “Measuring Market Power in the Ready-to-Eat Cereal Industry.” Econometrica, 69(2), 307–342.
  • Berry, S., Levinsohn, J., and Pakes, A. (1995). “Automobile Prices in Market Equilibrium.” Econometrica, 63(4), 841–890.
  • Berry, S., Levinsohn, J., and Pakes, A. (2004). “Differentiated Products Demand Systems from a Combination of Micro and Macro Data: The New Car Market.” Journal of Political Economy, 112(1), 68–105. 論文
  • Werden, G. J., and Froeb, L. M. (1994). “The Effects of Mergers in Differentiated Products Industries: Logit Demand and Merger Policy.” Journal of Law, Economics, & Organization, 10(2), 407–426.
  • Petrin, A. (2002). “Quantifying the Benefits of New Products: The Case of the Minivan.” Journal of Political Economy, 110(4), 705–729. 論文
  • Miller, N. H., and Weinberg, M. C. (2017). “Understanding the Price Effects of the MillerCoors Joint Venture.” Econometrica, 85(6), 1763–1791.
  • Berry, S. T., and Haile, P. A. (2024). “Nonparametric Identification of Differentiated Products Demand Using Micro Data.” Econometrica, 92(4), 1135–1162. 論文
  • PyBLP Documentation. “Micro Moments” and “Second Choice Micro Moments.” 解説
  • Adam, H., He, P., and Zheng, F. (2023). “Machine Learning for Demand Estimation in Long Tail Markets.” Management Science, 70(8), 5040–5065. https://doi.org/10.1287/mnsc.2023.4893