このシリーズではE資格対策として、シラバスの内容を項目別にまとめています。

E資格まとめ

試験概要 ディープラーニングの理論を理解し、適切な手法を選択して実装する能力や知識を有しているかを認定する。 1.応用数学 (1)確率・統計 (2)情報理論 2.機…

全結合型ニューラルネットワーク

全結合型ニューラルネットワークの概要

全結合型ニューラルネットワーク(Fully Connected Neural Network、FCNN)は、ニューラルネットワークの最も基本的な形です。その名前が示す通り、全てのニューロン(人工ニューロン)が前の層の全てのニューロンと接続されています。

全結合型ニューラルネットワークは以下の要素で構成されています:

  1. 入力層(Input Layer): この層はネットワークにデータを供給します。一般的には、ネットワークへの入力は数値データ(例えば、画像のピクセル強度やテキストデータのバイナリ表現など)であり、それぞれのデータポイントは一つのニューロンに対応します。
  2. 隠れ層(Hidden Layers): これらの層はネットワークの内部で情報を処理します。一つ以上の隠れ層を持つことで、ニューラルネットワークは非線形な関数を学習し、より複雑なパターンを捉えることができます。
  3. 出力層(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]])

まとめ

最後までご覧いただきありがとうございました。