🎓 レベル:標準 | 重要度:A(必須)
📎 関連:第5章 顧客選好と選択モデル 目次 | 前提:需要曲線と価格弾力性
要点(BLUF)
- 離散選択モデルは、消費者が選択肢の中から「効用が最大」のものを選ぶというランダム効用モデル(RUM)に基づきます。効用は 、確定部分は属性の線形結合 。誤差 が i.i.d. の第I種極値分布(Gumbel)なら、選択確率は閉じた形のソフトマックス になります。
- 観測された選択データの対数尤度 を最大化(=負の対数尤度を最小化)して を推定します。本ノートの合成データ(3選択肢 × 4000機会、真値 )では、
scipy.optimize.minimize(BFGS)が推定 とよく回復し、推定モデルの予測シェアが実シェアと一致します。 - MNL は扱いやすい反面、IIA(無関係な選択肢からの独立)という強い性質を持ち、似た選択肢があると非現実的になります(赤バス・青バス問題)。係数は効用スケール上の量で、規模そのものは識別されず符号と比に意味があります。個人差(異質性)を無視する点は後続ノートで緩めます。
1. ランダム効用モデル(RUM):選択を確率で表す
需要曲線と価格弾力性 では、価格に対して需要が連続的にどう動くかを「集計レベル」で見ました。離散選択モデルは、同じ需要を「個人がどの選択肢を選ぶか」という離散の意思決定から組み立て直します。鍵になるのが**ランダム効用モデル(Random Utility Model, RUM)**です。
消費者 が選択肢 から得る効用を
と置きます。 は観測できる属性(価格・品質・ブランドなど )から決まる確定効用、 は分析者には見えない要因をまとめたランダムな誤差です。消費者は効用が最大の選択肢を選ぶ——これが行動の仮定です。分析者には が見えないので、「選ぶ/選ばない」は確率的にしか予測できません。だから選択を確率で表すのです。
flowchart LR X["属性 x(価格・品質)"] --> V["確定効用 V = β·x"] E["Gumbel 誤差 ε"] --> U["ランダム効用 U = V + ε"] V --> U U --> P["選択確率 = ソフトマックス"] P --> L["対数尤度を最大化して β を推定"]
2. Gumbel 誤差からソフトマックスへ(数式)
選択肢 が選ばれるのは、その効用が他のすべてを上回るときです。
ここで誤差 が互いに独立に同一の第I種極値分布(Gumbel) に従うと仮定すると、上の最大化確率は驚くほどきれいな閉じた形になります(導出は2つの Gumbel の差がロジスティック分布になることを使いますが、ここでは結果を採ります)。
これが多項ロジット(Multinomial Logit, MNL)で、右辺はまさにソフトマックス関数です。確定効用 が大きい選択肢ほど指数で増幅され、合計が1になるよう正規化されて選択確率になります。
機会ぶんの選択データ ( は機会 で実際に選ばれた選択肢)が得られたら、対数尤度
を最大化して を推定します(実装では符号を反転した負の対数尤度を最小化します)。
ここで MNL の核心的な性質が見えます。選択肢 と の選択確率の比は
で、他のどの選択肢 にも依存しません。これを **IIA(Independence of Irrelevant Alternatives、無関係な選択肢からの独立)**と呼びます。計算を軽くする便利な性質ですが、似た選択肢が混じると非現実的な予測を生みます(§⚠️で扱う赤バス・青バス問題)。
もうひとつ。 の分散は Gumbel で に固定されています。これは効用に絶対的な単位がないことを意味し、 は誤差のばらつきを基準にした相対値として識別されます。全係数を定数倍しても誤差スケールを同じだけ変えれば確率は不変なので、規模そのものは決まらず、符号と係数間の比だけが解釈可能です。後で WTP(係数の比)が意味を持つのはこのためです。
3. β の推定と選択確率カーブ(コード)
3選択肢 × 4000機会の合成選択データを作ります。各選択肢に価格 price~U(1,5)・品質 quality~U(1,5) を機会ごとに与え、真の係数 の確定効用に Gumbel ノイズを足して、効用最大の選択肢を選ばせます。そのデータから負の対数尤度を scipy.optimize.minimize(BFGS)で最小化して を推定し、真値を回復することを確かめます。
import numpy as np
import pandas as pd
from scipy.optimize import minimize
# 3選択肢×4000機会の合成選択データ。各選択肢に価格と品質を機会ごとに与え、
# 真の係数 β_price=-0.8, β_quality=1.5 の効用に Gumbel ノイズを足し、効用最大を選ぶ。
rng = np.random.default_rng(42)
N, J = 4000, 3
price = rng.uniform(1, 5, (N, J)) # 各機会・各選択肢の価格(順序厳守)
quality = rng.uniform(1, 5, (N, J)) # 各機会・各選択肢の品質
beta_true = np.array([-0.8, 1.5]) # [価格, 品質] の真の係数
V = beta_true[0] * price + beta_true[1] * quality # 確定効用 V_ij
eps = rng.gumbel(0, 1, (N, J)) # 第I種極値分布の誤差
U = V + eps # ランダム効用 U_ij = V_ij + ε_ij
choice = U.argmax(axis=1) # 各機会で効用最大の選択肢を選ぶ
# 負の対数尤度。β を受け取り、ソフトマックスで選択確率を作り、選ばれた肢の対数確率の和の符号を反転。
def neg_loglik(beta):
v = beta[0] * price + beta[1] * quality # (N, J)
v = v - v.max(axis=1, keepdims=True) # オーバーフロー防止の平行移動
expv = np.exp(v)
P = expv / expv.sum(axis=1, keepdims=True) # ソフトマックス
chosen_p = P[np.arange(N), choice]
return -np.sum(np.log(chosen_p))
res = minimize(neg_loglik, x0=np.zeros(2), method="BFGS")
beta_hat = res.x
tbl = pd.DataFrame({"真値": beta_true, "推定値": beta_hat}, index=["price", "quality"])
print("=== MNL:負の対数尤度最小化(BFGS)による係数の回復 ===")
print(tbl.to_string(formatters={"真値": "{:.2f}".format, "推定値": "{:.3f}".format}))
print(f"\n収束: {res.success} 最終の負の対数尤度: {res.fun:.1f}")
# 推定 β での選択確率から予測シェアを作り、実データの選択シェアと比べる
v = beta_hat[0] * price + beta_hat[1] * quality
v = v - v.max(axis=1, keepdims=True)
P = np.exp(v) / np.exp(v).sum(axis=1, keepdims=True)
share_pred = P.mean(axis=0)
share_obs = np.bincount(choice, minlength=J) / N
share = pd.DataFrame({"実シェア": share_obs, "予測シェア": share_pred},
index=["選択肢A", "選択肢B", "選択肢C"])
print("\n=== 選択シェア:実データ vs 推定モデル予測 ===")
print(share.to_string(formatters={"実シェア": "{:.1%}".format, "予測シェア": "{:.1%}".format}))
出力:
=== MNL:負の対数尤度最小化(BFGS)による係数の回復 ===
真値 推定値
price -0.80 -0.856
quality 1.50 1.556
収束: True 最終の負の対数尤度: 2307.2
=== 選択シェア:実データ vs 推定モデル予測 ===
実シェア 予測シェア
選択肢A 33.0% 33.7%
選択肢B 32.4% 33.0%
選択肢C 34.7% 33.3%
出力の意味:まず推定係数が真値をよく回復しました——price (真 )、quality (真 )。符号も正しく、価格係数は負(高いほど選ばれにくい)、品質係数は正(良いほど選ばれやすい)です。係数の比 も真の比 に近く、「価格と品質の重み付け」を取り戻せています。4000機会ぶんの argmax 選択というノイズの多い離散データから、最尤推定が連続的な を推定できているのがポイントです。次に選択シェア。3つの選択肢は属性の分布が対称なので、実シェアはほぼ ずつ()。推定モデルの予測シェア()もこれに一致し、モデルが選択行動を再現できていることを確認できます。
推定した係数を使うと、ある選択肢の属性が変わったとき選択確率がどう動くかを描けます。選択肢 B・C を「価格3・品質3」に固定し、選択肢 A の品質を3に保ったまま価格を から へ動かして、A の選択確率を見ます。
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 推定で得た係数(前のブロックの出力)を使い、選択肢の価格に対する選択確率の変化を描く。
beta = np.array([-0.856, 1.556]) # [価格, 品質]
# 選択肢B・Cは価格3・品質3に固定。選択肢Aの品質を3に固定し、価格を1〜5で動かす。
prices = np.linspace(1, 5, 100)
qA = 3.0
VB = beta[0] * 3 + beta[1] * 3
VC = beta[0] * 3 + beta[1] * 3
VA = beta[0] * prices + beta[1] * qA
expA, expB, expC = np.exp(VA), np.exp(VB), np.exp(VC)
PA = expA / (expA + expB + expC)
PB = expB / (expA + expB + expC)
PC = expC / (expA + expB + expC)
fig, ax = plt.subplots(figsize=(7, 4.3))
ax.plot(prices, PA, color="C3", lw=2.2, label="選択肢A(価格が変化)")
ax.plot(prices, PB, color="C0", lw=1.6, ls="--", label="選択肢B(価格3・品質3で固定)")
ax.plot(prices, PC, color="C2", lw=1.6, ls=":", label="選択肢C(価格3・品質3で固定)")
ax.axvline(3.0, color="gray", lw=1.0, alpha=0.6)
ax.set_xlabel("選択肢Aの価格")
ax.set_ylabel("選択確率")
ax.set_title("価格が上がると選択肢Aの選択確率は下がる(MNL)")
ax.legend(loc="center right", fontsize=9)
fig.tight_layout()
plt.show()
3本の曲線が描くのは「個人の選択レベルの需要曲線」です。3つが同条件(価格3・品質3)になる中央では A の選択確率は 。A の価格が まで下がると A は割安になり選択確率は まで上がり、逆に まで上がると まで落ちます。価格係数が負であることが、この右下がりの曲線として現れています。集計の需要曲線(需要曲線と価格弾力性)を、ソフトマックスを通じて選択肢間の競争として描き直したものだと捉えてください——A が下がった分は B・C から奪っています。
⚠️ よくある誤解
- IIA(赤バス・青バス問題):MNL は選択確率の比 が他の選択肢に依存しない(IIA)。便利ですが、似た選択肢があると壊れます。有名な例:通勤手段が「自動車」と「赤バス」で のとき、色だけ違う青バスを足すと、直感的にはバス需要を赤・青で分け合って「自動車 /バス計 」のままのはず。ところが MNL は3択を機械的に ずつ(自動車 /赤 /青 )に割ってしまいます。赤バスと青バスの誤差が強く相関する(ほぼ同じもの)ことを無視するからです。入れ子ロジットや混合ロジットはこの相関を許して緩和します。
- 係数は効用スケール上の量で、規模は識別されない: の分散が Gumbel で に固定されているため、 は誤差のばらつきを基準にした相対値です。全係数を 倍しても誤差スケールを 倍にすれば確率は変わらないので、絶対的な大きさには意味がなく、符号と係数間の比だけが解釈できます。だから「価格係数が 」を単体で大小評価せず、他属性との比(=WTP、次ノート)で読みます。
- ロジスティック回帰の多クラス版そのもの:2択の MNL は二項ロジスティック回帰、 択の MNL はソフトマックス回帰と数式的に同じです。ここではマーケの選択データへの応用として最小限を扱い、最尤推定・標準誤差・正則化といった推定論の詳細は統計・機械学習テキストのロジスティック回帰/ソフトマックスへ譲ります(重複させません)。
- 単一の β は「平均的な消費者」を仮定する:本ノートの は全員共通で、人によって価格感度が違うこと(選好の異質性)を無視しています。実はこれが IIA 問題の一因でもあります。個人差を確率分布として表す混合ロジット・階層ベイズは 05-03 選好の異質性で扱い、そこで「平均だけ見ると隠れるもの」を取り戻します。
関連ノート
- コンジョイント分析(部分効用・WTP・市場シェア)(同じ MNL を製品属性の評価に当てはめ、部分効用・WTP・市場シェアを取り出す応用)
- 第5章 顧客選好と選択モデル 目次
- 需要曲線と価格弾力性(価格は選択の主要属性。選択モデルは集計の需要を個人の選択レベルから組み立て直す)
- ソフトマックス/ロジスティック回帰の推定論は統計・機械学習テキスト、選好の異質性(混合ロジット・階層ベイズ)は 05-03 選好の異質性で扱います
- マーケティング・サイエンス 全体目次