Add unit test for Conv2D validator

This commit is contained in:
Trevor Morris 2019-01-02 16:13:58 -08:00
parent db95d28671
commit a42746772f
2 changed files with 118 additions and 7 deletions

View File

@ -1556,6 +1556,11 @@ enum class ConvolutionType { DEFAULT, DEPTHWISE_CONV };
tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, int group) { tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, int group) {
const auto& inputs = params->inputs; const auto& inputs = params->inputs;
const auto& node_def = params->node_def; const auto& node_def = params->node_def;
if (inputs.size() != 2) {
return tensorflow::errors::InvalidArgument("Two inputs are expected for ",
node_def.op(), ", at ",
node_def.name());
}
if (inputs.at(0).is_weights()) { if (inputs.at(0).is_weights()) {
return tensorflow::errors::Unimplemented( return tensorflow::errors::Unimplemented(
node_def.op(), " is only implemented for tensors, not weights, at ", node_def.op(), " is only implemented for tensors, not weights, at ",
@ -1568,8 +1573,8 @@ tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, int group) {
} }
TRT_ShapedWeights weights_rsck = inputs.at(1).weights(); TRT_ShapedWeights weights_rsck = inputs.at(1).weights();
if (weights_rsck.shape_.nbDims != 4) { if (weights_rsck.shape_.nbDims != 4) {
return tensorflow::errors::Internal( return tensorflow::errors::InvalidArgument(
"Conv2D expects kernel of dimension 4, at: " + node_def.name()); "Conv2D expects kernel of dimension 4, at " + node_def.name());
} }
TFAttrs attrs(node_def); TFAttrs attrs(node_def);
auto data_format = attrs.get<string>("data_format"); auto data_format = attrs.get<string>("data_format");
@ -1587,8 +1592,13 @@ tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, int group) {
"Dilation rate must be 1 for batch and channel dimensions, at ", "Dilation rate must be 1 for batch and channel dimensions, at ",
node_def.name()); node_def.name());
} }
nvinfer1::DimsHW dilation(tf_dilations[h_index], tf_dilations[w_index]); const nvinfer1::DimsHW dilation(tf_dilations[h_index], tf_dilations[w_index]);
const auto tf_stride = attrs.get<std::vector<int>>("strides"); const auto tf_stride = attrs.get<std::vector<int>>("strides");
if (tf_stride.size() != 4) {
return tensorflow::errors::InvalidArgument(
"Convolution strides field must specify 4 dimensions, at ",
node_def.name());
}
if (tf_stride[0] != 1 || tf_stride[c_index] != 1) { if (tf_stride[0] != 1 || tf_stride[c_index] != 1) {
return tensorflow::errors::Unimplemented( return tensorflow::errors::Unimplemented(
"Stride must be 1 for batch and channel dimensions, at ", "Stride must be 1 for batch and channel dimensions, at ",
@ -1608,10 +1618,9 @@ tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, int group) {
// Dimensions of transposed tensor. // Dimensions of transposed tensor.
const auto tensor_dim = tensor->getDimensions(); const auto tensor_dim = tensor->getDimensions();
// This is a depthwise convolution when num_groups is 0. Otherwise, num_groups // For depthwise convolution, group will be 0 so set num_groups to size of
// will be 1. // input's channel dim. For a non-depthwise conv, num_groups will be 1.
int num_groups = group; const int num_groups = (group == 0) ? tensor_dim.d[0] : group;
if (num_groups == 0) num_groups = tensor_dim.d[0];
if (params->converter->precision_mode() == FP16MODE) { if (params->converter->precision_mode() == FP16MODE) {
weights_rsck = weights_rsck =

View File

@ -2378,6 +2378,8 @@ TEST_F(OpConverterTest, ConvertStridedSlice) {
}; };
{ {
// Input is weights, should fail.
Reset();
NodeDef node_def = get_strided_slice_nodedef(); NodeDef node_def = get_strided_slice_nodedef();
AddTestWeights<int32>("input", {1, 2, 3}, {1, 2, 3, 4, 5, 6}); AddTestWeights<int32>("input", {1, 2, 3}, {1, 2, 3, 4, 5, 6});
AddTestWeights<int32>("begin", {4}, {0, 0, 0, 0}); AddTestWeights<int32>("begin", {4}, {0, 0, 0, 0});
@ -2619,6 +2621,106 @@ TEST_F(OpConverterTest, ConvertStridedSlice) {
} }
} }
TEST_F(OpConverterTest, ConvertConv2D) {
{
// Input list is empty, should fail.
NodeDef node_def = MakeNodeDef("my_conv2d", "Conv2D", {});
RunValidationAndConversion(
node_def, error::INVALID_ARGUMENT,
"Two inputs are expected for Conv2D, at my_conv2d");
}
// Get nodedef for Conv2D layer.
auto get_conv2d_nodedef = [](
std::vector<int> strides = {1, 1, 1, 1}, string padding = "SAME",
string data_format = "NCHW",
std::vector<int> dilations = {1, 1, 1, 1}) -> NodeDef {
Scope s = Scope::NewRootScope();
auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT);
auto filter = ops::Placeholder(s.WithOpName("weights"), DT_FLOAT);
ops::Conv2D::Attrs attrs =
ops::Conv2D::Attrs().DataFormat(data_format).Dilations(dilations);
auto conv2d = ops::Conv2D(s.WithOpName("my_conv2d"), input, filter, strides,
padding, attrs);
return conv2d.operation.node()->def();
};
{
// Input is weights, should fail.
Reset();
NodeDef node_def = get_conv2d_nodedef();
AddTestWeights<float>("input", {1, 2, 3}, {1, 2, 3, 4, 5, 6});
AddTestWeights<float>("weights", {3, 3, 1, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9});
RunValidationAndConversion(
node_def, error::UNIMPLEMENTED,
"Conv2D is only implemented for tensors, not weights, at my_conv2d");
}
{
// Filter is tensor, should fail.
Reset();
NodeDef node_def = get_conv2d_nodedef();
AddTestTensor("input", {1, 2, 3});
AddTestTensor("weights", {3, 3, 1, 1});
RunValidationAndConversion(
node_def, error::UNIMPLEMENTED,
"Kernel for Conv2D must be constant weights, at my_conv2d");
}
{
// Filter is not 4D, should fail.
Reset();
NodeDef node_def = get_conv2d_nodedef();
AddTestTensor("input", {1, 2, 3});
AddTestWeights<float>("weights", {3, 3, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9});
RunValidationAndConversion(
node_def, error::INVALID_ARGUMENT,
"Conv2D expects kernel of dimension 4, at my_conv2d");
}
{
// Dilations is not 4D, should fail.
Reset();
NodeDef node_def =
get_conv2d_nodedef({1, 1, 1, 1}, "SAME", "NCHW", {1, 1, 1});
AddTestTensor("input", {1, 2, 3});
AddTestWeights<float>("weights", {3, 3, 1, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9});
RunValidationAndConversion(
node_def, error::INVALID_ARGUMENT,
"Convolution dilations field must specify 4 dimensions, at my_conv2d");
}
{
// Dilation value is not 1 for channel, should fail.
Reset();
NodeDef node_def =
get_conv2d_nodedef({1, 1, 1, 1}, "SAME", "NCHW", {1, 2, 1, 1});
AddTestTensor("input", {1, 2, 3});
AddTestWeights<float>("weights", {3, 3, 1, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9});
RunValidationAndConversion(node_def, error::UNIMPLEMENTED,
"Dilation rate must be 1 for batch and channel "
"dimensions, at my_conv2d");
}
{
// Strides is not 4D, should fail.
Reset();
NodeDef node_def =
get_conv2d_nodedef({1, 1, 1}, "SAME", "NCHW", {1, 1, 1, 1});
AddTestTensor("input", {1, 2, 3});
AddTestWeights<float>("weights", {3, 3, 1, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9});
RunValidationAndConversion(
node_def, error::INVALID_ARGUMENT,
"Convolution strides field must specify 4 dimensions, at my_conv2d");
}
{
// Stride value is not 1 for channel, should fail.
Reset();
NodeDef node_def =
get_conv2d_nodedef({1, 2, 1, 1}, "SAME", "NCHW", {1, 1, 1, 1});
AddTestTensor("input", {1, 2, 3});
AddTestWeights<float>("weights", {3, 3, 1, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9});
RunValidationAndConversion(
node_def, error::UNIMPLEMENTED,
"Stride must be 1 for batch and channel dimensions, at my_conv2d");
}
}
} // namespace convert } // namespace convert
} // namespace tensorrt } // namespace tensorrt
} // namespace tensorflow } // namespace tensorflow