Skip to content

DNET_DSMathDifferentiation

nishi_74322014 edited this page Sep 11, 2026 · 1 revision

DS:数学的基礎 - 微分・偏微分

概要

  • 微分係数(関数の変化率)、

    • つまりグラフの接線の傾きを求める計算処理
    • グラフの接線の傾き=ある瞬間の変化の量。
  • 勾配降下法(ニューラルネットワーク(学習)の該当節を参照)と言う最適解の探索手法では
    広大なパラメタ空間から、複雑な関数(=損失関数)が、
    最小(最大)値を出力する鞍点を、勾配を使用して探す。

  • 微分・偏微分・連鎖律

    • 微分

      • 入力パラメタを変化させたら、出力はどれだけ変化するか?
      • 微分では、記号として、𝑑を使う。
    • 偏微分

      • 入力パラメタが複数ある場合、同様に、出力はどれだけ変化するか?
      • 偏微分では、記号として、𝑑ではなく∂を使う。
    • 連鎖律

      • 関数が複数ある(合成関数の)場合、出力はどれだけ変化するか?
      • 連鎖律では計算に使った関数の偏微分をかけると合成関数の微分値が求まる。

微分

導関数

df(x)  yの増量        f(x+h) - f(x)        f(x+h) - f(x)
── = ───  = lim  ──────  = lim  ──────
 dx    xの増量   h→0 (x+h) - (x)     h→0      h

解析的

式の展開によって微分を求める(誤差がない)。

数値的

計算によって微分を求める(誤差がある)。

Python実装

"""This is a test program."""

import numpy as np
import matplotlib.pyplot as plt

def numerical_diff(f, x):
    """数値微分"""
    h = 1e-4 # 微小な値hとして1の-4乗を用いる
    return (f(x + h) - f(x - h)) / (2 * h) # 前方差分から中心差分にして誤差減

def function_1(x):
    """f(x)=0.01x^2+0.1x"""
    return 0.01 * x ** 2 + 0.1 * x

X=5
print("X=" + str(X) + " : " + str(numerical_diff(function_1, X)))
X=10
print("X=" + str(X) + " : " + str(numerical_diff(function_1, X)))

X = np.arange(0.0, 20.0, 0.1)
Y = function_1(X)
plt.xlabel("x")
plt.ylabel("f(x)")
plt.plot(X, Y)
plt.show()

Python出力

  • グラフ

グラフ

微分

偏微分

概要(偏微分)

  • 多変数関数をある変数について微分することを偏微分と言う。
  • 着目した変数以外の変数は定数であると見なされる。
  • 曲面で説明すると、
    • 当該座標で着目した変数の2変数関数の接線を求める。
    • 曲面の座標上の2つの接線から接平面が求まる。

計算

  • 偏微分では、記号として、𝑑ではなく∂を使う。

  • 以下、x1に着目した場合の偏微分。

    y = 4x1^3 + 2x2^2 + 1
    
    ∂y
    ── = 12x1^2
    ∂x1
    

例1

2つの引数の2乗和を計算する式

  •               2    2
    f(x0, x1) = x0 + x1
    
  • Python

    • 実装

      """This is a test program."""
      
      import numpy as np
      
      def function_2(x):
          """f(x0, x1) = x0^2 + x1^2"""
          return x[0] ** 2 + x[1] ** 2
          # or return np.sum(x ** 2)

例2

2つの引数の2乗和を計算する式の偏微分

  • ∂f(x0, x1)
    ─────  = 2 * x0
        ∂x0
    
    ∂f(x0, x1)
    ─────  = 2 * x1
        ∂x1
    
  • Python

    • 実装

      """This is a test program."""
      
      import numpy as np
      
      def numerical_diff(f, x):
          """数値微分"""
          h = 1e-4 # 微小な値hとして1の-4乗を用いる
          return (f(x + h) - f(x - h)) / (2 * h) # 前方差分から中心差分にして誤差減
      
      def function_tmp1(x0):
          """x0=3, x1=4 の場合の x0 に対する偏微分用"""
          return x0 ** 2 + 4.0 ** 2
      
      def function_tmp2(x1):
          """x0=3, x1=4 の場合の x1 に対する偏微分用"""
          return 3.0 ** 2.0 + x1 ** 2
      
      print(numerical_diff(function_tmp1, 3.0))
      print(numerical_diff(function_tmp2, 4.0))
    • 出力 (x0=3, x1=4)

      6.00000000000378   (2 * x0 = 2 * 3 = 6)
      7.999999999999119   (2 * x1 = 2 * 4 = 8)
      

連鎖律

合成関数の微分についての性質。

  • 「合成関数のゴールの微分係数」=「経路上の関数の微分係数の積」となる公式

  • 「ある関数が、合成関数で表される場合、合成関数の微分は、
    合成関数を構成する関数の微分の積で表すことが出来る。」

合成関数

合成関数(関数Aと関数B)

z = t^2 = f(t)
t = x + y = g(x)
z = f(g(x))

関数の微分

関数Aの微分

∂z
 ─ = 2t
∂t

関数Bの微分

∂t
 ─ = 1
∂x

合成関数の微分

∂z   ∂z ∂t
 ─ =  ─  ─ = 2t * 1 = 2t = 2(x + y)
∂x   ∂t ∂x

全微分

解析的手法の例

y=x^nの微分

公式(y=x^n)

y=x^n

df(x)  d(x^n)
── = ──   = nx^(n-1)
 dx      dx

導出(y=x^n)

  • y=x^2の例

    df(x)  yの増量        (x+h)^2 - x^2        (x^2+2hx+h^2) - (x^2)
    ── = ───  = lim  ──────  = lim  ──────────
     dx    xの増量   h→0 (x+h) - (x)     h→0           h
    
     dy         2hx+h^2
    ── = lim ──── = lim 2x+h  = 2x
     dx    h→0    h      h→0
    
  • y=x^nの場合
    n乗の展開公式で、 h→0とすると、nx^(n-1) と同じ結果になる。

y=a^xの微分

公式(y=a^x)

y=a^x

df(x)  d(a^x)
── = ──   = logea・a^x
 dx      dx

ネイピア数

df(x)  d(a^x)   a^(x+dx) - a^x   a^x(a^dx - 1)        a^dx - 1
── = ──   = ─────── = ─────── = a^x─────
 dx     dx            dx              dx                 dx

    a^h - 1
lim ──── = 1 となるような h = e
h→0    h

df(x)  d(e^x)   e^(x+dx) - e^x   e^x(e^dx - 1)        e^dx - 1
── = ──   = ─────── = ─────── = e^x───── = e^x・1 = e^x
 dx     dx            dx              dx                 dx

導出(y=a^x)

連鎖律を使う

  • 𝑎^x = e^((log𝑒a)・x)
  • t = (log𝑒a)・x
df(x)  d(a^x)   d(e^((log𝑒a)・x))  d(e^t) dt
── = ──   = ──────── = ─── ─ = e^t・(log𝑒a) = a^x・(log𝑒a) = logea・a^x
 dx     dx            dx             dt   dx

y=logea^xの微分

は、逆関数の微分値の逆数(的なもの)

公式(y=logea^x)

y=logea^x

dy/dx = 1/(logea・x)

導出(y=logea^x)

  • y=logea^xの逆関数は、

    x=a^y
    
  • この逆関数の微分値は、

    dx/dy = logea・a^y = logea・x
    
  • この逆関数の微分値の逆数的なものは、

    dy/dx = 1/(dx/dy) = 1/(logea・x)
    

三角関数の微分

https://www.headboost.jp/derivatives-of-trigonometric-function/#index_id1

  • 𝜃(ラジアン)は90°が1/2π、360°が2π

  • 小さな直角三角形は、元の大きな直角三角形と相似形

公式(三角関数)

  • sin'(𝜃)

    sin'(𝜃) = cos(𝜃)
    
  • cos'(𝜃)

    cos'(𝜃) = -sin(𝜃)
    

導出(三角関数)

  • sin

              sin(𝜃 + d𝜃) − sin(𝜃)    d(sin(𝜃))    d𝜃・cos𝜃
    sin'(𝜃) = ────────── = ───── = ───── = cos(𝜃)
                       d𝜃                d𝜃           d𝜃
    
  • cos

              cos(𝜃 + d𝜃) − cos(𝜃)    d(cos(𝜃))   -d𝜃・sin𝜃
    cos'(𝜃) = ────────── = ───── = ───── = -sin(𝜃)
                       d𝜃                d𝜃           d𝜃
    

実際の計算

以下を使う(いずれも元 Wiki では見出しのみで未記載)。

  • 公式
  • 連鎖律
  • 多変数関数の全微分の公式?

参考

移行メモ

  • 「ラフの接線の傾き」→「グラフの接線の傾き」、 「連鎖率」→「連鎖律」(2 箇所)に修正した。
  • ネイピア数の導出で a^(x-dx) - a^x となっていたが、 導関数の定義に従い a^(x+dx) - a^x に修正した(e^x の式も同様)。
  • 「y=logea^xの微分」の公式が dy/dx = logea・x となっていたが、 直後の導出の結論(逆関数の微分値の逆数)と矛盾するため dy/dx = 1/(logea・x) に修正した。
  • 例2 の偏微分の式で分母が dx0 / dx1 になっていたため ∂x0 / ∂x1 に修正した。 また Python 実装の先頭に紛れ込んでいた numerical_diff の文字列を除去した。
  • 「全微分」「実際の計算」配下は本文の無い見出しだったため、 箇条書きにまとめ、未記載である旨を明示した。
  • 三角関数の微分の「(図を参照)」は、対応する図が元 Wiki に無いため除去した。
  • 同名の見出し(「概要」「公式」「導出」)が複数あり、GitHub Wiki では アンカが衝突するため、括弧で文脈を補って一意にした。
  • 添付 3 点のうち、本文から参照されているのは graf.png(→ _1)と gradient_1d.png(→ _2)の 2 点。参照の無い gradient_2d.pngDNET_DSMathDifferentiation_3.png として取得した。
  • PukiWiki のページ内アンカ(#xxxxxxxx)は GitHub Wiki では再現できないため、 他ページのアンカを指すリンクは「〜(ページ名 の該当節を参照)」の形に置き換えた。

Tags: 移行, DS, 数学的基礎, 微分, 偏微分, 連鎖律, 数値微分, ネイピア数, 勾配降下法, Python

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally