From 4641285c75eccedef135e3d211d65d9707e910b3 Mon Sep 17 00:00:00 2001 From: wangyang59 Date: Mon, 28 Nov 2016 17:24:58 -0800 Subject: [PATCH] Added a test in test_NetworkCompare to verify cudnn and exconv, fixed a bug in cudnn_conv in dealing with groups --- paddle/gserver/layers/ConvProjection.cpp | 7 +-- paddle/gserver/tests/img_conv2_a.conf | 36 ++++++++++++++ paddle/gserver/tests/img_conv2_b.conf | 36 ++++++++++++++ paddle/gserver/tests/test_ConvUnify.cpp | 41 ++++++++++++++-- paddle/gserver/tests/test_LayerGrad.cpp | 47 +++++++++++++++++++ paddle/gserver/tests/test_NetworkCompare.cpp | 9 ++++ .../paddle/trainer_config_helpers/layers.py | 21 +++++++-- 7 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 paddle/gserver/tests/img_conv2_a.conf create mode 100644 paddle/gserver/tests/img_conv2_b.conf diff --git a/paddle/gserver/layers/ConvProjection.cpp b/paddle/gserver/layers/ConvProjection.cpp index 4ab0a1dc841..946d249dc5d 100644 --- a/paddle/gserver/layers/ConvProjection.cpp +++ b/paddle/gserver/layers/ConvProjection.cpp @@ -59,7 +59,8 @@ void ConvProjection::getConvParams() { void ConvProjection::initCudnn() { hl_create_filter_descriptor( - &filterDesc_, channels_, numFilters_, filterH_, filterW_); + &filterDesc_, channels_ / groups_, numFilters_ / groups_, + filterH_, filterW_); hl_create_tensor_descriptor(&inputDesc_); hl_create_tensor_descriptor(&outputDesc_); hl_create_convolution_descriptor(&convDesc_, @@ -86,7 +87,7 @@ void ConvProjection::initCudnn() { void ConvProjection::reshapeTensorDesc(int batchSize) { hl_tensor_reshape(inputDesc_, batchSize, - channels_, + channels_ / groups_, imageH_, imageW_, channels_ * imageH_ * imageW_, @@ -115,7 +116,7 @@ void ConvProjection::reshapeTensorDesc(int batchSize) { hl_tensor_reshape(outputDesc_, batchSize, - numFilters_, + numFilters_ / groups_, outputH_, outputW_, nStride, diff --git a/paddle/gserver/tests/img_conv2_a.conf b/paddle/gserver/tests/img_conv2_a.conf new file mode 100644 index 00000000000..cb9d0b97146 --- /dev/null +++ b/paddle/gserver/tests/img_conv2_a.conf @@ -0,0 +1,36 @@ +#edit-mode: -*- python -*- +# Copyright (c) 2016 Baidu, Inc. 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. + +from paddle.trainer_config_helpers import * + +settings(batch_size=10) +data = data_layer(name ="input", size=8*16*16) + +conv = img_conv_layer(input=data, filter_size=2, filter_size_y=2, + num_channels=8, + num_filters=16, stride=1, + bias_attr=True, + act=LinearActivation(), + layer_type="exconv") + +conv2 = img_conv_layer(input=data, filter_size=3, filter_size_y=3, + num_channels=8, + num_filters=16, stride=2, + bias_attr=True, + act=LinearActivation(), + groups=1, + layer_type="exconv") + +outputs(conv, conv2) diff --git a/paddle/gserver/tests/img_conv2_b.conf b/paddle/gserver/tests/img_conv2_b.conf new file mode 100644 index 00000000000..db69b206889 --- /dev/null +++ b/paddle/gserver/tests/img_conv2_b.conf @@ -0,0 +1,36 @@ +#edit-mode: -*- python -*- +# Copyright (c) 2016 Baidu, Inc. 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. + +from paddle.trainer_config_helpers import * + +settings(batch_size=10) +data = data_layer(name ="input", size=8*16*16) + +conv = img_conv_layer(input=data, filter_size=2, filter_size_y=2, + num_channels=8, + num_filters=16, stride=1, + bias_attr=True, + act=LinearActivation(), + layer_type="cudnn_conv") + +conv2 = img_conv_layer(input=data, filter_size=3, filter_size_y=3, + num_channels=8, + num_filters=16, stride=2, + bias_attr=True, + act=LinearActivation(), + groups=1, + layer_type="cudnn_conv") + +outputs(conv, conv2) diff --git a/paddle/gserver/tests/test_ConvUnify.cpp b/paddle/gserver/tests/test_ConvUnify.cpp index 83639251e68..5acf02bea0e 100644 --- a/paddle/gserver/tests/test_ConvUnify.cpp +++ b/paddle/gserver/tests/test_ConvUnify.cpp @@ -38,7 +38,7 @@ P_DECLARE_bool(prev_batch_state); // matches the given result MatrixPtr doOneConvTest(size_t imgSize, size_t output_x, size_t stride, size_t padding, size_t filter_size, size_t channel, - size_t numfilters, MatrixPtr& inputData, + size_t numfilters, size_t groups, MatrixPtr& inputData, real* param, bool useGpu) { TestConfig config; config.biasSize = numfilters; @@ -51,9 +51,11 @@ MatrixPtr doOneConvTest(size_t imgSize, size_t output_x, size_t stride, config.layerConfig.set_partial_sum(1); config.layerConfig.set_shared_biases(true); + size_t weightSize = channel* filter_size * filter_size * + config.layerConfig.num_filters() / groups; config.inputDefs.push_back({INPUT_DATA, "layer_0", imgSize * imgSize * channel, - channel* filter_size * filter_size * config.layerConfig.num_filters()}); + weightSize}); LayerInputConfig* input = config.layerConfig.add_inputs(); ConvConfig* conv = input->mutable_conv_conf(); conv->set_filter_size(filter_size); @@ -63,8 +65,8 @@ MatrixPtr doOneConvTest(size_t imgSize, size_t output_x, size_t stride, conv->set_padding_y(padding); conv->set_stride(stride); conv->set_stride_y(stride); - conv->set_groups(1); - conv->set_filter_channels(channel); + conv->set_groups(groups); + conv->set_filter_channels(channel/groups); conv->set_img_size(imgSize); conv->set_output_x(output_x); @@ -87,7 +89,7 @@ MatrixPtr doOneConvTest(size_t imgSize, size_t output_x, size_t stride, convLayer->getBiasParameter()->zeroMem(); convLayer->getParameters()[0]->zeroMem(); convLayer->getParameters()[0]->getBuf(PARAMETER_VALUE)->copyFrom(param, - channel* filter_size * filter_size * config.layerConfig.num_filters()); + weightSize); convLayer->forward(PASS_GC); return convLayer->getOutputValue(); @@ -113,6 +115,7 @@ TEST(Layer, convParaUnified) { /* filter_size */ 3, /*channel*/ 1, /*numfilters*/ 2, + /*groups*/ 1, input, param, false); resultGpu = doOneConvTest(/* imgSize */ 4, @@ -122,6 +125,7 @@ TEST(Layer, convParaUnified) { /* filter_size */ 3, /*channel*/ 1, /*numfilters*/ 2, + /*groups*/ 1, input, param, true); checkMatrixEqual(resultCpu, resultGpu); @@ -145,6 +149,7 @@ TEST(Layer, convParaUnified) { /* filter_size */ 2, /*channel*/ 2, /*numfilters*/ 2, + /*groups*/ 1, input, param2, false); resultGpu = doOneConvTest(/* imgSize */ 3, @@ -154,8 +159,34 @@ TEST(Layer, convParaUnified) { /* filter_size */ 2, /*channel*/ 2, /*numfilters*/ 2, + /*groups*/ 1, input, param2, true); checkMatrixEqual(resultCpu, resultGpu); + + + float param3[] = {1, 2, 3, 4, + 4, 3, 2, 1}; + + resultCpu = doOneConvTest(/* imgSize */ 3, + /* output_x */ 2, + /* stride */ 1, + /* padding */ 0, + /* filter_size */ 2, + /*channel*/ 2, + /*numfilters*/ 2, + /*groups*/ 2, + input, param3, false); + + resultGpu = doOneConvTest(/* imgSize */ 3, + /* output_x */ 2, + /* stride */ 1, + /* padding */ 0, + /* filter_size */ 2, + /*channel*/ 2, + /*numfilters*/ 2, + /*groups*/ 2, + input, param3, true); + checkMatrixEqual(resultCpu, resultGpu); #endif } diff --git a/paddle/gserver/tests/test_LayerGrad.cpp b/paddle/gserver/tests/test_LayerGrad.cpp index 374ae57dd36..4610c805a62 100644 --- a/paddle/gserver/tests/test_LayerGrad.cpp +++ b/paddle/gserver/tests/test_LayerGrad.cpp @@ -213,6 +213,53 @@ TEST(Projection, conv) { NUM_FILTERS, true); } + +TEST(Projection, conv2) { + const int NUM_FILTERS = 18; + const int FILTER_SIZE = 2; + const int FILTER_SIZE_Y = 3; + const int CHANNELS = 3; + const int IMAGE_SIZE = 16; + + ProjectionConfig conf; + conf.set_type("conv"); + conf.set_num_filters(NUM_FILTERS); + + ConvConfig* conv = conf.mutable_conv_conf(); + conv->set_filter_size(FILTER_SIZE); + conv->set_filter_size_y(FILTER_SIZE_Y); + conv->set_channels(CHANNELS); + conv->set_padding(0); + conv->set_padding_y(1); + conv->set_stride(2); + conv->set_stride_y(2); + conv->set_groups(3); + conv->set_filter_channels(conv->channels() / conv->groups()); + conv->set_img_size(IMAGE_SIZE); + int output_x = outputSize(conv->img_size(), + conv->filter_size(), + conv->padding(), + conv->stride(), + /* caffeMode */ true); + int output_y = outputSize(conv->img_size(), + conv->filter_size_y(), + conv->padding_y(), + conv->stride_y(), + /* caffeMode */ true); + conv->set_output_x(output_x); + conf.set_input_size(IMAGE_SIZE * IMAGE_SIZE * CHANNELS); + conf.set_output_size(output_x * output_y * NUM_FILTERS); + + testProjectionGrad( + conf, + INPUT_DATA, + /* parameterSize */ NUM_FILTERS * FILTER_SIZE * FILTER_SIZE_Y, + /* batchSize */ 100, + true, + false, + NUM_FILTERS, + true); +} #endif TEST(Layer, BilinearInterpLayer) { diff --git a/paddle/gserver/tests/test_NetworkCompare.cpp b/paddle/gserver/tests/test_NetworkCompare.cpp index 1810bc31fc2..8d16c2373c2 100644 --- a/paddle/gserver/tests/test_NetworkCompare.cpp +++ b/paddle/gserver/tests/test_NetworkCompare.cpp @@ -255,6 +255,15 @@ TEST(Compare, img_conv) { compareNetwork(config_file_a, config_file_b); FLAGS_use_gpu = useGpu; } + +TEST(Compare, img_conv2) { + std::string config_file_a = "./gserver/tests/img_conv2_a.conf"; + std::string config_file_b = "./gserver/tests/img_conv2_b.conf"; + bool useGpu = FLAGS_use_gpu; + FLAGS_use_gpu = true; + compareNetwork(config_file_a, config_file_b); + FLAGS_use_gpu = useGpu; +} #endif P_DEFINE_string(config_file_a, "", "config of one network to compare"); diff --git a/python/paddle/trainer_config_helpers/layers.py b/python/paddle/trainer_config_helpers/layers.py index 9a45a515898..1d56a2aaf62 100644 --- a/python/paddle/trainer_config_helpers/layers.py +++ b/python/paddle/trainer_config_helpers/layers.py @@ -129,6 +129,9 @@ class LayerType(object): HSIGMOID = 'hsigmoid' CONV_LAYER = "conv" CONVTRANS_LAYER = "convt" + EXCONV_LAYER = "exconv" + EXCONVTRANS_LAYER = "exconvt" + CUDNNCONV_LAYER = "cudnn_conv" POOL_LAYER = "pool" BATCH_NORM_LAYER = 'batch_norm' NORM_LAYER = 'norm' @@ -1762,7 +1765,8 @@ def img_conv_layer(input, filter_size_y=None, stride_y=None, padding_y=None, - trans=False): + trans=False, + layer_type=None): """ Convolution layer for image. Paddle only support square input currently and thus input image's width equals height. @@ -1829,6 +1833,10 @@ def img_conv_layer(input, :type layer_attr: ExtraLayerAttribute :param trans: true if it is a convTransLayer, false if it is a convLayer :type trans: bool + :param layer_type: specify the layer_type, default is None. If trans=True, + layer_type has to be "exconvt", otherwise layer_type + has to be either "exconv" or "cudnn_conv" + :type layer_type: String :return: LayerOutput object. :rtype: LayerOutput """ @@ -1864,8 +1872,15 @@ def img_conv_layer(input, param_attr.attr["initial_std"] = init_w param_attr.attr["initial_strategy"] = 0 param_attr.attr["initial_smart"] = False - - lt = LayerType.CONVTRANS_LAYER if trans else LayerType.CONV_LAYER + + if layer_type: + if trans: + assert layer_type in ["exconvt"] + else: + assert layer_type in ["exconv", "cudnn_conv"] + lt = layer_type + else: + lt = LayerType.CONVTRANS_LAYER if trans else LayerType.CONV_LAYER l = Layer( name=name, -- GitLab