XORはなぜ一本の直線で分けられない? 隠れ層と非線形変換をPythonで試す
XORは、2つの入力が異なるときだけ1を返す判定です。その4点を学習させると、今回のパーセプトロンは2/4点、隠れ層8ユニットの多層ネットは4/4点で正解しました。
さらに、隠れ層の数を変えずに非線形変換を外すと、正解は2/4点に戻りました。学習した4点への予測を比べながら、層を重ねることと、途中で非線形に変換することの役割を確かめます。
XORの4点を一本の直線で分けてみる
XORは、2つの入力が異なるときに1、同じときに0を返す判定です。入力を座標にすると、[0, 0]と[1, 1]が0、[0, 1]と[1, 0]が1になり、同じ答えの2点が対角に並びます。
パーセプトロンは、入力に重みを掛けて足し、バイアスを加えた値がしきい値を超えるかどうかで判定します。入力が2つなら、計算は w1 × x1 + w2 × x2 + b。この判定の境界は一本の直線になります。
学習では、予測を間違えたときに重みを更新します。ただし、更新によって動かせるのは、この直線の位置や傾きです。
NumPyとscikit-learnを読み込んだ準備セルの後で、次のコードを実行します。4点をすべて学習に使い、その同じ4点への予測を確かめます。入力の順序と正解の並びにも注目してください。
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=float)
y = np.array([0, 1, 1, 0])
model = Perceptron(
max_iter=1000, tol=None, random_state=42, shuffle=False
)
model.fit(X, y)
print(model.predict(X))
この設定での出力は [0, 0, 0, 0] となり、正解は2/4点でした。これは random_state=42、shuffle=False などを指定した今回の出力です。パーセプトロンが必ずすべて0を返す、という意味ではありません。
4点の配置を見ると、直線の向きを変えても、対角の2点だけを片側へまとめられません。入力をこの2つの値のまま使い、一本の直線で判定する限り、XORの4点をすべて正しく分けることはできません。
たとえば「x1 + x2が0.5より大きければ1」という判定なら3/4点は当たりますが、[1, 1]を間違えます。今回の2/4点という出力と、直線では全点を分けられないという限界は、区別して読みます。
この限界は、学習回数を増やすだけでは解消しません。そこで、入力から判定までの間に、別の表現へ変換する層を加えます。
非線形変換を外すとどうなるか
隠れ層のユニット数を8のままにして、activation だけを tanh から identity に替えてみます。identity は、受け取った値をそのまま返す関数です。ほかのMLPの引数は同じにそろえ、最初から学習し直しました。
結果は次のとおりです。各配列の順序は、冒頭の入力4点と対応しています。
| モデル | 4点への予測 | 正解数 |
|---|---|---|
| パーセプトロン | [0, 0, 0, 0] | 2/4 |
| MLP・tanh | [0, 1, 1, 0] | 4/4 |
| MLP・identity | [1, 1, 0, 0] | 2/4 |
identity では、隠れ層があっても正解は2/4点でした。途中で行うのが重み付きの足し算だけなら、何段重ねても、一段の重み付きの足し算にまとめられます。そのため、この構成でも判定の境界は一本の直線になり、XORを分ける限界が残ります。
モデル内部の重みを学習するときは、出力の誤りを減らす方向を求めます。誤差逆伝播は、各重みに対する損失の勾配を計算する方法です。今回指定した lbfgs は、その勾配を使って重みを調整する準ニュートン法の一種です。
Pythonで同じ4点を確かめる
手元で試す場合は、ノートブックの「依存ライブラリ → 共通準備 → XOR → 結果を保存」の順に実行してください。Attentionのセルは飛ばせます。
ノートブックを使わない場合は、下のZIPを展開し、python -m pip install -r requirements.txt でライブラリを準備してから、python run-foundations.py --out foundation-results-local.json を実行すると、XORとAttentionの両方の結果を保存できます。APIキーや学習済みLLMは使いません。初回のライブラリ取得には通信が必要です。
記事の数値は2026年10月20日JSTにサーバーCPUで実行した結果です。環境はPython 3.11.2、NumPy 2.4.6、SciPy 1.16.2、scikit-learn 1.7.2。ColabやGPUで取得した記録ではありません。
設定を変えて試すときは、まず activation だけを変更し、4点それぞれの予測を比べてみてください。正解数だけでなく、どの入力への答えが変わったかを見ると、今回の比較を追いやすくなります。
計算と実装を確認した公式資料
- Perceptron — scikit-learn公式API
線形の分類器と、指定できる学習パラメーター。
- MLPClassifier — scikit-learn公式API
隠れ層、activation、lbfgsの設定。
- 多層パーセプトロン — scikit-learn公式ガイド
非線形変換と、勾配の計算・最適化の説明。
確認日:2026年10月20日。本文の数値は、教材用の入力と記載したライブラリの版で実行した結果です。現在の資料にある既定値や、未知データ・実モデルの性能を示すものではありません。