TensorFlowの日本語まとめ

TensorFlowの公式サイトに書かれている英文を英語ど素人が翻訳(日本語訳/和訳)します。 間違いがありましたら、優しく教えていただけますと幸いです。 内容を理解したら、使ってみたい。

8.OP登録 Polymorphism

Polymorphism

Type Polymorphism

 入力として、異なる種類取るか、または異なる出力タイプを生成することができOPSでは、OPの登録で入力または出力タイプattrを指定することができます通常は、各サポートされているタイプの OpKernelを登録する必要があります。

 

f:id:TensorFlow:20160130022551j:plain

スポンサーリンク

 

 

たとえばあなたがint32sに加えて、floats上で動作するようにZeroOut OPのようにしたい場合はあなたのオペアンプ登録は、次のようになります。:

REGISTER_OP("ZeroOut")
    .Attr("T: {float, int32}")
    .Input("to_zero: T")
    .Output("zeroed: T");

あなたのオペアンプ登録は現在、両方の型はT有しているので入力タイプfloatまたはint32でなければならないことおよびその出力は同じ型になることを指定します

 

命名上の注意:{#naming}入力は出力およびattrsに、一般snake_case与えられるべきです唯一の例外は、入力のタイプとして、または入力のタイプで使用されているattrsにあります。これらattrsには、OPをグラフに追加されたときに推測することができるので、OPの機能には表示されません。例えば、ZeroOutのこの最後の定義は以下のようになりますPythonの関数を生成します。

def zero_out(to_zero, name=None):
  """...
  Args:
    to_zero: A `Tensor`. Must be one of the following types:
        `float32`, `int32`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor`. Has the same type as `to_zero`.
  """

to_zeroint32テンソルを渡された場合、Tは、自動的に(実際には、よくDT_INT32)をint32に設定されています

出力タイプを決定するタイプattrのを持つOPとこれを比較します。

REGISTER_OP("StringToNumber")
    .Input("string_tensor: string")
    .Output("output: out_type")
    .Attr("out_type: {float, int32}");
    .Doc(R"doc(
Converts each string in the input Tensor to the specified numeric type.
)doc");


この場合、ユーザは、生成されたPythonでのように、出力形式を指定する必要があります。:

def string_to_number(string_tensor, out_type=None, name=None):
  """Converts each string in the input Tensor to the specified numeric type.

  Args:
    string_tensor: A `Tensor` of type `string`.
    out_type: An optional `tf.DType` from: `tf.float32, tf.int32`.
      Defaults to `tf.float32`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` of type `out_type`.
  """

 

#include "tensorflow/core/framework/op_kernel.h"
class ZeroOutInt32Op : public OpKernel { // as before };
class ZeroOutFloatOp : public OpKernel { public: explicit ZeroOutFloatOp(OpKernelConstruction* context) : OpKernel(context) {}
void Compute(OpKernelContext* context) override { // Grab the input tensor const Tensor& input_tensor = context->input(0); auto input = input_tensor.flat<float>();
// Create an output tensor Tensor* output = NULL; OP_REQUIRES_OK(context, context->allocate_output(0, input_tensor.shape(), &output)); auto output_flat = output->template flat<float>();
// Set all the elements of the output tensor to 0 const int N = input.size(); for (int i = 0; i < N; i++) { output_flat(i) = 0; }
// Preserve the first input value if (N > 0) output_flat(0) = input(0); } };
// Note that TypeConstraint<int32>("T") means that attr "T" (defined // in the Op registration above) must be "int32" to use this template // instantiation. REGISTER_KERNEL_BUILDER( Name("ZeroOut") .Device(DEVICE_CPU) .TypeConstraint<int32>("T"), ZeroOutOpInt32); REGISTER_KERNEL_BUILDER( Name("ZeroOut") .Device(DEVICE_CPU) .TypeConstraint<float>("T"), ZeroOutFloatOp);

既存のOPにattrを追加する際に後方互換性を維持するには、デフォルト値を指定する必要があります。

 REGISTER_OP("ZeroOut")

  .Attr("T: {float, int32} = DT_INT32")
  .Input("to_zero: T")
  .Output("zeroed: T")

 それでは、あなたはdouble言うより多くの種類を追加したいとしましょう:

REGISTER_OP("ZeroOut")
    .Attr("T: {float, double, int32}")
    .Input("to_zero: T")
    .Output("zeroed: T");

 代わりに、上記のように冗長なコードで別のOpKernel書き込むので多くの場合、あなたの代わりにC++テンプレートを使用することができるようになりますあなたはまだ過負荷ごとにカーネル登録(REGISTER\_KERNEL\_BUILDER コール)を持つことになります。

template <typename T>
class ZeroOutOp : public OpKernel {
 public:
  explicit ZeroOutOp(OpKernelConstruction* context) : OpKernel(context) {}
void Compute(OpKernelContext* context) override { // Grab the input tensor const Tensor& input_tensor = context->input(0); auto input = input_tensor.flat<T>();
// Create an output tensor Tensor* output = NULL; OP_REQUIRES_OK(context, context->allocate_output(0, input_tensor.shape(), &output)); auto output_flat = output->template flat<T>();
// Set all the elements of the output tensor to 0 const int N = input.size(); for (int i = 0; i < N; i++) { output_flat(i) = 0; }
// Preserve the first input value if (N > 0) output_flat(0) = input(0); } };
// Note that TypeConstraint<int32>("T") means that attr "T" (defined // in the Op registration above) must be "int32" to use this template // instantiation. REGISTER_KERNEL_BUILDER( Name("ZeroOut") .Device(DEVICE_CPU) .TypeConstraint<int32>("T"), ZeroOutOp<int32>); REGISTER_KERNEL_BUILDER( Name("ZeroOut") .Device(DEVICE_CPU) .TypeConstraint<float>("T"), ZeroOutOp<float>); REGISTER_KERNEL_BUILDER( Name("ZeroOut") .Device(DEVICE_CPU) .TypeConstraint<double>("T"), ZeroOutOp<double>);


あなたはカップルのオーバーロードが複数ある場合は、マクロの登録を置くことができます。

#include "tensorflow/core/framework/op_kernel.h"

#define REGISTER_KERNEL(type)                                       \
  REGISTER_KERNEL_BUILDER(                                          \
      Name("ZeroOut").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      ZeroOutOp<type>)

REGISTER_KERNEL(int32);
REGISTER_KERNEL(float);
REGISTER_KERNEL(double);

#undef REGISTER_KERNEL

あなたがカーネルを登録しているタイプのリストに応じて、tensorflow/core/framework/register_types.hが提供するマクロを使用することができる場合があります。:

#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"

REGISTER_OP("ZeroOut")
    .Attr("T: realnumbertype")
    .Input("to_zero: T")
    .Output("zeroed: T");

template <typename T>
class ZeroOutOp : public OpKernel { ... };

#define REGISTER_KERNEL(type)                                       \
  REGISTER_KERNEL_BUILDER(                                          \
      Name("ZeroOut").Device(DEVICE_CPU).TypeConstraint<type>("T"), \
      ZeroOutOp<type>)

TF_CALL_REAL_NUMBER_TYPES(REGISTER_KERNEL);

#undef REGISTER_KERNEL

List Inputs and Outputs

受け入れまたは異なるタイプを生成することが可能であることに加えて、OPSは、消費またはテンソルの可変数を生成することができます

 

次の例では、attr Tはタイプのリストを保持し、入力と出力のうちの両方のタイプとして使用されます。入力と出力は、その型のテンソルのリスト(両方の型はTを有しているので、出力におけるテンソルの数と種類は、入力と同じである)です。

 REGISTER_OP("PolymorphicListExample")

    .Attr("T: list(type)")
    .Input("in: T")
    .Output("out: T");

 また、リストで指定することができますどのような種類に制限を置くことができますこの次の場合、入力はfloatdouble テンソルのリストです。OPは、例えば、受け入れ、入力タイプ(float, double, float) その場合には、出力タイプもあろう(float, double, float)

 REGISTER_OP("ListTypeRestrictionExample")

    .Attr("T: list({float, double})")
    .Input("in: T")
    .Output("out: T");

あなたは、リスト内のすべてのセンサーが同じタイプになりたい場合はあなたのような何かをする可能性があります。

REGISTER_OP("IntListInputExample")
    .Attr("N: int")
    .Input("in: N * int32")
    .Output("out: int32");

これは、int32 テンソルリストを受け取り、リスト長さを指定するintattrのNを使用しています。

 

これは、同様type polymorphicとすることができます。次の例では、入力が入力するのと同じ(ただし、未指定)("T")のテンソル(長さ"N")のリストであり、出力が一致するタイプの単一テンソルです。:

REGISTER_OP("SameListInputExample")
    .Attr("N: int")
    .Attr("T: type")
    .Input("in: N * T")
    .Output("out: T");

デフォルトではテンソルリストは、1の最小の長さを有しています。あなたはa ">=" constraint on the corresponding attrを使用して、デフォルトを変更することができます。この次の例では、入力は、2以下の int32テンソルのリストは、次のとおりです。

REGISTER_OP("MinLengthIntListExample")
    .Attr("N: int >= 2")
    .Input("in: N * int32")
    .Output("out: int32");


同じ構文は、"list(type)"attrsにと連携して動作します。

REGISTER_OP("MinimumLengthPolymorphicListExample")
    .Attr("T: list(type) >= 3")
    .Input("in: T")
    .Output("out: T");

 

(原文)

Adding a New Op