【ディープラーニング入門:Pythonをベースにした理論と実装】

パーセプトロン

パーセプトロンは複数の入力信号を受信し、信号を出力します。パーセプトロンの信号には、「フロー/フローなし」(1/0) の 2 つの値しかありません。本書では、0 は「信号なし」に対応し、1 は「信号あり」に対応します。図 2-1 は、2 つの入力信号を受信するパーセプトロンの例です。x1、x2 は入力信号、y は出力信号、w1、w2 は重み (w は重みの最初の文字) です。図中の○は「ニューロン」または「ノード」と呼ばれます。入力信号がニューロンに送信されると、それぞれ固定の重み (w1x1、w2x2) が乗算されます。ニューロンは送信された信号の合計を計算し、合計が特定の制限を超えた場合にのみ 1 を出力します。これは「ニューロンが活性化される」とも呼ばれます。この限界はここでは閾値と呼ばれ、記号 θ で表されます。
図 2-1 2 つの入力を持つパーセプトロン
上記の内容を数学的に表現すると式 (2.1) になります。
画像の説明を追加してください
式 (2.1) の θ を −b に置き換えると、式 (2.2) を使用してパーセプトロンの動作を表現できます。
画像の説明を追加してください

ここで −θ をバイアス b と名付けますが、バイアスは重み w1 や w2 とは異なる関数を持つことに注意してください。具体的には、w1、w2は入力信号の重要度を制御するパラメータであり、重みが大きいほど、その重みに対応する信号の重要度が高くなります。バイアスとは、ニューロンの活性化のしやすさ(出力信号が1になる程度)を調整するパラメータです。

複数の層が重ねられたパーセプトロンは多層パーセプトロンとも呼ばれます。
「単層のパーセプトロンでは表現できないことは、別の層を追加することで解決できます。」つまり、レイヤーを重ねる(レイヤーを深くする)ことで、より柔軟にパーセプトロンを表現できるようになります。

ニューラルネットワーク

パーセプトロンの欠点は、ニューラル ネットワークがデータから適切な重みパラメータを自動的に学習できるのに対し、予想される入出力を満たす適切な重みを決定するには手動設定が必要であることです。

パーセプトロンからニューラルネットワークへ

ニューラルネットワークの例

図 3-1 ニューラルネットワークの例

この本は次のように同意しています。

  1. 図 3-1 では、レイヤ 0 が入力層、レイヤ 1 が中間層、レイヤ 2 が出力層に対応し、
    図 3-1 のネットワークは 3 層のニューロンで構成されていますが、実際には 1 つのニューロンだけで構成されています。 2 層のニューロンに重みがあるため、「2 層ネットワーク」と呼ばれます。書籍によっては、図 3-1 のネットワークを、ネットワークを構成する層の数に基づいて 3 層ネットワークと呼ぶ場合もあります。本書では、ネットワークの名前を
    実際に重みを持つ層の数(入力層、隠れ層、出力層の数から1を引いた数)に従って表現します。

パーセプトロンを確認する

図 3-2 パーセプトロンの確認
図 3-2 のパーセプトロンは 3 つの入力信号 x1、x2、および 1 を受信し、y を出力します。b はニューロンの活性化のしやすさを制御するバイアスと呼ばれるパラメータ、w1 と w2 は各信号の重要性を制御するために各信号の重みを表すパラメータです。数式で表すと式 (3.1) のようになります。
ここに画像の説明を挿入します
図 3-2 は 3 つの信号 x1、x2、1 をニューロンへの入力として使用し、それぞれの重みを乗算した後、次のニューロンに送信します。 。次のニューロンでは、これらの重み付けされた信号の合計が計算されます。合計が 0 を超えた場合は 1 を出力し、それ以外の場合は 0 を出力します。この状況の動作を関数を使用して表現し、新しい関数 h(x) を導入し、式 (3.1) を次の式 (3.2) と式 ( 3.3)。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

アクティベーション機能が登場

ここで紹介した h(x) 関数は、入力信号の和を出力信号に変換する関数で、一般に活性化関数と呼ばれ、入力信号の和をどのように活性化するかを決定するために使用されます。
式 (3.2) をさらに詳しく書くと、次の 2 つの式に分けられます。
ここに画像の説明を挿入します
式 (3.4) と式 (3.5) を図でわかりやすく表現したい場合は、図 3-4 のようにすればよいでしょう。
図 3-4 は、活性化関数の計算プロセスを明確に示しています。
図 3-4 に示すように、活性化関数の計算プロセスは、ニューロンを表す○で明確に示されています。つまり、信号の加重和がニューロン a であり、ニューロン a は活性化関数によってニューロン y に変換されます。 h()

活性化関数は、パーセプトロンとニューラル ネットワーク間のブリッジです。本書で「パーセプトロン」という用語が使用されている場合、それが参照するアルゴリズムが厳密に統一されているわけではありません。一般に、「ナイーブ パーセプトロン」とは単層ネットワークを指し、活性化関数がステップ関数 A を使用するモデルを指します。「多層パーセプトロン」とは、ニューラルネットワーク、すなわちシグモイド関数(後述)などの平滑活性化関数を用いた多層ネットワークを指す。

活性化関数

式 (3.3) で表される活性化関数には閾値があり、入力が閾値を超えると出力が切り替わります。このような関数を「ステップ関数」と呼びます。したがって、パーセプトロンではステップ関数が活性化関数として利用されていると言えます。活性化関数をステップ関数から別の関数に変更すると、ニューラル ネットワークの世界に入ることができます。次に、ニューラルネットワークで使用される活性化関数を紹介します。

シグモイド関数

ニューラル ネットワークでよく使用される活性化関数は、式 (3.6) で表されるシグモイド関数です。
ここに画像の説明を挿入します

ステップ関数の実装

ステップ関数は式(3.3)で示され、入力が0を超える場合は1を出力し、それ以外の場合は0を出力します。ステップ関数は以下のように簡単に実装できます。

def step_function(x):
 if x > 0:
 return 1
 else:
 return 0

上記の実装では、パラメーター x は実数 (浮動小数点数) のみを受け入れることができ、パラメーターを NumPy 配列にすることはできません。その後の操作を容易にするために、NumPy 配列の実装をサポートするように修正し、最初に NumPy 配列 x を用意し、この NumPy 配列に対して不等号演算を実行しました。

>>> import numpy as np
>>> x = np.array([-1.0, 1.0, 2.0])
>>> x
array([-1., 1., 2.])
>>> y = x > 0
>>> y
array([False, True, True], dtype=bool)

NumPy 配列に対して不等号演算が実行された後、配列の各要素に不等号演算が適用されてブール配列が生成されます。ここでは、配列 x の 0 より大きい要素は True に変換され、0 以下の要素は False に変換され、新しい配列 y が生成されます。
配列 y はブール配列ですが、必要なステップ関数は 0 または 1 の int 型を出力する関数です。したがって、配列 y の要素の型を boolean から int に変換する必要があります。

>>> y = y.astype(np.int)
>>> y
array([0, 1, 1])

上に示したように、astype() メソッドを使用して NumPy 配列の型を変換できます。astype() メソッドは、パラメーターを通じて目的の型を指定します。この例では、np.int です。PythonでBoolean型をint型に変換すると、Trueは1、Falseは0に変換されます

シグモイド関数の実装

def sigmoid(x):
 return 1 / (1 + np.exp(-x))

パラメータ x が NumPy 配列の場合も、NumPy のブロードキャスト機能により、結果が正しく計算されます。

シグモイド関数とステップ関数の比較

図 3-8 ステップ関数とシグモイド関数(点線はステップ関数)
同じ点:

  1. 似たような形をしています。実はどちらも「入力が小さいと出力は0に近くなる(0になる)、入力が大きくなると出力は1に近づく(1になる)」という構造になっています。つまり、入力信号が重要な情報である場合には、ステップ関数とシグモイド関数の両方がより大きな値を出力し、入力信号が重要でない情報である場合には、両方ともより小さな値を出力する。
  2. 入力信号がどれほど小さくても大きくても、出力信号の値は 0 から 1 の間になります。
  3. どちらも非線形関数です。

ニューラル ネットワークの活性化関数は非線形関数を使用する必要があります。一次関数を使うとニューラルネットワークの層数を深くしても意味がないからです。線形関数の問題は、層がどれほど深くても、常に同等の「隠れ層のないニューラル ネットワーク」が存在することです。

違い:

  1. 「滑らかさ」の違い。シグモイド関数は滑らかな曲線であり、入力に応じて出力が連続的に変化します。ステップ関数は 0 で制限され、出力は大幅に変化します。
  2. 0 または 1 しか返せないステップ関数と比較して、シグモイド関数は 0.731...、0.880... などの実数を返すことができます (これは、先ほど述べた滑らかさに関係します)。つまり、パーセプトロンではニューロン間を流れるのは0か1の2値信号ですが、ニューラルネットワークでは連続した実数値の信号となります。

ReLU関数

ニューラルネットワークの開発の歴史の中で、シグモイド関数は非常に早くから使われており、最近ではReLU(Rectified Linear Unit)関数が主に使われています。ReLU 関数は、入力が 0 より大きい場合は値を直接出力し、入力が 0 以下の場合は
0 を出力します (図 3-9)。ReLU関数は以下の式(3.7)で表すことができる。
ここに画像の説明を挿入します
図 3-9 ReLU 関数
ReLU関数の実装:

def relu(x):
 return np.maximum(0, x)

3層ニューラルネットワークの実装

記号の確認

図 3-16 重量の記号
重みと隠れ層ニューロンの右上隅には「(1)」があり、これは重みとニューロンの層番号 (つまり、層 1 の重み、層 1 のニューロン) を示します。さらに、重みの右下隅に 2 つの数字があります。これらは、次の層のニューロンと前の層のニューロンのインデックス番号です。

コード

# 保存每一层所需的参数(权重和偏置)
def init_network():
 network = {
    
    }
 network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
 network['b1'] = np.array([0.1, 0.2, 0.3])
 network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
 network['b2'] = np.array([0.1, 0.2])
 network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
network['b3'] = np.array([0.1, 0.2])
 return network
def forward(network, x):
 W1, W2, W3 = network['W1'], network['W2'], network['W3']
 b1, b2, b3 = network['b1'], network['b2'], network['b3']
 a1 = np.dot(x, W1) + b1
 z1 = sigmoid(a1)
 a2 = np.dot(z1, W2) + b2
 z2 = sigmoid(a2)
 a3 = np.dot(z2, W3) + b3
 y = identity_function(a3)
 return y
network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y) # [ 0.31682708 0.69627909]

出力層の設計

ニューラルネットワークは分類問題や回帰問題に利用できますが、出力層の活性化関数は状況に応じて変更する必要があります。一般に、恒等関数は回帰問題に使用され、ソフトマックス関数は分類問題に使用されます。

機械学習の問題は大きく分類問題と回帰問題に分けられます。分類問題は、データがどのカテゴリに属する​​かという問題です。たとえば、画像内の人物が男性か女性かを区別する問題は分類問題です。回帰問題は、何らかの入力に基づいて (連続的な) 数値を予測する問題です。例えば、画像に基づいて人の体重を予測する問題は回帰問題です(「57.4kg」のような予測)

恒等関数とソフトマックス関数

恒等関数は入力をそのまま出力し、入力された情報をそのまま出力します。分類問題で使用されるソフトマックス関数は次の式(3.10)で表すことができ、その出力はソフトマックス関数を実現するための
「確率」として理解できます。
ここに画像の説明を挿入します

>>> a = np.array([0.3, 2.9, 4.0])
>>>
>>> exp_a = np.exp(a) # 指数函数
>>> print(exp_a)
[ 1.34985881 18.17414537 54.59815003]
>>>
>>> sum_exp_a = np.sum(exp_a) # 指数函数的和
>>> print(sum_exp_a)
74.1221542102
>>>
>>> y = exp_a / sum_exp_a
>>> print(y)
[ 0.01821127 0.24519181 0.73659691]

上記の実装は方程式 (3.10) を正確に記述していますが、コンピュータの動作中にオーバーフローの問題が発生する可能性があります。ソフトマックス関数の実装には指数関数の計算が必要ですが、このとき指数関数の値が非常に大きくなりやすいです。たとえば、e10 の値は 20,000 を超え、e100 は 40 個を超えるゼロが続く非常に大きな値になり、e1000 の結果は無限大を示す inf を返します。これらの非常に大きな値の間で除算すると、結果は「不定」になります。これに基づいて、次の改良を行います。
ここに画像の説明を挿入します
まず、式 (3.11) の分子と分母の両方に、任意の定数 C を掛けます。次に、この C を指数関数 (exp) に移動し、log C として記録します。最後に、ログ C を別のシンボル C' に置き換えます。式 (3.11) は、ソフトマックス指数関数の計算を実行するときに、特定の定数を加算 (または減算) しても計算結果が変化しないことを示しています。ここでの C' は任意の値を使用できますが、オーバーフローを防ぐため、通常は入力信号内の最大値が使用されます。要約すると、softmax 関数は次のように実装できます。

def softmax(a):
 c = np.max(a)
 exp_a = np.exp(a - c) # 溢出对策
 sum_exp_a = np.sum(exp_a)
 y = exp_a / sum_exp_a
 return y

一般に、ニューラル ネットワークでは、出力値が最大のニューロンに対応するカテゴリのみが認識結果として使用されます。また、ソフトマックス関数を使用しても、出力値が最も大きいニューロンの位置は変わりません。したがって、ニューラルネットワークが分類を行う場合、出力層のソフトマックス関数を省略することができる。実際の問題では、指数関数の演算にはある程度のコンピュータ演算が必要となるため、出力層のソフトマックス関数は省略されるのが一般的です。

機械学習の問題を解く手順は「学習」と「推論」の2段階に分けられます。まず、学習フェーズでモデルが学習 B され、次に推論フェーズで、学習されたモデルを使用して未知のデータが推論 (分類) されます。前述したように、出力層のソフトマックス関数は通常、推論段階では省略されます。ソフトマックス関数はニューラル ネットワークの学習に関連するため、出力層で使用されます。

出力層のニューロンの数

分類問題の場合、出力層のニューロンの数は通常、カテゴリの数に設定されます。

手書き数字認識

機械学習の問題を解く手順(学習と推論の2段階に分かれる)と同様に、ニューラルネットワークを使って問題を解く場合も、まず訓練データ(学習データ)を使って重みパラメータを学習し、推論を行う際には、学習データ(学習データ)を使用する必要があります。学習したばかりのパラメータ、入力データの分類、および推論プロセスはニューラル ネットワークの順伝播とも呼ばれます

MNIST データセット

MNIST データセットを使用する一般的な方法は、最初にトレーニング画像を使用して学習し、次に学習したモデルを使用してテスト画像がどの程度正しく分類できるかを測定することです。MNIST の画像データは 28 ピクセル × 28 ピクセルのグレースケール画像 (1 チャンネル) であり、
各ピクセルの値は 0 ~ 255 です。各画像データには、「7」、「2」、「1」などのラベルが付けられています。
本書では、 mnist.py のload_mnist()関数を使用して、MNISTデータセットのダウンロードからNumPy配列への変換までの処理をサポートする便利なPythonスクリプト mnist.py (mnist.pyはデータセットディレクトリにあります)を提供しています。次のようにして MNIST データを簡単に読み込むことができます。

import sys, os
sys.path.append(os.pardir) # 为了导入父目录中的文件而进行的设定
from dataset.mnist import load_mnist
# 第一次调用会花费几分钟 ……
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True,
normalize=False)
# 输出各个数据的形状
print(x_train.shape) # (60000, 784)
print(t_train.shape) # (60000,)
print(x_test.shape) # (10000, 784)
print(t_test.shape) # (10000,)

上記のコードは mnist_show.py ファイルにあります。mnist_show.py ファイルの現在のディレクトリは ch03 ですが、load_mnist() 関数を含む mnist.py ファイルはデータセット ディレクトリにあります。したがって、mnist_show.py ファイルは、ディレクトリを越えて mnist.py ファイルを直接インポートできません。sys.path.append(os.pardir) ステートメントは、実際に親ディレクトリ deep-learning-from-scratch を sys.path (Python の検索モジュールのパス セット) に追加し、deep-learning-from-scratch をインポートできるようにします。 load_mnist 関数下の任意のディレクトリ (データセット ディレクトリを含む) にあるファイルは、
読み取られた MNIST データを「(トレーニング画像、トレーニング ラベル)、(テスト画像、テスト ラベル)」の形式で返します。さらに、load_mnist(normalize=True, flatten=True, one_hot_label=False) のような 3 つのパラメータを設定することもできます。最初のパラメータnormalizeは、入力画像を0.0から1.0の間の値に正規化するかどうかを設定します。このパラメータが False に設定されている場合、入力画像のピクセルは元の 0 ~ 255 のままになります。2 番目のパラメーター flatten は、入力画像を (1 次元配列に) 展開するかどうかを設定します。このパラメータが False に設定されている場合、入力画像は 1 × 28 × 28 の 3 次元配列になり、True に設定されている場合、入力画像は 784 要素で構成される 1 次元配列として保存されます。3 番目のパラメータ one_hot_label は、ラベルをワンホット表現として保存するかどうかを設定します。ワンホットとは、ラベルが 1 である配列のみが正しく解決され、[0,0,1,0,0,0,0,0,0,0] と同様に、残りはすべて 0 であることを意味します。one_hot_label が False の場合、正しいソリューション ラベルは 7 や 2 のように単純に保存されます。one_hot_label が True の場合、ラベルはワンホット表現として保存されます

Pythonにはpickleという便利な機能があります。この機能は、実行中のプログラム内のオブジェクトをファイルとして保存できます。保存した pickle ファイルをロードすると、前回のプログラム実行時のオブジェクトをすぐに復元できます。MNISTデータセットの読み込みに使用されるload_mnist()関数も、内部(2回目以降の読み込み時)でpickle関数を使用します。pickle 機能を使用することで、MNIST データの準備を効率的に完了できます。

MNIST イメージを表示します (ソース コードは ch03/mnist_show.py にあります)

import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image
def img_show(img):
 pil_img = Image.fromarray(np.uint8(img))
 pil_img.show()
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True,
normalize=False)
img = x_train[0]
label = t_train[0]
print(label) # 5
print(img.shape) # (784,)
img = img.reshape(28, 28) # 把图像的形状变成原来的尺寸
print(img.shape) # (28, 28)
img_show(img)

ここで注意すべき点は、 flatten=True のときに読み込んだ画像が列(1 次元)の NumPy 配列の形で保存されることです。そのため、画像を表示する際には、元の28ピクセル×28ピクセルの形状に変更する必要があります。NumPy 配列の形状を変更するには、 reshape() メソッドの引数として目的の形状を指定します。また、NumPy配列として保存した画像データもPIL用のデータオブジェクトに変換する必要があり、この変換処理はImage.fromarray()で完了します。
図 3-25 MNIST 画像の表示

ニューラルネットワーク推論処理

ニューラル ネットワークの入力層には 784 個のニューロンがあり、出力層には 10 個のニューロンがあります。入力層の数字 784 は画像サイズ 28 × 28 = 784 に由来し、出力層の数字 10 は 10 カテゴリ分類 (数字 0 ~ 9、合計 10 カテゴリ) に由来します。さらに、このニューラル ネットワークには 2 つの隠れ層があり、最初の隠れ層には 50 個のニューロンがあり、2 番目の隠れ層には 100 個のニューロンがあります。50 と 100 は任意の値に設定できます。次に、まず get_data()、init_network()、predict() の 3 つの関数を定義します (コードは ch03/neuralnet_mnist.py にあります)。

def get_data():
	(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False) 
	return x_test, t_test

# init_network()会读入保存在pickle文件sample_weight.pkl中的学习到的权重参数A。这个文件中以字典变量的形式保存了权重和偏置参数
def init_network():
	with open("sample_weight.pkl", 'rb') as f:
		network = pickle.load(f) 
	return network

def predict(network, x):
	W1, W2, W3 = network['W1'], network['W2'], network['W3'] 
	b1, b2, b3 = network['b1'], network['b2'], network['b3']
	a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1)
	a2 = np.dot(z1, W2) + b2 z2 = sigmoid(a2)
	a3 = np.dot(z2, W3) + b3 y = softmax(a3)
	return y

まず、MNIST データセットを取得し、ネットワークを生成します。次に、for 文を使用して x に格納されている画像データを 1 つずつ取得し、predict() 関数を使用して分類します。detect() 関数は、各ラベルに対応する確率を NumPy 配列の形式で出力します。たとえば、[0.1, 0.3, 0.2, …, 0.04] の配列が出力された場合、その配列は、「0」の確率が 0.1、「1」の確率が 0.3 などを示します。そして、この確率リストの最大値のインデックス(どの要素が最も確率が高いか)を予測結果として取り出します。np.argmax(x) 関数を使用すると、配列内の最大値のインデックスを取得できます。np.argmax(x) は、パラメーター x に割り当てられた配列内の最大値要素のインデックスを取得します。最後に、ニューラルネットワークが予測した答えと正解ラベルを比較し、正解の確率を認識精度とします。

x, t = get_data() network = init_network()

accuracy_cnt = 0
for i in range(len(x)):
	y = predict(network, x[i])
	p = np.argmax(y) # 获取概率最高的元素的索引 
	if p == t[i]:
		accuracy_cnt += 1
		
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

上記コードを実行すると「精度:0.9352」と表示されます。これは、データの 93.52% が正しく分類されていることを意味します。

この例では、load_mnist 関数のパラメータ Normalize を True に設定します。Normalize を True に設定すると、関数は内部で変換を実行し、データの値が 0.0 ~ 1.0 の範囲になるように、画像の各ピクセル値を 255 で除算します。このようにデータを特定の範囲に制限するプロセスを正規化と呼びます。また、ニューラルネットワークの入力データに対して何らかの変換を施すことを前処理といいます。ここでは、入力画像の前処理として正則化を行います。
実際、多くの前処理ではデータの全体的な分布が考慮されます。たとえば、データ全体の平均や標準偏差を使用してデータ全体が 0 付近に分布するようにデータを移動したり、正規化してデータの広がりを一定の範囲内に制御したりできます。また、データ全体の分布形状を均一化する手法として、データホワイトニングなどがあります。

バッチ処理

Python インタプリタを使用して、ニューラル ネットワークの各層の重みの形状を出力します。

>>> x, _ = get_data()
>>> network = init_network()
>>> W1, W2, W3 = network['W1'], network['W2'], network['W3'] 
>>>
>>> x.shape (10000, 784) >>> x[0].shape (784,)
>>> W1.shape
(784, 50) 
>>> W2.shape 
(50, 100) 
>>> W3.shape 
(100, 10)

図 3-26 に示すように、784 要素からなる 1 次元配列 (元は 28 × 28 の 2 次元配列) を入力すると、10 要素からなる 1 次元配列が出力されます。画像データが1枚だけ入力された場合の処理​​フローです。
図 3-26 配列形状の変化
次に、複数の画像をパッケージ化して入力する場合を考えてみましょう。たとえば、predict() 関数を使用して、一度に 100 枚の画像をパッケージ化して処理したいとします。これを行うには、x の形状を 100 × 784 に変更し、100 枚の画像を入力データとしてパックします。図で表すと図 3-27 のようになります。
図 3-27 バッチ処理中の配列形状の変化
図 3-27 に示すように、入力データの形状は 100 × 784、出力データの形状は 100 × 10 です。これは、入力された 100 枚の画像の結果が一度に出力されることを意味します。たとえば、x[0] と y[0] には 0 番目の画像とその推論結果が格納されます。

このパッケージ化された入力データはバッチと呼ばれます。

以下では、バッチベースのコード実装を実装します。

x, t = get_data() 
network = init_network()

batch_size = 100 # 批数量 
accuracy_cnt = 0

for i in range(0, len(x), batch_size):
	x_batch = x[i:i+batch_size]
	y_batch = predict(network, x_batch)
	p = np.argmax(y_batch, axis=1)
	accuracy_cnt += np.sum(p == t[i:i+batch_size])

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

range() 関数が range(start, end) として指定されている場合、start と end-1 の間の整数で構成されるリストが生成されます。range(start, end, step) のように 3 つの整数を指定すると、生成されるリストの次の要素が step で指定した値だけ増加します。例を見てみましょう。

>>> list( range(0, 10) )
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list( range(0, 10, 3) )
[0, 3, 6, 9]

range() 関数によって生成されたリストに基づいて、x[i:i+batch_size] を介して入力データからバッチ データが抽出されます。x[i:i+batch_n]はi番目からi+batch_n番目までのデータを取り出します。
次に、argmax() を通じて最大値を持つ要素のインデックスを取得します。パラメータ axis=1 を指定したことに注意してください。これは、100×10 配列の 1 番目の次元 (1 番目の次元を軸とする) に沿って見つかった最大値を持つ要素のインデックス A を指定します (0 番目の次元は 1 番目の次元に対応します)。ここでも例を見てみましょう。

>>> x = np.array([[0.1, 0.8, 0.1], [0.3, 0.1, 0.6], ... [0.2, 0.5, 0.3], [0.8, 0.1, 0.1]])
>>> y = np.argmax(x, axis=1)
>>> print(y)
[1 2 1 ... 0]

行列の0次元が列方向、1次元が行方向です。

最後に、バッチごとの分類結果と実際の回答を比較します。これを行うには、NumPy 配列間の比較演算子 (==) を使用して、True/False で構成されるブール配列を生成し、True の数をカウントする必要があります。以下の例でこれを確認します。

>>> y = np.array([1, 2, 1, 0]) 
>>> t = np.array([1, 2, 0, 0]) 
>>> print(y==t)
[True True False True]
>>> np.sum(y==t) 3

ニューラルネットワーク学習

ニューラル ネットワークの特徴は、データから学習できることです。いわゆる「データからの学習」とは、データから重みパラメータの値を自動的に決定できることを意味します。

学習回数が有限であれば、線形分離可能な問題は解決可能です。ただし、非線形分離可能問題は (自動) 学習では解決できません。

データから学ぶ

まず画像から特徴が抽出され、次に機械学習テクノロジーを使用してこれらの特徴のパターンが学習されます。ここでいう「特徴量」とは、
入力データ(入力画像)から本質的なデータ(重要なデータ)を正確に抽出することができる変換器のことをいう。画像の特徴量は通常ベクトルで表現されます。

解決すべき問題が 5、犬、顔を特定することであっても、ニューラル ネットワークは提供されたデータを継続的に学習することで、解決すべき問題のパターンを見つけようとします。

トレーニングデータとテストデータ

機械学習では、データは通常、トレーニング データと学習および実験用のテスト データの 2 つの部分に分けられます。まず、トレーニング データを使用して学習し、最適なパラメーターを見つけます。次に、テスト データを使用して、トレーニングされたモデルの実際の機能を評価します。データをトレーニング データとテスト データに分割する必要があるのはなぜですか? 私たちが追求しているのはモデルの一般化能力だからです。モデルの汎化能力を正しく評価するには、トレーニングデータとテストデータを分割する必要があります。なお、訓練データは教師ありデータとも呼ばれます。一般化能力とは、観測されていないデータ(訓練データに含まれないデータ)を処理する能力を指します。一般化機能を達成することは、機械学習の最終目標です。

特定のデータセットのみを過学習させる状態を過学習といいます。

損失関数

ニューラル ネットワークの学習は、特定の指標を通じて現在の状態を表します。つまり、ニューラル ネットワークは、最適な重みパラメーターを見つけるための手がかりとして特定の指標を使用します。ニューラル ネットワークの学習に使用される指標は損失関数と呼ばれます。この損失関数は任意の関数を使用できますが、一般的には平均二乗誤差とクロスエントロピー誤差が使用されます。
損失関数は、ニューラル ネットワークのパフォーマンスの「悪さ」、つまり、現在のニューラル ネットワークが教師付きデータにどの程度適合せず、一貫性がないかを示す指標です。

平均二乗誤差

最も有名な損失関数は平均二乗誤差です。yk
ここに画像の説明を挿入します
はニューラル ネットワークの出力を表し、tk は教師付きデータを表し、k はデータの次元を表します。例えば、3.6 節の手書き数字認識の例では、yk と tk は以下の 10 個の要素から構成されるデータです。

>>> y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
>>> t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

配列要素のインデックスは、先頭から「0」、「1」、「2」の数字に対応します。 ここで、ニューラル ネットワークの出力 y は、softmax 関数の出力です。ソフトマックス関数の出力は確率として理解できるため、上記の例では、「0」の確率は 0.1、「1」の確率は 0.05、「2」の確率は 0.6 などを示します。t は教師ありデータで、正解ラベルは 1 に設定され、その他は 0 に設定されます。ここではラベル「2」が1となっており、正解が「2」であることを示している。正解ラベルを1、その他のラベルを0で表現する表現方法をワンホット表現といいます。

おすすめ

転載: blog.csdn.net/CaraYQ/article/details/131104510