提交 ebad8e52 编写于 作者: X xuwei06

Add SumCost

This allows user to implement any type of cost by summing over the output of non-cost layers.

Change-Id: Ic55aaabbf0c1299e70b8e48a0effcc91f8f5bd29
上级 4905751a
...@@ -562,4 +562,33 @@ void HuberTwoClass::backwardImpIn( ...@@ -562,4 +562,33 @@ void HuberTwoClass::backwardImpIn(
} }
} }
class SumCostLayer : public Layer {
public:
explicit SumCostLayer(const LayerConfig& config) : Layer(config) {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap) {
bool ret = Layer::init(layerMap, parameterMap);
if (!ret) return ret;
CHECK_EQ(inputLayers_.size(), 1UL);
return true;
}
virtual void forward(PassType passType) {
Layer::forward(passType);
const MatrixPtr& input = getInputValue(0);
/* malloc memory for the output_ if necessary */
int batchSize = input->getHeight();
int size = 1;
resizeOutput(batchSize, size);
output_.value->sumRows(*input);
}
virtual void backward(const UpdateCallback& callback = nullptr) {
getInputGrad(0)->add((real)1);
}
};
REGISTER_LAYER(sum_cost, SumCostLayer);
} // namespace paddle } // namespace paddle
...@@ -935,6 +935,19 @@ TEST(Layer, rankCostLayer) { ...@@ -935,6 +935,19 @@ TEST(Layer, rankCostLayer) {
} }
} }
TEST(Layer, sumCostLayer) {
TestConfig config;
config.layerConfig.set_type("sum_cost");
config.biasSize = 0;
config.inputDefs.push_back({INPUT_DATA, "layer_0", 1, 0});
config.layerConfig.add_inputs();
for (auto useGpu : {false, true}) {
testLayerGrad(config, "sum_cost", 100, false, useGpu);
}
}
TEST(Layer, weightedRankCostLayer) { TEST(Layer, weightedRankCostLayer) {
TestConfig config; TestConfig config;
config.layerConfig.set_type("rank-cost"); config.layerConfig.set_type("rank-cost");
......
...@@ -1795,6 +1795,7 @@ define_cost('SumOfSquaresCostLayer', 'square_error') ...@@ -1795,6 +1795,7 @@ define_cost('SumOfSquaresCostLayer', 'square_error')
define_cost('MultiBinaryLabelCrossEntropy', 'multi_binary_label_cross_entropy') define_cost('MultiBinaryLabelCrossEntropy', 'multi_binary_label_cross_entropy')
define_cost('SoftBinaryClassCrossEntropy', 'soft_binary_class_cross_entropy') define_cost('SoftBinaryClassCrossEntropy', 'soft_binary_class_cross_entropy')
define_cost('HuberTwoClass', 'huber') define_cost('HuberTwoClass', 'huber')
define_cost('SumCost', 'sum_cost')
@config_layer('hsigmoid') @config_layer('hsigmoid')
class HierarchicalSigmoidLayer(LayerBase): class HierarchicalSigmoidLayer(LayerBase):
......
...@@ -52,7 +52,7 @@ __all__ = ["full_matrix_projection", "AggregateLevel", "ExpandLevel", ...@@ -52,7 +52,7 @@ __all__ = ["full_matrix_projection", "AggregateLevel", "ExpandLevel",
'convex_comb_layer', 'ctc_layer', 'crf_layer', 'crf_decoding_layer', 'convex_comb_layer', 'ctc_layer', 'crf_layer', 'crf_decoding_layer',
'nce_layer', 'nce_layer',
'cross_entropy_with_selfnorm', 'cross_entropy', 'cross_entropy_with_selfnorm', 'cross_entropy',
'multi_binary_label_cross_entropy', 'multi_binary_label_cross_entropy', 'sum_cost',
'rank_cost', 'lambda_cost', 'huber_cost', 'rank_cost', 'lambda_cost', 'huber_cost',
'block_expand_layer', 'block_expand_layer',
'maxout_layer', 'out_prod_layer', 'print_layer' 'maxout_layer', 'out_prod_layer', 'print_layer'
...@@ -126,6 +126,7 @@ class LayerType(object): ...@@ -126,6 +126,7 @@ class LayerType(object):
CROSS_ENTROPY_WITH_SELFNORM = "multi_class_cross_entropy_with_selfnorm" CROSS_ENTROPY_WITH_SELFNORM = "multi_class_cross_entropy_with_selfnorm"
SOFT_BIN_CLASS_CROSS_ENTROPY = "soft_binary_class_cross_entropy" SOFT_BIN_CLASS_CROSS_ENTROPY = "soft_binary_class_cross_entropy"
MULTI_BIN_LABEL_CROSS_ENTROPY = "multi_binary_label_cross_entropy" MULTI_BIN_LABEL_CROSS_ENTROPY = "multi_binary_label_cross_entropy"
SUM_COST = "sum_cost"
@staticmethod @staticmethod
def is_layer_type(type_name): def is_layer_type(type_name):
...@@ -3924,8 +3925,6 @@ def cross_entropy(input, label, name=None, coeff=1.0, layer_attr=None): ...@@ -3924,8 +3925,6 @@ def cross_entropy(input, label, name=None, coeff=1.0, layer_attr=None):
:type input: LayerOutput. :type input: LayerOutput.
:param label: The input label. :param label: The input label.
:type input: LayerOutput. :type input: LayerOutput.
:param type: The type of cost.
:type type: basestring.
:param name: The name of this layers. It is not necessary. :param name: The name of this layers. It is not necessary.
:type name: None|basestring. :type name: None|basestring.
:param coeff: The coefficient affects the gradient in the backward. :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, ...@@ -3961,8 +3960,6 @@ def cross_entropy_with_selfnorm(input, label, name=None, coeff=1.0,
:type input: LayerOutput. :type input: LayerOutput.
:param label: The input label. :param label: The input label.
:type input: LayerOutput. :type input: LayerOutput.
:param type: The type of cost.
:type type: basestring.
:param name: The name of this layers. It is not necessary. :param name: The name of this layers. It is not necessary.
:type name: None|basestring. :type name: None|basestring.
:param coeff: The coefficient affects the gradient in the backward. :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, ...@@ -3987,6 +3984,36 @@ def cross_entropy_with_selfnorm(input, label, name=None, coeff=1.0,
parents=[input, label]) parents=[input, label])
@wrap_name_default()
@layer_support()
def sum_cost(input, name=None, layer_attr=None):
"""
A loss layer which calculate the sum of the input as loss
.. code-block:: python
cost = sum_cost(input)
:param input: The first input layer.
:type input: LayerOutput.
:param name: The name of this layers. It is not necessary.
:type name: None|basestring.
:param layer_attr: Extra Layer Attribute.
:type layer_attr: ExtraLayerAttribute
:return: LayerOutput object.
:rtype: LayerOutput.
"""
Layer(name=name,
type=LayerType.SUM_COST,
inputs=[input.name],
**ExtraLayerAttribute.to_kwargs(layer_attr)
)
return LayerOutput(name,
LayerType.SUM_COST,
parents=[input])
@wrap_name_default() @wrap_name_default()
@layer_support() @layer_support()
def huber_cost(input, label, name=None, coeff=1.0, layer_attr=None): def huber_cost(input, label, name=None, coeff=1.0, layer_attr=None):
......
...@@ -11,8 +11,9 @@ labels = data_layer(name='labels', size=5000) ...@@ -11,8 +11,9 @@ labels = data_layer(name='labels', size=5000)
probs = data_layer(name='probs', size=10) probs = data_layer(name='probs', size=10)
xe_label = data_layer(name='xe-label', size=10) xe_label = data_layer(name='xe-label', size=10)
hidden = fc_layer(input=seq_in, size=4)
outputs(ctc_layer(input=seq_in, label=labels), outputs(ctc_layer(input=seq_in, label=labels),
crf_layer(input=fc_layer(input=seq_in, size=4), crf_layer(input=hidden,
label=data_layer(name='crf_label', size=4)), label=data_layer(name='crf_label', size=4)),
rank_cost(left=data_layer(name='left', size=1), rank_cost(left=data_layer(name='left', size=1),
right=data_layer(name='right', size=1), right=data_layer(name='right', size=1),
...@@ -23,4 +24,5 @@ outputs(ctc_layer(input=seq_in, label=labels), ...@@ -23,4 +24,5 @@ outputs(ctc_layer(input=seq_in, label=labels),
cross_entropy_with_selfnorm(input=probs, label=xe_label), cross_entropy_with_selfnorm(input=probs, label=xe_label),
huber_cost(input=data_layer(name='huber_probs', size=1), huber_cost(input=data_layer(name='huber_probs', size=1),
label=data_layer(name='huber_label', size=1)), label=data_layer(name='huber_label', size=1)),
multi_binary_label_cross_entropy(input=probs, label=xe_label)) multi_binary_label_cross_entropy(input=probs, label=xe_label),
sum_cost(hidden))
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册