多段の関数の場合の傾きの求め方 - 合成関数の微分

多段の関数の場合の傾きの求め方について解説します。傾きの求め方については、傾きとはで解説しているので、これを理解していることを前提とします。

多段の関数を使って傾きを求める場合は、数学の専門用語では、合成関数の微分という言葉で解説されています。ここでは、ソフトウェアエンジニアが理解できるわかりやすい言葉で解説します。

多段に関数を適用する

まず、二乗する関数と、2倍する関数を連続して、適用したサンプルについて考えます。

use strict;
use warnings;

sub pow2 {
  my ($input) = @_;
  
  my $output = $input ** 2;
  
  return $output;
}

sub mul2 {
  my ($input) = @_;
  
  my $output = $input * 2;
  
  return $output;
}

my $input = 3;
my $output_pow2 = pow2($input);
my $output_mul2_pow2 = mul2($output_pow2);

print "$output_mul2_pow2\n";

3を二乗して、2倍したので、結果は18となります。

傾きの定義に基づいて、値を求める

傾きの定義に基づいて、値を求めてみましょう。関数が多段になっていますが、最初の入力の微小変化と最後の出力の微小変化の比(分母は入力の微小変化)を見るだけなので、難しくありません。

use strict;
use warnings;

sub pow2 {
  my ($input) = @_;
  
  my $output = $input ** 2;
  
  return $output;
}

sub mul2 {
  my ($input) = @_;
  
  my $output = $input * 2;
  
  return $output;
}

my $input = 3;
my $output_pow2 = pow2($input);
my $output_mul2_pow2 = mul2($output_pow2);

my $delta = 0.00000001;
my $input_plus_delta = $input + $delta;
my $output_pow2_plus_delta = pow2($input_plus_delta);
my $output_mul2_pow2_plus_delta = mul2($output_pow2_plus_delta);

my $grad = ($output_mul2_pow2_plus_delta - $output_mul2_pow2) / ($input_plus_delta - $input);

# 12
print "$grad\n";

傾きは12となりました。

多段の関数の傾きを求める公式

実は、多段の関数の傾きを求める公式があります。それぞれの関数の導関数を使って求めた傾きの結果を乗算すればよいというものです。

# 多段の関数の傾きを求める公式
my $grad = pow2_derivative($input) * mul2_derivative($input_plus_delta);

では、実際にそれぞれの関数の導関数が与えられた場合に、誤差を除いて、結果が一致するかを見てみましょう。

use strict;
use warnings;

sub pow2 {
  my ($input) = @_;
  
  my $output = $input ** 2;
  
  return $output;
}

sub pow2_derivative {
  my ($input) = @_;
  
  my $output = $input * 2;
  
  return $output;
}


sub mul2 {
  my ($input) = @_;
  
  my $output = $input * 2;
  
  return $output;
}

sub mul2_derivative {
  my ($input) = @_;
  
  my $output = 2;
  
  return $output;
}

my $input = 3;
my $output_pow2 = pow2($input);
my $output_mul2_pow2 = mul2($output_pow2);

my $delta = 0.00000001;
my $input_plus_delta = $input + $delta;
my $output_pow2_plus_delta = pow2($input_plus_delta);
my $output_mul2_pow2_plus_delta = mul2($output_pow2_plus_delta);

# 定義を使って求めた傾き
my $grad = ($output_mul2_pow2_plus_delta - $output_mul2_pow2) / ($input_plus_delta - $input);

# 公式を使って求めた傾き
my $grad_formula = pow2_derivative($input) * mul2_derivative($output_pow2_plus_delta);

# 12
print "$grad_formula\n";

結果は、12となりました。合っていますね。今回は、誤差がないようです。

今回は、2段階の場合の傾きの求め方ですが、3段になっても、4段になっても、考え方は変わりません。

ディープラーニングの場合は、偏微分という言葉がでてきますが、これは、ひとつの入力に対して傾きを求めるという意味と考えてください。変化させるひとつの入力以外は、定数とみなすことが偏微分です。ですので、今回の内容が理解できれば、偏微分についても自然と理解できています。

数式を使った場合は、数学の言葉と数学の言葉が含んでいる暗黙の了解を理解している必要がありますが、コードで表現すると、すべてがコードで表現されているので、ソフトウェアエンジニアにとっては、わかりやすく感じると思います。

関連情報