Select Language

AI Technology Community

Pythonを用いた機械学習アルゴリズムの実現――簡単なニューラルネットワーク

私たちは、2次元の入力ベクトルを2値出力値にマッピングする簡単なニューラルネットワークアーキテクチャを実装します。私たちのニューラルネットワークは、2つの入力ニューロン、6つの隠れニューロンを含む隠れ層、および1つの出力ニューロンを持っています。

私たちは、層間の重み行列を使ってニューラルネットワークの構造を表現します。以下の例では、入力層と隠れ層の間の重み行列はで表され、隠れ層と出力層の間の重み行列はです。ニューロンを接続する重みベクトルの他に、各隠れニューロンと出力ニューロンにはサイズ1のバイアス量があります。

私たちの訓練データセットはm = 750個のサンプルで構成されています。したがって、行列の次元は以下の通りです:

  • 訓練データセットの次元: X = (750, 2)

  • 目標の次元: Y = (750, 1)

  • の次元:(m, nhidden) = (2,6)

  • の次元:(バイアスベクトル):(1, nhidden) = (1,6)

  • の次元: (nhidden, noutput)= (6,1)

  • の次元:(バイアスベクトル):(1, noutput) = (1,1)



損失関数

私たちは、ロジスティック回帰アルゴリズムと同じ損失関数を使用します:

多クラス分類タスクでは、この関数の一般形を損失関数として使用し、分類交差エントロピー関数と呼びます。

訓練

私たちは、勾配降下法を使ってニューラルネットワークを訓練し、誤差逆伝播法を使って必要な偏微分を計算します。訓練プロセスには主に以下のステップがあります:

1. パラメータ(重みとバイアス)を初期化する

2. 収束するまで以下のプロセスを繰り返す:

  • 現在の入力のバッチサイズをネットワークに通し、すべての隠れユニットと出力ユニットの活性化値と出力値を計算する。

  • 各パラメータについて、損失関数に対する偏微分を計算する

  • パラメータを更新する

順伝播プロセス

まず、ネットワーク内の各ユニットの活性化値と出力値を計算します。このプロセスの実装を高速化するために、各入力サンプルに対して個別にこれを行うのではなく、すべてのサンプルを一度にベクトル化して処理します。ここで:

  • は、すべての訓練サンプルに対する隠れ層ユニットの活性化行列を表します

  • は、すべての訓練サンプルに対する隠れ層ユニットの出力行列を表します

隠れ層のニューロンは、活性化関数としてtanh関数を使用します:

出力層のニューロンは、活性化関数としてシグモイド関数を使用します:

活性化値と出力値は以下のように計算されます(·はドット積を表します):

誤差逆伝播プロセス

重みベクトルの更新値を計算するために、各ニューロンの損失関数に対する偏微分を計算する必要があります。ここではこれらの公式の導出は示さず、他のウェブサイトでより良い説明が見つかるでしょう(https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/)。

出力ニューロンについて、勾配は以下のように計算されます(行列記号):

入力層と隠れ層の重み行列について、勾配は以下のように計算されます:

重みの更新

In [3]:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split
np.random.seed(123)
% matplotlib inline


データセット


In [4]:

X, y = make_circles(n_samples=1000, factor=0.5, noise=.1)
fig = plt.figure(figsize=(8,6))plt.scatter(X[:,0], X[:,1], c=y)plt.xlim([-1.5, 1.5])
plt.ylim([-1.5, 1.5])
plt.title("データセット")
plt.xlabel("第1特徴量")
plt.ylabel("第2特徴量")
plt.show()


In [5]:

# 目標値を(n_samples, 1)の形状の列ベクトルに変形する
y_true = y[:, np.newaxis]
# データを訓練セットとテストセットに分割する
X_train, X_test, y_train, y_test = train_test_split(X, y_true)
print(f'X_trainの形状: {X_train.shape}')
print(f'y_trainの形状: {y_train.shape}')
print(f'X_testの形状: {X_test.shape}')
print(f'y_testの形状: {y_test.shape}')


X_trainの形状: (750, 2)

y_trainの形状: (750, 1)

X_testの形状: (250, 2)

y_testの形状: (250, 1)


ニューラルネットワーククラス

以下の実装は、吳恩達のコースによる恩恵を受けています

post
  • 1

    item of content