はじめに
因果推論の勉強をしようと思っていたのです(記事)が、本棚の空きがなく捨てる本を迷ってしまい、気分転換にシミュレーションの記事でも書こうと思います。
XとThreadsどちらが栄えるかを考えた記事も書いているように、SNSよく見ているので感じているのですが、意見の分断はよく見られ、罵り合いが始まります。そこで、良い議論とは何か考えまして、簡単なシミュレーションでも組もうと思います。
個人的には、意見は違っていても、互いの理解が進めばそれはいい議論ではないかと考えています。その観点から議論をモデル化し、意見が分断しても理解度が高まるかシミュレーションで検証を行ってみました。
まぁ、理解が進んだところで、ヘイトしてしまうと駄目なんですがね。
モデル化
-
意見を$i$の人の意見を$x_i$と表現
- $x_i \in [0,1]$
- 連続値の1次元意見軸
- 0と1は対立する立場を表す
-
発言を $s_i$と表現
- $x_i$の意見から、誤差を乗せた発言を$s_i$とする
-
$j$に対する$i$の意見の予測を $\hat{x}_{j,i}$ と表現
- 相手の意見を予測した意見となる
-
理解度を $u_{i,j}$ と表現
- 相手の意見をどれだけ正確に予測できているかを計算
- 発言$s_i$と予測 $\hat{x}_{i,j}$ から計算
- $u_{i,j} = \exp(-\gamma(s_i - \hat{x}_{i,j})^{2})$
- $u_{i,j} \in (0,1]$
- 予測が正確なほど理解度が高い
- $\gamma$は、理解の厳しさを表すパラメータ
-
議論の進め方
- 発言と意見の更新
- 発言
- $s_i = x_i + noise$
- 発言に誤差を表現による誤差をのせます
- 意見の予測更新
- $ \hat{x_{i,j}} \leftarrow \hat{x_{i,j}} + \alpha( s_i - \hat{x_{i,j}} )$
- 理解度$\alpha$により、意見の予測の精度を高めます
- 意見の更新
- 理解をしたからと言って賛成する訳ではなく、三パターンで表現
- 賛成
- 反対
- 意見を変えない
- $x_j \leftarrow x_j + \beta u_{i,j} r_j (s_i - x_j)$
- $r_j \in \{ +1,0,-1 \}$
- 理解度が高いほど意見が変わりやすい
- 反対タイプは理解したうえで逆に動く
- 理解をしたからと言って賛成する訳ではなく、三パターンで表現
- 発言
- 発言と意見の更新
モデルについてまとめ
- 意見と理解度を分離して表現して、議論のモデルを組み立てた
- 理解度は相手の意見の予測精度とした
- 意見が一致しない場合は、反対に意見が動くように設計した
モデル化できない部分
単純化されたモデルなので厳密ではありません。
- 意見は1次元
- 感情や立場の固定化は考慮していない
- 発言戦略は存在しない
ただし、意見と理解度を分離した最小限のモデルだと考えています。
シミュレーションと結果
$u_{i,j}$の対角線分を除いた平均値を理解度として、シミュレーション回数ごとにプロットしたものと、$x_i$のシミュレーション回数ごとの変化を示す事によって、意見の偏りと理解度を可視化したいと思います。
パラメータは以下です。
# -----------------------------
# パラメータ
# -----------------------------
N = 10 # エージェント数
T = 100 # 議論ステップ数
alpha = 0.4 # 理解学習率
beta = 0.3 # 意見更新率
gamma = 5.0 # 理解度の進み方(意見が予想とズレた時、小さいと理解度が下がりずらく、大きいと理解度が下がりやすい)
sigma = 0.1 # 表現ノイズ
agree_ratio = 0.4 # 賛成率
disagree_ratio = 0.6 # 反対率
# -----------------------------
# 初期化
# -----------------------------
x = np.random.rand(N) # 意見
u = np.zeros((N, N)) # 理解度
np.fill_diagonal(u, 1.0) # 自己理解=1
x_hat = np.random.rand(N,N) # i->jの相手意見の予測
10名中2名を除いていは、意見がはっきり分かれていますが、理解度は1に近い値をとる、パラメータが、ある事がわかりました。
これは、相手を理解しているが、意見は違う状態です。
理解度のパラメータ $\alpha$ が高く、表現ノイズ$sigma$が低ければ、だいたい理解度は上がるんですけどね。
まとめ
理解度と意見を考慮した、議論の簡単なモデル化を行い、意見が分断されても理解度は深まる事が自然に起こりえる事を示した。
おわりに
モデル化して検証してみましたが、至極当たり前の話しで、相手の話をちゃんと理解しましょうというお話でした。
表現ノイズを上げると理解度が下がったり、反対率を下げると意見が割れなくなったりするので、パラメータ変更していろいろ試してみてください。
続編も書いたのでよかったら読んでください。
「議論で意固地な人がいても理解が進むのか:議論モデルの続編」
プログラム
import numpy as np
import matplotlib.pyplot as plt
# -----------------------------
# パラメータ
# -----------------------------
N = 10 # エージェント数
T = 100 # 議論ステップ数
alpha = 0.4 # 理解学習率
beta = 0.3 # 意見更新率
gamma = 5.0 # 理解度の進み方(意見が予想とズレた時、小さいと理解度が下がりずらく、大きいと理解度が下がりやすい)
sigma = 0.1 # 表現ノイズ
agree_ratio = 0.4 # 賛成率
disagree_ratio = 0.6 # 反対率
understand_ratio = 1 - agree_ratio - disagree_ratio
np.random.seed(0)
# -----------------------------
# 初期化
# -----------------------------
x = np.random.rand(N) # 意見
u = np.zeros((N, N)) # 理解度
np.fill_diagonal(u, 1.0) # 自己理解=1
x_hat = np.random.rand(N,N) # i->jの相手意見の予測
x_history = np.zeros((T, N))
U_history = []
# -----------------------------
# シミュレーション
# -----------------------------
reactivity = np.random.choice([1.0, 0.0, -1.0], size=N, p=[agree_ratio, understand_ratio,disagree_ratio])
for t in range(T):
for _ in range(N): # ランダムなペアで議論
i, j = np.random.choice(N, 2, replace=False)
# i が発言
s = x[i] + np.random.normal(0, sigma)
# 相手モデル更新(理解)
x_hat[j, i] += alpha * (s - x_hat[j, i])
# j の予測(単純化:現在の意見)
pred = x_hat[j,i]
# 予測誤差
error = abs(s - pred)
# --- 理解更新 ---
# 理解度
u[j, i] = np.exp(-gamma * (s - pred)**2)
# 意見更新(反応タイプ)
x[j] += beta * u[j, i] * reactivity[j] * (s - x[j])
x = np.clip(x,0,1)
# 指標記録
x_history[t] = x
U_history.append(np.mean(u[np.eye(N) == 0]))
# -----------------------------
# 可視化
# -----------------------------
fig, ax = plt.subplots(1, 2, figsize=(10, 4))
ax[0].plot(U_history)
ax[0].set_title("Average Mutual Understanding")
ax[0].set_xlabel("Time")
ax[0].set_ylabel("U")
ax[0].set_ylim(0, 1.1)
for i in range(N):
ax[1].plot(x_history[:, i], lw=2)
ax[1].set_xlabel("Time")
ax[1].set_ylabel("Opinion x")
ax[1].set_title("Opinion Trajectories (Understanding-based Update)")
ax[1].set_ylim(-0.1, 1.1)
plt.tight_layout()
plt.show()
コードは GitHub に置いてあります:
https://github.com/YASUHARA-Wataru/tiny_simulations
