TensorFlow : Guide : 低位 API : テンソル (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 07/14/2018
作成日時 : 09/11/2017
* TensorFlow 1.9 でドキュメント構成が変わりましたので調整しました。
* 本ページは、TensorFlow 本家サイトの Guide – Low Level APIs – Tensors を翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、適宜、追加改変している場合もあります。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
TensorFlow は、名前が示すように、テンソルを伴う計算を定義して実行するフレームワークです。テンソルは潜在的にベクトルと行列の高次元への一般化です。内部的には、TensorFlow はテンソルを基本データ型の n-次元配列として表現します。
TensorFlow プログラムを書く時、貴方が操作し渡し回る主要なオブジェクトは tf.Tensor です。tf.Tensor オブジェクトは部分的に定義された計算を表わし、結果的に値を生成するでしょう。TensorFlow プログラムは、最初に tf.Tensor オブジェクトのグラフを構築し、各テンソルが他の利用可能なテンソルを基にどのように計算されるかを詳述し、そして望む結果を得るためにこのグラフの一部を実行することにより、動作します。
tf.Tensor は次のプロパティを持ちます :
- データ型 (float32, int32, また文字列、例として)
- shape (形状)
テンソルの各要素は同じデータ型を持ち、データ型は常に知られています。shape (すなわち、それが持つ次元の数と各次元のサイズ) は部分的にのみ知られているかもしれません。殆どの演算はそれらの入力の shape がまた完全に知られている時、完全に知られた shape のテンソルを生成しますが、ある場合にはグラフ実行時にテンソルの shape を見つけることが可能であるだけです。
テンソルの幾つかの型は特殊で、これらは Programmer’s guide の他のユニットでカバーされるでしょう。主要なものは :
- tf.Variable
- tf.Constant
- tf.Placeholder
- tf.SparseTensor
tf.Variable を除いては、テンソルの値は immutable (= 不変) で、これは単一の実行のコンテキストではテンソルは単一の値を持つだけであることを意味しています。けれども、同じテンソルを二回評価することは異なる値を返す可能性はあります; 例えばそのテンソルはディスクからデータを読んだ結果にも、乱数を生成した結果にも成り得ます。
Rank
tf.Tensor オブジェクトの rank はその次元の数です。rank の同意語は order または degree または n-次元を含みます。TensorFlow の rank は数学の行列 rank (= 階数) と同じではないことに注意してください。以下のテーブルが示すように、TensorFlow の各 rank は異なる数学的実体 (= mathematical entity) に相当します :
Rank | 数学的実体 (= Math entity) |
0 | スカラー (大きさ (= magnitude) のみ) |
1 | ベクトル (大きさと方向) |
2 | 行列 (数のテーブル) |
3 | 3-Tensor (数の立方 (= cube of numbers)) |
n | n-Tensor (you get the idea) |
Rank 0
次のスニペットは2、3の rank 0 variable の作成を示します :
mammal = tf.Variable("Elephant", tf.string) ignition = tf.Variable(451, tf.int16) floating = tf.Variable(3.14159265359, tf.float64) its_complicated = tf.Variable((12.3, -4.85), tf.complex64)
Note : 文字列は TensorFlow ではキャラクタのシークエンスとしてではなく、単一のアイテムとして扱われます。スカラー文字列、文字列のベクトル, etc. を持つことが可能です。
Rank 1
rank 1 tf.Tensor オブジェクトを作成するために、初期値としてアイテムのリストを渡すことができます。例えば :
mystr = tf.Variable(["Hello"], tf.string) cool_numbers = tf.Variable([3.14159, 2.71828], tf.float32) first_primes = tf.Variable([2, 3, 5, 7, 11], tf.int32) its_very_complicated = tf.Variable([(12.3, -4.85), (7.5, -6.23)], tf.complex64)
高 rank (= Higher ranks)
rank 2 tf.Tensor オブジェクトは少なくとも一つの行と少なくとも一つのカラムから成ります :
mymat = tf.Variable([[7],[11]], tf.int16) myxor = tf.Variable([[False, True],[True, False]], tf.bool) linear_squares = tf.Variable([[4], [9], [16], [25]], tf.int32) squarish_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32) rank_of_squares = tf.rank(squarish_squares) mymatC = tf.Variable([[7],[11]], tf.int32)
高-rank テンソルは、同様に、n-次元配列から成ります。例えば、画像処理の間、バッチのサンプル, 画像幅, 画像高さ, そしてカラーチャネルに相当する次元を持つ、rank 4 の多くのテンソルが使用されます。
my_image = tf.zeros([10, 299, 299, 3]) # batch x height x width x color
tf.Tensor オブジェクトの rank を取得する
tf.Tensor オブジェクトの rank を決定するためには、tf.rank メソッドを呼び出します。例えば、次のメソッドは前のセクションで定義された tf.Tensor の rank をプログラムで決定します :
r = tf.rank(my3d) # After the graph runs, r will hold the value 3.
tf.Tensor スライスを参照する
tf.Tensor はセルの n-次元配列ですから、tf.Tensor の単一のセルにアクセスするためには n インデックスを指定する必要があります。
rank 0 テンソル (スカラー) に対しては、インデックスは必要ありません、何故ならばそれは既に単一の数字だからです。
rank 1 テンソル (ベクトル) に対しては、単一のインデックスを渡すことで数字にアクセスすることが可能になります :
my_scalar = my_vector[2]
[] の内側で渡されるインデックスはそれ自身がスカラー tf.Tensor であることも可能です、もしベクトルから要素を動的に選択することを望む場合には。
rank 2 またはそれ以上のテンソルに対しては、状況はより興味深いです。rank 2 の tf.Tensor に対しては、2つの数字を渡すことはスカラーを返します、期待通りです :
my_scalar = my_matrix[1, 2]
単一の数字を渡すことは、けれども、行列の部分ベクトル (= subvector) を返します、次のように :
my_row_vetor = my_matrix[2] my_column_vector = my_matrix[:, 3]
: 表記は “この次元はそのままでおく” ための python スライス・シンタックスです。これは高-rank テンソルでは有用です、その部分ベクトル、部分行列、そして他の部分テンソルにさえもアクセスすることを可能にしますので。
Shape
テンソルの shape は各次元の要素の数です。TensorFlow はグラフ構築の間に shape を自動的に推論します。これらの推論された shape は rank を知っていたかもしれませんし、知らなかったかもしれません。rank が知られていたのであれば、各次元のサイズは知られているかもしれませんし、知られていないかもしれません。
TensorFlow ドキュメンテーションはテンソル次元性を記述するために3つの表記規則を使用します : rank, shape, そして次元数です。次のテーブルはこれらが他のもの一つとどのように関係するかを示します :
Rank | Shape | 次元数 (= Dimension number) | 例 |
0 | [] | 0-D | 0-D テンソル。スカラー。 |
1 | [D0] | 1-D | shape [5] を持つ 1-D テンソル。 |
2 | [D0, D1] | 2-D | shape [3, 4] を持つ 2-D テンソル。 |
3 | [D0, D1, D2] | 3-D | shape [1, 4, 3] を持つ 3-D テンソル。 |
n | [D0, D1, … Dn-1] | n-D | shape [D0, D1, … Dn-1] を持つテンソル。 |
shape は int のPython リスト / タプルを通して、または tf.TensorShape で表されます。
tf.Tensor オブジェクトの shape を取得する
tf.Tensor の shape にアクセスする2つの方法があります。グラフを構築する間、テンソルの shape について既に何が知れているのか問うことはしばしば有用です。これは tf.Tensor オブジェクトの shape プロパティを読むことで成されます。このメソッドは TensorShape オブジェクトを返します、これは部分的に指定された shape を表す便利な方法です(何故ならば、グラフを構築する時に、総ての shape が完全には知られていないからです)。
実行時に他の tf.Tensor の完全に定義された shape を表す tf.Tensor を取得することもまた可能です。これは tf.shape 演算子を呼び出すことで成されます。このようにして、入力 tf.Tensor の動的な shape に依存する他のテンソルを構築することによりテンソルの shape を操作するグラフを構築できます。
例えば、これが、与えられた行列のカラム数と同じサイズを持つゼロのベクトルをどのように作成するかです :
zeros = tf.zeros(tf.shape(my_matrix)[1])
tf.Tensor の shape を変更する
テンソルの要素の数は総てのその shape のサイズの積です。スカラーの要素の数は常に 1 です。同じ要素数を持つ多くの異なる shape がしばしばあるので、その要素数は固定したまま、tf.Tensor の shape を変更することができることはしばしば便利です。これは tf.reshape で成されます。
次のサンプルはテンソルをどのように reshape するかを示します :
rank_three_tensor = tf.ones([3, 4, 5]) matrix = tf.reshape(rank_three_tensor, [6, 10]) # Reshape existing content into # a 6x10 matrix matrixB = tf.reshape(matrix, [3, -1]) # Reshape existing content into a 3x20 # matrix. -1 tells reshape to calculate # the size of this dimension. matrixAlt = tf.reshape(matrixB, [4, 3, -1]) # Reshape existing content into a #4x3x5 tensor # Note that the number of elements of the reshaped Tensors has to match the # original number of elements. Therefore, the following example generates an # error because no possible value for the last dimension will match the number # of elements. yet_another = tf.reshape(matrixAlt, [13, 2, -1]) # ERROR!
データ型
次元性に加えて、テンソルはデータ型を持ちます。データ型の完全なリストのためには programmer’s guide の tf.DataType ページを参照してください。(訳注: リンク欠落)
一つ以上のデータ型を持つ tf.Tensor を持つことはできません。けれども、任意のデータ構造を文字列としてシリアライズ化してそれらを tf.Tensor にストアすることは可能です。
tf.cast を使用して一つのデータ型から他へ tf.Tensor をキャストすることは可能です :
# Cast a constant integer tensor into floating point. float_tensor = tf.cast(tf.constant([1, 2, 3]), dtype=tf.float32)
tf.Tensor のデータ型を調べるためには Tensor.dtype プロパティを使用します。python オブジェクトから tf.Tensor を作成する時 datatype をオプションで指定しても良いです。そうしない場合、TensorFlow は貴方のデータを表せる datatype を選択します。TensorFlow は Python 整数を tf.int32 にそして python 浮動小数点数を tf.float32 に変換します。それ以外では TensorFlow は配列に変換する時 numpy が使用するのと同じ規則を使用します。
Tensor を評価する
計算グラフが一度構築されれば、特定の tf.Tensor を生成してそれに割り当てられた値を取得する計算を実行できます。これは TensorFlow の多くが動作するために必要なだけでなくしばしばデバッグに有用です。
Tensor を評価する最も単純な方法は Tensor.eval メソッドを使用することです。例えば :
constant = tf.constant([1, 2, 3]) tensor = constant * constant print tensor.eval()
eval メソッドは default tf.Session がアクティブである時だけ動作します (更なる情報のためには Graphs and Sessions を見てください (訳注: リンク欠落))。
Tensor.eval はテンソルとして同じ内容を持つ numpy 配列を返します。
時々 tf.Tensor が no context で評価できません、これはその値が利用可能でない動的な情報に依存しているからかもしれません。例えば、Placeholder に依存するテンソルは Placeholder に値を提供することなしに評価できません。
p = tf.placeholder(tf.float32) t = p + 1.0 t.eval() # This will fail, since the placeholder did not get a value. t.eval(feed_dict={p:2.0}) # This will succeed because we're feeding a value # to the placeholder.
placeholder だけでなく、任意の tf.Tensor に供給できることに注意してください。
他のモデル構築は tf.Tensor の評価を複雑にするかもしれません。関数の内側や制御フロー構築の内側で定義された tf.Tensor を直接的に評価することはできません。tf.Tensor がキューからの値に依存するのであれば、tf.Tensor の評価は何かがキューに入れられた時に限り動作するでしょう ; そうでなければ、その評価はハングアップするでしょう。キューで作業する時は、どのような tf.Tensor でも評価する前に tf.train.start_queue_runners を呼び出すことを忘れないでください。
Tensor を出力表示する
デバッグ目的でtf.Tensor の値を出力表示することを望む場合もあるでしょう。tfdbg が高度なデバッグ・サポートを提供する一方で、TensorFlow は tf.Tensor の値を直接的に出力表示する演算子もまた持っています。
tf.Tensor を出力表示するとき次のパターンを使用することを望むことは滅多にないことに注意してください :
t = <> print t # This will print the symbolic tensor when the graph is being built. # This tensor does not have a value in this context.
このコードは tf.Tensor オブジェクト (これは繰延べられた計算を表します) を出力表示します、その値ではありません。代わりに、TensorFlow は tf.Print 演算子を提供します、これはその最初のテンソル引数をそのまま返す一方で2番目の引数として渡された tf.Tensor のセットを出力表示します。
tf.Print を正しく使用するためにはその戻り値が使用されなければなりません。下のサンプルを見てください :
t = <> tf.Print(t, [t]) # This does nothing t = tf.Print(t, [t]) # Here we are using the value returned by tf.Print result = t + 1 # Now when result is evaluated the value of `t` will be printed.
result を評価するとき result が依存する総てのものを評価するでしょう。result は t に依存し、そして t の評価はその入力 (t の古い値) を出力表示する副作用を持ちますので、t は出力表示されます。
以上