Heの初期値

Heの初期値を求めてみましょう。Heの初期値は、正規分布に従う乱数で、平均を0、標準偏差を「sqrt(2/入力数)」と指定したものです。

入力数とは、mからn個への変換におけるmの値のことです。

主にReLU関数活性化関数として使う場合の重みの初期値に利用するようです。良い初期値を選ぶことで、各層でのmからnへの変換後に活性化関数が適用された値が、適度にばらつきます。

# Heの初期値を取得
sub he_init_value {
  my ($inputs_length) = @_;
  
  return randn(0, sqrt(1 / $inputs_length));
}

Heの初期値を使って重みの配列を初期化

use strict;
use warnings;

# 正規分布に従う乱数を求める関数
# $m は平均, $sigma は標準偏差、
sub randn {
  my ($m, $sigma) = @_;
  my ($r1, $r2) = (rand(), rand());
  while ($r1 == 0) { $r1 = rand(); }
  return ($sigma * sqrt(-2 * log($r1)) * sin(2 * 3.14159265359 * $r2)) + $m;
}

# Heの初期値を作成
sub create_he_init_value {
  my ($inputs_length) = @_;
  
  return randn(0, sqrt(2 / $inputs_length));
}

# Heの初期値で配列を作成する
sub array_create_he_init_value {
  my ($array_length, $inputs_length) = @_;
  
  my $nums_out = [];
  for (my $i = 0; $i < $array_length; $i++) {
    $nums_out->[$i] = create_he_init_value($inputs_length);
  }
  
  return $nums_out;
}

# 入力数を728として、出力数を30とすると、行列が持つ配列の長さは「728 * 30」
my $inputs_length = 728;
my $outputs_length = 30;
my $weights_mat = {
  rows_length => $outputs_length,
  columns_length => $inputs_length,
};
my $weights_values_length = $inputs_length * $outputs_length;
$weights_mat->{values} = array_create_he_init_value($weights_values_length, $inputs_length);

use Data::Dumper;
print Dumper $weights_mat;

Heの初期値以外の初期値

シグモイド関数を活性化関数として使う場合は、Xavierの初期値を使うのが良い用です。

関連情報