|
|
|
@ -15,6 +15,7 @@
|
|
|
|
|
# TODO: define loss functions of neural network
|
|
|
|
|
import paddle.fluid as fluid
|
|
|
|
|
import paddle
|
|
|
|
|
from .. import functional as F
|
|
|
|
|
|
|
|
|
|
__all__ = [
|
|
|
|
|
# 'NCELoss',
|
|
|
|
@ -460,11 +461,11 @@ class NLLLoss(fluid.dygraph.Layer):
|
|
|
|
|
:alias_main: paddle.nn.NLLLoss
|
|
|
|
|
:alias: paddle.nn.NLLLoss,paddle.nn.layer.NLLLoss,paddle.nn.layer.loss.NLLLoss
|
|
|
|
|
|
|
|
|
|
This op accepts input and target label and returns negative log likelihood
|
|
|
|
|
This class accepts input and target label and returns negative log likelihood
|
|
|
|
|
cross error. It is useful to train a classification problem with C classes.
|
|
|
|
|
|
|
|
|
|
The input for the loss is epected to contain log-probabilities of
|
|
|
|
|
each classes. It hs to be a Tensor of size either (batch_size, C) or
|
|
|
|
|
each classes. It has to be a Tensor of size either (batch_size, C) or
|
|
|
|
|
(batch_size, C, d1, d2, ..., dK) with K >= 1 for the K-dimensional case.
|
|
|
|
|
The label for the loss should be a class index in the range [0, C-1]
|
|
|
|
|
where C is the number of classes. If ignore_index is specified, the
|
|
|
|
@ -494,106 +495,77 @@ class NLLLoss(fluid.dygraph.Layer):
|
|
|
|
|
\\end{cases}
|
|
|
|
|
|
|
|
|
|
Parameters:
|
|
|
|
|
input (Variable): Input tensor, the data type is float32, float64.
|
|
|
|
|
label (Variable): Label tensor, the data type is int64_t.
|
|
|
|
|
weight (Variable, optional): Weight tensor, a manual rescaling weight given
|
|
|
|
|
to each class. If given, it has to be a Tensor of size `C`. Otherwise,
|
|
|
|
|
weight (Tensor, optional): Weight tensor, a manual rescaling weight given
|
|
|
|
|
to each class. If given, it has to be a 1D Tensor whose size is `[C, ]`. Otherwise,
|
|
|
|
|
it treated as if having all ones. the data type is
|
|
|
|
|
float32, float64, Default is ``'None'``.
|
|
|
|
|
ignore_index (int64, optional): Specifies a target value that is ignored
|
|
|
|
|
and does not contribute to the input gradient.
|
|
|
|
|
reduction (str, optional): Indicate how to average the loss,
|
|
|
|
|
the candicates are ``'none'`` | ``'mean'`` | ``'sum'``.
|
|
|
|
|
If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned;
|
|
|
|
|
If `reduction` is ``'mean'``, the reduced mean loss is returned;
|
|
|
|
|
if `reduction` is ``'sum'``, the reduced sum loss is returned;
|
|
|
|
|
if `reduction` is ``'none'``, no reduction will be apllied.
|
|
|
|
|
Default is ``'mean'``.
|
|
|
|
|
ignore_index (int64, optional): Specifies a target value that is ignored
|
|
|
|
|
and does not contribute to the input gradient.
|
|
|
|
|
name (str, optional): Name for the operation (optional, default is None).
|
|
|
|
|
For more information, please refer to :ref:`api_guide_Name`.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
The tensor variable storing the nll_loss.
|
|
|
|
|
Shape:
|
|
|
|
|
input (Tensor): Input tensor, the shape is :math:`[N, C]`, `C` is the number of classes.
|
|
|
|
|
But in K-dimension situation, the shape is :math:`[N, C, d_1, d_2, ..., d_K]`.
|
|
|
|
|
The data type is float32, float64.
|
|
|
|
|
label (Tensor): Label tensor, the shape is :math:`[N,]` or :math:`[N, d_1, d_2, ..., d_K]`.
|
|
|
|
|
The data type is int64.
|
|
|
|
|
output (Tensor): the `negative log likelihood loss` between input `x` and `label`.
|
|
|
|
|
If `reduction` is `'none'`, the shape is `[N, *]`.
|
|
|
|
|
If `reduction` is `'sum'` or `'mean'`, the shape is `[1]`.
|
|
|
|
|
|
|
|
|
|
Return type: Variable.
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
|
|
# declarative mode
|
|
|
|
|
import paddle.fluid as fluid
|
|
|
|
|
import numpy as np
|
|
|
|
|
import paddle
|
|
|
|
|
import paddle
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
|
|
input_np = np.random.random(size=(10, 10)).astype(np.float32)
|
|
|
|
|
label_np = np.random.randint(0, 10, size=(10,)).astype(np.int64)
|
|
|
|
|
prog = fluid.Program()
|
|
|
|
|
startup_prog = fluid.Program()
|
|
|
|
|
place = fluid.CPUPlace()
|
|
|
|
|
with fluid.program_guard(prog, startup_prog):
|
|
|
|
|
input = fluid.data(name='input', shape=[10, 10], dtype='float32')
|
|
|
|
|
label = fluid.data(name='label', shape=[10], dtype='int64')
|
|
|
|
|
nll_loss = paddle.nn.loss.NLLLoss()
|
|
|
|
|
res = nll_loss(input, label)
|
|
|
|
|
|
|
|
|
|
exe = fluid.Executor(place)
|
|
|
|
|
static_result = exe.run(
|
|
|
|
|
prog,
|
|
|
|
|
feed={"input": input_np,
|
|
|
|
|
"label": label_np},
|
|
|
|
|
fetch_list=[res])
|
|
|
|
|
print(static_result)
|
|
|
|
|
|
|
|
|
|
# imperative mode
|
|
|
|
|
import paddle.fluid.dygraph as dg
|
|
|
|
|
with dg.guard(place) as g:
|
|
|
|
|
input = dg.to_variable(input_np)
|
|
|
|
|
label = dg.to_variable(label_np)
|
|
|
|
|
output = nll_loss(input, label)
|
|
|
|
|
print(output.numpy())
|
|
|
|
|
"""
|
|
|
|
|
nll_loss = paddle.nn.layer.NLLLoss()
|
|
|
|
|
log_softmax = paddle.nn.LogSoftmax(axis=1)
|
|
|
|
|
|
|
|
|
|
def __init__(self, weight=None, reduction='mean', ignore_index=-100):
|
|
|
|
|
super(NLLLoss, self).__init__()
|
|
|
|
|
self.weight = weight
|
|
|
|
|
self.reduction = reduction
|
|
|
|
|
self.ignore_index = ignore_index
|
|
|
|
|
input_np = np.array([[0.88103855, 0.9908683 , 0.6226845 ],
|
|
|
|
|
[0.53331435, 0.07999352, 0.8549948 ],
|
|
|
|
|
[0.25879037, 0.39530203, 0.698465 ],
|
|
|
|
|
[0.73427284, 0.63575995, 0.18827209],
|
|
|
|
|
[0.05689114, 0.0862954 , 0.6325046 ]]).astype(np.float32)
|
|
|
|
|
label_np = np.array([0, 2, 1, 1, 0]).astype(np.int64)
|
|
|
|
|
|
|
|
|
|
def forward(self, input, label):
|
|
|
|
|
dtype = self._helper.input_dtype(input)
|
|
|
|
|
place = paddle.CPUPlace()
|
|
|
|
|
paddle.disable_static(place)
|
|
|
|
|
input = paddle.to_variable(input_np)
|
|
|
|
|
log_out = log_softmax(input)
|
|
|
|
|
label = paddle.to_variable(label_np)
|
|
|
|
|
result = nll_loss(log_out, label)
|
|
|
|
|
print(result.numpy()) # [1.0720209]
|
|
|
|
|
|
|
|
|
|
fluid.data_feeder.check_variable_and_dtype(
|
|
|
|
|
input, 'input', ['float32', 'float64'], 'nll_loss')
|
|
|
|
|
fluid.data_feeder.check_variable_and_dtype(label, 'label', ['int64'],
|
|
|
|
|
'nll_loss')
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.reduction not in ['sum', 'mean', 'none']:
|
|
|
|
|
def __init__(self,
|
|
|
|
|
weight=None,
|
|
|
|
|
ignore_index=-100,
|
|
|
|
|
reduction='mean',
|
|
|
|
|
name=None):
|
|
|
|
|
if reduction not in ['sum', 'mean', 'none']:
|
|
|
|
|
raise ValueError(
|
|
|
|
|
"The value of 'reduction' in nll_loss should be 'sum', 'mean' or 'none', but "
|
|
|
|
|
"received %s, which is not allowed." % self.reduction)
|
|
|
|
|
|
|
|
|
|
x_shape = list(input.shape)
|
|
|
|
|
n = x_shape[0]
|
|
|
|
|
c = x_shape[1]
|
|
|
|
|
x_dims = len(x_shape)
|
|
|
|
|
if x_dims < 2:
|
|
|
|
|
raise ValueError('Expected 2 or more dimensions (got {})'.format(
|
|
|
|
|
x_dims))
|
|
|
|
|
if x_dims != 2 and x_dims != 4:
|
|
|
|
|
input = fluid.layers.reshape(input, shape=[n, c, 1, -1])
|
|
|
|
|
label = fluid.layers.reshape(label, shape=[n, 1, -1])
|
|
|
|
|
out_shape = [n] + x_shape[2:]
|
|
|
|
|
|
|
|
|
|
inputs = {'X': input, 'Label': label}
|
|
|
|
|
attrs = {'reduction': self.reduction, 'ignore_index': self.ignore_index}
|
|
|
|
|
if self.weight is not None:
|
|
|
|
|
if isinstance(self.weight, fluid.framework.Variable):
|
|
|
|
|
inputs['Weight'] = self.weight
|
|
|
|
|
|
|
|
|
|
out = self._helper.create_variable_for_type_inference(dtype=input.dtype)
|
|
|
|
|
total_weight = self._helper.create_variable_for_type_inference(
|
|
|
|
|
dtype=input.dtype)
|
|
|
|
|
outputs = {'Out': out, 'Total_weight': total_weight}
|
|
|
|
|
|
|
|
|
|
self._helper.append_op(
|
|
|
|
|
type='nll_loss', inputs=inputs, outputs=outputs, attrs=attrs)
|
|
|
|
|
if x_dims != 2 and x_dims != 4 and self.reduction == 'none':
|
|
|
|
|
out = fluid.layers.reshape(out, shape=out_shape)
|
|
|
|
|
"The value of 'reduction' in nll_loss should be 'sum', 'mean' or "
|
|
|
|
|
"'none', but received %s, which is not allowed." % reduction)
|
|
|
|
|
super(NLLLoss, self).__init__()
|
|
|
|
|
self._weight = weight
|
|
|
|
|
self._ignore_index = ignore_index
|
|
|
|
|
self._reduction = reduction
|
|
|
|
|
self._name = name
|
|
|
|
|
|
|
|
|
|
return out
|
|
|
|
|
def forward(self, input, label):
|
|
|
|
|
return F.nll_loss(
|
|
|
|
|
input,
|
|
|
|
|
label,
|
|
|
|
|
weight=self._weight,
|
|
|
|
|
ignore_index=self._ignore_index,
|
|
|
|
|
reduction=self._reduction,
|
|
|
|
|
name=self._name)
|
|
|
|
|