[TF FE][Opset13] Enable Multinomial operator in TF frontend (#20646)
* Enable Multinomial operator in TF frontend * Implement requested changes * Update tests/layer_tests/tensorflow_tests/test_tf_Multinomial.py Co-authored-by: Roman Kazantsev <roman.kazantsev@intel.com> * Align with CPU implementation --------- Co-authored-by: Roman Kazantsev <roman.kazantsev@intel.com>
This commit is contained in:
parent
a29843013d
commit
a1e296eaa8
|
|
@ -233,6 +233,7 @@ const std::map<std::string, CreatorFunction> get_supported_ops() {
|
|||
{"Merge", CreatorFunction(translate_merge_op)},
|
||||
{"MirrorPad", CreatorFunction(translate_mirror_pad_op)},
|
||||
{"MulNoNan", CreatorFunction(translate_mul_no_nan_op)},
|
||||
{"Multinomial", CreatorFunction(translate_multinomial_op)},
|
||||
{"MutableHashTable", CreatorFunction(translate_hash_table_op)},
|
||||
{"MutableHashTableV2", CreatorFunction(translate_hash_table_op)},
|
||||
{"NonMaxSuppression", CreatorFunction(translate_non_max_suppression_op)},
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ OP_CONVERTER(translate_max_pool_op);
|
|||
OP_CONVERTER_NAMED(translate_max_pool_with_argmax);
|
||||
OP_CONVERTER(translate_mirror_pad_op);
|
||||
OP_CONVERTER(translate_mul_no_nan_op);
|
||||
OP_CONVERTER(translate_multinomial_op);
|
||||
OP_CONVERTER_NAMED(translate_non_max_suppression_op);
|
||||
OP_CONVERTER(translate_parallel_dynamic_stitch_op);
|
||||
OP_CONVERTER(translate_placeholder_op);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "openvino/op/multinomial.hpp"
|
||||
|
||||
#include "common_op_table.hpp"
|
||||
|
||||
namespace ov {
|
||||
namespace frontend {
|
||||
namespace tensorflow {
|
||||
namespace op {
|
||||
|
||||
OutputVector translate_multinomial_op(const NodeContext& node) {
|
||||
default_op_checks(node, 2, {"Multinomial"});
|
||||
auto logits = node.get_input(0);
|
||||
auto num_samples = node.get_input(1);
|
||||
auto global_seed = node.get_attribute<int64_t>("seed", 0);
|
||||
auto op_seed = node.get_attribute<int64_t>("seed2", 0);
|
||||
auto output_type = node.get_attribute<ov::element::Type>("output_dtype");
|
||||
|
||||
auto res =
|
||||
std::make_shared<ov::op::v13::Multinomial>(logits, num_samples, output_type, true, true, global_seed, op_seed);
|
||||
set_node_name(node.get_name(), res);
|
||||
return res->outputs();
|
||||
}
|
||||
|
||||
} // namespace op
|
||||
} // namespace tensorflow
|
||||
} // namespace frontend
|
||||
} // namespace ov
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
markers =
|
||||
nightly
|
||||
precommit
|
||||
precommit_tf_fe
|
||||
precommit_ts_backend
|
||||
precommit_fx_backend
|
||||
timeout
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
# Copyright (C) 2018-2023 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import pytest
|
||||
import tensorflow as tf
|
||||
from common.tf_layer_test_class import CommonTFLayerTest
|
||||
import numpy as np
|
||||
|
||||
|
||||
class TestMultinomial(CommonTFLayerTest):
|
||||
def _prepare_input(self, inputs_dict, kwargs):
|
||||
inputs_dict["num_samples"] = np.array(kwargs["num_samples"], dtype=np.int32)
|
||||
inputs_dict["probs"] = kwargs["input"]
|
||||
return inputs_dict
|
||||
|
||||
def create_tf_multinomial_net_shape(
|
||||
self, global_seed, op_seed, logits_shape, input_type, out_type
|
||||
):
|
||||
tf.compat.v1.reset_default_graph()
|
||||
# Configuration required to make multinomial randomness predictable across devices, results depends on TF parallel execution.
|
||||
session_conf = tf.compat.v1.ConfigProto(
|
||||
intra_op_parallelism_threads=1, inter_op_parallelism_threads=1
|
||||
)
|
||||
# Create the graph and model
|
||||
with tf.compat.v1.Session(config=session_conf) as sess:
|
||||
probs = tf.compat.v1.placeholder(input_type, logits_shape, "probs")
|
||||
num_samples = tf.compat.v1.placeholder(tf.int32, [], "num_samples")
|
||||
if global_seed is not None:
|
||||
tf.random.set_seed(global_seed)
|
||||
tf.raw_ops.ZerosLike(
|
||||
x=tf.raw_ops.Multinomial(
|
||||
logits=tf.math.log(probs),
|
||||
num_samples=num_samples,
|
||||
seed=global_seed,
|
||||
seed2=op_seed,
|
||||
output_dtype=out_type,
|
||||
)
|
||||
)
|
||||
|
||||
tf.compat.v1.global_variables_initializer()
|
||||
tf_net = sess.graph_def
|
||||
|
||||
return tf_net, None
|
||||
|
||||
def create_tf_multinomial_net_exact(
|
||||
self, global_seed, op_seed, logits_shape, input_type, out_type
|
||||
):
|
||||
tf.compat.v1.reset_default_graph()
|
||||
# Configuration required to make multinomial randomness predictable across devices, results depends on TF parallel execution.
|
||||
session_conf = tf.compat.v1.ConfigProto(
|
||||
intra_op_parallelism_threads=1, inter_op_parallelism_threads=1
|
||||
)
|
||||
# Create the graph and model
|
||||
with tf.compat.v1.Session(config=session_conf) as sess:
|
||||
probs = tf.compat.v1.placeholder(input_type, logits_shape, "probs")
|
||||
num_samples = tf.compat.v1.placeholder(tf.int32, [], "num_samples")
|
||||
if global_seed is not None:
|
||||
tf.random.set_seed(global_seed)
|
||||
tf.raw_ops.Multinomial(
|
||||
logits=tf.math.log(probs),
|
||||
num_samples=num_samples,
|
||||
seed=global_seed,
|
||||
seed2=op_seed,
|
||||
output_dtype=out_type,
|
||||
)
|
||||
|
||||
tf.compat.v1.global_variables_initializer()
|
||||
tf_net = sess.graph_def
|
||||
|
||||
return tf_net, None
|
||||
|
||||
@pytest.mark.parametrize("out_type", [tf.int32, tf.int64])
|
||||
@pytest.mark.parametrize(
|
||||
("input", "num_samples", "seed", "test_type"),
|
||||
[
|
||||
(
|
||||
np.array([[0, 1, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0]], dtype=np.float32),
|
||||
1024,
|
||||
[32465, 48971],
|
||||
"exact",
|
||||
),
|
||||
(
|
||||
np.array(
|
||||
[
|
||||
[0.001, 0.001, 0.1, 0.9],
|
||||
[5, 10, 1e-5, 256],
|
||||
[1, 1e-5, 1e-5, 1e-5],
|
||||
],
|
||||
dtype=np.float64,
|
||||
),
|
||||
256,
|
||||
[32465, 48971],
|
||||
"shape",
|
||||
),
|
||||
(np.array([[1, 1, 1, 1]], dtype=np.float16), 1024, [1, 1], "shape"),
|
||||
(
|
||||
np.array([[1, 2, 3, 4], [4, 3, 2, 1], [1, 0, 0, 0]], dtype=np.float32),
|
||||
1,
|
||||
[78132, None],
|
||||
"shape",
|
||||
),
|
||||
(
|
||||
np.array([[7, 7, 7, 7], [7, 7, 7, 7], [7, 7, 7, 7]], dtype=np.float32),
|
||||
1024,
|
||||
[32465, None],
|
||||
"shape",
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.nightly
|
||||
@pytest.mark.precommit_tf_fe
|
||||
def test_multinomial_basic(
|
||||
self,
|
||||
input,
|
||||
num_samples,
|
||||
seed,
|
||||
out_type,
|
||||
test_type,
|
||||
ie_device,
|
||||
precision,
|
||||
ir_version,
|
||||
temp_dir,
|
||||
use_new_frontend,
|
||||
use_old_api,
|
||||
):
|
||||
if ie_device == "GPU":
|
||||
pytest.skip("Multinomial is not supported on GPU")
|
||||
net = getattr(self, f"create_tf_multinomial_net_{test_type}")
|
||||
self._test(
|
||||
*net(
|
||||
global_seed=seed[0],
|
||||
op_seed=seed[1],
|
||||
logits_shape=input.shape,
|
||||
input_type=input.dtype,
|
||||
out_type=out_type,
|
||||
),
|
||||
ie_device,
|
||||
precision,
|
||||
temp_dir=temp_dir,
|
||||
ir_version=ir_version,
|
||||
use_new_frontend=use_new_frontend,
|
||||
use_old_api=use_old_api,
|
||||
kwargs_to_prepare_input={"input": input, "num_samples": num_samples},
|
||||
)
|
||||
Loading…
Reference in New Issue