Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

実験計画(属性・水準の設計)

コンジョイント分析の精度は、回答者に提示するプロファイル(属性の組み合わせ)をどう設計するかに大きく依存する。ここでは属性・水準の選び方と、プロファイルの組み合わせ方(実験計画法)について整理する。

属性・水準を選ぶ際の原則

  • 識別可能性(communicability):回答者が理解・比較できる具体的な属性・水準にする

  • 選好独立性(preferential independence):ある属性の望ましさが他の属性の水準に依存しないことが望ましい(加法モデルの前提)

  • 実現可能性(actionability):意思決定者が実際にコントロールできる属性を選ぶ

  • 水準数のバランス:ある属性だけ水準数を多くすると、その属性の重要度が過大評価される傾向がある(number-of-levels effect)ため、属性間で水準数を揃えることが望ましい

フルプロファイル法と部分プロファイル法

  • フルプロファイル法(full-profile method):すべての属性を同時に1つのプロファイルとして提示する。属性数が少ない(〜6個程度)場合に向く

  • 部分プロファイル法(partial-profile method):属性数が多い場合に、一部の属性のみを提示して回答負荷を下げる手法。CBCで属性数が多いときに用いられる

完全要因計画とフラクショナル要因計画

属性数をKK、属性kkの水準数をLkL_kとすると、考えられるプロファイルの総数(完全要因計画、full factorial design)は

N=k=1KLkN = \prod_{k=1}^{K} L_k

となり、属性数・水準数が増えると組み合わせ数は急激に増加する(組み合わせ爆発)。

import itertools
import pandas as pd

attributes = {
    "価格":   ["1,000円", "1,500円", "2,000円"],
    "容量":   ["500ml", "1000ml"],
    "ブランド": ["A社", "B社", "C社"],
    "パッケージ": ["缶", "瓶", "ペットボトル"],
}

full_factorial = list(itertools.product(*attributes.values()))
print(f"完全要因計画のプロファイル数: {len(full_factorial)}")
pd.DataFrame(full_factorial, columns=attributes.keys()).tail()
完全要因計画のプロファイル数: 54
Loading...

4属性・3×2×3×3水準でも54通りとなり、回答者に全プロファイルを評価させるのは現実的でない。そこで実務では、全体の情報のごく一部(フラクション)だけを抽出する フラクショナル要因計画(fractional factorial design) を用いる。

直交計画(orthogonal design)

フラクショナル要因計画の中でも、各属性間の水準の組み合わせ頻度が均等になるように選ばれた計画を 直交計画(orthogonal array) と呼ぶ。直交性(orthogonality)が保たれていると、

  • 各属性の主効果(main effect)を独立に、バイアスなく推定できる

  • 説明変数間の多重共線性を避けられる

という利点がある。古典的にはTaguchi(田口玄一)の直交表(L8L_8L9L_9L18L_{18}など)がよく用いられてきた。

例えば2水準属性を最大7つまで、8回の質問で主効果を推定できるL8L_8直交表は次のような構造を持つ(1/+1-1/+1は各属性の2水準を表す):

import numpy as np
import pandas as pd

# L8直交表(2水準7列)
L8 = np.array([
    [-1, -1, -1, -1, -1, -1, -1],
    [-1, -1, -1, +1, +1, +1, +1],
    [-1, +1, +1, -1, -1, +1, +1],
    [-1, +1, +1, +1, +1, -1, -1],
    [+1, -1, +1, -1, +1, -1, +1],
    [+1, -1, +1, +1, -1, +1, -1],
    [+1, +1, -1, -1, +1, +1, -1],
    [+1, +1, -1, +1, -1, -1, +1],
])
df_L8 = pd.DataFrame(L8, columns=[f"属性{i+1}" for i in range(7)])

# 任意の2列間の相関が0であることを確認(直交性)
print(df_L8.corr().round(2))
df_L8
     属性1  属性2  属性3  属性4  属性5  属性6  属性7
属性1  1.0 -0.0  0.0  0.0  0.0  0.0  0.0
属性2 -0.0  1.0  0.0 -0.0  0.0  0.0 -0.0
属性3  0.0  0.0  1.0  0.0 -0.0 -0.0  0.0
属性4  0.0 -0.0  0.0  1.0  0.0  0.0  0.0
属性5  0.0  0.0 -0.0  0.0  1.0  0.0  0.0
属性6  0.0  0.0 -0.0  0.0  0.0  1.0  0.0
属性7  0.0 -0.0  0.0  0.0  0.0  0.0  1.0
Loading...

D-効率的計画(D-efficient design)

属性数・水準数が多様(属性ごとに水準数が異なる、交互作用も推定したいなど)な場合、古典的な直交表がそのまま使えないことが多い。
そこで現代のCBCソフトウェア(Sawtooth SoftwareのCBC/Webなど)では、推定量の分散共分散行列を最小化するように数値最適化でプロファイルの組み合わせを選ぶ D-最適計画(D-optimal design) が使われる。

推定パラメータβ\boldsymbol{\beta}の情報行列をXX\mathbf{X}^\top \mathbf{X}(線形モデルの場合)とすると、D-最適基準は

maxX det(XX)\max_{\mathbf{X}} \ \det(\mathbf{X}^\top \mathbf{X})

を満たす計画行列X\mathbf{X}を選ぶことに相当する。行列式を最大化する(=推定量の分散を最小化する)ことから “D”(determinant)-optimalと呼ばれる。厳密な最適解を解析的に求めるのは難しいため、実務では 交換アルゴリズム(exchange algorithm、Fedorov法など) を使って数値的に構築する。

ホールドアウトタスク

推定に使わないプロファイル(ホールドアウトタスク、holdout task)をあらかじめ用意し、推定したモデルの予測精度を検証するために用いる。詳細はモデル評価で扱う。