【ふくだ学習録】ゼロから作るDeepLearning part3【8日目】

# ふくだ学習録とは？
ふくだが学習したことの備忘録。
目に見える形で残すことによってやる気を出す個人的な作戦です。
他人に見せるように書いているわけではないので、すごく読みにくいです。

### 読了した本
[データベースエンジニア養成読本 [DBを自由自在に活用するための知識とノウハウ満載!]](https://www.amazon.co.jp/dp/4774158062/ref=cm_sw_r_tw_dp_U_x_FPphEbQFPPQRM )

# ゼロから作るDeepLearningを読んで

### 恒等関数とは？
入力値をそのまま出力する際に使用される関数。

### 活性化関数はどういったものをよく使う？
回帰問題では、**恒等関数**
２クラス分類問題では、**シグモイド関数**
多クラス分類問題では、**ソフトマックス関数**
を使うのが一般的。とのこと。

### ソフトマックス関数とは？
非正規化されたベクターを取って、それを確率分布に正規化するもの。
噛み砕いて言うと、出力された数字を和が綺麗に100%(1.0)になる数字に変えてくれる関数。
下記サイトがすごいわかりやすかった！

[SoftMax（ソフトマックス）関数とは？文系の人にもわかりやすく](https://qiita.com/Hatomugi/items/158b8656da5cc4cce0fe)

### ソフトマックス関数と、シグモイド関数の違い。
- **ソフトマックス関数**
2値分類でも多クラス分類でも使える。

- **シグモイド関数**
2値分類で使えるが多クラス分類では使えない。

【補足】シグモイド関数はソフトマックス関数を元に作られたもの。

[SoftMax（ソフトマックス）関数とは？文系の人にもわかりやすく](https://qiita.com/Hatomugi/items/158b8656da5cc4cce0fe)
のコメント欄にわかりやすく記載してくれていた！神！


### 機械学習問題の分類
大きく分けて、**分類問題**と**回帰問題**の2つに分けられる。

### ソフトマックス関数の実装上の注意
ソフトマックス関数では、指数関数の計算を行うが、値の桁数が大きくなりすぎて計算不可に陥ってしまう可能性が高い。
（例えばeの1000乗をすると、無限大を表すinfが返って来てしまう）

### 出力層のソフトマックス関数は省略する
ソフトマックス関数を使用する他クラス分類問題では、通常必要になる最後の答えは一つだけになる。
またソフトマックス関数では、入力値の大小関係と出力値の大小関係は変わらない。
そのため、出力層でのソフトマックス関数の使用を省略することで、計算量を減らすことが一般的である。

### 出力層のニューロンの数
分類したいクラスの数に設定するのが一般的。
例えば、０〜９までの数字に分類したいときは、出力層のニューロン数は１０個に設定する。

### 白色化とは？
データ全体の分布の形状を均一にしておくこと。


### 書籍3-4の実装

```python:3-4.py
import numpy as np
import pprint

## 出力の整形
pp = pprint.PrettyPrinter(indent=4)

# シグモイド関数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 恒等関数
def identify_function(x):
    return x

# 入力層→第一層
print('入力層→第一層')
## 重み付き和
X = np.array([1.0, 0.5])
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B1 = np.array([0.1, 0.2, 0.3])

print(W1.shape)
print(X.shape)
print(B1.shape)

## 活性化関数の適応（今回はシグモイド関数）
print('活性化関数の適応（今回はシグモイド関数）')
A1 = np.dot(X, W1) + B1
Z1 = sigmoid(A1)

print(A1)
print(Z1)

# 第一層→第二層
print('第一層→第二層')
## 重み付き和
W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
B2 = np.array([0.1, 0.2])

print(Z1.shape)
print(W2.shape)
print(B2.shape)

## 活性化関数の適応（今回はシグモイド関数）
print('活性化関数の適応（今回はシグモイド関数）')
A2 = np.dot(Z1, W2) + B2
Z2 = sigmoid(A2)

print(A2)
print(Z2)

# 第二層→出力層
print('第二層→出力層')
# 重み付き和
W3 = np.array([[0.1, 0.3], [0.2, 0.4]])
B3 = np.array([0.1, 0.2])

## 活性化関数の適応（今回は恒等関数）
print('活性化関数の適応（今回は恒等関数）')
A3 = np.dot(Z2, W3) + B3
Y = identify_function(A3)  # Y = A3　でも良い

#3-4まとめ
print('3-4まとめ')
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 = identify_function(a3)

    return y

network = init_network()
## 重みやバイアス
print('重みやバイアス')
pp.pprint(network)

x = np.array([1.0, 0.5])
y = forward(network, x)
## 出力
print('出力')
print(y)
```

### 書籍3-5の実装

```python:3-5.py
import numpy as np
import pprint

## 出力の整形
pp = pprint.PrettyPrinter(indent=4)


# ソフトマックス関数の実装(第一段階)
def softmax(a):
    exp_a = np.exp(a)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a

    return y


# 上記のソフトマックス関数で計算できない場合(指数が大きすぎるとき)
print('上記のソフトマックス関数で計算できない場合(指数が大きすぎるとき)')
a = np.array([1010, 1000, 990])
pp.pprint(a)

## [nan, nan, nan]になってしまう。
print(softmax(a))

# 計算できるように最大値で引き算してあげる
print('計算できるように最大値で引き算してあげる')
c = np.max(a)
pp.pprint(softmax(a - c))

# ソフトマックス関数の実装(第二段階)
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
```


# 今日の一言
実装作業をVScodeでして、最後にまとめでQiitaに記載する方法が一番頭に入りやすい気がしてきた！
池田エライザとタコパしたい！