「現代の好み引き出しにおける回帰とベイズ手法」

Regression and Bayesian methods in modern preference extraction

シンプルなスムージー作りへの応用

UnsplashのDenis Tuksarによる写真

線形回帰は予測モデリングの中でも基本的なものとされていますが、その応用は単純な予測タスクを超えています。この記事では、好みのモデリングにおいて効果的なツールであるプロビット線形回帰を紹介することで、回帰技術に関する対話を豊かにします。さらに、古典的な線形回帰からベイズ線形回帰への移行にベイズ的な枠組みを採用し、コストベースの最適化(具体的にはバイナリクロスエントロピー(BCE)損失の最小化)と最尤推定との間の本質的な関係を明らかにします。

そうすることで、正則化はベイズ的な事前選択の形態と考えることができるため、コスト関数のアプローチと確率的な推論とを結びつけます。

最後に、ベイズ線形回帰によって単なる点推定だけでなく、これらの予測に対する分布も提供されるため、より豊かで不確実性を考慮した視点を提供します。

ベイズの枠組み

ベイズの枠組みでは、データDとモデルwの2つの主要な要素が特定されます。尤度P(D∣w)とモデルへの事前分布P(w)を指定することで、ベイズの定理によって導出された事後確率P(w∣D)を最大化するモデルを見つけることを目指します。

好みの学習では、wの分布を持つことは人間の好みに固有の不確実性を捕捉する利点を提供し、単一の「最良の推測」だけでなく、複数の妥当なモデルの範囲を提供します。

好みの引き出し問題

好みの引き出しは意思決定理論における重要な要素であり、利用可能なデータに基づいて意思決定者の選択を特定することを目指しています。この研究では、部分的な好みのセットにモデルを適合させることによって好みの引き出し問題に取り組みます。この場合、好みは最もシンプルな形式で表現される:対の比較となります。この概念を説明するために、リンゴ、バナナ、オレンジ、ライチ、マンゴーからなるフルーツのセットFを考えてみましょう。

この文脈では、代替セットAはセットFから1つまたは複数の成分を使用して作成できるすべてのスムージーからなります。

ユーザーは、順序付けられた対(A,B)のセットを通じて自分の好みを表現します。ここでAはBよりも明確に好まれます。

この記事の次のセクションでは、ユーザーの好みを捉えるために特に選ばれた関数のファミリー、加法関数を紹介します。これらの数学的な構造は、さまざまな要素が個々の好みにどのように寄与するかを理解するための直感的で堅牢なフレームワークを提供し、対の比較を通じて表現される選択の効果的なモデリングを可能にします。

加法モデル

加法線形モデルは、ユーザーの好みを捉えるために使用できる最も直接的なモデルです。

加法線形モデル

加法効用モデルは、セット内の各個々の成分に特定の重みを割り当てるモデルです。スムージーの総効用または「好ましさ」は、構成成分の重みを合計することで計算されます。形式的には、重みのベクトルが与えられた場合

成分Aから作られたスムージーの効用は次のようになります:

ここで、IはAに存在するかどうかをテストする恒等関数です。

バイナリ相互作用を持つ加法モデル

2つの加法モデルは、1つの加法モデルを基にした追加の複雑さを導入しています。重みベクトルには、個々の成分ごとの重みだけでなく、すべての可能な成分のペアごとの重みも含まれています。これにより、2つの成分の組み合わせが全体の有用性にどのように影響を与えるかを認識することができます。厳密には、重みベクトルwは、シングルトンに加えて、各ペア(i,j)ごとの重みも含めて拡張されます:

そして、2つの加法線形モデルでは、スムージーの有用性は次のように表されます:

ここで、F²はシングルトンとペアのセットです。

n加法モデル

さらに概念を拡張すると、n加法モデルは非常に柔軟な効用フレームワークを提供します。このモデルでは、重みベクトルは個々の成分とペアだけでなく、最大n個の成分の任意の部分集合に対する重みも含まれます。この一般化により、モデルは複数の成分間の複雑な関係やシナジーを同時に捉えることができます。

厳密には、重みベクトルwは最大n個の成分のすべての可能な組み合わせに対する重みも含めて拡張されます:

このn加法モデルは、成分間の相互作用の全範囲を捉えることができるため、複雑な好みの構造を理解するための非常に強力なツールです。

この分析では、成分間の好みの関係の複雑さがペアワイズの相互作用を超えることはないと考えられるため、2つの加法モデルに制限します。

プロビット回帰問題を解決することによる好みの学習

従来の回帰モデルは実数値の予測を出力しますが、私たちの目標はバイナリの好み関係を予測することです。

これを達成するために、回帰モデルを修正してオプションAがオプションBより好まれる確率を出力します。そして、データにこの確率モデルを効果的に適合させるための適切なコスト関数を導出します。

0から1の値を圧縮する一般的な方法の1つは、プロビット関数を使用することです。プロビット関数は次のように定義されます

次の図はその形状を示しています

Shape of the probit function (by me)

この関数をf(A)とf(B)の差に適用することで、f(A)がf(B)を大幅に上回る場合、モデルは確率が1に近づくようになります。逆に、f(A)がf(B)とほぼ等しい場合、確率は0.5に近くなります。

したがって、好みの引き出し問題は、最適な重みベクトルwを探索することとして再定義できます:

二値交差エントロピー(BCE)損失

二値交差エントロピー(BCE)損失、またはログ損失は、通常、0から1までの確率を出力する分類モデルのパフォーマンス指標として使用される、2値分類タスクでの損失関数です。数学的には、真のラベルy(0または1)と予測確率pが与えられた場合、BCEは次のように定義されます:

トイデータの生成

手法を検証するために、合成データを生成するためのプロトコルを紹介します。

プロセスは、重みベクトル w をランダムにサンプリングすることから始まります。その後、いくつかのパラメータをゼロに設定します。これにより、現実味とシンプルさのレイヤーを導入します。

ユーザーの選好がこのサンプリングされた関数と一致するという仮定のもとで、予測モデルの精度を評価するためのベンチマークとして使用することができます。

def singletons_and_pairs(lst):    singletons = [(x,) for x in lst]    pairs = list(combinations(lst, 2))    return singletons + pairsingredients = ["o", "a", "b","l", "m"]model = singletons_and_pairs(ingredients)w = np.random.normal(0, 1, size = (len(model),))p = np.random.randint(0, 2, size = (len(model),))w = w * p

次に、各代替品をバイナリベクトルでエンコードします。モデルパラメータと同じ順序で成分が配置されます。以下の関数を使用します。

def vectorize_smoothie(smoothie):    arr = np.zeros(len(model))    print(list(smoothie))    for i in range(arr.shape[0]):        if all(j in list(smoothie) for j in model[i]):            arr[i] = 1    return arr

次に、特定のスムージーを評価するために、積を使用します。

vectorize_smoothie("oa") @ w# Return w_a + w_o + w_oa

データセットを構築するために、重みベクトル w をサンプリングして開始します。次に、スムージーの集合を生成し、サンプルされた重みに基づいてそれぞれを評価します。f(A)>f(B) となるすべてのスムージー A と B のペアに対して、対応する選好をデータセットに追加します。A と B の間の各選好は、次のように定義されるベクトルで表されます:

f(A) > f(B) の場合、f(A) < f(B) の場合、v(A,B) と v(B,A) の2つの行を追加し、最初の行はクラス1でラベル付けされ、2番目の行はクラス0でラベル付けされます。

次のコードは、n個のスムージーに関するデータセットを提供します。

def sample_dataset(n):    ingredients = ["o", "a", "b","l", "m"]    model = singletons_and_pairs(ingredients)    X = []    y = []    w = sample_w(model)    subsets = set()    while len(subsets) != n:        s = random_subset(ingredients)        subsets.add(s)    subsets = list(subsets)    for i in range(len(subsets)-1):        x_i = vectorize_smoothie(subsets[i])        for j in range(i+1, len(subsets)):            x_j = vectorize_smoothie(subsets[j])            x1 = x_i - x_j            x2 = x_j - x_i            if f(subsets[i], w) == f(subsets[j], w):                continue            if f(subsets[i], w) > f(subsets[j], w):                X.append(x1)                X.append(x2)                y.append(1)                y.append(0)                continue            if f(subsets[i], w) < f(subsets[j], w):                X.append(x1)                X.append(x2)                y.append(0)                y.append(1)                continue    X = np.array(X)    y = np.array(y)    return X,y,w,model

コストベースの解決

問題を解決する方法の1つは、BCE損失の凸性とTorchなどのライブラリを使用することです。

まず、生成されたデータをPyTorchが提供する適切なデータセットローダーにラップします。

X,y,w,model = sample_dataset(30)X_tensor = torch.FloatTensor(X)y_tensor = torch.FloatTensor(y)dataset = TensorDataset(X_tensor, y_tensor)train_size = int(0.3 * len(dataset))test_size = len(dataset) - train_sizetrain_dataset, test_dataset = random_split(dataset, [train_size, test_size])train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True)test_loader = DataLoader(dataset=test_dataset, batch_size=1, shuffle=False)

今、私たちは単純な線形モデルを作成します

class BinaryClassifier(nn.Module):    def __init__(self, input_dim):        super(BinaryClassifier, self).__init__()        self.fc1 = nn.Linear(input_dim, 1)            def forward(self, x):        x = torch.sigmoid(self.fc1(x))        return x

そして、PyTorchのautograd機能を使用してトレーニングします。

input_dim = X.shape[1]model = BinaryClassifier(input_dim)# 損失とオプティマイザcriterion = nn.BCELoss()optimizer = optim.Adam(model.parameters(), lr=0.01)losses = []# モデルを訓練するepochs = 200for epoch in range(epochs):    for batch_idx, (data, target) in enumerate(train_loader):        optimizer.zero_grad()        output = model(data).squeeze()        loss = criterion(output, target)        loss.backward()        optimizer.step()

次に、テストデータセットを使用して取得したモデルをテストします

model.eval()with torch.no_grad():  correct = 0  total = 0  for data, target in test_loader:    output = model(data).squeeze()    predicted = (output > 0.5).float()    total += target.size(0)    correct += (predicted == target).sum().item()  acc = correct / total  accuracy.append(acc)if (epoch+1) % 50 == 0:  print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')  print(f'Test Accuracy: {100 * correct / total:.2f}%')

トレーニングにはデータの20%を使用し、98.32%の正確さを得ました。

最尤推定(MLE)

プロビット回帰の課題に対処する別の方法は、重みベクトルwが与えられたデータの尤度を明示的に定式化することです。

まず、AがBよりも好まれる確率pを生成するモデルを仮定します。このシナリオの予測分布は次のように表されます:

重みベクトルが与えられた場合の対(x、y)の尤度は次のように表されます:

データセットの確率は次のように表されます:

尤度値は非常に小さくなる場合があり、多くの確率を一緒に乗算すると重要です。これは数値のアンダーフロー(非常に小さい浮動小数点数がゼロに丸められる)につながる可能性があります。これらの値の対数を取ると、一般に負で大きな値になり、より管理しやすい数値になります。

したがって、対数尤度は次のようになります:

この損失はBCE損失の負であるため、尤度を最大化することはBCE損失を最小化することと等しいです。

正則化技術

正則化は、機械学習において過学習に対抗するための重要な技術であり、モデルが訓練データに過度に適応し、そのノイズを含めているため、新しいデータでのパフォーマンスが低下することを防ぎます。これは、損失にペナルティ項を追加して、モデルパラメータの複雑さを制限することによって機能します。これにより、より単純なモデルが促進され、訓練データに適合し、モデルの単純さを維持するバランスが取れます。

L1(Lasso)とL2(Ridge)は一般的な正則化形式であり、各々がモデルの目的に独自のペナルティ項を導入します。

L1はパラメータの絶対値に基づいたペナルティを追加し、いくつかの重みがゼロになるスパースなモデルを生み出します。

対照的に、L2はパラメータの二乗の大きさにペナルティを科し、重みを縮小しますが、ゼロにはしません。

L1(Lasso)とL2(Ridge)の正則化技術は、モデルのパラメータにペナルティを科す方法によって異なります。L1は絶対値に比例するペナルティを適用し、一部の重みがまったくゼロになることで特徴量の選択を容易にします。対照的に、L2は重みの二乗の大きさにペナルティを科し、重みが小さくなるが一般的にゼロ以外の値を持ち、影響が減少したままであるすべての特徴量を保持します。

最大事後確率

前述のように、ベイズの定理を用いると、尤度関数とパラメータの事前分布P(w)を利用して、モデルパラメータの事後分布P(w∣X,y)を推定することができます。

本質的に、事前分布はデータを観測する前のパラメータに関する初期の信念や仮定を表現し、尤度はパラメータが観測されたデータをどれだけ説明できるかを定量化します。ベイズの定理はこれらの要素を組み合わせて、事前分布とデータの両方を考慮したパラメータに関する更新された信念を表す事後分布を生成します。

非常によく知られた2つの事前分布は、ラプラス事前分布とガウス事前分布です。

ラプラス事前分布は、重みwがラプラス分布(位置パラメータμ=0、スケールパラメータb)から抽出されるという仮定に基づいています。

言い換えれば、重みの分布はゼロを中心として指数的に減衰し、多くの重みがゼロに設定されるスパースなモデルを好みます。

ガウス事前分布は、重みwが平均μ=0、分散σのガウス(または正規)分布から抽出されるという仮定に基づいています。

本質的には、重みの分布はゼロを中心として対称的であり、ベル型のプロファイルを持ち、重みが平均値に近い値であることが最もありそうで、遠くに移動するにつれてより少ない確率で値を持つことを示しています。これにより、重みが滑らかに正則化されたモデルを好むことができ、重みが必ずしもゼロになるわけではありませんが、大きさが小さくなることが保証されます。

対数事後確率は次のようになります。

モデルを最適化することにより、対数事後確率を最大化することは、特定の正則化された損失を最小化することと基本的に同等です。

特筆すべきは、L1とL2の正則化の違いは、考慮される事前分布の形式に基づいています。

事後分布をMCMC法で使用する

ベイズのフレームワークでは、すべてが確率的に扱われます。したがって、クラシカルな線形回帰とは異なり、ベイズ線形回帰では可能な係数値の分布が推定されます。

事後分布を使用する方法の1つは、分布P(w|X,y)から一連の重みをサンプリングすることです。

これを行うための簡単な方法は、MCMC法を使用することであり、MCMC法を理解するための出発点はメトロポリス・ヘイスティング法です。

メトロポリス・ヘイスティング法

メトロポリス・ヘイスティング(M-H)アルゴリズムは、複雑な確率分布からサンプリングするためのベイズ統計の手法です。

このアルゴリズムは、ターゲット分布を探索するためのより単純な「提案分布」を使用し、計算された確率に基づいてサンプルを受け入れるか拒否するかを決定します。特に、M-Hアルゴリズムは正確なターゲット分布の知識を必要とせず、それに比例する分布を持っていることが十分です。

他の手法がより信頼性と効率性があるため、私たちはそれを使用しないでしょうが、M-Hアルゴリズムは基礎となるMCMC法であるため、その動作原理を簡単に説明します。

  • 初期の推定値を選択する
  • 提案分布を設定する。通常は、現在の値wを中心としたガウス分布です。

次に、各イテレーションでは以下のように進行します:

  • 提案分布P(w’|w)から新しいw’をサンプルする。
  • 受容確率を計算する。

  • 一様分布[0,1]上のランダムな数uを抽出する。u ≤ αの場合、w’を新しいサンプルとして受け入れる。そうでない場合、wを保持する。

NUTS サンプラーと pyMC3

メトロポリス・ヘイスティングス手法では、パラメータ空間で新しい点を提案し、その点の尤度と現在の点の尤度を比較して、新しい点を受け入れるかどうかを決定します。その効率は提案分布の選択に大きく依存し、高次元空間でのランダムウォークの振る舞いにより収束が遅くなる可能性があります。

NUTS(No-U-Turn Sampler)は、ハミルトニアン・モンテカルロ(HMC)法の一拡張です。ランダムウォークではなく、NUTSは対象分布からの勾配情報を利用してリープフロッグステップを提案し、効率的に分布を走査します。その主な利点の一つは、最適なリープフロッグステップの数を自動的に決定できることであり、ランダムウォークの問題や手動での調整の手間を回避できます。

PyMC3は人気のある確率的プログラミングフレームワークであり、これらの方法(およびその他)をシームレスに統合しています。これにより、ユーザーは基礎となるアルゴリズムの複雑さにこだわることなく、複雑なベイジアンモデルを簡単にフィットさせることができます。

このコードでは、事後分布P(w|X,y)から一連の重みをサンプリングします。

import pymc3 as pmwith pm.Model() as probit_model:        # 重みとバイアスの事前分布    weights = pm.Normal('weights', mu=0, sd=4, shape=X.shape[1])    bias = pm.Normal('bias', mu=0, sd=4)        # Probitリンク関数    mu = pm.math.dot(X, weights) + bias    phi = pm.math.invprobit(mu)  # 逆Probitリンク関数        # 尤度    y_obs = pm.Bernoulli('y_obs', p=phi, observed=y)        # 事後分布からサンプリング    trace = pm.sample(5000, tune=1000, chains=5, target_accept = 0.90)

各重みの異なる分布をプロットできます。

重みの分布と収束プロット(作成者による)

各重みがガウス分布に収束していることがわかります。したがって、各予測は確率的に行われ、予測の分布もガウス分布になります。

たとえば、架空の決定者のオレンジスムージー、オレンジ-アップルスムージー、バナナ-アップルスムージーへの好みは、以下のガウス分布で表されます。

データを生成したモデルを使用すると、3つのスムージーの真の効用はそれぞれ-0.66、-0.24、0.79であり、ガウス分布が好みとその間の差を非常によく反映しています。

結論

このブログ記事では、好みの引き出しの複雑さからベイズ線形回帰モデルの複雑さまでを探索しました。議論は、実際的で計算可能な手段である2加法モデルの探求から始まりました。基本的な線形回帰からより高度なプロビットモデルに移行することで、好みデータを理解する新たな視点を提供しました。

また、コストベースの視点と確率的な視点の同等性について深く掘り下げ、バイナリクロスエントロピー損失の最小化が尤度の最大化と類似していること、および正則化が事前分布の暗黙的な選択として機能することに光を当てました。

最後に、ベイズフレームワークの有用性について議論しました。このアプローチは、単なるポイント推定ではなく、予測分布全体を生成するために役立ちます。このアプローチにより、モデルに対する信頼性と解釈可能性が高まり、特に好みの学習という微妙なタスクにおいて非常に役立ちます。

この基礎が整ったことで、将来の研究は、これらの高度なモデルをますます複雑で大規模な好みのデータに適用することにより、さらに深く掘り下げることができます。

謝辞

この仕事に対する貢献について、私の同僚/友人であるアニサ・ハセネさんに特別な感謝の意を表します。また、TDSチームには迅速なレビューと洞察に富んだコメントをいただきました。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more