提交 d19355a5 编写于 作者: G guosheng

Refine ClipLayer and add unit test for it

上级 f35e0847
...@@ -316,6 +316,11 @@ scaling ...@@ -316,6 +316,11 @@ scaling
.. autoclass:: paddle.v2.layer.scaling .. autoclass:: paddle.v2.layer.scaling
:noindex: :noindex:
clip
----
.. autoclass:: paddle.v2.layer.clip
:noindex:
slope_intercept slope_intercept
--------------- ---------------
.. autoclass:: paddle.v2.layer.slope_intercept .. autoclass:: paddle.v2.layer.slope_intercept
......
...@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and ...@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
limitations under the License. */ limitations under the License. */
#include "Layer.h" #include "Layer.h"
#include "paddle/math/Matrix.h"
namespace paddle { namespace paddle {
...@@ -26,8 +25,8 @@ namespace paddle { ...@@ -26,8 +25,8 @@ namespace paddle {
class ClipLayer : public Layer { class ClipLayer : public Layer {
protected: protected:
real clipThresholdLow_; double min_;
real clipThresholdHigh_; double max_;
public: public:
explicit ClipLayer(const LayerConfig& config) : Layer(config) {} explicit ClipLayer(const LayerConfig& config) : Layer(config) {}
...@@ -47,9 +46,9 @@ bool ClipLayer::init(const LayerMap& layerMap, ...@@ -47,9 +46,9 @@ bool ClipLayer::init(const LayerMap& layerMap,
CHECK_EQ(inputLayers_.size(), 1U); CHECK_EQ(inputLayers_.size(), 1U);
auto layerConf = config_.inputs(0).clip_conf(); auto layerConf = config_.inputs(0).clip_conf();
clipThresholdLow_ = layerConf.clip_threshold_low(); min_ = layerConf.min();
clipThresholdHigh_ = layerConf.clip_threshold_high(); max_ = layerConf.max();
CHECK_LT(clipThresholdLow_, clipThresholdHigh_); CHECK_LT(min_, max_);
return true; return true;
} }
...@@ -60,19 +59,21 @@ void ClipLayer::forward(PassType passType) { ...@@ -60,19 +59,21 @@ void ClipLayer::forward(PassType passType) {
resetOutput(inV->getHeight(), inV->getWidth()); resetOutput(inV->getHeight(), inV->getWidth());
MatrixPtr outV = getOutputValue(); MatrixPtr outV = getOutputValue();
outV->copyFrom(*inV); outV->copyFrom(*inV);
outV->clip(clipThresholdLow_, clipThresholdHigh_); outV->clip(min_, max_);
} }
void ClipLayer::backward(const UpdateCallback& callback) { void ClipLayer::backward(const UpdateCallback& callback) {
MatrixPtr inV = getInputValue(0); MatrixPtr inV = getInputValue(0);
MatrixPtr inG = getInputGrad(0); MatrixPtr inG = getInputGrad(0);
MatrixPtr outV = getOutputValue(); if (inG) {
MatrixPtr outG = getOutputGrad(); MatrixPtr outV = getOutputValue();
MatrixPtr tmpMtx; MatrixPtr outG = getOutputGrad();
Matrix::resizeOrCreate( MatrixPtr tmpMtx;
tmpMtx, outG->getHeight(), outG->getWidth(), false, useGpu_); Matrix::resizeOrCreate(
tmpMtx->clipDerivative(*inV, clipThresholdLow_, clipThresholdHigh_); tmpMtx, outG->getHeight(), outG->getWidth(), false, useGpu_);
inG->addDotMul(*outG, *tmpMtx, 1, 1); tmpMtx->clipDerivative(*inV, min_, max_);
inG->addDotMul(*outG, *tmpMtx, 1, 1);
}
} }
} // namespace paddle } // namespace paddle
...@@ -1887,8 +1887,8 @@ TEST(Layer, ClipLayer) { ...@@ -1887,8 +1887,8 @@ TEST(Layer, ClipLayer) {
config.inputDefs.push_back({INPUT_DATA, "input", size, 0}); config.inputDefs.push_back({INPUT_DATA, "input", size, 0});
LayerInputConfig* input = config.layerConfig.add_inputs(); LayerInputConfig* input = config.layerConfig.add_inputs();
ClipConfig* layerConf = input->mutable_clip_conf(); ClipConfig* layerConf = input->mutable_clip_conf();
layerConf->set_clip_threshold_low(std::rand() / (real)RAND_MAX); layerConf->set_min(std::rand() / (double)RAND_MAX);
layerConf->set_clip_threshold_high(std::rand() / (real)RAND_MAX); layerConf->set_max(std::rand() / (double)RAND_MAX);
for (auto useGpu : {false, true}) { for (auto useGpu : {false, true}) {
testLayerGrad(config, "clip", batchSize, false, useGpu, false); testLayerGrad(config, "clip", batchSize, false, useGpu, false);
} }
......
...@@ -290,8 +290,8 @@ message DetectionOutputConfig { ...@@ -290,8 +290,8 @@ message DetectionOutputConfig {
} }
message ClipConfig { message ClipConfig {
required float clip_threshold_low = 1; required double min = 1;
required float clip_threshold_high = 2; required double max = 2;
} }
message LayerInputConfig { message LayerInputConfig {
......
...@@ -2171,19 +2171,16 @@ class RowConvLayer(LayerBase): ...@@ -2171,19 +2171,16 @@ class RowConvLayer(LayerBase):
@config_layer('clip') @config_layer('clip')
class ClipLayer(LayerBase): class ClipLayer(LayerBase):
def __init__(self, name, inputs, clip_threshold_low, clip_threshold_high): def __init__(self, name, inputs, min, max, **xargs):
super(ClipLayer, self).__init__(name, 'clip', 0, inputs=inputs) super(ClipLayer, self).__init__(name, 'clip', 0, inputs=inputs, **xargs)
config_assert( config_assert(
len(self.inputs) == 1, len(self.inputs) == 1,
'ClipLayer layer must have one and only one input.') 'ClipLayer must have one and only one input.')
config_assert( config_assert(min < max, 'min must be less than max.')
clip_threshold_low < clip_threshold_high,
'clip_threshold_low must be less than clip_threshold_high.')
input_layer = self.get_input_layer(0) input_layer = self.get_input_layer(0)
self.set_layer_size(input_layer.size) self.set_layer_size(input_layer.size)
self.config.inputs[0].clip_conf.clip_threshold_low = clip_threshold_low self.config.inputs[0].clip_conf.min = min
self.config.inputs[ self.config.inputs[0].clip_conf.max = max
0].clip_conf.clip_threshold_high = clip_threshold_high
# key: cost type # key: cost type
......
...@@ -6011,7 +6011,7 @@ def crop_layer(input, offset, axis=2, shape=None, name=None, layer_attr=None): ...@@ -6011,7 +6011,7 @@ def crop_layer(input, offset, axis=2, shape=None, name=None, layer_attr=None):
@wrap_name_default("clip") @wrap_name_default("clip")
def clip_layer(input, clip_threshold_low, clip_threshold_high, name=None): def clip_layer(input, min, max, name=None):
""" """
A layer for clipping the input value by the threshold. A layer for clipping the input value by the threshold.
...@@ -6021,23 +6021,23 @@ def clip_layer(input, clip_threshold_low, clip_threshold_high, name=None): ...@@ -6021,23 +6021,23 @@ def clip_layer(input, clip_threshold_low, clip_threshold_high, name=None):
.. code-block:: python .. code-block:: python
clip = clip_layer(input=input_layer, clip_threshold_low=-10, clip_threshold_high=10) clip = clip_layer(input=input_layer, min=-10, max=10)
:param name: The Layer Name. :param name: The Layer Name.
:type name: basestring :type name: basestring
:param input: The input layer. :param input: The input layer.
:type input: LayerOutput. :type input: LayerOutput.
:param clip_threshold_low: The lower threshold for clipping. :param min: The lower threshold for clipping.
:type clip_threshold_low: float :type min: double
:param clip_threshold_high: The upper threshold for clipping. :param max: The upper threshold for clipping.
:type clip_threshold_high: float :type max: double
:return: LayerOutput :return: LayerOutput
""" """
Layer( Layer(
name=name, name=name,
type=LayerType.CLIP_LAYER, type=LayerType.CLIP_LAYER,
inputs=[input.name], inputs=[input.name],
clip_threshold_low=clip_threshold_low, min=min,
clip_threshold_high=clip_threshold_high) max=max)
return LayerOutput( return LayerOutput(
name, LayerType.CLIP_LAYER, parents=[input], size=input.size) name, LayerType.CLIP_LAYER, parents=[input], size=input.size)
...@@ -7,6 +7,6 @@ test_rnn_group shared_fc shared_lstm shared_gru test_cost_layers_with_weight ...@@ -7,6 +7,6 @@ test_rnn_group shared_fc shared_lstm shared_gru test_cost_layers_with_weight
test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops
test_seq_concat_reshape test_pad test_smooth_l1 test_multiplex_layer test_seq_concat_reshape test_pad test_smooth_l1 test_multiplex_layer
test_prelu_layer test_row_conv test_detection_output_layer test_multibox_loss_layer test_prelu_layer test_row_conv test_detection_output_layer test_multibox_loss_layer
test_recursive_topology test_gated_unit_layer) test_recursive_topology test_gated_unit_layer test_clip_layer)
export whole_configs=(test_split_datasource) export whole_configs=(test_split_datasource)
from paddle.trainer_config_helpers import *
data = data_layer(name='input', size=300)
clip = clip_layer(input=data, min=-10, max=10)
outputs(clip)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册