diff --git a/paddle/fluid/framework/ir/conv_affine_channel_fuse_pass.cc b/paddle/fluid/framework/ir/conv_affine_channel_fuse_pass.cc index b50b4f37caecd8d8d5c393ee3a5c5b76c1f406be..fd8b55a6b7deb9bf4685b27f8849a49ab77f64e9 100644 --- a/paddle/fluid/framework/ir/conv_affine_channel_fuse_pass.cc +++ b/paddle/fluid/framework/ir/conv_affine_channel_fuse_pass.cc @@ -18,6 +18,7 @@ #include #include #include "paddle/fluid/framework/lod_tensor.h" +#include "paddle/fluid/framework/op_version_registry.h" #include "paddle/fluid/operators/math/cpu_vec.h" #include "paddle/fluid/platform/enforce.h" @@ -225,3 +226,14 @@ REGISTER_PASS(conv_affine_channel_fuse_pass, paddle::framework::ir::ConvAffineChannelFusePass); REGISTER_PASS(conv_eltwiseadd_affine_channel_fuse_pass, paddle::framework::ir::ConvEltwiseAddAffineChannelFusePass); +REGISTER_PASS_CAPABILITY(conv_affine_channel_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("conv2d", 0) + .EQ("affine_channel", 0)); +REGISTER_PASS_CAPABILITY(conv_eltwiseadd_affine_channel_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("conv2d", 0) + .EQ("elementwise_add", 0) + .EQ("affine_channel", 0)); diff --git a/paddle/fluid/framework/ir/conv_bn_fuse_pass.cc b/paddle/fluid/framework/ir/conv_bn_fuse_pass.cc index 9d3e0806ac79d838765ca5a4bbf61d0f67ab6ed5..fb787e08814429781bf64efda2f1eb915f185f63 100644 --- a/paddle/fluid/framework/ir/conv_bn_fuse_pass.cc +++ b/paddle/fluid/framework/ir/conv_bn_fuse_pass.cc @@ -18,6 +18,7 @@ #include #include #include "paddle/fluid/framework/lod_tensor.h" +#include "paddle/fluid/framework/op_version_registry.h" #include "paddle/fluid/operators/math/cpu_vec.h" #include "paddle/fluid/platform/enforce.h" @@ -372,3 +373,14 @@ REGISTER_PASS(depthwise_conv_bn_fuse_pass, paddle::framework::ir::DepthwiseConvBNFusePass); REGISTER_PASS(depthwise_conv_eltwiseadd_bn_fuse_pass, paddle::framework::ir::DepthwiseConvEltwiseAddBNFusePass); +REGISTER_PASS_CAPABILITY(conv_bn_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("conv2d", 0) + .EQ("batch_norm", 0)); +REGISTER_PASS_CAPABILITY(conv_eltwiseadd_bn_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("conv2d", 0) + .EQ("elementwise_add", 0) + .EQ("batch_norm", 0)); diff --git a/paddle/fluid/framework/ir/conv_elementwise_add2_act_fuse_pass.cc b/paddle/fluid/framework/ir/conv_elementwise_add2_act_fuse_pass.cc index 2627da7dc40f19a9df22d2f44a4b1032df5cea01..ad6af69ae02e4f6262ee8760dbda90e0b5833feb 100644 --- a/paddle/fluid/framework/ir/conv_elementwise_add2_act_fuse_pass.cc +++ b/paddle/fluid/framework/ir/conv_elementwise_add2_act_fuse_pass.cc @@ -11,9 +11,9 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - #include "paddle/fluid/framework/ir/conv_elementwise_add2_act_fuse_pass.h" #include +#include "paddle/fluid/framework/op_version_registry.h" namespace paddle { namespace framework { @@ -116,3 +116,10 @@ void ConvElementwiseAdd2ActFusePass::ApplyImpl(ir::Graph* graph) const { REGISTER_PASS(conv_elementwise_add2_act_fuse_pass, paddle::framework::ir::ConvElementwiseAdd2ActFusePass); +REGISTER_PASS_CAPABILITY(conv_elementwise_add2_act_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("conv2d", 0) + .EQ("elementwise_add", 0) + .EQ("relu", 0) + .EQ("identity", 0)); diff --git a/paddle/fluid/framework/ir/conv_elementwise_add_act_fuse_pass.cc b/paddle/fluid/framework/ir/conv_elementwise_add_act_fuse_pass.cc index 0b454a0407e48fcf2693975b00c60ee5448786e4..c5fa47ec55fe9a15caca493a4b0c72c22f2cf5c7 100644 --- a/paddle/fluid/framework/ir/conv_elementwise_add_act_fuse_pass.cc +++ b/paddle/fluid/framework/ir/conv_elementwise_add_act_fuse_pass.cc @@ -15,6 +15,7 @@ #include "paddle/fluid/framework/ir/conv_elementwise_add_act_fuse_pass.h" #include #include "paddle/fluid/framework/ir/graph_viz_pass.h" +#include "paddle/fluid/framework/op_version_registry.h" namespace paddle { namespace framework { @@ -102,3 +103,10 @@ void ConvElementwiseAddActFusePass::ApplyImpl(ir::Graph* graph) const { REGISTER_PASS(conv_elementwise_add_act_fuse_pass, paddle::framework::ir::ConvElementwiseAddActFusePass); +REGISTER_PASS_CAPABILITY(conv_elementwise_add_act_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("conv2d", 0) + .EQ("elementwise_add", 0) + .EQ("relu", 0) + .EQ("identity", 0)); diff --git a/paddle/fluid/framework/ir/conv_elementwise_add_fuse_pass.cc b/paddle/fluid/framework/ir/conv_elementwise_add_fuse_pass.cc index 007770cf57d278d155650c00996413e3bc8e7b53..38c0b773ddeddddea68ecefd6c8525449c52d7a6 100644 --- a/paddle/fluid/framework/ir/conv_elementwise_add_fuse_pass.cc +++ b/paddle/fluid/framework/ir/conv_elementwise_add_fuse_pass.cc @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include - #include "paddle/fluid/framework/ir/conv_elementwise_add_fuse_pass.h" +#include #include "paddle/fluid/framework/ir/graph_viz_pass.h" +#include "paddle/fluid/framework/op_version_registry.h" namespace paddle { namespace framework { @@ -89,3 +89,8 @@ void ConvElementwiseAddFusePass::ApplyImpl(ir::Graph* graph) const { REGISTER_PASS(conv_elementwise_add_fuse_pass, paddle::framework::ir::ConvElementwiseAddFusePass); +REGISTER_PASS_CAPABILITY(conv_elementwise_add_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("conv2d", 0) + .EQ("elementwise_add", 0)); diff --git a/paddle/fluid/framework/ir/repeated_fc_relu_fuse_pass.cc b/paddle/fluid/framework/ir/repeated_fc_relu_fuse_pass.cc index 2396a7f3c4f84f70c2f350e2121c4044c56b141a..23f794c11c239225b31cea8a7e7f11f576c87081 100644 --- a/paddle/fluid/framework/ir/repeated_fc_relu_fuse_pass.cc +++ b/paddle/fluid/framework/ir/repeated_fc_relu_fuse_pass.cc @@ -18,6 +18,7 @@ limitations under the License. */ #include #include #include "paddle/fluid/framework/lod_tensor.h" +#include "paddle/fluid/framework/op_version_registry.h" #define MAX_NUM_FC 10 @@ -174,6 +175,10 @@ void BuildRepeatedFCReluPattern(PDPattern* pattern, if (x->outputs.size() <= 0 || x->inputs.size() <= 0U) { return false; } + if (x->IsVar() && x->Var() && x->Var()->GetShape().size() > 2) { + LOG(WARNING) << "repeated fc relu only supports input dims = 2"; + return false; + } int fc_idx = FindFCIdx(x); if (fc_idx < 0) { return false; @@ -384,3 +389,8 @@ void RepeatedFCReluFusePass::ApplyImpl(ir::Graph* graph) const { REGISTER_PASS(repeated_fc_relu_fuse_pass, paddle::framework::ir::RepeatedFCReluFusePass); +REGISTER_PASS_CAPABILITY(repeated_fc_relu_fuse_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("fc", 0) + .EQ("relu", 0)); diff --git a/paddle/fluid/framework/ir/shuffle_channel_detect_pass.cc b/paddle/fluid/framework/ir/shuffle_channel_detect_pass.cc index d9a65e71592ff464a2e6beaa2219a39103f6cae1..74ba0093a17beb5d30cd0234faf948d8a7dd620d 100644 --- a/paddle/fluid/framework/ir/shuffle_channel_detect_pass.cc +++ b/paddle/fluid/framework/ir/shuffle_channel_detect_pass.cc @@ -16,6 +16,7 @@ #include "paddle/fluid/framework/ir/graph_viz_pass.h" #include "paddle/fluid/framework/ir/shuffle_channel_detect_pass.h" +#include "paddle/fluid/framework/op_version_registry.h" namespace paddle { namespace framework { @@ -34,6 +35,8 @@ void ShuffleChannelDetectPass::ApplyImpl(ir::Graph* graph) const { const std::string pattern_name = "shufflechannel_pattern"; FusePassBase::Init(pattern_name, graph); + LOG(WARNING) << "There is fluid.layers.shuffle_channel API already, you can " + "use it instead of (reshape + transpose +reshape)"; GraphPatternDetector gpd; auto* x = gpd.mutable_pattern() ->NewNode("x") @@ -93,3 +96,8 @@ void ShuffleChannelDetectPass::ApplyImpl(ir::Graph* graph) const { REGISTER_PASS(shuffle_channel_detect_pass, paddle::framework::ir::ShuffleChannelDetectPass); +REGISTER_PASS_CAPABILITY(shuffle_channel_detect_pass) + .AddCombination( + paddle::framework::compatible::OpVersionComparatorCombination() + .EQ("reshape2", 0) + .EQ("transpose2", 0)); diff --git a/paddle/fluid/operators/cudnn_lstm_cache.h b/paddle/fluid/operators/cudnn_lstm_cache.h index 4b46e2b475e8bd59c59744bdfde7bfb1248bc99a..3181e4b1d990b775f2c80a5d13f391886f83b080 100644 --- a/paddle/fluid/operators/cudnn_lstm_cache.h +++ b/paddle/fluid/operators/cudnn_lstm_cache.h @@ -54,6 +54,8 @@ class ScopedRNNBase { x_descs_.emplace_back(x_desc_.descriptor(dims_x, strides_x)); y_descs_.emplace_back(y_desc_.descriptor(dims_y, strides_y)); } + +#if CUDNN_VERSION >= 7201 if (!sequence_length.empty()) { x_seq_desc_.descriptor(seq_length_, batch_size_, input_size_, true, sequence_length); @@ -61,6 +63,7 @@ class ScopedRNNBase { hidden_size_ * numDirections, true, sequence_length); } +#endif // ------------------- cudnn hx, hy, cx, cy descriptors---------- std::vector dims_hx = {num_layers_ * numDirections, batch_size_, @@ -96,10 +99,13 @@ class ScopedRNNBase { is_bidirec_ ? CUDNN_BIDIRECTIONAL : CUDNN_UNIDIRECTIONAL, CUDNN_LSTM, cudnn_type)); #endif + +#if CUDNN_VERSION >= 7201 if (!sequence_length.empty()) { PADDLE_ENFORCE_CUDA_SUCCESS(platform::dynload::cudnnSetRNNPaddingMode( rnn_desc_.desc(), CUDNN_RNN_PADDED_IO_ENABLED)); } +#endif // ------------------- cudnn weights_size --------------------- size_t weights_size_; @@ -125,8 +131,10 @@ class ScopedRNNBase { } cudnnTensorDescriptor_t* x_descs() { return x_descs_.data(); } cudnnTensorDescriptor_t* y_descs() { return y_descs_.data(); } +#if CUDNN_VERSION >= 7201 cudnnRNNDataDescriptor_t x_seq_desc() { return x_seq_desc_.desc(); } cudnnRNNDataDescriptor_t y_seq_desc() { return y_seq_desc_.desc(); } +#endif cudnnTensorDescriptor_t init_h_desc() { return init_h_desc_.desc(); } cudnnTensorDescriptor_t init_c_desc() { return init_c_desc_.desc(); } cudnnTensorDescriptor_t last_h_desc() { return last_h_desc_.desc(); } @@ -151,8 +159,10 @@ class ScopedRNNBase { platform::ScopedTensorDescriptor x_desc_; platform::ScopedTensorDescriptor y_desc_; +#if CUDNN_VERSION >= 7201 platform::ScopedRNNTensorDescriptor x_seq_desc_; platform::ScopedRNNTensorDescriptor y_seq_desc_; +#endif platform::ScopedTensorDescriptor init_h_desc_; platform::ScopedTensorDescriptor init_c_desc_; platform::ScopedTensorDescriptor last_h_desc_; diff --git a/paddle/fluid/platform/cudnn_helper.h b/paddle/fluid/platform/cudnn_helper.h index bb4c2a89f6fa5e531aa322b69218cf58d3e94285..4b9c5c429dabc32fad6f05e4f066ab063057e733 100644 --- a/paddle/fluid/platform/cudnn_helper.h +++ b/paddle/fluid/platform/cudnn_helper.h @@ -294,6 +294,7 @@ class ScopedTensorDescriptor { DISABLE_COPY_AND_ASSIGN(ScopedTensorDescriptor); }; +#if CUDNN_VERSION >= 7201 class ScopedRNNTensorDescriptor { public: ScopedRNNTensorDescriptor() { @@ -337,6 +338,7 @@ class ScopedRNNTensorDescriptor { cudnnRNNDataDescriptor_t desc_; DISABLE_COPY_AND_ASSIGN(ScopedRNNTensorDescriptor); }; +#endif class ScopedDropoutDescriptor { public: diff --git a/paddle/fluid/platform/dynload/cudnn.cc b/paddle/fluid/platform/dynload/cudnn.cc index 44a03d6f14a3ba07d73cfbc944d8db9601394103..1166dc5e4ad93fa23ef00623de6777b78b56ea09 100644 --- a/paddle/fluid/platform/dynload/cudnn.cc +++ b/paddle/fluid/platform/dynload/cudnn.cc @@ -46,6 +46,10 @@ CUDNN_DNN_ROUTINE_EACH_R6(DEFINE_WRAP); CUDNN_DNN_ROUTINE_EACH_R7(DEFINE_WRAP); #endif +#ifdef CUDNN_DNN_ROUTINE_EACH_AFTER_TWO_R7 +CUDNN_DNN_ROUTINE_EACH_AFTER_TWO_R7(DEFINE_WRAP); +#endif + #ifdef CUDNN_DNN_ROUTINE_EACH_AFTER_R7 CUDNN_DNN_ROUTINE_EACH_AFTER_R7(DEFINE_WRAP); #endif diff --git a/paddle/fluid/platform/dynload/cudnn.h b/paddle/fluid/platform/dynload/cudnn.h index 7e85cb57f339331d5dd4233c2cad562c56d1d3af..fba41417648ba606727d00e71f48766f47479989 100644 --- a/paddle/fluid/platform/dynload/cudnn.h +++ b/paddle/fluid/platform/dynload/cudnn.h @@ -101,9 +101,6 @@ extern void EnforceCUDNNLoaded(const char* fn_name); __macro(cudnnDropoutGetStatesSize); \ __macro(cudnnSetDropoutDescriptor); \ __macro(cudnnRestoreDropoutDescriptor); \ - __macro(cudnnCreateRNNDataDescriptor); \ - __macro(cudnnDestroyRNNDataDescriptor); \ - __macro(cudnnSetRNNDataDescriptor); \ __macro(cudnnCreateRNNDescriptor); \ __macro(cudnnGetRNNParamsSize); \ __macro(cudnnGetRNNWorkspaceSize); \ @@ -112,11 +109,6 @@ extern void EnforceCUDNNLoaded(const char* fn_name); __macro(cudnnRNNBackwardData); \ __macro(cudnnRNNBackwardWeights); \ __macro(cudnnRNNForwardInference); \ - __macro(cudnnRNNForwardTrainingEx); \ - __macro(cudnnSetRNNPaddingMode); \ - __macro(cudnnRNNBackwardDataEx); \ - __macro(cudnnRNNBackwardWeightsEx); \ - __macro(cudnnRNNForwardInferenceEx); \ __macro(cudnnDestroyDropoutDescriptor); \ __macro(cudnnDestroyRNNDescriptor); \ __macro(cudnnSetTensorNdDescriptorEx); @@ -188,6 +180,19 @@ CUDNN_DNN_ROUTINE_EACH_R6(DECLARE_DYNAMIC_LOAD_CUDNN_WRAP) CUDNN_DNN_ROUTINE_EACH_R7(DECLARE_DYNAMIC_LOAD_CUDNN_WRAP) #endif +#if CUDNN_VERSION >= 7201 +#define CUDNN_DNN_ROUTINE_EACH_AFTER_TWO_R7(__macro) \ + __macro(cudnnCreateRNNDataDescriptor); \ + __macro(cudnnDestroyRNNDataDescriptor); \ + __macro(cudnnSetRNNDataDescriptor); \ + __macro(cudnnSetRNNPaddingMode); \ + __macro(cudnnRNNForwardTrainingEx); \ + __macro(cudnnRNNBackwardDataEx); \ + __macro(cudnnRNNBackwardWeightsEx); \ + __macro(cudnnRNNForwardInferenceEx); +CUDNN_DNN_ROUTINE_EACH_AFTER_TWO_R7(DECLARE_DYNAMIC_LOAD_CUDNN_WRAP) +#endif + #if CUDNN_VERSION >= 7401 #define CUDNN_DNN_ROUTINE_EACH_AFTER_R7(__macro) \ __macro(cudnnGetBatchNormalizationForwardTrainingExWorkspaceSize); \ diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_affine_channel_fuse_pass.py b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_affine_channel_fuse_pass.py new file mode 100644 index 0000000000000000000000000000000000000000..ec0bd52e9261017335f0bf424d32f26d4c465029 --- /dev/null +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_affine_channel_fuse_pass.py @@ -0,0 +1,228 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import numpy as np +from inference_pass_test import InferencePassTest +import paddle.fluid as fluid +import paddle.fluid.core as core +from paddle.fluid.core import PassVersionChecker + + +class ConvAffineChannelFusePassExplicitPaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + groups=3, + padding=[1, 1, 1, 1], + bias_attr=False, + act=None) + input_scale = fluid.layers.create_parameter( + shape=[3], dtype="float32") + input_bias = fluid.layers.create_parameter( + shape=[3], dtype="float32") + ac_out = fluid.layers.affine_channel( + x=conv_out, scale=input_scale, bias=input_bias) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [ac_out] + + def test_check_output(self): + self.check_output() + + self.assertTrue( + PassVersionChecker.IsCompatible('conv_affine_channel_fuse_pass')) + + +class ConvAffineChannelFusePassValidPaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + groups=3, + padding='VALID', + bias_attr=False, + act=None) + input_scale = fluid.layers.create_parameter( + shape=[3], dtype="float32") + input_bias = fluid.layers.create_parameter( + shape=[3], dtype="float32") + ac_out = fluid.layers.affine_channel( + x=conv_out, scale=input_scale, bias=input_bias) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [ac_out] + + def test_check_output(self): + self.check_output() + + self.assertTrue( + PassVersionChecker.IsCompatible('conv_affine_channel_fuse_pass')) + + +class ConvAffineChannelFusePassSamePaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + groups=3, + padding='SAME', + bias_attr=False, + act=None) + input_scale = fluid.layers.create_parameter( + shape=[3], dtype="float32") + input_bias = fluid.layers.create_parameter( + shape=[3], dtype="float32") + ac_out = fluid.layers.affine_channel( + x=conv_out, scale=input_scale, bias=input_bias) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [ac_out] + + def test_check_output(self): + self.check_output() + + self.assertTrue( + PassVersionChecker.IsCompatible('conv_affine_channel_fuse_pass')) + + +class ConvEltwiseAddAffineChannelFusePassExplicitPaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + param_attr = fluid.ParamAttr( + initializer=fluid.initializer.Xavier(uniform=False), + learning_rate=0.001) + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + groups=3, + padding=[1, 1, 1, 1], + bias_attr=param_attr, + act=None) + input_scale = fluid.layers.create_parameter( + shape=[3], dtype="float32") + input_bias = fluid.layers.create_parameter( + shape=[3], dtype="float32") + ac_out = fluid.layers.affine_channel( + x=conv_out, scale=input_scale, bias=input_bias) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [ac_out] + + def test_check_output(self): + self.check_output() + + self.assertTrue( + PassVersionChecker.IsCompatible( + 'conv_eltwiseadd_affine_channel_fuse_pass')) + + +class ConvEltwiseAddAffineChannelFusePassValidPaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + param_attr = fluid.ParamAttr( + initializer=fluid.initializer.Xavier(uniform=False), + learning_rate=0.001) + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + groups=3, + padding='VALID', + bias_attr=param_attr, + act=None) + input_scale = fluid.layers.create_parameter( + shape=[3], dtype="float32") + input_bias = fluid.layers.create_parameter( + shape=[3], dtype="float32") + ac_out = fluid.layers.affine_channel( + x=conv_out, scale=input_scale, bias=input_bias) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [ac_out] + + def test_check_output(self): + self.check_output() + + self.assertTrue( + PassVersionChecker.IsCompatible( + 'conv_eltwiseadd_affine_channel_fuse_pass')) + + +class ConvEltwiseAddAffineChannelFusePassSamePaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + param_attr = fluid.ParamAttr( + initializer=fluid.initializer.Xavier(uniform=False), + learning_rate=0.001) + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + groups=3, + padding='Same', + bias_attr=param_attr, + act=None) + input_scale = fluid.layers.create_parameter( + shape=[3], dtype="float32") + input_bias = fluid.layers.create_parameter( + shape=[3], dtype="float32") + ac_out = fluid.layers.affine_channel( + x=conv_out, scale=input_scale, bias=input_bias) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [ac_out] + + def test_check_output(self): + self.check_output() + + self.assertTrue( + PassVersionChecker.IsCompatible( + 'conv_eltwiseadd_affine_channel_fuse_pass')) + + +if __name__ == "__main__": + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_bn_fuse_pass.py b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_bn_fuse_pass.py new file mode 100644 index 0000000000000000000000000000000000000000..ffe177e59d86e4451b3da1e40fd62e1d398b03b2 --- /dev/null +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_bn_fuse_pass.py @@ -0,0 +1,177 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import numpy as np +from inference_pass_test import InferencePassTest +import paddle.fluid as fluid +import paddle.fluid.core as core +from paddle.fluid.core import PassVersionChecker + + +class ConvBnFusePassExplicitPaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=6, + filter_size=6, + groups=3, + padding=[1, 1, 1, 1], + bias_attr=False, + act=None) + bn_out = fluid.layers.batch_norm(conv_out, is_test=True) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [bn_out] + + def test_check_output(self): + self.check_output() + self.assertTrue(PassVersionChecker.IsCompatible('conv_bn_fuse_pass')) + + +class ConvBnFusePassValidPaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=6, + filter_size=6, + groups=3, + padding='VALID', + bias_attr=False, + act=None) + bn_out = fluid.layers.batch_norm(conv_out, is_test=True) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [bn_out] + + def test_check_output(self): + self.check_output() + self.assertTrue(PassVersionChecker.IsCompatible('conv_bn_fuse_pass')) + + +class ConvBnFusePassSamePaddingTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=6, + filter_size=6, + groups=3, + padding='SAME', + bias_attr=False, + act=None) + bn_out = fluid.layers.batch_norm(conv_out, is_test=True) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [bn_out] + + def test_check_output(self): + self.check_output() + self.assertTrue(PassVersionChecker.IsCompatible('conv_bn_fuse_pass')) + + +class ConvEltwiseAddBnFuseExplicitPaddingPass(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=6, + filter_size=6, + groups=3, + padding=[1, 1, 1, 1], + bias_attr=None, + act=None) + bn_out = fluid.layers.batch_norm(conv_out, is_test=True) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [bn_out] + + def test_check_output(self): + self.check_output() + self.assertTrue( + PassVersionChecker.IsCompatible('conv_eltwiseadd_bn_fuse_pass')) + + +class ConvEltwiseAddBnFuseValidPaddingPass(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=6, + filter_size=6, + groups=3, + padding='VALID', + bias_attr=None, + act=None) + bn_out = fluid.layers.batch_norm(conv_out, is_test=True) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [bn_out] + + def test_check_output(self): + self.check_output() + self.assertTrue( + PassVersionChecker.IsCompatible('conv_eltwiseadd_bn_fuse_pass')) + + +class ConvEltwiseAddBnFuseSamePaddingPass(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + conv_out = fluid.layers.conv2d( + input=data, + num_filters=6, + filter_size=6, + groups=3, + padding='SAME', + bias_attr=None, + act=None) + bn_out = fluid.layers.batch_norm(conv_out, is_test=True) + + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [bn_out] + + def test_check_output(self): + self.check_output() + self.assertTrue( + PassVersionChecker.IsCompatible('conv_eltwiseadd_bn_fuse_pass')) + + +if __name__ == "__main__": + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add2_act_fuse_pass.py b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add2_act_fuse_pass.py index d6dbd397b90368d5cac27c3c5d92b7a7dce9dcf5..6907b6a7eb50eb90224af678c0ae6d053e05ac9b 100644 --- a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add2_act_fuse_pass.py +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add2_act_fuse_pass.py @@ -19,6 +19,7 @@ import numpy as np from inference_pass_test import InferencePassTest import paddle.fluid as fluid import paddle.fluid.core as core +from paddle.fluid.core import PassVersionChecker from paddle.fluid.core import AnalysisConfig """Test for fusion of conv, elementwise_add and 2 act.""" @@ -46,6 +47,9 @@ class ConvElementwiseAdd2ActFusePassTest(InferencePassTest): if core.is_compiled_with_cuda(): use_gpu = True self.check_output_with_option(use_gpu) + self.assertTrue( + PassVersionChecker.IsCompatible( + 'conv_elementwise_add2_act_fuse_pass')) if __name__ == "__main__": diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_act_fuse_pass.py b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_act_fuse_pass.py index 2e9035420d7ee45dd69de8d3cd8acc9bb1590c72..6ff60aa6debf8968e1f674e3c7aff822dfde075c 100644 --- a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_act_fuse_pass.py +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_act_fuse_pass.py @@ -19,6 +19,7 @@ import numpy as np from inference_pass_test import InferencePassTest import paddle.fluid as fluid import paddle.fluid.core as core +from paddle.fluid.core import PassVersionChecker from paddle.fluid.core import AnalysisConfig """Test for fusion of conv, elementwise_add and act.""" @@ -48,6 +49,9 @@ class ConvElementwiseAddActFusePassTest(InferencePassTest): if core.is_compiled_with_cuda(): use_gpu = True self.check_output_with_option(use_gpu) + self.assertTrue( + PassVersionChecker.IsCompatible( + 'conv_elementwise_add_act_fuse_pass')) if __name__ == "__main__": diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_fuse_pass.py b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_fuse_pass.py index 7c4e0d6e76ec45c4b75ba91522306a4dd0abc7c5..96b046edaec49038d6c8e137494c13bd7484cb7f 100644 --- a/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_fuse_pass.py +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_conv_elementwise_add_fuse_pass.py @@ -19,6 +19,7 @@ import numpy as np from inference_pass_test import InferencePassTest import paddle.fluid as fluid import paddle.fluid.core as core +from paddle.fluid.core import PassVersionChecker from paddle.fluid.core import AnalysisConfig """Test for fusion of conv and elementwise_add.""" @@ -44,6 +45,8 @@ class ConvElementwiseAddFusePassTest(InferencePassTest): if core.is_compiled_with_cuda(): use_gpu = True self.check_output_with_option(use_gpu) + self.assertTrue( + PassVersionChecker.IsCompatible('conv_elementwise_add_fuse_pass')) if __name__ == "__main__": diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_repeated_fc_relu_fuse_pass.py b/python/paddle/fluid/tests/unittests/ir/inference/test_repeated_fc_relu_fuse_pass.py new file mode 100644 index 0000000000000000000000000000000000000000..c78884480dab38446a20c456aed060eff847a9ed --- /dev/null +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_repeated_fc_relu_fuse_pass.py @@ -0,0 +1,94 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import numpy as np +from inference_pass_test import InferencePassTest +import paddle.fluid as fluid +import paddle.fluid.core as core +from paddle.fluid.core import PassVersionChecker + + +class RepeatedFcReluFusePass3Test(InferencePassTest): + def setUp(self): + fc_num = 3 + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + param_attr = fluid.ParamAttr( + initializer=fluid.initializer.Xavier(uniform=False), + learning_rate=0.001) + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + bias_attr=param_attr, + act=None) + fc_outs = [] + fc_outs.append( + fluid.layers.fc(input=[conv_out], act="relu", size=1000)) + for i in range(1, fc_num): + fc_outs.append( + fluid.layers.fc( + input=[fc_outs[i - 1]], act="relu", size=1000)) + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [fc_outs[fc_num - 1]] + + def test_check_output(self): + use_gpu = False + self.check_output_with_option(use_gpu) + + self.assertTrue( + PassVersionChecker.IsCompatible('repeated_fc_relu_fuse_pass')) + + +class RepeatedFcReluFusePass9Test(InferencePassTest): + def setUp(self): + fc_num = 9 + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 3, 64, 64], dtype="float32") + param_attr = fluid.ParamAttr( + initializer=fluid.initializer.Xavier(uniform=False), + learning_rate=0.001) + conv_out = fluid.layers.conv2d( + input=data, + num_filters=3, + filter_size=3, + bias_attr=param_attr, + act=None) + fc_outs = [] + fc_outs.append( + fluid.layers.fc(input=[conv_out], act="relu", size=1000)) + for i in range(1, fc_num): + fc_outs.append( + fluid.layers.fc( + input=[fc_outs[i - 1]], act="relu", size=1000)) + self.feeds = { + "data": np.random.random([1, 3, 64, 64]).astype("float32"), + } + self.fetch_list = [fc_outs[fc_num - 1]] + + def test_check_output(self): + use_gpu = False + self.check_output_with_option(use_gpu) + + self.assertTrue( + PassVersionChecker.IsCompatible('repeated_fc_relu_fuse_pass')) + + +if __name__ == "__main__": + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_trt_shuffle_channel_detect_pass.py b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_shuffle_channel_detect_pass.py new file mode 100644 index 0000000000000000000000000000000000000000..e9c304496afcc694e47924b9cf0fbd168d08c665 --- /dev/null +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_shuffle_channel_detect_pass.py @@ -0,0 +1,51 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import numpy as np +from inference_pass_test import InferencePassTest +import paddle.fluid as fluid +import paddle.fluid.core as core +from paddle.fluid.core import PassVersionChecker +from paddle.fluid.core import AnalysisConfig + + +class ShuffleChannelFuseTRTPassTest(InferencePassTest): + def setUp(self): + with fluid.program_guard(self.main_program, self.startup_program): + data = fluid.data( + name="data", shape=[-1, 6, 64, 64], dtype="float32") + reshape1 = fluid.layers.reshape(x=data, shape=[-1, 2, 3, 64, 64]) + trans = fluid.layers.transpose(x=reshape1, perm=[0, 2, 1, 3, 4]) + reshape2 = fluid.layers.reshape(x=trans, shape=[-1, 6, 64, 64]) + out = fluid.layers.batch_norm(reshape2, is_test=True) + + self.feeds = { + "data": np.random.random([1, 6, 64, 64]).astype("float32"), + } + self.enable_trt = True + self.trt_parameters = ShuffleChannelFuseTRTPassTest.TensorRTParam( + 1 << 30, 32, 1, AnalysisConfig.Precision.Float32, False, False) + self.fetch_list = [out] + + def test_check_output(self): + + self.check_output() + + self.assertTrue( + PassVersionChecker.IsCompatible('shuffle_channel_detect_pass')) + + +if __name__ == "__main__": + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_cross_entropy_loss.py b/python/paddle/fluid/tests/unittests/test_cross_entropy_loss.py index 4982cd195820811b9a8ec3fe6d01955234032120..c6190590108876ba97feb4dad0c31884727ec978 100644 --- a/python/paddle/fluid/tests/unittests/test_cross_entropy_loss.py +++ b/python/paddle/fluid/tests/unittests/test_cross_entropy_loss.py @@ -26,7 +26,7 @@ def stable_softmax(x): return exps / np.sum(exps) -def log_softmax(x, axis=-1): +def log_softmax(x, axis=1): softmax_out = np.apply_along_axis(stable_softmax, axis, x) return np.log(softmax_out) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index da086c0955e849619ccbce17a297ca4615a3f3d0..4395520eec70e8483cb61097a166576f4040cb4d 100644 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -1093,7 +1093,7 @@ def cross_entropy(input, " 'none', but received %s, which is not allowed." % reduction) #step 1. log_softmax - log_softmax_out = paddle.nn.functional.log_softmax(input) + log_softmax_out = paddle.nn.functional.log_softmax(input, axis=1) if weight is not None and not isinstance(weight, Variable): raise ValueError( "The weight' is not a Variable, please convert to Variable.") diff --git a/python/paddle/utils/__init__.py b/python/paddle/utils/__init__.py index 4a786679727fb1b42c216146685e0e6524e858c9..77f5ef7e9661e0ff8f4f200ff7e789ba475459c2 100644 --- a/python/paddle/utils/__init__.py +++ b/python/paddle/utils/__init__.py @@ -16,6 +16,7 @@ from .profiler import ProfilerOptions from .profiler import Profiler from .profiler import get_profiler from .deprecated import deprecated +from .lazy_import import try_import from ..fluid.framework import unique_name from ..fluid.framework import load_op_library from ..fluid.framework import require_version diff --git a/python/paddle/utils/lazy_import.py b/python/paddle/utils/lazy_import.py new file mode 100644 index 0000000000000000000000000000000000000000..69a32b77a8f3da7a5a3432b4c0cbf746bd0b0833 --- /dev/null +++ b/python/paddle/utils/lazy_import.py @@ -0,0 +1,34 @@ +# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Lazy imports for heavy dependencies.""" + +import importlib + + +def try_import(module_name): + """Try importing a module, with an informative error message on failure.""" + install_name = module_name + if module_name == 'cv2': + install_name = 'opencv-python' + + try: + mod = importlib.import_module(module_name) + return mod + except ImportError: + err_msg = ( + "Failed importing {}. This likely means that some paddle modules " + "requires additional dependencies that have to be " + "manually installed (usually with `pip install {}`). ").format( + module_name, install_name) + raise ImportError(err_msg) diff --git a/python/paddle/vision/datasets/folder.py b/python/paddle/vision/datasets/folder.py index 725fd9acafbab7b6adaf07139d02da8e2c9aaada..8a3053abefc1b28ba36150a1ff68a4dd4c3469c9 100644 --- a/python/paddle/vision/datasets/folder.py +++ b/python/paddle/vision/datasets/folder.py @@ -14,9 +14,9 @@ import os import sys -import cv2 from paddle.io import Dataset +from paddle.utils import try_import __all__ = ["DatasetFolder", "ImageFolder"] @@ -191,6 +191,7 @@ IMG_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.ppm', '.bmp', '.pgm', '.tif', def cv2_loader(path): + cv2 = try_import('cv2') return cv2.imread(path) diff --git a/python/paddle/vision/transforms/functional.py b/python/paddle/vision/transforms/functional.py index b5668fa8c7d6812664512a58faf836b5d9f09300..acceb111e6f84bc444dcfc7427653f77e3eedd3a 100644 --- a/python/paddle/vision/transforms/functional.py +++ b/python/paddle/vision/transforms/functional.py @@ -18,10 +18,11 @@ import random import math import functools -import cv2 import numbers import numpy as np +from paddle.utils import try_import + if sys.version_info < (3, 3): Sequence = collections.Sequence Iterable = collections.Iterable @@ -54,8 +55,8 @@ def flip(image, code): Accordding to the code (the type of flip), flip the input image Args: - image: Input image, with (H, W, C) shape - code: Code that indicates the type of flip. + image (np.ndarray): Input image, with (H, W, C) shape + code (int): Code that indicates the type of flip. -1 : Flip horizontally and vertically 0 : Flip vertically 1 : Flip horizontally @@ -77,18 +78,28 @@ def flip(image, code): # flip horizontally F.flip(fake_img, 1) """ + cv2 = try_import('cv2') return cv2.flip(image, flipCode=code) @keepdims -def resize(img, size, interpolation=cv2.INTER_LINEAR): +def resize(img, size, interpolation=1): """ resize the input data to given size Args: - input: Input data, could be image or masks, with (H, W, C) shape - size: Target size of input data, with (height, width) shape. - interpolation: Interpolation method. + input (np.ndarray): Input data, could be image or masks, with (H, W, C) shape + size (int|list|tuple): Target size of input data, with (height, width) shape. + interpolation (int, optional): Interpolation method. + 0 : cv2.INTER_NEAREST + 1 : cv2.INTER_LINEAR + 2 : cv2.INTER_CUBIC + 3 : cv2.INTER_AREA + 4 : cv2.INTER_LANCZOS4 + 5 : cv2.INTER_LINEAR_EXACT + 7 : cv2.INTER_MAX + 8 : cv2.WARP_FILL_OUTLIERS + 16: cv2.WARP_INVERSE_MAP Examples: .. code-block:: python @@ -102,7 +113,7 @@ def resize(img, size, interpolation=cv2.INTER_LINEAR): F.resize(fake_img, (200, 150)) """ - + cv2 = try_import('cv2') if isinstance(interpolation, Sequence): interpolation = random.choice(interpolation) @@ -179,6 +190,8 @@ def pad(img, padding, fill=(0, 0, 0), padding_mode='constant'): assert padding_mode in ['constant', 'edge', 'reflect', 'symmetric'], \ 'Expected padding mode be either constant, edge, reflect or symmetric, but got {}'.format(padding_mode) + cv2 = try_import('cv2') + PAD_MOD = { 'constant': cv2.BORDER_CONSTANT, 'edge': cv2.BORDER_REPLICATE, @@ -214,18 +227,22 @@ def pad(img, padding, fill=(0, 0, 0), padding_mode='constant'): @keepdims -def rotate(img, - angle, - interpolation=cv2.INTER_LINEAR, - expand=False, - center=None): +def rotate(img, angle, interpolation=1, expand=False, center=None): """Rotates the image by angle. Args: img (numpy.ndarray): Image to be rotated. angle (float|int): In degrees clockwise order. - interpolation (int, optional): - interpolation: Interpolation method. + interpolation (int, optional): Interpolation method. Default: 1. + 0 : cv2.INTER_NEAREST + 1 : cv2.INTER_LINEAR + 2 : cv2.INTER_CUBIC + 3 : cv2.INTER_AREA + 4 : cv2.INTER_LANCZOS4 + 5 : cv2.INTER_LINEAR_EXACT + 7 : cv2.INTER_MAX + 8 : cv2.WARP_FILL_OUTLIERS + 16: cv2.WARP_INVERSE_MAP expand (bool|optional): Optional expansion flag. If true, expands the output image to make it large enough to hold the entire rotated image. If false or omitted, make the output image the same size as the input image. @@ -250,8 +267,9 @@ def rotate(img, fake_img = rotate(fake_img, 10) print(fake_img.shape) """ - dtype = img.dtype + cv2 = try_import('cv2') + dtype = img.dtype h, w, _ = img.shape point = center or (w / 2, h / 2) M = cv2.getRotationMatrix2D(point, angle=-angle, scale=1) @@ -312,6 +330,7 @@ def to_grayscale(img, num_output_channels=1): fake_img = to_grayscale(fake_img) print(fake_img.shape) """ + cv2 = try_import('cv2') if num_output_channels == 1: img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) diff --git a/python/paddle/vision/transforms/transforms.py b/python/paddle/vision/transforms/transforms.py index 14809e0c1acaa1b6d5a494e6e3df1801e1c8f61b..9ea828271765cb8976909724bbf6079aa02c2460 100644 --- a/python/paddle/vision/transforms/transforms.py +++ b/python/paddle/vision/transforms/transforms.py @@ -17,7 +17,6 @@ from __future__ import division import math import sys import random -import cv2 import numpy as np import numbers @@ -26,6 +25,7 @@ import collections import warnings import traceback +from paddle.utils import try_import from . import functional as F if sys.version_info < (3, 3): @@ -214,7 +214,16 @@ class Resize(object): smaller edge of the image will be matched to this number. i.e, if height > width, then image will be rescaled to (size * height / width, size) - interpolation (int): Interpolation mode of resize. Default: cv2.INTER_LINEAR. + interpolation (int, optional): Interpolation mode of resize. Default: 1. + 0 : cv2.INTER_NEAREST + 1 : cv2.INTER_LINEAR + 2 : cv2.INTER_CUBIC + 3 : cv2.INTER_AREA + 4 : cv2.INTER_LANCZOS4 + 5 : cv2.INTER_LINEAR_EXACT + 7 : cv2.INTER_MAX + 8 : cv2.WARP_FILL_OUTLIERS + 16: cv2.WARP_INVERSE_MAP Examples: @@ -232,7 +241,7 @@ class Resize(object): print(fake_img.shape) """ - def __init__(self, size, interpolation=cv2.INTER_LINEAR): + def __init__(self, size, interpolation=1): assert isinstance(size, int) or (isinstance(size, Iterable) and len(size) == 2) self.size = size @@ -252,6 +261,16 @@ class RandomResizedCrop(object): output_size (int|list|tuple): Target size of output image, with (height, width) shape. scale (list|tuple): Range of size of the origin size cropped. Default: (0.08, 1.0) ratio (list|tuple): Range of aspect ratio of the origin aspect ratio cropped. Default: (0.75, 1.33) + interpolation (int, optional): Interpolation mode of resize. Default: 1. + 0 : cv2.INTER_NEAREST + 1 : cv2.INTER_LINEAR + 2 : cv2.INTER_CUBIC + 3 : cv2.INTER_AREA + 4 : cv2.INTER_LANCZOS4 + 5 : cv2.INTER_LINEAR_EXACT + 7 : cv2.INTER_MAX + 8 : cv2.WARP_FILL_OUTLIERS + 16: cv2.WARP_INVERSE_MAP Examples: @@ -273,7 +292,7 @@ class RandomResizedCrop(object): output_size, scale=(0.08, 1.0), ratio=(3. / 4, 4. / 3), - interpolation=cv2.INTER_LINEAR): + interpolation=1): if isinstance(output_size, int): self.output_size = (output_size, output_size) else: @@ -328,7 +347,16 @@ class CenterCropResize(object): Args: size (int|list|tuple): Target size of output image, with (height, width) shape. crop_padding (int): Center crop with the padding. Default: 32. - interpolation (int): Interpolation mode of resize. Default: cv2.INTER_LINEAR. + interpolation (int, optional): Interpolation mode of resize. Default: 1. + 0 : cv2.INTER_NEAREST + 1 : cv2.INTER_LINEAR + 2 : cv2.INTER_CUBIC + 3 : cv2.INTER_AREA + 4 : cv2.INTER_LANCZOS4 + 5 : cv2.INTER_LINEAR_EXACT + 7 : cv2.INTER_MAX + 8 : cv2.WARP_FILL_OUTLIERS + 16: cv2.WARP_INVERSE_MAP Examples: @@ -346,7 +374,7 @@ class CenterCropResize(object): print(fake_img.shape) """ - def __init__(self, size, crop_padding=32, interpolation=cv2.INTER_LINEAR): + def __init__(self, size, crop_padding=32, interpolation=1): if isinstance(size, int): self.size = (size, size) else: @@ -661,6 +689,7 @@ class ContrastTransform(object): if self.value == 0: return img + cv2 = try_import('cv2') dtype = img.dtype img = img.astype(np.float32) alpha = np.random.uniform(max(0, 1 - self.value), 1 + self.value) @@ -701,6 +730,8 @@ class SaturationTransform(object): if self.value == 0: return img + cv2 = try_import('cv2') + dtype = img.dtype img = img.astype(np.float32) alpha = np.random.uniform(max(0, 1 - self.value), 1 + self.value) @@ -742,6 +773,7 @@ class HueTransform(object): if self.value == 0: return img + cv2 = try_import('cv2') dtype = img.dtype img = img.astype(np.uint8) hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL) @@ -1036,7 +1068,16 @@ class RandomRotate(object): degrees (sequence or float or int): Range of degrees to select from. If degrees is a number instead of sequence like (min, max), the range of degrees will be (-degrees, +degrees) clockwise order. - interpolation (int|optional): Interpolation mode of resize. Default: cv2.INTER_LINEAR. + interpolation (int, optional): Interpolation mode of resize. Default: 1. + 0 : cv2.INTER_NEAREST + 1 : cv2.INTER_LINEAR + 2 : cv2.INTER_CUBIC + 3 : cv2.INTER_AREA + 4 : cv2.INTER_LANCZOS4 + 5 : cv2.INTER_LINEAR_EXACT + 7 : cv2.INTER_MAX + 8 : cv2.WARP_FILL_OUTLIERS + 16: cv2.WARP_INVERSE_MAP expand (bool|optional): Optional expansion flag. Default: False. If true, expands the output to make it large enough to hold the entire rotated image. If false or omitted, make the output image the same size as the input image. @@ -1061,11 +1102,7 @@ class RandomRotate(object): print(fake_img.shape) """ - def __init__(self, - degrees, - interpolation=cv2.INTER_LINEAR, - expand=False, - center=None): + def __init__(self, degrees, interpolation=1, expand=False, center=None): if isinstance(degrees, numbers.Number): if degrees < 0: raise ValueError( diff --git a/python/requirements.txt b/python/requirements.txt index 478884247553fbe44ba0295e6398d086cfcd9e41..6a88d61a94c182db3320e4de30f45be4c852f70f 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -1,4 +1,3 @@ -opencv-python<=4.2.0.32 requests>=2.20.0 numpy>=1.13, <=1.16.4 ; python_version<"3.5" numpy>=1.13 ; python_version>="3.5" diff --git a/python/setup.py.in b/python/setup.py.in index 773166400347ab550f82e4fabcb0d89b90818fc2..d85a23a5edd31f77514b468731097759f47533c1 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -237,9 +237,6 @@ if sys.version_info >= (3,7): setup_requires_tmp+=[setup_requires_i] setup_requires = setup_requires_tmp -if '${CMAKE_SYSTEM_PROCESSOR}' not in ['arm', 'armv7-a', 'aarch64']: - setup_requires+=['opencv-python'] - # the prefix is sys.prefix which should always be usr paddle_bins = ''