Perlで学ぶディープラーニング入門

行列の積の計算

ディープラーニングに必要な行列の積をPerlで求める方法を解説します。

重み行列と入力ベクトルの掛け算を行う場合に、必要です。

行列の計算にはいくつかの条件を設けておきます。

一つ目は、列優先の行列であるということです。列優先の行列というのは、列方向の向きにデータを持つということです。

# 数学の行列表現
# 3行2列の行列
# 1 4
# 2 5
# 3 6

# 列優先でのデータのもちかた
my $mat = {
  values => [1, 2, 3, 4, 5, 6],
  rows_length => 3,
  columns_length => 2,
};

列優先にしておく理由は、BLASという行列計算ライブラリを使う場合と、整合性をとるためです。

まずPerlで、行列演算を行い。それをSPVMに移植します。そして、最後に、BLUSと呼ばれるC言語ライブラリや、cuBLUSと呼ばれるcudaのGPUの計算を行えるライブラリに移植可能なようにします。

行列の積を求める

行列の積を求めましょう。3×2の行列と、2×1の行列(つまりベクトル)の積を求めます。

use strict;
use warnings;

# 行列の積を求める
sub mat_mul {
  my ($mat1, $mat2) = @_;
  
  my $mat1_rows_length = $mat1->{rows_length};
  my $mat1_columns_length = $mat1->{columns_length};
  my $mat1_values = $mat1->{values};
  
  my $mat2_rows_length = $mat2->{rows_length};
  my $mat2_columns_length = $mat2->{columns_length};
  my $mat2_values = $mat2->{values};
  
  # 行列の積の計算
  my $mat_out_values = [];
  for(my $row = 0; $row < $mat1_rows_length; $row++) {
    for(my $col = 0; $col < $mat2_columns_length; $col++) {
      for(my $incol = 0; $incol < $mat1_columns_length; $incol++) {
        $mat_out_values->[$row + $col * $mat1_rows_length]
         += $mat1_values->[$row + $incol * $mat1_rows_length] * $mat2_values->[$incol + $col * $mat2_rows_length];
      }
    }
  }
  
  my $mat_out = {
    rows_length => $mat1_rows_length,
    columns_length => $mat2_columns_length,
    values => $mat_out_values,
  };
  
  return $mat_out;
}

# 重み(3行2列の行列)
# 1 4
# 2 5
# 3 6
my $mat1 = {
  values => [1, 2, 3, 4, 5, 6],
  rows_length => 3,
  columns_length => 2,
};

# 入力ベクトル(2行1列の行列)
# 7 9
# 8 10
my $mat2 = {
  values => [7, 8, 9, 10],
  rows_length => 2,
  columns_length => 2,
};

# 計算方法
# 1 * 7 + 4 * 8    1 * 9 + 4 * 10
# 2 * 7 + 5 * 8    2 * 9 + 5 * 10 
# 3 * 7 + 6 * 8    3 * 9 + 6 * 10
my $outputs_mul = mat_mul($mat1, $mat2);

# rows_length => 3, columns_length => 2, values : [39, 54, 69, 49, 68, 87]
use Data::Dumper;
print Dumper $outputs_mul;

Perlでの行列の積の計算には、C言語で書かれた行列の積の計算アルゴリズムがありましたので、それを流用しました。

行列の積の計算は、一般には、3重ループになります。

Perlで学ぶディープラーニング入門のご紹介

コンテンツ