えーっと、単当直中に言うと、昨日の更新はサボりましたw。3日坊主にもなりませんでしたね。そのお詫びというか補填として今日は記事を長く書こうと思います。
tensorflowでのベクトル・行列宣言
本日1つ目の内容は、ベクトルと行列についてです。ベクトルと行列はプログラムを少しやっている人であれば似たような宣言方法で宣言することが出来ることがわかると思います。(実際のデータの保存もシンプルな方法で言えば1次元配列か2次元配列かの違いなので)では実際にtensorflowでのベクトルと行列の宣言方法を見ていきましょう。
- ベクトル:tensorflow.constant([要素1, 要素2,…])
- 行列:tensorflow.constant([[1行目の要素1,要素2,…], [2行目の要素1,…], …])
これを見てもわかりずらいかもしれません。結局のところ、pythonの1次元リストと多次元リストを渡しているだけなのでそんなに心配しなくても大丈夫です。実際のサンプルコードを見てみればおそらくピンとくると思います。
#インポート
import tensorflow as tf
#式の定義
# ベクトルの定数定義
vector1=tf.constant([1,2])
vector2=tf.constant([2,1])
# 行列の定数定義
matrix1=tf.constant([[1,2],[3,4]])
matrix2=tf.constant([[3,4],[1,2]])
# ベクトルの加算
add1=tf.add(vector1,vector2)
# 行列の加算
add2=tf.add(matrix1,matrix2)
#式の定義終了
#セッションの実行
with tf.Session() as session:
print("add vector\t:\n",session.run(add1))
print("add matrix\t:\n",session.run(add2))
<実行結果>
add vector :
[3 3]
add matrix :
[[4 6]
[4 6]]
実行結果を見ると、ベクトル同士の演算と、\(2 \times 2\)行列の足し算が正常に行われていることがわかります。一応、念のためにと、Webサイトに数式を書く練習ついでに計算式を書いておきます。
- ベクトル式
$$
\left(
\begin{array}{c}
1\\
2\\
\end{array}
\right)
+
\left(
\begin{array}{c}
2\\
1\\
\end{array}
\right)
=
\left(
\begin{array}{c}
3\\
3\\
\end{array}
\right)
$$
- 行列式
$$
\begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}
+
\begin{pmatrix} 3 & 4 \\ 1 & 2 \end{pmatrix}
=
\begin{pmatrix} 4 & 6 \\ 4 & 6 \end{pmatrix}
$$
簡単すぎて当然わかるレベルですが、実行結果と合っていることがわかりましたね。
tensorflowでの行列演算
ベクトル・行列、ベクトル・行列と来てこの節ではベクトルではなく行列を先にやります。その理由としてはベクトルの内積が少しややこしくなっているために行列を先に行った方が都合が良いためです。特に気にせずに行っていきましょう
行列では、スカラーでの四則演算を行うことができません。加算と減算は要素同士を足し引きする簡単なものですが、乗算は要素同士での乗算ではありません。そのため、行列の乗算には特別なメソットが用意されています。いつも同様見ていきましょう。
- 行列の乗算:tensorflow.matmul(行列1,行列2)
どうでしょうか?比較的簡単ですね。ただし、行列の乗算なので計算時には行列の次元に注意してください。行列の乗算が可能な場合は(\(n \times m\)行列と\(m \times p\)行列のみというルールがあります。では実際にやってみましょう。
#インポート
import tensorflow as tf
#式の定義
# 行列の定数定義
matrix1=tf.constant([[1,2],[3,4],[5,6]])
matrix2=tf.constant([[1,2,3],[4,5,6]])
# ベクトルの加算
matmul=tf.matmul(matrix1,matrix2)
#式の定義終了
#セッションの実行
with tf.Session() as session:
print("matmul\t:\n",session.run(matmul))
<実行結果>
matmul :
[[ 9 12 15]
[19 26 33]
[29 40 51]]
式で示すとこのような形になります。
$$
\begin{eqnarray}
\left(
\begin{array}{cc}
1 & 2 \\
3 & 4 \\
5 & 6
\end{array}
\right)
+
\left(
\begin{array}{ccc}
1 & 2 & 3 \\
4 & 5 & 6
\end{array}
\right)
=
\left(
\begin{array}{ccc}
9 & 12 & 15 \\
19 & 26 & 33 \\
29 & 40 & 51
\end{array}
\right)
\end{eqnarray}
$$
計算は複雑ですが、電卓などを使用して計算すると正しいことがわかりますね。
tensorflowでのベクトル演算
さて、行列の計算法も終わり、次はベクトルについてです。ベクトルといえば、スカラー値で使用する演算以外にも、特別な演算を行えると思います。いわゆる内積や外積ですね。それらをどのように実行していくかを確認してみましょう。まぁ、いつもの通り結果から書きます。と言いたいところですが、内積については少々複雑なので、先に外積の計算方法について見てみましょう。
- 外積:tensorflow.cross(ベクトル1,ベクトル2)
特に難しいことはないと思います。プログラムで試すのは少し後にして、先に内積についての説明をして見ましょう。
さて、ベクトルの内積についての説明をこんなにももったいぶったのにはきちんとわけがあります。簡単にいうと、ベクトルの内積を計算する関数はtensorflowには存在しません。もちろん不可能ではないですが、少々ソースコードを書くのが面倒くさくなってしまいますね。しかし、ベクトルではないのですが、ベクトルのように使えて内積や外積が簡単にできる方法があります。それは、ベクトルとしての記法ではなく、行列として計算を行うという手法です。何を言っているのかさっぱりだと思いますので、外積のものも含めてサンプルプログラムを動かしてみましょう
#インポート
import tensorflow as tf
#式の定義
# ベクトルの定数定義
vector1=tf.constant([1,2,3])
vector2=tf.constant([3,2,1])
# 行列としてのベクトルの定数定義
matrix_vector1=tf.constant([[1,2,3]])
matrix_vector2=tf.constant([[3,2,1]])
# ベクトルの内積 (内積の英語訳は"inner product"らしいね)
inner=tf.matmul(matrix_vector1,matrix_vector2,transpose_b=True)
# 行列の外積 (外積の英語訳は"cross product"らしいね)
cross=tf.cross(vector1,vector2)
cross_matrix=tf.cross(matrix_vector1,matrix_vector2)
#式の定義終了
#セッションの実行
with tf.Session() as session:
print("inner product\t\t:\n",session.run(inner))
print("cross product\t\t:\n",session.run(cross))
print("cross product on mtrix type\t:\n",session.run(cross_matrix))
注意:tf.matmulのtranspose_b=True引数はmatrix_vector2をmatrix_vector1と乗算可能にするように転地を行うという指定。
<実行結果>
inner product :
[[10]]
cross product :
[-4 8 -4]
cross product on mtrix type :
[[-4 8 -4]]
何をしているかわかったでしょうか?この記事の冒頭で、ベクトルは[a,b,…]と記載すると解説したと思います。しかし、上記のプログラムでは、ベクトルではなく、行列として(つまり[[a,b,…]]として)記載しています。これは一見どうでも良さそうですが非常に重要な意味を持ちます。これは、tensorflowの仕組みの話になるのですが、ベクトルの宣言方法を使用して定数を用意すると、tensorflowはRANK1の行列として認識します。RANK1というのは、プログラミング言語的にいうならば1次元配列だということです。そして、ここが重要なのですが、tensorflowのmatmul関数はRANK1の値では実行することができません。なので、行列として宣言することでRANK2の値として扱ってもらい、matmul関数を使用することで簡単に内積を実現しているのです。また、このRANKの確認方法はtensorflowにおいてshapeとして確認することができます。実際に確認して見ましょう。
#インポート
import tensorflow as tf
#ベクトルの定数定義
vector=tf.constant([1,2,3])
#行列としてのベクトルの定数定義
matrix_vector=tf.constant([[1,2,3]])
#shapeの確認
print("vector\t:",vector.shape)
print("matrix\t:",matrix_vector.shape)
<実行結果>
vector : (3,)
matrix : (1, 3)
どうでしょうか?ベクトルの場合には値が1つしかなかったのに対し、行列の場合には、2つ存在することがわかりますね。このことから、その変数のRANKを確認することができます。
さて、これらのことを踏まえると、記事の見出しに書いたこととは裏腹に、ベクトルの宣言はあまりしない方が良いと自分は思います。今後の記事でもベクトルの記法は多分しないのではないかと思います。
今日の内容は以上!
まとめ
- ベクトル宣言:tensorflow.constant([[ベクトルの要素1,ベクトルの要素2]])
- 行列宣言:tensorflow.constant([[1行目の要素1,…], [2行目の要素1,…], …])
- 内積:tensorflow.matmul(ベクトル1,ベクトル2,transpose_b=True)
- 外積:tensorflow.cross(ベクトル1,ベクトル2)
- 行列の乗算:tensorflow.matmul(行列1,行列2)