提交 d19355a5 编写于 作者: G guosheng

Refine ClipLayer and add unit test for it

上级 f35e0847
......@@ -316,6 +316,11 @@ scaling
.. autoclass:: paddle.v2.layer.scaling
:noindex:
clip
----
.. autoclass:: paddle.v2.layer.clip
:noindex:
slope_intercept
---------------
.. autoclass:: paddle.v2.layer.slope_intercept
......
......@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
limitations under the License. */
#include "Layer.h"
#include "paddle/math/Matrix.h"
namespace paddle {
......@@ -26,8 +25,8 @@ namespace paddle {
class ClipLayer : public Layer {
protected:
real clipThresholdLow_;
real clipThresholdHigh_;
double min_;
double max_;
public:
explicit ClipLayer(const LayerConfig& config) : Layer(config) {}
......@@ -47,9 +46,9 @@ bool ClipLayer::init(const LayerMap& layerMap,
CHECK_EQ(inputLayers_.size(), 1U);
auto layerConf = config_.inputs(0).clip_conf();
clipThresholdLow_ = layerConf.clip_threshold_low();
clipThresholdHigh_ = layerConf.clip_threshold_high();
CHECK_LT(clipThresholdLow_, clipThresholdHigh_);
min_ = layerConf.min();
max_ = layerConf.max();
CHECK_LT(min_, max_);
return true;
}
......@@ -60,19 +59,21 @@ void ClipLayer::forward(PassType passType) {
resetOutput(inV->getHeight(), inV->getWidth());
MatrixPtr outV = getOutputValue();
outV->copyFrom(*inV);
outV->clip(clipThresholdLow_, clipThresholdHigh_);
outV->clip(min_, max_);
}
void ClipLayer::backward(const UpdateCallback& callback) {
MatrixPtr inV = getInputValue(0);
MatrixPtr inG = getInputGrad(0);
if (inG) {
MatrixPtr outV = getOutputValue();
MatrixPtr outG = getOutputGrad();
MatrixPtr tmpMtx;
Matrix::resizeOrCreate(
tmpMtx, outG->getHeight(), outG->getWidth(), false, useGpu_);
tmpMtx->clipDerivative(*inV, clipThresholdLow_, clipThresholdHigh_);
tmpMtx->clipDerivative(*inV, min_, max_);
inG->addDotMul(*outG, *tmpMtx, 1, 1);
}
}
} // namespace paddle
......@@ -1887,8 +1887,8 @@ TEST(Layer, ClipLayer) {
config.inputDefs.push_back({INPUT_DATA, "input", size, 0});
LayerInputConfig* input = config.layerConfig.add_inputs();
ClipConfig* layerConf = input->mutable_clip_conf();
layerConf->set_clip_threshold_low(std::rand() / (real)RAND_MAX);
layerConf->set_clip_threshold_high(std::rand() / (real)RAND_MAX);
layerConf->set_min(std::rand() / (double)RAND_MAX);
layerConf->set_max(std::rand() / (double)RAND_MAX);
for (auto useGpu : {false, true}) {
testLayerGrad(config, "clip", batchSize, false, useGpu, false);
}
......
......@@ -290,8 +290,8 @@ message DetectionOutputConfig {
}
message ClipConfig {
required float clip_threshold_low = 1;
required float clip_threshold_high = 2;
required double min = 1;
required double max = 2;
}
message LayerInputConfig {
......
......@@ -2171,19 +2171,16 @@ class RowConvLayer(LayerBase):
@config_layer('clip')
class ClipLayer(LayerBase):
def __init__(self, name, inputs, clip_threshold_low, clip_threshold_high):
super(ClipLayer, self).__init__(name, 'clip', 0, inputs=inputs)
def __init__(self, name, inputs, min, max, **xargs):
super(ClipLayer, self).__init__(name, 'clip', 0, inputs=inputs, **xargs)
config_assert(
len(self.inputs) == 1,
'ClipLayer layer must have one and only one input.')
config_assert(
clip_threshold_low < clip_threshold_high,
'clip_threshold_low must be less than clip_threshold_high.')
'ClipLayer must have one and only one input.')
config_assert(min < max, 'min must be less than max.')
input_layer = self.get_input_layer(0)
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.clip_threshold_high = clip_threshold_high
self.config.inputs[0].clip_conf.min = min
self.config.inputs[0].clip_conf.max = max
# key: cost type
......
......@@ -6011,7 +6011,7 @@ def crop_layer(input, offset, axis=2, shape=None, name=None, layer_attr=None):
@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.
......@@ -6021,23 +6021,23 @@ def clip_layer(input, clip_threshold_low, clip_threshold_high, name=None):
.. 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.
:type name: basestring
:param input: The input layer.
:type input: LayerOutput.
:param clip_threshold_low: The lower threshold for clipping.
:type clip_threshold_low: float
:param clip_threshold_high: The upper threshold for clipping.
:type clip_threshold_high: float
:param min: The lower threshold for clipping.
:type min: double
:param max: The upper threshold for clipping.
:type max: double
:return: LayerOutput
"""
Layer(
name=name,
type=LayerType.CLIP_LAYER,
inputs=[input.name],
clip_threshold_low=clip_threshold_low,
clip_threshold_high=clip_threshold_high)
min=min,
max=max)
return LayerOutput(
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
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_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)
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.
先完成此消息的编辑!
想要评论请 注册