はじめに
CouseraのMachine Learning 講座のプログラミング課題ではOctaveという言語が使われます。ほとんどの課題は、その週で学ぶ機械学習アルゴリズムを表した数式を記述することが多いです。課題をやっている中で数式を書くことは分かっても、Octaveでの書き方が分からずに詰まったことがあったので、主な記述方法をまとめました。
よく使った演算子
行列の積(ベクトルの内積)
一番使った演算だと思います。A,Bは行列またはベクトルです。AかBかのどちらかがスカラーでも同じ演算子です。
C = A * B;
数式では次のようになります。
$$ c_{ij} = \sum_{k=1}^{m}a_{ik}b_{kj} $$
行列の要素ごとの積
これもよく使ったと思います。「.」を演算子の前につけると要素ごとの演算になります。行列の積とよく似てるので、注意しないとハマるかもしれません。
C = A .* B;
数式は
$$
c_{ij} = a_{ij} b_{ij}
$$
とか
$$
C = A \otimes B
$$
になります。(アダマール積というらしいです。)
行列の要素ごとの2乗
似たような演算で要素ごとの2乗もよく使いました。
C = A .^ 2;
行と列の転置
行列の積をする際に転置行列(行と列を入れ替える)ことがよくあります。
X';
X = \left( \begin{array}{ccc}
1 & 2 & 3 \\
4 & 5 & 6
\end{array} \right)
という行列だった場合、
X' = \left( \begin{array}{cc}
1 & 4 \\
2 & 5 \\
3 & 6
\end{array} \right)
となります。
よく使った関数
Octave では helpコマンドで関数の使い方を調べることができます。ただ慣れるまではhelpを見てもピンと来ませんでした。使用頻度の高かった関数をどんなときに使ったのかをまとめました。
help [関数名]
size()
引数に行列を指定すると、その行列のサイズを調べることができます。行列同士の積は行列サイズに注意をする必要があるので、引数のサイズや計算結果が正しいかどうか調べるために使いました。
X = \left( \begin{array}{ccc}
1 & 2 & 3 \\
4 & 5 & 6
\end{array} \right)
のような行列の場合、サイズは(2, 3)になります。
X = [1 2 3; 4 5 6];
size(X)
ans =
2 3
sum()
引数に指定した行列の合計を計算します。アルゴリズムに $ \sum $ が含まれることは多いのでよく使います。特につまづくことはないと思いますが、行毎の合計を計算する場合は、引数を指定する必要があります。
X = [1 2 3; 4 5 6];
%列方向の合計
sum(X)
ans =
5 7 9
%行方向の合計
sum(X,2)
ans =
6
15
%総合計
sum(sum(X))
ans = 21
特定の値のみを集計する場合もあります。引数に条件を指定すると真の場合のみ集計します。
X = [1 0 0; 1 1 0; 1 1 1];
%1の合計
sum(X == 1)
ans =
3 2 1
mean()、std()
行列の平均、標準偏差を計算するために使います。正規化(Normalization)で使います。
X = [1 2 3; 4 5 6];
%平均値
mean(X)
ans =
2.5000 3.5000 4.5000
%標準偏差
std(X)
ans =
2.1213 2.1213 2.1213
exp()
指数関数です。シグモイド関数の実装で使います。
g(x) = \frac{1}{1 + e^{-x}}
log()
対数関数です。ロジスティクス回帰の損失関数の実装で使います。
J(\theta) = \frac{1}{m} \sum_{i=1}^{m}\left[-y^i log(h_{\theta}(x^i)) - (1-y^i) log( 1-h_{\theta}(x^i)) \right]
max()、min()
列単位の最大値・最小値を求めます。行単位のときは引数を指定する必要があります。
X = [1 2 3; 4 5 6];
%列方向の最大値
max(X)
ans =
4 5 6
%行方向の最大値
max(X,[],2)
ans =
3
6
アルゴリズムによっては最大値そのものではなく、最大値のインデックスが必要な場合があります。max(),min()では、返り値が[値,インデックス]となります。
[val, index] = max(X)
val =
4 5 6
index =
2 2 2
よく使った行列操作
演算子と関数のみで実装できればいいんですが、課題の中には行列を操作する必要があります。最低限、知っていれば良い操作をまとめました。
行列の1行目を取り除く
確か正則項を求める際、バイアス部分は計算しなくていいので、1行目を省いて計算する必要があります。
X = [1 2 3; 4 5 6; 7 8 9];
%2行目以降を取得する(Octaveのインデックスは1始まり)
X(2:3, : )
ans =
4 5 6
7 8 9
1行目を0に初期化
1行目を省いて取得してもいいですが、1行目を0に初期化する場合もあります。
X = [1 2 3; 4 5 6; 7 8 9];
%2行目以降を取得する(Octaveのインデックスは1始まり)
X(1, : ) = 0
ans =
0 0 0
4 5 6
7 8 9
Xのi行目にxベクトルを代入
X = [1 2 3; 4 5 6; 7 8 9];
x = [2 2 2];
%2行目にxを代入
X(2, : ) = x
ans =
1 2 3
2 2 2
7 8 9
行列の合成
バイアスを含めて行列計算するために、1列目に1を追加します。
X = [1 2 3; 4 5 6; 7 8 9];
one = ones(3,1);
%1列目に追加
X[one X]
ans =
1 1 2 3
1 2 2 2
s 1 7 8 9