このシリーズではE資格対策として、シラバスの内容を項目別にまとめています。
全結合型ニューラルネットワーク
全結合型ニューラルネットワークの概要
全結合型ニューラルネットワーク(Fully Connected Neural Network、FCNN)は、ニューラルネットワークの最も基本的な形です。その名前が示す通り、全てのニューロン(人工ニューロン)が前の層の全てのニューロンと接続されています。
全結合型ニューラルネットワークは以下の要素で構成されています:
- 入力層(Input Layer): この層はネットワークにデータを供給します。一般的には、ネットワークへの入力は数値データ(例えば、画像のピクセル強度やテキストデータのバイナリ表現など)であり、それぞれのデータポイントは一つのニューロンに対応します。
- 隠れ層(Hidden Layers): これらの層はネットワークの内部で情報を処理します。一つ以上の隠れ層を持つことで、ニューラルネットワークは非線形な関数を学習し、より複雑なパターンを捉えることができます。
- 出力層(Output Layer): この層はネットワークの最終的な出力を生成します。出力層のニューロン数と活性化関数は、解きたい問題によって異なります。例えば、二値分類問題では1つのニューロンとシグモイド活性化関数を使用しますが、多クラス分類問題ではクラスの数だけニューロンとソフトマックス活性化関数を使用します。
全結合型ニューラルネットワークの訓練は、一般的には勾配降下法と呼ばれる最適化手法を用いて行われます。最も一般的な形は確率的勾配降下法(SGD)ですが、他にもAdam、RMSpropなどの最適化手法があります。また、訓練の過程で過学習を防ぐために正則化手法(例えば、ドロップアウト)も使用されることがあります。
全結合型ニューラルネットワークは非常に汎用性が高く、さまざまな種類のデータと問題に対して適用することができます。しかし、パラメータの数が多いため、訓練データが少ない場合や、計算資源が限られている場合には、適切な訓練が困難になることもあります。また、画像や音声などの構造化されたデータに対しては、全結合型よりも畳み込みニューラルネットワーク(CNN)や再帰型ニューラルネットワーク(RNN)の方が効果的であることが多いです。
全結合型ニューラルネットワークの実装
中間層が1つの単純なニューラルネットワークを定義し、その後で訓練と実行を行うものです。
最初に、シグモイド関数とReLU関数、そしてReLUの導関数が定義されています。シグモイド関数は活性化関数の1つで、出力を0から1の間に制約するために使用されます。ReLU(Rectified Linear Unit)も活性化関数の1つで、負の値を0に、それ以外の値をそのまま出力します。これらの活性化関数は、ニューラルネットワーク内の各ノード(ニューロン)の出力を計算するのに使用されます。
次に、NeuralNetwork
という名前のクラスが定義されています。このクラスのインスタンスは、一つの隠れ層を持つニューラルネットワークを表します。各層はノード(ニューロン)の集合で、これらのノードはそれぞれ重みを持つ接続で結合されています。
import numpy as np
# 活性化関数とその導関数
def sigmoid(x):
return 1 / (1 + np.exp(-x)) # シグモイド関数:xの値を0と1の間にマッピングする関数
def relu(x):
return np.maximum(0, x) # ReLU(Rectified Linear Unit)関数:負の値を0に、正の値はそのまま出力する関数
def relu_derivative(x):
x[x<=0] = 0 # 入力値が0以下のとき、導関数の値は0
x[x>0] = 1 # 入力値が正のとき、導関数の値は1
return x # ReLU関数の導関数を返す
# ニューラルネットワーク
class NeuralNetwork:
def __init__(self, input_nodes, hidden_nodes, output_nodes):
self.input_nodes = input_nodes # 入力層のノード数
self.hidden_nodes = hidden_nodes # 隠れ層のノード数
self.output_nodes = output_nodes # 出力層のノード数
# 重みを正規分布に従って初期化
self.weights_input_to_hidden = np.random.normal(0.0, self.input_nodes**-0.5,
(self.input_nodes, self.hidden_nodes))
self.weights_hidden_to_output = np.random.normal(0.0, self.hidden_nodes**-0.5,
(self.hidden_nodes, self.output_nodes))
self.lr = 0.1 # 学習率
def forward_pass(self, X):
# 隠れ層への入力信号を計算
self.hidden_inputs = np.dot(X, self.weights_input_to_hidden)
# 隠れ層から出る信号を計算
self.hidden_outputs = relu(self.hidden_inputs)
# 最終出力層への入力信号を計算
self.final_inputs = np.dot(self.hidden_outputs, self.weights_hidden_to_output)
# 最終出力層から出る信号を計算
self.final_outputs = sigmoid(self.final_inputs)
return self.final_outputs # 最終出力を返す
def backward_pass(self, X, y, output):
# 出力層の誤差は、目標値と実際の出力との差
self.output_errors = y - output
self.output_grad = self.output_errors * output * (1 - output) # シグモイド関数の導関数を用いて勾配を計算
# 隠れ層に伝播した誤差
self.hidden_errors = np.dot(self.output_grad, self.weights_hidden_to_output.T)
# 隠れ層の勾配
self.hidden_grad = self.hidden_errors * relu_derivative(self.hidden_outputs)
# 重みを更新
self.weights_hidden_to_output += self.lr * np.dot(self.hidden_outputs.T, self.output_grad)
self.weights_input_to_hidden += self.lr * np.dot(X.T, self.hidden_grad)
def train(self, X, y):
output = self.forward_pass(X) # 順伝播を行い、出力を得る
self.backward_pass(X, y, output) # 逆伝播を行い、重みを更新する
def run(self, X):
return self.forward_pass(X) # ニューラルネットワークの出力を返す
# ニューラルネットワークの初期化
input_nodes = 3
hidden_nodes = 5
output_nodes = 1
nn = NeuralNetwork(input_nodes, hidden_nodes, output_nodes) # ニューラルネットワークのインスタンスを作成
# サンプルデータ
X = np.array([[0.5, 0.6, 0.1],
[0.2, 0.1, 0.7],
[0.9, 0.4, 0.8]])
y = np.array([[0.75], [0.82], [0.93]])
# ニューラルネットワークの訓練
for _ in range(1000): # 1000回のエポックで訓練
nn.train(X, y)
# ニューラルネットワークの実行
output = nn.run(X) # 訓練後のニューラルネットワークで新たに出力を生成
output # 出力を表示
実行結果:
array([[0.752185 ],
[0.81689645],
[0.92963282]])
まとめ
最後までご覧いただきありがとうございました。