MATLABの行列演算を使いこなそう。

7回目のMATLAB記事です。

今回は「行列（1次元や2次元の配列）の演算」に焦点を当てたいと思います。

といっても、取り上げるのは基礎的な技術というより応用に近いです。


# アダマール積

MATLABのデフォルトでは、行列どうし、ベクトルどうし、行列とベクトルの積に**ドット積**を使用します。

ドット積というのは、数学Cや線形代数で学習した"普通の"行列の積のことです。まるでベクトルの内積のように計算しましたよね(実際、それを目論んで定義したそうです)。

MATLABにおけるドット積の演算子は「*(アスタリスク)」です。これはMATLABのスカラどうしの積の演算子と同じです。というのも、スカラは1×1行列とみなせますのでこの演算子が適用できるのはある意味、当然です。

ドット積に対して**アダマール積**という積演算が存在します。これは行列（ベクトル）どうしを要素ごとに掛けるという演算です。

数学では演算子として「〇(まる)」記号を使います。MATLABでは「.*(ピリオド&アスタリスク)」を使います。

「.」は[5回目](https://qiita.com/arcadia13/items/32d59d91629b83ac3b2b)で既に登場しました。積や累乗の演算を**要素ごとに行うようにする**ためのものでしたね。つまり、アダマール積は「.」と「*」の組み合わせで実現するのです。

例として二つの縦ベクトルのアダマール積を計算してみましょう。

```math
\begin{equation}
\begin{bmatrix}
1\\
2\\
3
\end{bmatrix}
	\circ
\begin{bmatrix}
3\\
4\\
5
\end{bmatrix}
=
\begin{bmatrix}
3\\
8\\
15
\end{bmatrix}
\end{equation}
```

上からそれぞれの第1要素、第2要素、第3要素どうしの積を計算していますね。

MATLABでやってみましょう。

```matlab
 >> [1; 2; 3].*[3; 4; 5]
```

```:実行結果
ans =

     3
     8
    15
```

このアダマール積ですが、例えば機械学習の分野で非常に重要な**誤差逆伝播法**（Backpropagation）を支える技術として使用されています。


# ブロードキャスト

※ブロードキャストという言葉は私がPythonを勉強している時に知ったのですが、それをそのまま持ってきました。なので厳密には間違っているかもしれません。

MATLABで次の演算をやってみましょう。


```matlab
 >>[1; 2]+[1, 2, 3; 4, 5, 6]
```

これをそのまま数式で表すと以下のようになります。

```math
\begin{equation}
\begin{bmatrix}
1\\
2
\end{bmatrix}
+
\begin{bmatrix}
1 & 2 & 3\\
4 & 5 & 6
\end{bmatrix}
\end{equation}
```

普通はできませんね。しかしMATLABでの実行結果はこうなります。

```:実行結果
ans =

     2     3     4
     6     7     8
```

第1項の縦ベクトルの第1要素（つまり1）が第2項の1行目へ、第2要素（つまり2）が2行目へ加算されています。

このように、サイズの違う行列の計算を（限界はあるものの）少しだけ楽にできる機能をブロードキャストといいます。


# ロジカル値配列

MATLABで次の演算をやってみましょう。

```matlab
 >> A=[2, -1; -1, 2];
 >> A>0
```

これをそのまま数式で表すと以下のようになります。

```math
\begin{equation}
A=
\begin{bmatrix}
2 & -1\\
-1 & 2
\end{bmatrix}
>0
\end{equation}
```

この式は数学において、行列 $A$ が**正定である**と主張します。正定とはスカラにおける符号の概念を行列に拡張したものです。実際に行列 $A$ は正定です。

しかし、MATLABでは正定かどうかを判定するわけではありません。

```:実行結果
ans =

  2×2 の logical 配列

   1   0
   0   1
```

このように、$A$ の中で0より大きな要素の場所に1が出てきて、それ以外は0になります。つまり、各要素が0より大きいかどうかを判定しているのです。

結果として出力されたこの配列をロジカル値配列といい、boolean型の配列と全く同じものです。

これを使うと少し面白いことができます。

例えば以下のようなプログラムを実行してみてください。

```matlab
 >> A(A>0)
```

```:実行結果
ans =

     2
     2
```

なんと行列 $A$ の中で0より大きな要素を全て抜き出すことに成功しました。

さらに次のような事も出来ます。

```matlab
 >> A(A>0)=10
```

```:実行結果
A =

    10    -1
    -1    10
```

行列 $A$ において、0より大きい要素を全て10に置き換わっています。

こんな芸当ができるのもロジカル値配列のおかげです。



# 連立方程式の求解

義務教育で習う連立一次方程式（以下、連立方程式）の簡単な例を解いてみましょう。

以下の連立方程式の解を求めます。

```math
\begin{equation}
\left\{
\begin{array}{l}
x+y=4 \\
x+2y=10
\end{array}
\right.
\end{equation}
```

言うまでもありませんが、ここでいう解とは連立方程式を満たす$[x,y]^T$のことです。
※ $T$は行列の転置を表します。

先に答えを示しておくと
```math
\begin{equation}
\begin{bmatrix}
    x\\
    y
  \end{bmatrix}=
\begin{bmatrix}
    -2\\
    6
  \end{bmatrix}
\end{equation}
```
です。実際にこれは問題の連立方程式を満たします。得意なやり方で求めてみてください。

蛇足ですが、連立方程式の求解は**2次元平面において2直線の交点を求めなさい**ということに対応します。

実際にMATLABで図を書いてみました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2736302/46877904-1521-ff66-0685-843d8fb5f7ce.png" width=70%>

青とオレンジの直線が問題の連立方程式が表す直線、赤い縦の点線が両者の交点です。

確かに $[-2,6]^T$ で交わっています。

さて、この連立方程式をMATLABで解いてみましょう。

行列を使って連立方程式を書き直してみると

```math
\begin{equation}
\begin{bmatrix}
    1 & 1\\
    1 & 2
  \end{bmatrix}
\begin{bmatrix}
    x\\
    y
  \end{bmatrix}=
\begin{bmatrix}
    4\\
    10
  \end{bmatrix}
\end{equation}
```

となります。ここで

```math
\begin{equation}
A=
\begin{bmatrix}
    1 & 1\\
    1 & 2
  \end{bmatrix}, 
b=
\begin{bmatrix}
    4\\
    10
  \end{bmatrix}
\end{equation}
```

と置きます。

次に行列 $A$ と ベクトル $b$ をMATLABに定義します。

```matlab
 >> A=[1,1; 1,2]
 >> b=[4; 10]
```

最後に以下のように入力してください。すると解が求まります！

```matlab
 >> A\b
```

```:実行結果
ans =

    -2
     6
```

めちゃくちゃ簡単でしたね！

今回は $x,y$ の2変数でとても簡単でした。手計算で簡単に解を求めることができますし、暗算だって可能でしょう。

しかし、この世には何百、何千、何万もの変数で構成された連立方程式が存在します。私の知る例では**最先端のニューラルネットワーク**がそれに該当します。

その解を手計算で求めるのは現実的に不可能ですし、仮にできたとしても非常に面倒です。

MATLAB等のプログラムで手軽に求めてしまえるのは、本当に時代の進歩を感じます。


# まとめ

今回は行列の演算に焦点を当てました。取り上げた話題を以下にまとめておきます。

* アダマール積
* ブロードキャスト
* ロジカル値配列
* 連立方程式の求解

私自身、基礎的なものより割とニッチな所を取り上げた気がしています。しかし、難しいと感じる内容ではなかったでしょう。

仮に難しかったとしても、少しずつチャレンジしながら自分のMATLABの技術を広げていってほしいです。


# 終わりに

私の高校のカリキュラムは新課程でした。そこでは数学Cが消えて、代わりに数学3を勉強しました。

数学3では数学Cにあった行列が消えて、代わりに複素平面（ガウス平面）が登場します。

工学系の私にとっては行列も複素平面も重要な分野です。しかし、高校で後者を習うということは、一般的には後者の方が扱う分野が多いのでしょうか。

私見ですが、近年の機械学習の潮流を鑑みると、行列を勉強した方が少しだけ楽になるかな、と考えてます。なぜなら機械学習では行列を多用するからです。

まあ、本当のところは分からないですけどね...。

よろしければ次回の記事も読んでくださると大変嬉しいです。

※本記事に対する改善点や修正点、またはこんな事が知りたいといったご意見がありましたらぜひご連絡ください。