# 勾配

- ある関数の偏微分
- その関数の変化を表す
- ロス関数の値を減らす方向が分かる


```python
import numpy as np
```


```python
# 数値微分
def numerical_diff(f, x):
    h = 0.0000000001
    e = (f(x+h) - f(x-h)) / (2*h) # 中心差分
    return e
```

2つの変数を持つ関数

\begin{equation}
  f(x_1, x_2) = x_1^2 + x_2^2
\end{equation}

x1 = 2.0, x2 = 3.0のとき、偏微分を求める

$$
\frac{\partial f}{\partial x_1}
$$


```python
def func1(x1):
    x2 = 3.0
    e = pow(x1, 2) + pow(x2, 2)
    return e
```


```python
numerical_diff(func1, 2.0)
```




    4.000000330961484



# 勾配法

- 勾配方向への移動を繰り返すことで、関数の値を減らす（または増やす方向）
- ディープラーニングでは勾配降下法（ロス関数の値を減らすため）

\begin{equation}
  x_n = x_n - \eta\frac{\partial f}{\partial x_n}
\end{equation}


```python
def gradient(f, x):
    h = 0.0000000001
    g = np.zeros_like(x)
    
    for i in range(x.size):
        # 偏微分 : 変数一つずつを対象に微分
        tmp = x[i]
        x[i] = tmp + h
        f1 = f(x)
        x[i] = tmp - h
        f2 = f(x)
        x[i] = tmp # 戻す
        g[i] = (f1-f2) / (2*h)
    
    return g
```


```python
def gradient_descent(f, x, le, step):
    for i in range(step):
        g = gradient(f, x)
        x -= le * g
    return x
```


```python
def func2(x):
    y = 2.0 * pow(x[0], 2.0) + 2.0 * pow(x[1], 2.0)
    return y
```

テスト

\begin{equation}
  f(x_1, x_2) = 2x_1^2 + 2x_2^2
\end{equation}

の最小値を求める

解 : (0, 0)

### 学習率について


```python
# 学習率 0.1(まあまあ適切)
x = np.array([5.0, -5.0])
gradient_descent(func2, x, 0.1, 100)
```




    array([  3.26660446e-22,  -3.26660446e-22])




```python
# 学習率 1.0（大きい）
x = np.array([5.0, -5.0])
gradient_descent(func2, x, 1.0, 100)
```




    array([-1244739.50700518,  1244739.50700518])




```python
# 学習率 0.01（小さい）
x = np.array([5.0, -5.0])
gradient_descent(func2, x, 0.01, 100)
```




    array([ 0.08435156, -0.08435156])



### ステップ数について


```python
# ステップ数 10
x = np.array([5.0, -5.0])
gradient_descent(func2, x, 0.1, 10)
```




    array([ 0.03023296, -0.03023296])




```python
# ステップ数 1000
x = np.array([5.0, -5.0])
gradient_descent(func2, x, 0.1, 1000)
```




    array([  6.17694113e-27,  -6.17694113e-27])




```python
# 学習率 0.01 ステップ数 1000
x = np.array([5.0, -5.0])
gradient_descent(func2, x, 0.01, 1000)
```




    array([  9.33690313e-18,  -9.33690313e-18])



# 確立的勾配降下法

ランダムに選んだデータから勾配を求める

# モーメンタムを使用

- momentum
- 確立的勾配降下法では、ランダムにデータを選ぶため、すべてのデータから求めた勾配の方向とは、一致しない
- 勾配の方向を足しあげることで、ばらつきが減らせる

# Momentum SGD

- v : 更新量
- γ : 係数
- g : 勾配

\begin{equation}
  v_step = \gamma v_{step-1} + (1 - \gamma)g
\end{equation}


```python

```

f2eaa848f29a1d77a311e0b9c3d22dabe774af41
ipynb
Jupyter Notebook
Notebook/4_gradient.ipynb
YusukeKato/Start_DeepLearning
8b20f2b15ae16fa1c9cb9c10db740fa2d9cc0c4d
MIT
Notebook/4_gradient.ipynb
YusukeKato/Start_DeepLearning
8b20f2b15ae16fa1c9cb9c10db740fa2d9cc0c4d
MIT
Notebook/4_gradient.ipynb
YusukeKato/Start_DeepLearning
8b20f2b15ae16fa1c9cb9c10db740fa2d9cc0c4d
MIT
Qwen/Qwen-72B
1. YES
2. YES