Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
机器未来
Paddle
提交
e52e7944
P
Paddle
项目概览
机器未来
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
e52e7944
编写于
8月 20, 2020
作者:
G
Guanghua Yu
提交者:
GitHub
8月 20, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add paddle.nn.SmoothL1Loss,test=develop (#26398)
上级
e3612de8
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
342 addition
and
2 deletion
+342
-2
python/paddle/fluid/tests/unittests/test_smooth_l1_loss.py
python/paddle/fluid/tests/unittests/test_smooth_l1_loss.py
+181
-0
python/paddle/nn/__init__.py
python/paddle/nn/__init__.py
+1
-0
python/paddle/nn/functional/__init__.py
python/paddle/nn/functional/__init__.py
+1
-0
python/paddle/nn/functional/loss.py
python/paddle/nn/functional/loss.py
+79
-0
python/paddle/nn/layer/__init__.py
python/paddle/nn/layer/__init__.py
+1
-0
python/paddle/nn/layer/loss.py
python/paddle/nn/layer/loss.py
+79
-2
未找到文件。
python/paddle/fluid/tests/unittests/test_smooth_l1_loss.py
0 → 100644
浏览文件 @
e52e7944
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
#
# 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.
from
__future__
import
print_function
import
paddle
import
paddle.fluid
as
fluid
import
numpy
as
np
import
unittest
def
smooth_l1_loss_forward
(
val
,
delta
):
abs_val
=
abs
(
val
)
if
abs_val
<=
delta
:
return
0.5
*
val
*
val
else
:
return
delta
*
(
abs_val
-
0.5
*
delta
)
def
smooth_l1_loss_np
(
input
,
label
,
reduction
=
'mean'
,
delta
=
1.0
):
diff
=
input
-
label
out
=
np
.
vectorize
(
smooth_l1_loss_forward
)(
diff
,
delta
)
if
reduction
==
'sum'
:
return
np
.
sum
(
out
)
elif
reduction
==
'mean'
:
return
np
.
mean
(
out
)
elif
reduction
==
'none'
:
return
out
class
SmoothL1Loss
(
unittest
.
TestCase
):
def
setUp
(
self
):
np
.
random
.
seed
(
123
)
def
test_smooth_l1_loss_mean
(
self
):
input_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
label_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
prog
=
fluid
.
Program
()
startup_prog
=
fluid
.
Program
()
place
=
fluid
.
CUDAPlace
(
0
)
if
fluid
.
core
.
is_compiled_with_cuda
(
)
else
fluid
.
CPUPlace
()
with
fluid
.
program_guard
(
prog
,
startup_prog
):
input
=
fluid
.
data
(
name
=
'input'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
label
=
fluid
.
data
(
name
=
'label'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
()
ret
=
smooth_l1_loss
(
input
,
label
)
exe
=
fluid
.
Executor
(
place
)
static_ret
=
exe
.
run
(
prog
,
feed
=
{
'input'
:
input_np
,
'label'
:
label_np
,
},
fetch_list
=
[
ret
])
self
.
assertIsNotNone
(
static_ret
)
with
fluid
.
dygraph
.
guard
():
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
()
dy_ret
=
smooth_l1_loss
(
fluid
.
dygraph
.
to_variable
(
input_np
),
fluid
.
dygraph
.
to_variable
(
label_np
))
dy_ret_value
=
dy_ret
.
numpy
()
self
.
assertIsNotNone
(
dy_ret_value
)
expected
=
smooth_l1_loss_np
(
input_np
,
label_np
,
reduction
=
'mean'
)
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
dy_ret_value
))
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
expected
))
self
.
assertTrue
(
np
.
allclose
(
dy_ret_value
,
expected
))
def
test_smooth_l1_loss_sum
(
self
):
input_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
label_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
prog
=
fluid
.
Program
()
startup_prog
=
fluid
.
Program
()
place
=
fluid
.
CUDAPlace
(
0
)
if
fluid
.
core
.
is_compiled_with_cuda
(
)
else
fluid
.
CPUPlace
()
with
fluid
.
program_guard
(
prog
,
startup_prog
):
input
=
fluid
.
data
(
name
=
'input'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
label
=
fluid
.
data
(
name
=
'label'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
(
reduction
=
'sum'
)
ret
=
smooth_l1_loss
(
input
,
label
)
exe
=
fluid
.
Executor
(
place
)
static_ret
=
exe
.
run
(
prog
,
feed
=
{
'input'
:
input_np
,
'label'
:
label_np
,
},
fetch_list
=
[
ret
])
self
.
assertIsNotNone
(
static_ret
)
with
fluid
.
dygraph
.
guard
():
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
(
reduction
=
'sum'
)
dy_ret
=
smooth_l1_loss
(
fluid
.
dygraph
.
to_variable
(
input_np
),
fluid
.
dygraph
.
to_variable
(
label_np
))
dy_ret_value
=
dy_ret
.
numpy
()
self
.
assertIsNotNone
(
dy_ret_value
)
expected
=
smooth_l1_loss_np
(
input_np
,
label_np
,
reduction
=
'sum'
)
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
dy_ret_value
))
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
expected
))
self
.
assertTrue
(
np
.
allclose
(
dy_ret_value
,
expected
))
def
test_smooth_l1_loss_none
(
self
):
input_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
label_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
prog
=
fluid
.
Program
()
startup_prog
=
fluid
.
Program
()
place
=
fluid
.
CUDAPlace
(
0
)
if
fluid
.
core
.
is_compiled_with_cuda
(
)
else
fluid
.
CPUPlace
()
with
fluid
.
program_guard
(
prog
,
startup_prog
):
input
=
fluid
.
data
(
name
=
'input'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
label
=
fluid
.
data
(
name
=
'label'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
(
reduction
=
'none'
)
ret
=
smooth_l1_loss
(
input
,
label
)
exe
=
fluid
.
Executor
(
place
)
static_ret
=
exe
.
run
(
prog
,
feed
=
{
'input'
:
input_np
,
'label'
:
label_np
,
},
fetch_list
=
[
ret
])
self
.
assertIsNotNone
(
static_ret
)
with
fluid
.
dygraph
.
guard
():
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
(
reduction
=
'none'
)
dy_ret
=
smooth_l1_loss
(
fluid
.
dygraph
.
to_variable
(
input_np
),
fluid
.
dygraph
.
to_variable
(
label_np
))
dy_ret_value
=
dy_ret
.
numpy
()
self
.
assertIsNotNone
(
dy_ret_value
)
expected
=
smooth_l1_loss_np
(
input_np
,
label_np
,
reduction
=
'none'
)
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
dy_ret_value
))
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
expected
))
self
.
assertTrue
(
np
.
allclose
(
dy_ret_value
,
expected
))
def
test_smooth_l1_loss_delta
(
self
):
input_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
label_np
=
np
.
random
.
random
([
100
,
200
]).
astype
(
np
.
float32
)
delta
=
np
.
random
.
rand
()
prog
=
fluid
.
Program
()
startup_prog
=
fluid
.
Program
()
place
=
fluid
.
CUDAPlace
(
0
)
if
fluid
.
core
.
is_compiled_with_cuda
(
)
else
fluid
.
CPUPlace
()
with
fluid
.
program_guard
(
prog
,
startup_prog
):
input
=
fluid
.
data
(
name
=
'input'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
label
=
fluid
.
data
(
name
=
'label'
,
shape
=
[
100
,
200
],
dtype
=
'float32'
)
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
(
delta
=
delta
)
ret
=
smooth_l1_loss
(
input
,
label
)
exe
=
fluid
.
Executor
(
place
)
static_ret
=
exe
.
run
(
prog
,
feed
=
{
'input'
:
input_np
,
'label'
:
label_np
,
},
fetch_list
=
[
ret
])
self
.
assertIsNotNone
(
static_ret
)
with
fluid
.
dygraph
.
guard
():
smooth_l1_loss
=
paddle
.
nn
.
loss
.
SmoothL1Loss
(
delta
=
delta
)
dy_ret
=
smooth_l1_loss
(
fluid
.
dygraph
.
to_variable
(
input_np
),
fluid
.
dygraph
.
to_variable
(
label_np
))
dy_ret_value
=
dy_ret
.
numpy
()
self
.
assertIsNotNone
(
dy_ret_value
)
expected
=
smooth_l1_loss_np
(
input_np
,
label_np
,
delta
=
delta
)
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
dy_ret_value
))
self
.
assertTrue
(
np
.
allclose
(
static_ret
,
expected
))
self
.
assertTrue
(
np
.
allclose
(
dy_ret_value
,
expected
))
if
__name__
==
"__main__"
:
unittest
.
main
()
python/paddle/nn/__init__.py
浏览文件 @
e52e7944
...
...
@@ -101,6 +101,7 @@ from .layer.loss import NLLLoss #DEFINE_ALIAS
from
.layer.loss
import
BCELoss
#DEFINE_ALIAS
from
.layer.loss
import
KLDivLoss
#DEFINE_ALIAS
from
.layer.loss
import
MarginRankingLoss
#DEFINE_ALIAS
from
.layer.loss
import
SmoothL1Loss
#DEFINE_ALIAS
from
.layer.norm
import
BatchNorm
#DEFINE_ALIAS
from
.layer.norm
import
SyncBatchNorm
#DEFINE_ALIAS
from
.layer.norm
import
GroupNorm
#DEFINE_ALIAS
...
...
python/paddle/nn/functional/__init__.py
浏览文件 @
e52e7944
...
...
@@ -140,6 +140,7 @@ from .loss import sampled_softmax_with_cross_entropy #DEFINE_ALIAS
from
.loss
import
sigmoid_cross_entropy_with_logits
#DEFINE_ALIAS
from
.loss
import
sigmoid_focal_loss
#DEFINE_ALIAS
from
.loss
import
smooth_l1
#DEFINE_ALIAS
from
.loss
import
smooth_l1_loss
#DEFINE_ALIAS
from
.loss
import
softmax_with_cross_entropy
#DEFINE_ALIAS
from
.loss
import
square_error_cost
#DEFINE_ALIAS
from
.loss
import
ssd_loss
#DEFINE_ALIAS
...
...
python/paddle/nn/functional/loss.py
浏览文件 @
e52e7944
...
...
@@ -65,6 +65,7 @@ __all__ = [
'sigmoid_cross_entropy_with_logits'
,
'sigmoid_focal_loss'
,
'smooth_l1'
,
'smooth_l1_loss'
,
'softmax_with_cross_entropy'
,
'square_error_cost'
,
'ssd_loss'
,
...
...
@@ -72,6 +73,84 @@ __all__ = [
]
def
smooth_l1_loss
(
input
,
label
,
reduction
=
'mean'
,
delta
=
1.0
,
name
=
None
):
"""
This operator calculates smooth_l1_loss. Creates a criterion that uses a squared
term if the absolute element-wise error falls below 1 and an L1 term otherwise.
In some cases it can prevent exploding gradients and it is more robust and less
sensitivity to outliers. Also known as the Huber loss:
.. math::
loss(x,y)=
\\
frac{1}{n}
\\
sum_{i}z_i
where z_i is given by:
.. math::
\\
mathop{z_i}=
\\
left
\\
{
\\
begin{array}{rcl}
0.5(x_i - y_i)^2 & & {if |x_i - y_i| < delta}
\\\\
delta * |x_i - y_i| - 0.5 * delta^2 & & {otherwise}
\\
end{array}
\\
right.
Parameters:
input (Tensor): Input tensor, the data type is float32 or float64. Shape is
(N, C), where C is number of classes, and if shape is more than 2D, this
is (N, C, D1, D2,..., Dk), k >= 1.
label (Tensor): Label tensor, the data type is float32 or float64. The shape of label
is the same as the shape of input.
reduction (str, optional): Indicate how to average the loss by batch_size,
the candicates are ``'none'`` | ``'mean'`` | ``'sum'``.
If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned;
If :attr:`reduction` is ``'sum'``, the reduced sum loss is returned.
If :attr:`reduction` is ``'none'``, the unreduced loss is returned.
Default is ``'mean'``.
delta (float, optional): Specifies the hyperparameter delta to be used.
The value determines how large the errors need to be to use L1. Errors
smaller than delta are minimized with L2. Parameter is ignored for
negative/zero values. Default = 1.0
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 smooth_l1_loss of input and label.
Return type: Tensor.
Examples:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
input_data = np.random.rand(3,3).astype("float32")
label_data = np.random.rand(3,3).astype("float32")
input = paddle.to_tensor(input_data)
label = paddle.to_tensor(label_data)
output = paddle.nn.functioanl.smooth_l1_loss(input, label)
print(output.numpy())
"""
fluid
.
data_feeder
.
check_variable_and_dtype
(
input
,
'input'
,
[
'float32'
,
'float64'
],
'smooth_l1_loss'
)
fluid
.
data_feeder
.
check_variable_and_dtype
(
label
,
'label'
,
[
'float32'
,
'float64'
],
'smooth_l1_loss'
)
out
=
huber_loss
(
input
=
input
,
label
=
label
,
delta
=
delta
)
if
reduction
not
in
[
'sum'
,
'mean'
,
'none'
]:
raise
ValueError
(
"The value of 'reduction' in smooth_l1_loss should be 'sum', 'mean' or"
" 'none', but received %s, which is not allowed."
%
reduction
)
if
reduction
==
'none'
:
return
out
elif
reduction
==
'mean'
:
return
fluid
.
layers
.
reduce_mean
(
out
)
elif
reduction
==
'sum'
:
return
fluid
.
layers
.
reduce_sum
(
out
)
def
margin_ranking_loss
(
input
,
other
,
label
,
...
...
python/paddle/nn/layer/__init__.py
浏览文件 @
e52e7944
...
...
@@ -74,6 +74,7 @@ from .loss import NLLLoss #DEFINE_ALIAS
from
.loss
import
BCELoss
#DEFINE_ALIAS
from
.loss
import
KLDivLoss
#DEFINE_ALIAS
from
.loss
import
MarginRankingLoss
#DEFINE_ALIAS
from
.loss
import
SmoothL1Loss
#DEFINE_ALIAS
from
.norm
import
BatchNorm
#DEFINE_ALIAS
from
.norm
import
SyncBatchNorm
#DEFINE_ALIAS
from
.norm
import
GroupNorm
#DEFINE_ALIAS
...
...
python/paddle/nn/layer/loss.py
浏览文件 @
e52e7944
...
...
@@ -27,7 +27,8 @@ __all__ = [
'NLLLoss'
,
'BCELoss'
,
'KLDivLoss'
,
'MarginRankingLoss'
'MarginRankingLoss'
,
'SmoothL1Loss'
,
]
...
...
@@ -700,7 +701,7 @@ class MarginRankingLoss(fluid.dygraph.Layer):
def
__init__
(
self
,
margin
=
0.0
,
reduction
=
'mean'
,
name
=
None
):
if
reduction
not
in
[
'sum'
,
'mean'
,
'none'
]:
raise
ValueError
(
"The value of 'reduction' in
L1
Loss should be 'sum', 'mean' or 'none', but "
"The value of 'reduction' in
MarginRanking
Loss should be 'sum', 'mean' or 'none', but "
"received %s, which is not allowed."
%
reduction
)
super
(
MarginRankingLoss
,
self
).
__init__
()
self
.
margin
=
margin
...
...
@@ -711,3 +712,79 @@ class MarginRankingLoss(fluid.dygraph.Layer):
out
=
paddle
.
nn
.
functional
.
margin_ranking_loss
(
input
,
other
,
label
,
self
.
margin
,
self
.
reduction
,
self
.
name
)
return
out
class
SmoothL1Loss
(
fluid
.
dygraph
.
Layer
):
"""
This operator calculates smooth_l1_loss. Creates a criterion that uses a squared
term if the absolute element-wise error falls below 1 and an L1 term otherwise.
In some cases it can prevent exploding gradients and it is more robust and less
sensitivity to outliers. Also known as the Huber loss:
.. math::
loss(x,y)=
\\
frac{1}{n}
\\
sum_{i}z_i
where z_i is given by:
.. math::
\\
mathop{z_i}=
\\
left
\\
{
\\
begin{array}{rcl}
0.5(x_i - y_i)^2 & & {if |x_i - y_i| < delta}
\\\\
delta * |x_i - y_i| - 0.5 * delta^2 & & {otherwise}
\\
end{array}
\\
right.
Parameters:
reduction (str, optional): Indicate how to average the loss by batch_size,
the candicates are ``'none'`` | ``'mean'`` | ``'sum'``.
If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned;
If :attr:`reduction` is ``'sum'``, the reduced sum loss is returned.
If :attr:`reduction` is ``'none'``, the unreduced loss is returned.
Default is ``'mean'``.
delta (float, optional): Specifies the hyperparameter delta to be used.
The value determines how large the errors need to be to use L1. Errors
smaller than delta are minimized with L2. Parameter is ignored for
negative/zero values. Default = 1.0
name (str, optional): Name for the operation (optional, default is
None). For more information, please refer to :ref:`api_guide_Name`.
Call Parameters:
input (Tensor): Input tensor, the data type is float32 or float64. Shape is
(N, C), where C is number of classes, and if shape is more than 2D, this
is (N, C, D1, D2,..., Dk), k >= 1.
label (Tensor): Label tensor, the data type is float32 or float64. The shape of label
is the same as the shape of input.
Returns:
The tensor variable storing the smooth_l1_loss of input and label.
Return type: Tensor.
Examples:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
input_data = np.random.rand(3,3).astype("float32")
label_data = np.random.rand(3,3).astype("float32")
input = paddle.to_tensor(input_data)
label = paddle.to_tensor(label_data)
loss = paddle.nn.SmoothL1Loss()
output = loss(input, label)
print(output.numpy())
"""
def
__init__
(
self
,
reduction
=
'mean'
,
delta
=
1.0
,
name
=
None
):
super
(
SmoothL1Loss
,
self
).
__init__
()
self
.
reduction
=
reduction
self
.
delta
=
delta
self
.
name
=
name
def
forward
(
self
,
input
,
label
):
return
F
.
smooth_l1_loss
(
input
,
label
,
reduction
=
self
.
reduction
,
delta
=
self
.
delta
,
name
=
self
.
name
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录