2016-02-17 10 views
12

478 x 717 x 3 = 1028178ピクセルで、ランクが1の画像があります。tf.shapeとtf.rankを呼び出して確認しました。tf.Tensor.set_shape()の説明

image.set_shape([478,717,3])を呼び出すと、次のエラーがスローされます。

"Shapes %s and %s must have the same rank" % (self, other)) 
ValueError: Shapes (?,) and (478, 717, 3) must have the same rank 

最初に1028178にキャストして再度テストしましたが、エラーは依然として存在します。 1ランク1であり、他方が、なぜそれが総画素数はまだ一致して、エラーをスローする必要がある。しかし、ランク3であるので、意味を成さない

ValueError: Shapes (1028178,) and (478, 717, 3) must have the same rank 

まあ、。

もちろん、tf.reshapeを使うこともできますが、うまく動作しますが、最適ではないと思います。 TensorFlowよくある質問

x.set_shape()とx = tf.reshape(x)の違いは何である上に述べたように

tf.Tensor.set_shape()メソッドは、Tensor オブジェクトの静的形状を更新し、これを直接推論することができない場合には追加の形状 情報を提供するために通常使用されます。 テンソルの動的形状を変更しません。

tf.reshape()演算は、異なる動的形状を持つ新しいテンソルを作成します。

新しいテンソルを作成するとメモリ割り当てが行われ、より多くのトレーニング例が含まれていると、コストが高くなる可能性があります。これは設計上のものか、ここに何か不足していますか?

+1

実際の問題は、再構成されたTensorが元のテンソルとデータバッファを共有するかどうか、またはコピーを行うかどうかです。私はコードの速読からかなり分かりませんでしたが、コピーをすると固定されるべきものです –

+0

mrryは下の彼の答えで浅いコピーであると精緻化しました。 – jkschin

答えて

34

私が知る限り(そして私はそのコードを書いた)、Tensor.set_shape()にはバグはありません。私はその誤解がその方法の混乱した名前に由来していると思います。 FAQ entry you quotedに詳しく説明し

Tensor.set_shape()が所定tf.Tensorオブジェクトの形状情報を改善することを純粋なPythonの関数です。 「改善する」とは、「より具体的にする」という意味です。

したがってTensorオブジェクトtの形状が(?,)の場合、それは未知の長さの1次元テンソルです。 t.set_shape((1028178,))に電話をし、tt.get_shape()に電話すると(1028178,)の形になります。これは、基礎となるストレージ、またはバックエンドで実際には何も影響しません:それは単にtを使用して、その後の形状の推論は、(?,)を形作るた長さ1028178.

tた場合のベクトル、であるという主張に頼ることができることを意味しt.set_shape((478, 717, 3))への呼び出しは失敗します.TensorFlowは既にtがベクトルであることを知っているため、の形状は(478, 717, 3)ではありません。その形の新しいテンソルをtの内容から作成する場合は、reshaped_t = tf.reshape(t, (478, 717, 3))を使用できます。これにより、Pythonで新しいtf.Tensorオブジェクトが作成されます。実際のimplementation of tf.reshape()はテンソルバッファの浅いコピーを使用してこれを行いますので、実際には安価です。

1つの類推は、Tensor.set_shape()は、Javaのようなオブジェクト指向言語の実行時キャストのようなものです。たとえば、Objectへのポインタがありますが、実際にはStringであることがわかっている場合、String引数を受け取るメソッドにobjを渡すには、キャスト(String) objを実行することがあります。しかし、Stringsがあり、java.util.Vectorにキャストしようとすると、これらの2つのタイプは無関係であるため、コンパイラはエラーを表示します。

+0

詳細な回答をいただきありがとうございます。 – jkschin