<jupyter_start><jupyter_text>自動微分のPython実装：autograd自動微分を行うpythonモジュールにautogradがある．これを使って自動微分の計算を行う．<jupyter_code># autogradのインストール

!pip install autograd
# numpyをｎnpとしてインポート（普通はnpだが，ここでは別名にする）
import numpy as npnp

# autograd内にnumpy互換のモジュールが用意されている．これをnpとしてインポート
import autograd.numpy as np

# from autograd import grad # こちらは1変数関数のみ（引数にarrayを受け取れない）
from autograd import elementwise_grad as grad # 引数にarrayを受け取る関数用
from autograd import jacobian


import matplotlib.pyplot as plt
%matplotlib inline<jupyter_output><empty_output><jupyter_text>シグモイドまずは普通のnumpyでsigmoid関数を実装し，プロットしてみる<jupyter_code># numpyでシグモイド関数を実装
def sig(x):
    return 1 / (1 + npnp.exp(-x))
x = np.arange(-10, 10, 0.1)
plt.plot(x, sig(x), label="f(x)")
plt.title("sigmoid function f(x)")
plt.xlabel("x")
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>次にautograd用のnumpyでsigmoid関数を実装する．<jupyter_code># numpyでシグモイド関数を実装
def sig(x):
    return 1 / (1 + np.exp(-x))<jupyter_output><empty_output><jupyter_text>この関数を微分するには`grad`を用いる．返り値は関数になる．<jupyter_code>grad_sig = grad(sig)
grad_sig # autogradオブジェクトになっている
grad_sig(1.0) # 値が計算できる<jupyter_output><empty_output><jupyter_text>導関数は普通の関数のように使える．元の関数と同様にプロットしてみる．<jupyter_code>x = np.arange(-10, 10, 0.1)
plt.plot(x, sig(x), label="f(x)")
plt.plot(x, grad_sig(x), label="f'(x)")
plt.plot(x, grad(grad_sig)(x), label="f''(x)") # 直接gradで関数オブジェクトを作成してもよい
plt.title("sigmoid f(x) and derivatives f'(x), f''(x)")
plt.xlabel("x")
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>条件分岐を含む1変数関数関数がif文を含んでもよいし，関数が不連続でもよい．（実装上の注意：引数にarrayが取れない）<jupyter_code>def f(x):
    if x >= 0: # xはスカラーのみ．arrayは不可
        return x
    else:
        return x * np.exp(x) - 1
grad_f = grad(f)
x = np.arange(-10, 10, 0.1)
plt.plot(x, [f(xi) for xi in x], label="f(x)")
plt.plot(x, [grad_f(xi) for xi in x], label="f'(x)")
plt.xlabel("x")
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>線形関数 + シグモイド線形関数$\boldsymbol{w}^T \boldsymbol{x} + b$のあとにシグモイド関数を適用する．つまり$\mathrm{sig}(\boldsymbol{w}^T \boldsymbol{x} + b)$を考える．`x`は10次元ベクトルとする．`w`と`b`はランダムに初期化する．<jupyter_code>N = 10
w = np.random.randn(N)
b = np.random.randn(1)
w, b<jupyter_output><empty_output><jupyter_text>線形関数を実装．シグモイド関数は先程の関数を再利用．これが最小のネットワークなので，`small_net`と名付ける．連鎖率は自動的に適用される．<jupyter_code>def linear(x):
    h = w.dot(x) + b
    return h
def small_net(x):
    return sig(linear(x))<jupyter_output><empty_output><jupyter_text>微分（勾配ベクトル）を計算．<jupyter_code>grad_small_net = grad(small_net)<jupyter_output><empty_output><jupyter_text>呼び出せることを確認する．<jupyter_code>small_net(np.random.randn(N))
grad_small_net(np.random.randn(N))<jupyter_output><empty_output><jupyter_text>ヤコビ行列の計算ベクトル値関数のヤコビ行列（微分）の計算には`jacobian`を用いる． アフィン関数の例入力`x`のアフィン関数$W \boldsymbol{x} + \boldsymbol{b}$を考える．入力`x`は$M$次元，出力は$N$次元の関数である．<jupyter_code>N = 2
M = 3
W = np.random.randn(N, M)
b = np.random.randn(N)
W, b<jupyter_output><empty_output><jupyter_text>アフィン関数を`tiny_net`とする．<jupyter_code>def tiny_net(x):
    h = np.dot(W, x) + b # 注意：autograd.numpyではW.dot(x)は使えない．np.dot(W, x)を使う．
    return h<jupyter_output><empty_output><jupyter_text>ヤコビ行列を計算する（つまりヤコビ行列関数を作成する）．<jupyter_code>Jacobian_tiny_net = jacobian(tiny_net)
x = np.random.randn(M) # ランダムな入力
tiny_net(x) # xを入力
Jacobian_tiny_net(x) # 入力がxの時のヤコビ行列<jupyter_output><empty_output><jupyter_text>この場合のヤコビ行列は$W$であるので，この出力が`W`と一致している．  非線形関数の例$\boldsymbol{f}(\boldsymbol{p}) =                \begin{pmatrix}                a \sin(bx+c) \\ a\cos(bx+c)                \end{pmatrix},			\boldsymbol{p}=                \begin{pmatrix}                 a \\ b \\ c                \end{pmatrix}            $のヤコビ行列$\dfrac{\partial\boldsymbol{f}}{\partial \boldsymbol{p}}$を求める．<jupyter_code>def f(p):
    a, b, c = p # 3D parameter vector
    f1 = a * np.sin(b * x + c)
    f2 = a * np.cos(b * x + c)
    return np.array([f1, f2])
df_dp = jacobian(f)
x = 10.0 # use float. using int results in errors...
p = np.array([10.0, 2.0, 4.0]) # use float !
f(p)
df_dp(p)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16100848726909636, 'fraction_numerical': 0.012481278082875686, 'mean_word_length': 6.029824561403509, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 58, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '87707', 'license': 'MIT', 'n_tokens_mistral': 2240, 'n_tokens_neox': 2195, 'n_words': 234, 'path': 'MachineLearningMath/differentiation_autograd.ipynb', 'repo_name': 'shutoushu/lecture_code', 'size': '4006'}