前回の記事では、ロジスティック回帰 について解説しました。ロジスティック回帰は、2クラス分類問題に非常に有効なアルゴリズムでしたが、画像認識や自然言語処理などの線形分離不可能な問題には限界があります。そこで今回は、ニューラルネットワークの基本概念から、実際にXOR問題を解くための方法を、Excelシートで説明します。また参考資料としてPythonによる解決方法のソースも載せてあります。
XOR問題を解く計算式が入った Excelファイルは、次のリンクからダウンロードできますので、記事を読みながらExcelシートを触って理解を深めてください。
📂 Excelファイルのダウンロードはこちら↓

- ニューラルネットワークの基本概念を説明しています。
- ニューラルネットワークの学習時の理論を数式で説明しています。
- Excelを使って、ニューラルネットワークの学習工程を確認できるようにしています。
ニューラルネットワークの構造図
今回の使うニューラルネットワークの基本構造を図に示します。
入力層(2ノード)、隠れ層(2ノード)、そして出力層(2ノード)からなるシンプルな構成を表しています。
※XOR問題を解だけなら1ノードで良いですが、ロジスティック回帰の記事で1ノードの出力を説明していますので、今回は出力層のノードは2つにしました。

本記事では、入力層 → 隠れ層 → 出力層 という構成のニューラルネットワークを前提に、最急降下法 (gradient descent) を用いて重みとバイアスの最適化を行う際の数式を示します。
パラメータには、重み wを8個と、バイアス bを4個使います。
入力層の説明変数はx1,x2です。
隠れ層の変数は y1, y2です。
出力層の目的変数はz1,z2です。
教師信号は t1,t2です。
損失関数としての誤差には Lを用います。
変数の丸マークの中の矢印(→)は、活性化関数による値の変換を表します。本記事では活性化関数にシグモイド関数を使用しますが、するとニューラルネットワークとは、ロジスティック回帰モデルを縦と横に沢山並べた構造になっている事がわかります。
そうです、ニューラルネットワークとは、ロジスティック回帰モデルの集合体と言っても過言ではありありません!
ニューラルネットワークの基本

ニューラルネットワークは、人間の脳の神経回路を模倣して設計されたモデルで、ニューロンという基本ユニットが多数組み合わさって構成されています。
ニューロンのモデル
各ニューロンは、以下の要素から成り立っています。
- 入力: 前の層からの出力または外部データ
- 重み: 各入力の重要度を表すパラメータ
- バイアス: ニューロンの出力を調整する定数項
- 活性化関数: 線形変換だけでは表現できない非線形性を付与するための関数(例:シグモイド、ReLU、tanhなど)
層の概念
ニューラルネットワークは、複数の層で構成されます。
- 入力層: 外部からデータを受け取る。
- 隠れ層(中間層): 入力層と出力層の間に位置し、データの特徴抽出や変換を担う。1層~数千層になる事もあり、この層が多いニューラルネットワークはディープラーニングと呼ばれる。
- 出力層: 最終的な予測結果を出力する。
損失関数 (Loss Function)
ここでは、二乗和誤差 (sum-of-squares error) を損失関数として採用します。
出力層の出力ベクトルを z=(z1,z2)、教師信号を t=(t1,t2) とすると、損失関数 Lは
\[L= 0.5\sum_{n}(z_n – t_n)^2 = 0.5\{(z_1 – t_1)^2 + (z_2 – t_2)^2\} \]
と定義されます。
※ ここで 0.5 をかけるのは、後の微分計算を簡略化するためです。
各層へのインプット(内部変数)
入力データは、入力層から隠れ層、そして出力層へと順に伝播(forward propagation)します。
1 隠れ層へのインプット
隠れ層の各ニューロンは、入力層の値 x1,x2x_1, x_2 と重みおよびバイアスによって次のように総入力(前活性化値)を計算します。
- 隠れ層ニューロン 1 の総入力
\[yi1= \sum_{i} w_{y1i}x_i + b_{y1} = w_{y11}x_1 + w_{y12}x_2 + b_{y1} \] - 隠れ層ニューロン 2 の総入力
\[y\text{i}_2=\sum_{i} w_{y2i}x_i + b_{y2} = w_{y21}x_1 + w_{y22}x_2 + b_{y2} \]
【補足】
ここでの\(w_{yij} \) は、入力層の \(x_i \)から隠れ層のニューロン \(y_j \) への重みを表し、\(b_{yj} \)は対応するバイアス項です。
隠れ層の各ニューロンは、総入力に対してシグモイド活性化関数を適用し、出力を計算します。
\[y_j = \sigma(y\text{i}_j) = \frac{1}{1+\exp(-y\text{i}_j)} \quad (j=1,2) \]
2 出力層へのインプット
出力層の各ニューロンは、隠れ層からの出力 y1,y2y_1, y_2 と重み・バイアスによって次のように計算されます。
- 出力層ニューロン 1 の総入力
\[ z\text{i}_1 = \sum_{j} w_{z1j}y_j + b_{z1} = w_{z11}y_1 + w_{z12}y_2 + b_{z1} \] - 出力層ニューロン 2 の総入力
\[ z\text{i}_2= \sum_{j} w_{z2j}y_j + b_{z2} = w_{z21}y_1 + w_{z22}y_2 + b_{z2} \]
出力層では、同様にシグモイド関数を適用して最終出力を求めます。
\[ z_k = \sigma(z\text{i}_k) = \frac{1}{1+\exp(-z\text{i}_k)} \quad (k=1,2) \]
【補足】
シグモイド関数は滑らかなS字型の関数で、出力が常に 0 と 1 の間に収まるため、確率として解釈しやすくなります。
また、その微分は次式で表されます:σ′(x)=σ(x)(1−σ(x))
出力層における誤差逆伝播の偏微分
1 出力層バイアスの偏微分
出力層ニューロン 1 について、バイアス\(b_{z1} \) に関する偏微分は以下の通りです。
\[\frac{\partial L}{\partial b_{z1}} = \frac{\partial L}{\partial z_1} \cdot \frac{\partial z_1}{\partial z\text{i}_1} \cdot \frac{\partial z\text{i}_1}{\partial b_{z1}} \]
ここで、
- \(\frac{\partial z\text{i}_1}{\partial b_{z1}} = 1\)
- \(\frac{\partial L}{\partial z_1} = z_1 – t_1\)
(二乗誤差の微分) - \(\frac{\partial z_1}{\partial z\text{i}_1} = z_1(1-z_1)\)
(シグモイド関数の微分)
よって、 \(\frac{\partial L}{\partial b_{z1}} = (z_1 – t_1)\, z_1(1-z_1) \)
同様に、出力層ニューロン 2 では、 \(\frac{\partial L}{\partial b_{z2}} = (z_2 – t_2)\, z_2(1-z_2) \)
2 出力層重みの偏微分
- \(w_{z11} \) に関して
\(\frac{\partial L}{\partial w_{z11}} = \frac{\partial L}{\partial b_{z1}} \cdot \frac{\partial z\text{i}_1}{\partial w_{z11}} = \frac{\partial L}{\partial b_{z1}} \cdot y_1 \) - \(w_{z12}\) に関して
\(\frac{\partial L}{\partial w_{z12}} = \frac{\partial L}{\partial b_{z1}} \cdot y_2\) - \(w_{z21}\) に関して
\(\frac{\partial L}{\partial w_{z21}} = \frac{\partial L}{\partial b_{z2}} \cdot y_1\) - \(w_{z22}\) に関して
\(\frac{\partial L}{\partial w_{z22}} = \frac{\partial L}{\partial b_{z2}} \cdot y_2 \)
【補足】
ここでは、出力層での各パラメータ更新が、出力層のバイアスに関する偏微分の結果に隠れ層の出力 y を掛け合わせた形で表される点に注目してください。
隠れ層における誤差逆伝播の偏微分
1 隠れ層出力の偏微分
隠れ層ニューロン 1 に対して、出力層からの誤差が伝播される場合、隠れ層出力 \(y_1\) の偏微分は
\(\frac{\partial L}{\partial y_1} = \frac{\partial L}{\partial z_1} \cdot \frac{\partial z_1}{\partial z\text{i}_1} \cdot \frac{\partial z\text{i}_1}{\partial y_1} + \frac{\partial L}{\partial z_2} \cdot \frac{\partial z_2}{\partial z\text{i}_2} \cdot \frac{\partial z\text{i}_2}{\partial y_1} \)
すなわち、
\(\frac{\partial L}{\partial y_1} = \frac{\partial L}{\partial b_{z1}} \cdot w_{z11} + \frac{\partial L}{\partial b_{z2}} \cdot w_{z21} \)
隠れ層ニューロン 2 については、
\(\frac{\partial L}{\partial y_2} = \frac{\partial L}{\partial b_{z1}} \cdot w_{z12} + \frac{\partial L}{\partial b_{z2}} \cdot w_{z22} \)
2 隠れ層バイアスの偏微分
隠れ層ニューロン 1 のバイアス \(b_{y1} \)については、
\(\frac{\partial L}{\partial b_{y1}} = \frac{\partial L}{\partial y_1} \cdot \frac{\partial y_1}{\partial y\text{i}_1} \cdot \frac{\partial y\text{i}_1}{\partial b_{y1}} \)
ここで、
- \(\frac{\partial y\text{i}_1}{\partial b_{y1}} = 1 \)
- \(\frac{\partial y_1}{\partial y\text{i}_1} = y_1(1-y_1) \)
よって、
\( \frac{\partial L}{\partial b_{y1}} = \frac{\partial L}{\partial y_1} \, y_1(1-y_1) \)
隠れ層ニューロン 2 も同様に、
\(\frac{\partial L}{\partial b_{y2}} = \frac{\partial L}{\partial y_2} \, y_2(1-y_2) \)
3 隠れ層重みの偏微分
- \(w_{y11} \) に関して
\(\frac{\partial L}{\partial w_{y11}} = \frac{\partial L}{\partial y_1} \cdot \frac{\partial y_1}{\partial y\text{i}_1} \cdot \frac{\partial y\text{i}_1}{\partial w_{y11}} = \frac{\partial L}{\partial b_{y1}} \cdot x_1 \) - \(w_{y12} \)に関して
\(\frac{\partial L}{\partial w_{y12}} = \frac{\partial L}{\partial b_{y1}} \cdot x_2 \) - \(w_{y21} \)に関して
\(\frac{\partial L}{\partial w_{y21}} = \frac{\partial L}{\partial b_{y2}} \cdot x_1 \) - \(w_{y22} \) に関して
\(\frac{\partial L}{\partial w_{y22}} = \frac{\partial L}{\partial b_{y2}} \cdot x_2 \)
【補足】
隠れ層では、出力層から伝播された誤差に対して、シグモイド関数の微分 \(y_j(1-y_j) \)を掛けた結果が、各バイアスや重みの更新に寄与します。
学習フェーズと検証フェーズ
- 学習フェーズ:
入力 x と教師信号 t を用い、上記の偏微分に基づいて重み w とバイアス b の最適値を最急降下法で求めるプロセスです。具体的には、各パラメータ p(重みやバイアス)を \(p \leftarrow p – \eta \frac{\partial L}{\partial p} \)のように更新します。ここで、η は学習率です。 - 検証フェーズ:
学習済みのパラメータ w, b を用いて、入力 xから出力 zを計算し、モデルの性能を評価します。
ExcelでXOR問題を解くニューラルネットワークの実装
排他的論理和(XOR)の問題は、直線的な分離が不可能なため、単一層のロジスティック回帰では解けません。
しかし、隠れ層を持つニューラルネットワークなら、非線形な境界を学習してXOR問題に対応可能です。
ここではExcelシートで排他的論理和(XOR)を題材にして、ニューラルネットワークの動きを見てましょう。
XOR問題の定義
XORは、2つの入力に対して以下のように定義されます:
\[ XOR(x_1, x_2) = \begin{cases} 0 & \text{if } x_1 = x_2, \\ 1 & \text{if } x_1 \neq x_2. \end{cases}
\]
今回はこのXORをExcel上のニューラルネットワークに学習させてみます。
Excelシートイメージ
Excelシートの左側にXORの訓練データを貼り付け、その右側に上で計算した式を入れていきます。具体的な計算式は、本記事の上部に掲載していますExcelシートをダウンロードして、セル内の関数を確認してください。


- 入力値教師値データをExcelのシートに入力
- X1・X2列: 排他的論理和の入力値
- T1・T2列: 排他的論理和の出力値
- 推論値の計算
- W・X列で 排他的論理和の結果を算算。
- 損失関数の計算
- Y列で損失関数Lを、その右で平均値を計算。収束の度合いを見る為の列。
- 反復処理
- 各行でパラメータWとBの更新を繰り返す。
- この更新が収束したかどうかは、損失関数Lを平均したL平均の列の収束度合いを見て判断する。
Excelシートの反復は数千行にもなります。下に行くに従い、損失関数の平均を表す「L平均」の値が小さくなっている、つまり学習が進んでいるのがわかります。
参考:PythonでXOR問題を解くニューラルネットワークの実装
以下は、Pythonのsklearnライブラリを用いて、XOR問題を解くシンプルなニューラルネットワークの実装例です。
import numpy as np
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score
# XOR データセットの定義
X = np.array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
y = np.array([0, 1, 1, 0])
# MLPClassifier の初期化
# hidden_layer_sizes=(2,) で隠れ層に 2 個のニューロンを指定
# activation='logistic' でシグモイド関数を利用
# solver='lbfgs' を使用、alpha と tol を調整してより精度の高い学習を実現
mlp = MLPClassifier(hidden_layer_sizes=(2,),
activation='logistic',
solver='lbfgs',
alpha=1e-6, # 正則化項を非常に小さくする
tol=1e-8, # 許容誤差を小さく設定
max_iter=1000,
random_state=2)
# モデルの学習
mlp.fit(X, y)
# 学習済みモデルで予測
y_pred = mlp.predict(X)
# 結果の表示
print("Predictions:", y_pred)
print("Accuracy:", accuracy_score(y, y_pred))
このコード例では、隠れ層を追加することでXORの非線形な関係を学習させ、下の実行結果のように、最終的な出力が正しく分類されることを確認できます。
Predictions: [0 1 1 0]
Accuracy: 1.0
まとめ
- ロジスティック回帰からの進化: 単一層のモデルでは解けなかった非線形問題(例:XOR)に対して、隠れ層を持つニューラルネットワークは柔軟な解法を提供します。
- 基本的な構造: ニューロン、層、活性化関数の組み合わせにより、複雑なパターンを表現可能です。
- 順伝播と誤差逆伝播: 入力から出力への計算(順伝播)と、誤差を各層に逆向きに伝える(逆伝播)仕組みが、学習の鍵となります。
- 実装例: Pythonとsklearnを用いた具体的な例を通して、理論と実装の両面からニューラルネットワークの理解を深められます。
ニューラルネットワークは、単純なロジスティック回帰を超え、画像認識や自然言語処理など、さまざまな分野で応用されていますので、ニューラルネットワークの基本の仕組みは、このサイトで押さえておきましょう。