提交 23a8d015 编写于 作者: G guosheng

add ClipLayer

上级 0973c2c9
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
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. */
#include "Layer.h"
#include "paddle/math/Matrix.h"
namespace paddle {
/**
* A layer for clipping the input value by the threshold.
* \f[
* out[i] = \min\left(\max\left(in[i],p_{1}\right),p_{2}\right)
* \f]
*/
class ClipLayer : public Layer {
protected:
real clipThresholdLow_;
real clipThresholdHigh_;
public:
explicit ClipLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void forward(PassType passType) override;
void backward(const UpdateCallback& callback = nullptr) override;
};
REGISTER_LAYER(clip, ClipLayer);
bool ClipLayer::init(const LayerMap& layerMap,
const ParameterMap& parameterMap) {
Layer::init(layerMap, parameterMap);
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_);
return true;
}
void ClipLayer::forward(PassType passType) {
Layer::forward(passType);
MatrixPtr inV = getInputValue(0);
resetOutput(inV->getHeight(), inV->getWidth());
MatrixPtr outV = getOutputValue();
outV->copyFrom(*inV);
outV->clip(clipThresholdLow_, clipThresholdHigh_);
}
void ClipLayer::backward(const UpdateCallback& callback) {
MatrixPtr inV = getInputValue(0);
MatrixPtr inG = getInputGrad(0);
MatrixPtr outV = getOutputValue();
MatrixPtr outG = getOutputGrad();
MatrixPtr tmpMtx;
Matrix::resizeOrCreate(
tmpMtx, outG->getHeight(), outG->getWidth(), false, useGpu_);
tmpMtx->clipDerivative(*inV, clipThresholdLow_, clipThresholdHigh_);
inG->addDotMul(*outG, *tmpMtx, 1, 1);
}
} // namespace paddle
...@@ -1879,6 +1879,21 @@ TEST(Layer, CropLayer) { ...@@ -1879,6 +1879,21 @@ TEST(Layer, CropLayer) {
} }
} }
TEST(Layer, ClipLayer) {
const size_t batchSize = 128;
const size_t size = 512;
TestConfig config;
config.layerConfig.set_type("clip");
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);
for (auto useGpu : {false, true}) {
testLayerGrad(config, "clip", batchSize, false, useGpu, false);
}
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
initMain(argc, argv); initMain(argc, argv);
......
...@@ -442,6 +442,12 @@ DEFINE_MATRIX_UNARY_PARAMETER_OP(Clip, TWO_PARAMETER, ...@@ -442,6 +442,12 @@ DEFINE_MATRIX_UNARY_PARAMETER_OP(Clip, TWO_PARAMETER,
template<class T> template<class T>
void BaseMatrixT<T>::clip(T p1, T p2) { applyUnary(unary::Clip<T>(p1, p2)); } void BaseMatrixT<T>::clip(T p1, T p2) { applyUnary(unary::Clip<T>(p1, p2)); }
DEFINE_MATRIX_BINARY_PARAMETER_OP(ClipDerivative, TWO_PARAMETER, a = b < p1 ? 0 : (b > p2 ? 0 : 1));
template<class T>
void BaseMatrixT<T>::clipDerivative(BaseMatrixT& b, T p1, T p2) {
applyBinary(binary::ClipDerivative<T>(p1, p2), b);
}
DEFINE_MATRIX_UNARY_PARAMETER_OP(BiggerThanScalar, ONE_PARAMETER, DEFINE_MATRIX_UNARY_PARAMETER_OP(BiggerThanScalar, ONE_PARAMETER,
a = a > p ? 1.0f : 0.0f); a = a > p ? 1.0f : 0.0f);
template<class T> template<class T>
......
...@@ -488,6 +488,13 @@ public: ...@@ -488,6 +488,13 @@ public:
*/ */
void clip(T p1, T p2); void clip(T p1, T p2);
/**
* this = b < low ? 0 : 1
*
* this = b > high ? 0 : 1
*/
void clipDerivative(BaseMatrixT& b, T p1, T p2);
/** /**
* @code * @code
* a = a > p ? 1.0f : 0.0f * a = a > p ? 1.0f : 0.0f
......
...@@ -289,6 +289,11 @@ message DetectionOutputConfig { ...@@ -289,6 +289,11 @@ message DetectionOutputConfig {
optional uint32 width = 9 [default = 1]; optional uint32 width = 9 [default = 1];
} }
message ClipConfig {
required float clip_threshold_low = 1;
required float clip_threshold_high = 2;
}
message LayerInputConfig { message LayerInputConfig {
required string input_layer_name = 1; required string input_layer_name = 1;
optional string input_parameter_name = 2; optional string input_parameter_name = 2;
...@@ -309,6 +314,7 @@ message LayerInputConfig { ...@@ -309,6 +314,7 @@ message LayerInputConfig {
optional RowConvConfig row_conv_conf = 15; optional RowConvConfig row_conv_conf = 15;
optional MultiBoxLossConfig multibox_loss_conf = 16; optional MultiBoxLossConfig multibox_loss_conf = 16;
optional DetectionOutputConfig detection_output_conf = 17; optional DetectionOutputConfig detection_output_conf = 17;
optional ClipConfig clip_conf = 18;
} }
message LayerConfig { message LayerConfig {
......
...@@ -2169,6 +2169,23 @@ class RowConvLayer(LayerBase): ...@@ -2169,6 +2169,23 @@ class RowConvLayer(LayerBase):
self.create_input_parameter(0, psize, dims) self.create_input_parameter(0, psize, dims)
@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)
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.')
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
# key: cost type # key: cost type
# value: cost class # value: cost class
g_cost_map = {} g_cost_map = {}
......
...@@ -31,103 +31,33 @@ except ImportError: ...@@ -31,103 +31,33 @@ except ImportError:
import copy import copy
__all__ = [ __all__ = [
'full_matrix_projection', 'full_matrix_projection', 'AggregateLevel', 'ExpandLevel',
'AggregateLevel', 'identity_projection', 'dotmul_projection', 'dotmul_operator',
'ExpandLevel', 'repeat_layer', 'seq_reshape_layer', 'table_projection', 'mixed_layer',
'identity_projection', 'data_layer', 'embedding_layer', 'fc_layer', 'grumemory', 'pooling_layer',
'dotmul_projection', 'lstmemory', 'last_seq', 'first_seq', 'cos_sim', 'hsigmoid',
'dotmul_operator', 'conv_projection', 'mse_cost', 'regression_cost', 'classification_cost',
'repeat_layer', 'LayerOutput', 'img_conv_layer', 'img_pool_layer', 'batch_norm_layer',
'seq_reshape_layer', 'img_cmrnorm_layer', 'addto_layer', 'concat_layer', 'seq_concat_layer',
'table_projection', 'lstm_step_layer', 'recurrent_group', 'memory', 'StaticInput',
'mixed_layer', 'expand_layer', 'scaling_layer', 'scaling_projection', 'power_layer',
'data_layer', 'interpolation_layer', 'bilinear_interp_layer', 'trans_layer',
'embedding_layer', 'rotate_layer', 'sum_to_one_norm_layer', 'get_output_layer', 'LayerType',
'fc_layer', 'context_projection', 'beam_search', 'maxid_layer', 'GeneratedInput',
'grumemory', 'SubsequenceInput', 'gru_step_layer', 'gru_step_naive_layer',
'pooling_layer', 'recurrent_layer', 'BaseGeneratedInput', 'conv_operator',
'lstmemory', 'conv_shift_layer', 'tensor_layer', 'selective_fc_layer',
'last_seq', 'sampling_id_layer', 'slope_intercept_layer',
'first_seq', 'trans_full_matrix_projection', 'linear_comb_layer', 'convex_comb_layer',
'cos_sim', 'ctc_layer', 'warp_ctc_layer', 'crf_layer', 'crf_decoding_layer',
'hsigmoid', 'nce_layer', 'cross_entropy_with_selfnorm', 'cross_entropy',
'conv_projection', 'multi_binary_label_cross_entropy', 'sum_cost', 'rank_cost', 'lambda_cost',
'mse_cost', 'huber_cost', 'block_expand_layer', 'maxout_layer', 'out_prod_layer',
'regression_cost', 'printer_layer', 'print_layer', 'priorbox_layer',
'classification_cost', 'cross_channel_norm_layer', 'multibox_loss_layer', 'detection_output_layer',
'LayerOutput', 'spp_layer', 'pad_layer', 'eos_layer', 'smooth_l1_cost', 'layer_support',
'img_conv_layer', 'multiplex_layer', 'row_conv_layer', 'dropout_layer', 'prelu_layer',
'img_pool_layer', 'gated_unit_layer', 'crop_layer', 'clip_layer'
'batch_norm_layer',
'img_cmrnorm_layer',
'addto_layer',
'concat_layer',
'seq_concat_layer',
'lstm_step_layer',
'recurrent_group',
'memory',
'StaticInput',
'expand_layer',
'scaling_layer',
'scaling_projection',
'power_layer',
'interpolation_layer',
'bilinear_interp_layer',
'trans_layer',
'rotate_layer',
'sum_to_one_norm_layer',
'get_output_layer',
'LayerType',
'context_projection',
'beam_search',
'maxid_layer',
'GeneratedInput',
'SubsequenceInput',
'gru_step_layer',
'gru_step_naive_layer',
'recurrent_layer',
'BaseGeneratedInput',
'conv_operator',
'conv_shift_layer',
'tensor_layer',
'selective_fc_layer',
'sampling_id_layer',
'slope_intercept_layer',
'trans_full_matrix_projection',
'linear_comb_layer',
'convex_comb_layer',
'ctc_layer',
'warp_ctc_layer',
'crf_layer',
'crf_decoding_layer',
'nce_layer',
'cross_entropy_with_selfnorm',
'cross_entropy',
'multi_binary_label_cross_entropy',
'sum_cost',
'rank_cost',
'lambda_cost',
'huber_cost',
'block_expand_layer',
'maxout_layer',
'out_prod_layer',
'printer_layer',
'print_layer',
'priorbox_layer',
'cross_channel_norm_layer',
'multibox_loss_layer',
'detection_output_layer',
'spp_layer',
'pad_layer',
'eos_layer',
'smooth_l1_cost',
'layer_support',
'multiplex_layer',
'row_conv_layer',
'dropout_layer',
'prelu_layer',
'gated_unit_layer',
'crop_layer',
] ]
...@@ -220,6 +150,7 @@ class LayerType(object): ...@@ -220,6 +150,7 @@ class LayerType(object):
PRELU = 'prelu' PRELU = 'prelu'
CROP_LAYER = 'crop' CROP_LAYER = 'crop'
CLIP_LAYER = 'clip'
@staticmethod @staticmethod
def is_layer_type(type_name): def is_layer_type(type_name):
...@@ -6006,3 +5937,36 @@ def crop_layer(input, offset, axis=2, shape=None, name=None, layer_attr=None): ...@@ -6006,3 +5937,36 @@ def crop_layer(input, offset, axis=2, shape=None, name=None, layer_attr=None):
layer_type=LayerType.CROP_LAYER, layer_type=LayerType.CROP_LAYER,
parents=input, parents=input,
size=l.config.size) size=l.config.size)
@wrap_name_default("clip")
def clip_layer(input, clip_threshold_low, clip_threshold_high, name=None):
"""
A layer for clipping the input value by the threshold.
.. math::
out[i] = \min\left(\max\left(in[i],p_{1}\right),p_{2}\right)
.. code-block:: python
clip = clip_layer(input=input_layer, clip_threshold_low=-10, clip_threshold_high=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
:return: LayerOutput
"""
Layer(
name=name,
type=LayerType.CLIP_LAYER,
inputs=[input.name],
clip_threshold_low=clip_threshold_low,
clip_threshold_high=clip_threshold_high)
return LayerOutput(
name, LayerType.CLIP_LAYER, parents=[input], size=input.size)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册