このページは Cloud Translation API によって翻訳されました。
Switch to English

tf.map_fn

TensorFlow 1バージョン GitHubでソースを表示する

変換elems適用することによってfn軸0(非推奨の引数)にアンスタックの各要素に対して

ノートブックで使用

ガイドで使用チュートリアルで使用

tf.scanも参照してください。

map_fnは、要素0の要素をスタックelemsして、要素のシーケンスを取得します。 fnを呼び出して各要素を変換します。次に、変換された値をスタックします。

シングルテンソル入力および出力を使用したマッピング関数

elemsが単一のテンソルであり、 fnのシグネチャがtf.Tensor->tf.Tensorである場合、 map_fn(fn, elems)tf.stack([fn(elem) for elem in tf.unstack(elems)]) 。例えば:

tf.map_fn(fn=lambda t: tf.range(t, t + 3), elems=tf.constant([3, 5, 2]))
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
  array([[3, 4, 5],
         [5, 6, 7],
         [2, 3, 4]], dtype=int32)>

map_fn(fn, elems).shape = [elems.shape[0]] + fn(elems[0]).shape

マルチアリティの入力と出力を持つマッピング関数

map_fnは、マルチアリティの入出力を備えた関数もサポートしています。

  • elemsがテンソルのタプル(またはネストされた構造)である場合、それらのテンソルはすべて同じ外次元サイズ( num_elems )でなければなりません。そしてfnは、対応するスライスの各タプル(または構造)をelemsから変換するために使用されます。たとえば、 elemsがタプル(t1, t2, t3)場合、 fnを使用してスライスの各タプル(t1[i], t2[i], t3[i])を変換します( 0 <= i < num_elems ) 。

  • fnがテンソルのタプル(またはネストされた構造)を返す場合、結果はそれらの構造の対応する要素をスタックすることによって形成されます。

fnの出力署名の指定

fnの入力署名と出力署名が異なる場合は、 fn_output_signatureを使用して出力署名を指定する必要があります。 (入力と出力のシグネチャは、それらの構造、dtype、またはテンソルタイプが一致しない場合は異なります)。例えば:

tf.map_fn(fn=tf.strings.length,  # input & output have different dtypes
          elems=tf.constant(["hello", "moon"]),
          fn_output_signature=tf.int32)
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([5, 4], dtype=int32)>
tf.map_fn(fn=tf.strings.join,  # input & output have different structures
          elems=[tf.constant(['The', 'A']), tf.constant(['Dog', 'Cat'])],
          fn_output_signature=tf.string)
<tf.Tensor: shape=(2,), dtype=string,
 numpy=array([b'TheDog', b'ACat'], dtype=object)>

fn_output_signatureは、次のいずれかを使用して指定できます。

RaggedTensors

map_fnは、 tf.RaggedTensor入力と出力をサポートします。特に:

  • elemsRaggedTensor場合、その不規則なテンソルの各行でfnが呼び出されます。

    • elems不揃いな次元が1つしかない場合、 fn渡される値はtf.Tensor sになります。
    • elemsに複数の不規則な次元がある場合、 fn渡される値は、1つ少ない不規則な次元を持つtf.RaggedTensorなります。
  • 結果ならばmap_fnあるべきRaggedTensor 、その後、使用tf.RaggedTensorSpec指定するfn_output_signature

# Example: RaggedTensor input
rt = tf.ragged.constant([[1, 2, 3], [], [4, 5], [6]])
tf.map_fn(tf.reduce_sum, rt, fn_output_signature=tf.int32)
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([6, 0, 9, 6], dtype=int32)>
# Example: RaggedTensor output
elems = tf.constant([3, 5, 0, 2])
tf.map_fn(tf.range, elems,
          fn_output_signature=tf.RaggedTensorSpec(shape=[None],
                                                  dtype=tf.int32))
<tf.RaggedTensor [[0, 1, 2], [0, 1, 2, 3, 4], [], [0, 1]]>
  • tf.ragged.map_flat_values(fn, rt) (fnがTensorFlow opsとして表現可能な場合)
  • rt.with_flat_values(map_fn(fn, rt.flat_values)) (それ以外の場合)

例えば:

rt = tf.ragged.constant([[1, 2, 3], [], [4, 5], [6]])
tf.ragged.map_flat_values(lambda x: x + 2, rt)
<tf.RaggedTensor [[3, 4, 5], [], [6, 7], [8]]>

SparseTensors

map_fntf.sparse.SparseTensor入力と出力をサポートします。特に:

  • elemsSparseTensor場合、その疎なテンソルの各行でfnが呼び出されます。特に、 fn渡される値は、 tf.sparse.SparseTensorよりも次元が1つ少ないelemsます。

  • 結果ならばmap_fnあるべきSparseTensor 、その後、使用tf.SparseTensorSpec指定するfn_output_signaturefnによって返される個々のSparseTensor 、もう1つの次元を持つ単一のSparseTensorスタックされます。

# Example: SparseTensor input
st = tf.sparse.SparseTensor([[0, 0], [2, 0], [2, 1]], [2, 3, 4], [4, 4])
tf.map_fn(tf.sparse.reduce_sum, st, fn_output_signature=tf.int32)
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([2, 0, 7, 0], dtype=int32)>
# Example: SparseTensor output
tf.sparse.to_dense(
    tf.map_fn(tf.sparse.eye, tf.constant([2, 3]),
              fn_output_signature=tf.SparseTensorSpec(None, tf.float32)))
<tf.Tensor: shape=(2, 3, 3), dtype=float32, numpy=
  array([[[1., 0., 0.],
          [0., 1., 0.],
          [0., 0., 0.]],
         [[1., 0., 0.],
          [0., 1., 0.],
          [0., 0., 1.]]], dtype=float32)>
  • 関数がTensorFlow opsとして表現できる場合は、次を使用します。
 tf.sparse.SparseTensor(st.indices, fn(st.values), st.dense_shape)
 
  • それ以外の場合は、次を使用します。
 tf.sparse.SparseTensor(st.indices, tf.map_fn(fn, st.values),
                       st.dense_shape)
 

map_fnとベクトル化された演算

map_fnは、 fnによって使用される操作をelems各要素にelems 、結果としてO(elems.shape[0])合計操作になります。これは、 map_fnが要素を並行して処理できるという事実によって多少緩和されます。ただし、 map_fnを使用して表現された変換は、通常、ベクトル化された演算を使用して表現された同等の変換よりも効率的ではありません。

map_fnは通常、次のいずれかに該当する場合にのみ使用する必要があります。

  • ベクトル化された演算で目的の変換を表現することは困難または費用がかかります。
  • fnは大きな中間値を作成するため、同等のベクトル化された変換はメモリを大量に消費します。
  • 要素の並列処理は、同等のベクトル化された変換よりも効率的です。
  • 変換の効率は重要ではなく、 map_fnを使用map_fnと読みやすくなります。

例えば、マップ上で与えた例fn=lambda t: tf.range(t, t + 3)を横切るelemsベクトル化OPSを使用して、より効率的に書き換えることができます。

elems = tf.constant([3, 5, 2])
tf.range(3) + tf.expand_dims(elems, 1)
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
  array([[3, 4, 5],
         [5, 6, 7],
         [2, 3, 4]], dtype=int32)>

場合によっては、 tf.vectorized_mapを使用して、関数をベクトル化された等価に自動的に変換できます。

熱心な実行

熱心に実行する場合、 parallel_iterationsが1より大きい値に設定されていても、 map_fnは並列で実行されませんtf.functionデコレーターを使用すると、関数を並列で実行することによるパフォーマンス上の利点を得ることができます。

fn=lambda t: tf.range(t, t + 3)
@tf.function
def func(elems):
  return tf.map_fn(fn, elems, parallel_iterations=3)
func(tf.constant([3, 5, 2]))
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
  array([[3, 4, 5],
         [5, 6, 7],
         [2, 3, 4]], dtype=int32)>

fn 実行される呼び出し可能オブジェクト。これは、 elemsと同じ(おそらくネストされている)構造を持つ1つの引数を受け入れます。出力が提供されてfn_output_signature場合、その出力はfn_output_signatureと同じ構造でなければなりません。それ以外の場合は、 elemsと同じ構造でなければなりません。
elems テンソルまたは(場合によってはネストされた)テンソルのシーケンス。各テンソルは、最初の次元に沿ってスタック解除されます。 fnは、結果のスライスのネストされたシーケンスに適用されます。 elemsは、不揃いで疎なテンソルが含まれる場合があります。
dtype 非推奨: fn_output_signature同等fn_output_signature
parallel_iterations (オプション)並行して実行できる反復の数。グラフ作成時のデフォルト値は10です。熱心に実行している間、デフォルト値は1に設定されます。
back_prop (オプション)非推奨:代わりにtf.stop_gradientを使用することをおtf.stop_gradientます。 Falseは、逆伝播のサポートを無効にします。
swap_memory (オプション)Trueは、GPU-CPUメモリスワッピングを有効にします。
infer_shape (オプション)Falseは、一貫した出力形状のテストを無効にします。
name (オプション)返されるテンソルの名前接頭辞。
fn_output_signature fnの出力署名。 fnの入力署名と出力署名が異なる場合(つまり、それらの構造、dtype、またはテンソルタイプが一致しない場合)を指定する必要があります。 fn_output_signatureは、次のいずれかを使用して指定できます。

テンソルまたは(場合によってはネストされた)テンソルのシーケンス。各テンソルは、最初から最後まで、最初の次元に沿って要素からelemsれたテンソルにfnを適用した結果をスタックします。結果には、不規則で疎なテンソルが含まれる場合があります。

TypeError fnが呼び出し可能でないか、 fnの出力の構造とfn_output_signatureが一致しない場合。
ValueError fnfn_output_signature出力の長さが一致しない場合。

例:

elems = np.array([1, 2, 3, 4, 5, 6])
tf.map_fn(lambda x: x * x, elems)
<tf.Tensor: shape=(6,), dtype=int64, numpy=array([ 1,  4,  9, 16, 25, 36])>
elems = (np.array([1, 2, 3]), np.array([-1, 1, -1]))
tf.map_fn(lambda x: x[0] * x[1], elems, fn_output_signature=tf.int64)
<tf.Tensor: shape=(3,), dtype=int64, numpy=array([-1,  2, -3])>
elems = np.array([1, 2, 3])
tf.map_fn(lambda x: (x, -x), elems,
         fn_output_signature=(tf.int64, tf.int64))
(<tf.Tensor: shape=(3,), dtype=int64, numpy=array([1, 2, 3])>,
 <tf.Tensor: shape=(3,), dtype=int64, numpy=array([-1, -2, -3])>)