Skip to content

Commit ebad8e5

Browse files
author
xuwei06
committed
Add SumCost
This allows user to implement any type of cost by summing over the output of non-cost layers. Change-Id: Ic55aaabbf0c1299e70b8e48a0effcc91f8f5bd29
1 parent 4905751 commit ebad8e5

File tree

5 files changed

+79
-7
lines changed

5 files changed

+79
-7
lines changed

paddle/gserver/layers/CostLayer.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,4 +562,33 @@ void HuberTwoClass::backwardImpIn(
562562
}
563563
}
564564

565+
class SumCostLayer : public Layer {
566+
public:
567+
explicit SumCostLayer(const LayerConfig& config) : Layer(config) {}
568+
569+
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) {
570+
bool ret = Layer::init(layerMap, parameterMap);
571+
if (!ret) return ret;
572+
CHECK_EQ(inputLayers_.size(), 1UL);
573+
return true;
574+
}
575+
576+
virtual void forward(PassType passType) {
577+
Layer::forward(passType);
578+
const MatrixPtr& input = getInputValue(0);
579+
580+
/* malloc memory for the output_ if necessary */
581+
int batchSize = input->getHeight();
582+
int size = 1;
583+
resizeOutput(batchSize, size);
584+
output_.value->sumRows(*input);
585+
}
586+
587+
virtual void backward(const UpdateCallback& callback = nullptr) {
588+
getInputGrad(0)->add((real)1);
589+
}
590+
};
591+
592+
REGISTER_LAYER(sum_cost, SumCostLayer);
593+
565594
} // namespace paddle

paddle/gserver/tests/test_LayerGrad.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,19 @@ TEST(Layer, rankCostLayer) {
935935
}
936936
}
937937

938+
TEST(Layer, sumCostLayer) {
939+
TestConfig config;
940+
config.layerConfig.set_type("sum_cost");
941+
config.biasSize = 0;
942+
943+
config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0});
944+
config.layerConfig.add_inputs();
945+
946+
for (auto useGpu : {false, true}) {
947+
testLayerGrad(config, "sum_cost", 100, false, useGpu);
948+
}
949+
}
950+
938951
TEST(Layer, weightedRankCostLayer) {
939952
TestConfig config;
940953
config.layerConfig.set_type("rank-cost");

python/paddle/trainer/config_parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,7 @@ def init(cls, name, inputs, device=None, coeff=1.):
17951795
define_cost('MultiBinaryLabelCrossEntropy', 'multi_binary_label_cross_entropy')
17961796
define_cost('SoftBinaryClassCrossEntropy', 'soft_binary_class_cross_entropy')
17971797
define_cost('HuberTwoClass', 'huber')
1798+
define_cost('SumCost', 'sum_cost')
17981799

17991800
@config_layer('hsigmoid')
18001801
class HierarchicalSigmoidLayer(LayerBase):

python/paddle/trainer_config_helpers/layers.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
'convex_comb_layer', 'ctc_layer', 'crf_layer', 'crf_decoding_layer',
5353
'nce_layer',
5454
'cross_entropy_with_selfnorm', 'cross_entropy',
55-
'multi_binary_label_cross_entropy',
55+
'multi_binary_label_cross_entropy', 'sum_cost',
5656
'rank_cost', 'lambda_cost', 'huber_cost',
5757
'block_expand_layer',
5858
'maxout_layer', 'out_prod_layer', 'print_layer'
@@ -126,6 +126,7 @@ class LayerType(object):
126126
CROSS_ENTROPY_WITH_SELFNORM = "multi_class_cross_entropy_with_selfnorm"
127127
SOFT_BIN_CLASS_CROSS_ENTROPY = "soft_binary_class_cross_entropy"
128128
MULTI_BIN_LABEL_CROSS_ENTROPY = "multi_binary_label_cross_entropy"
129+
SUM_COST = "sum_cost"
129130

130131
@staticmethod
131132
def is_layer_type(type_name):
@@ -3924,8 +3925,6 @@ def cross_entropy(input, label, name=None, coeff=1.0, layer_attr=None):
39243925
:type input: LayerOutput.
39253926
:param label: The input label.
39263927
:type input: LayerOutput.
3927-
:param type: The type of cost.
3928-
:type type: basestring.
39293928
:param name: The name of this layers. It is not necessary.
39303929
:type name: None|basestring.
39313930
:param coeff: The coefficient affects the gradient in the backward.
@@ -3961,8 +3960,6 @@ def cross_entropy_with_selfnorm(input, label, name=None, coeff=1.0,
39613960
:type input: LayerOutput.
39623961
:param label: The input label.
39633962
:type input: LayerOutput.
3964-
:param type: The type of cost.
3965-
:type type: basestring.
39663963
:param name: The name of this layers. It is not necessary.
39673964
:type name: None|basestring.
39683965
:param coeff: The coefficient affects the gradient in the backward.
@@ -3987,6 +3984,36 @@ def cross_entropy_with_selfnorm(input, label, name=None, coeff=1.0,
39873984
parents=[input, label])
39883985

39893986

3987+
@wrap_name_default()
3988+
@layer_support()
3989+
def sum_cost(input, name=None, layer_attr=None):
3990+
"""
3991+
A loss layer which calculate the sum of the input as loss
3992+
3993+
.. code-block:: python
3994+
3995+
cost = sum_cost(input)
3996+
3997+
:param input: The first input layer.
3998+
:type input: LayerOutput.
3999+
:param name: The name of this layers. It is not necessary.
4000+
:type name: None|basestring.
4001+
:param layer_attr: Extra Layer Attribute.
4002+
:type layer_attr: ExtraLayerAttribute
4003+
:return: LayerOutput object.
4004+
:rtype: LayerOutput.
4005+
"""
4006+
Layer(name=name,
4007+
type=LayerType.SUM_COST,
4008+
inputs=[input.name],
4009+
**ExtraLayerAttribute.to_kwargs(layer_attr)
4010+
)
4011+
4012+
return LayerOutput(name,
4013+
LayerType.SUM_COST,
4014+
parents=[input])
4015+
4016+
39904017
@wrap_name_default()
39914018
@layer_support()
39924019
def huber_cost(input, label, name=None, coeff=1.0, layer_attr=None):

python/paddle/trainer_config_helpers/tests/configs/test_cost_layers.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
probs = data_layer(name='probs', size=10)
1212
xe_label = data_layer(name='xe-label', size=10)
1313

14+
hidden = fc_layer(input=seq_in, size=4)
1415
outputs(ctc_layer(input=seq_in, label=labels),
15-
crf_layer(input=fc_layer(input=seq_in, size=4),
16+
crf_layer(input=hidden,
1617
label=data_layer(name='crf_label', size=4)),
1718
rank_cost(left=data_layer(name='left', size=1),
1819
right=data_layer(name='right', size=1),
@@ -23,4 +24,5 @@
2324
cross_entropy_with_selfnorm(input=probs, label=xe_label),
2425
huber_cost(input=data_layer(name='huber_probs', size=1),
2526
label=data_layer(name='huber_label', size=1)),
26-
multi_binary_label_cross_entropy(input=probs, label=xe_label))
27+
multi_binary_label_cross_entropy(input=probs, label=xe_label),
28+
sum_cost(hidden))

0 commit comments

Comments
 (0)