Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
机器未来
Paddle
提交
f7f40635
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看板
提交
f7f40635
编写于
9月 27, 2020
作者:
L
LiuChiaChi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
upadte save inference model in dygraph without input
上级
5d2fad7b
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
95 addition
and
19 deletion
+95
-19
python/paddle/hapi/model.py
python/paddle/hapi/model.py
+58
-12
python/paddle/tests/test_model.py
python/paddle/tests/test_model.py
+37
-7
未找到文件。
python/paddle/hapi/model.py
浏览文件 @
f7f40635
...
...
@@ -598,6 +598,7 @@ class DynamicGraphAdapter(object):
'test_batch'
:
0
}
self
.
_shapes
=
None
if
self
.
_nranks
>
1
:
stradegy
=
fluid
.
dygraph
.
parallel
.
ParallelStrategy
()
stradegy
.
nranks
=
ParallelEnv
().
nranks
...
...
@@ -617,11 +618,13 @@ class DynamicGraphAdapter(object):
# TODO multi device in dygraph mode not implemented at present time
def
train_batch
(
self
,
inputs
,
labels
=
None
):
assert
self
.
model
.
_optimizer
,
\
"model not ready, please call `model.prepare()` first"
self
.
model
.
network
.
train
()
self
.
mode
=
'train'
inputs
=
to_list
(
inputs
)
self
.
_shapes
=
[
list
(
input
.
shape
)
for
input
in
inputs
]
labels
=
labels
or
[]
labels
=
[
to_variable
(
l
)
for
l
in
to_list
(
labels
)]
...
...
@@ -656,6 +659,7 @@ class DynamicGraphAdapter(object):
self
.
model
.
network
.
eval
()
self
.
mode
=
'eval'
inputs
=
to_list
(
inputs
)
self
.
_shapes
=
[
list
(
input
.
shape
)
for
input
in
inputs
]
labels
=
labels
or
[]
labels
=
[
to_variable
(
l
)
for
l
in
to_list
(
labels
)]
...
...
@@ -704,6 +708,7 @@ class DynamicGraphAdapter(object):
self
.
model
.
network
.
eval
()
self
.
mode
=
'test'
inputs
=
[
to_variable
(
x
)
for
x
in
to_list
(
inputs
)]
self
.
_shapes
=
[
list
(
input
.
shape
)
for
input
in
inputs
]
outputs
=
self
.
model
.
network
.
forward
(
*
inputs
)
if
self
.
_nranks
>
1
and
isinstance
(
self
.
model
.
_place
,
fluid
.
CUDAPlace
):
outputs
=
[
_all_gather
(
o
,
self
.
_nranks
)
for
o
in
to_list
(
outputs
)]
...
...
@@ -778,7 +783,7 @@ class DynamicGraphAdapter(object):
if
not
hasattr
(
self
.
model
.
_optimizer
,
'set_state_dict'
):
warnings
.
warn
(
"paddle.fluid.optimizer is deprecated in API 2.0, please use paddle.optimizer instead"
"paddle.fluid.optimizer is deprecated in API 2.0, please use paddle.optimizer instead
.
"
)
self
.
model
.
_optimizer
.
set_dict
(
converted_state
)
else
:
...
...
@@ -846,14 +851,18 @@ class Model(object):
self
.
_loss
=
None
self
.
_loss_weights
=
None
self
.
_optimizer
=
None
self
.
_optimizer
=
None
self
.
_shapes
=
None
self
.
_is_shape_inferred
=
False
self
.
_test_dataloader
=
None
if
not
in_dygraph_mode
():
if
not
isinstance
(
inputs
,
(
list
,
dict
,
Input
)):
raise
TypeError
(
"'inputs' must be list or dict, and couldn't be None."
)
self
.
_inputs
=
self
.
_verify_spec
(
inputs
,
True
)
elif
inputs
:
self
.
_shapes
=
[
list
(
input
.
shape
)
for
input
in
inputs
]
self
.
_inputs
=
self
.
_verify_spec
(
inputs
,
is_input
=
True
)
self
.
_labels
=
self
.
_verify_spec
(
labels
)
# init backend
...
...
@@ -905,7 +914,12 @@ class Model(object):
loss = model.train_batch([data], [label])
print(loss)
"""
return
self
.
_adapter
.
train_batch
(
inputs
,
labels
)
loss
=
self
.
_adapter
.
train_batch
(
inputs
,
labels
)
if
fluid
.
in_dygraph_mode
()
and
self
.
_shapes
is
None
:
self
.
_shapes
=
self
.
_adapter
.
_shapes
self
.
_is_shape_inferred
=
True
self
.
_inputs
=
self
.
_verify_spec
(
None
,
self
.
_shapes
,
True
)
return
loss
def
eval_batch
(
self
,
inputs
,
labels
=
None
):
"""
...
...
@@ -951,7 +965,12 @@ class Model(object):
loss = model.eval_batch([data], [label])
print(loss)
"""
return
self
.
_adapter
.
eval_batch
(
inputs
,
labels
)
loss
=
self
.
_adapter
.
eval_batch
(
inputs
,
labels
)
if
fluid
.
in_dygraph_mode
()
and
self
.
_shapes
is
None
:
self
.
_shapes
=
self
.
_adapter
.
_shapes
self
.
_is_shape_inferred
=
True
self
.
_inputs
=
self
.
_verify_spec
(
None
,
self
.
_shapes
,
True
)
return
loss
def
test_batch
(
self
,
inputs
):
"""
...
...
@@ -988,7 +1007,12 @@ class Model(object):
out = model.test_batch([data])
print(out)
"""
return
self
.
_adapter
.
test_batch
(
inputs
)
loss
=
self
.
_adapter
.
test_batch
(
inputs
)
if
fluid
.
in_dygraph_mode
()
and
self
.
_shapes
is
None
:
self
.
_shapes
=
self
.
_adapter
.
_shapes
self
.
_is_shape_inferred
=
True
self
.
_inputs
=
self
.
_verify_spec
(
None
,
self
.
_shapes
,
True
)
return
loss
def
save
(
self
,
path
,
training
=
True
):
"""
...
...
@@ -1671,6 +1695,14 @@ class Model(object):
if
fluid
.
in_dygraph_mode
():
with
fluid
.
framework
.
_dygraph_guard
(
None
):
layer
=
self
.
network
if
self
.
_shapes
is
None
:
# No provided or inferred
raise
RuntimeError
(
"Saving inference model needs `inputs` or running before saving."
)
if
self
.
_is_shape_inferred
:
warnings
.
warn
(
'Saving actual input shapes only if `inputs` is provided, otherwise variable input dimension is immutable.'
)
layer
.
forward
=
paddle
.
jit
.
to_static
(
layer
.
forward
,
input_spec
=
self
.
_inputs
)
...
...
@@ -1769,6 +1801,7 @@ class Model(object):
data
=
flatten
(
data
)
# LoDTensor.shape is callable, where LoDTensor comes from
# DataLoader in static graph
batch_size
=
data
[
0
].
shape
()[
0
]
if
callable
(
data
[
0
].
shape
)
else
data
[
0
].
shape
[
0
]
...
...
@@ -1811,6 +1844,14 @@ class Model(object):
callbacks
.
on_batch_end
(
mode
,
step
,
logs
)
self
.
_reset_metrics
()
if
self
.
_shapes
is
None
and
mode
==
"train"
:
self
.
_shapes
=
[
data
[
i
].
shape
()
if
callable
(
data
[
i
].
shape
)
else
data
[
i
].
shape
for
i
in
range
(
len
(
data
)
-
1
)
]
self
.
_is_shape_inferred
=
True
self
.
_inputs
=
self
.
_verify_spec
(
None
,
self
.
_shapes
,
True
)
if
mode
==
'test'
:
return
logs
,
outputs
return
logs
...
...
@@ -1862,18 +1903,23 @@ class Model(object):
_input_size
=
self
.
_inputs
return
summary
(
self
.
network
,
_input_size
,
dtype
)
def
_verify_spec
(
self
,
specs
,
is_input
=
False
):
def
_verify_spec
(
self
,
specs
,
shapes
=
None
,
is_input
=
False
):
out_specs
=
[]
if
specs
is
None
:
# Note(Aurelius84): If not specific specs of `Input`, using argument names of `forward` function
# to generate `Input`. But how can we know the actual shape of each input tensor?
if
is_input
:
out_specs
=
[
Input
(
name
=
n
,
shape
=
[
None
])
for
n
in
extract_args
(
self
.
network
.
forward
)
if
n
!=
'self'
]
arg_names
=
extract_args
(
self
.
network
.
forward
)[
1
:]
if
shapes
is
not
None
and
fluid
.
in_dygraph_mode
():
out_specs
=
[
Input
(
name
=
n
,
shape
=
shapes
[
i
])
for
i
,
n
in
enumerate
(
arg_names
)
]
else
:
out_specs
=
[
Input
(
name
=
n
,
shape
=
[
None
])
for
n
in
arg_names
]
else
:
out_specs
=
to_list
(
specs
)
elif
isinstance
(
specs
,
dict
):
...
...
python/paddle/tests/test_model.py
浏览文件 @
f7f40635
...
...
@@ -552,6 +552,33 @@ class TestModelFunction(unittest.TestCase):
shutil
.
rmtree
(
save_dir
)
paddle
.
enable_static
()
def
test_export_deploy_model_without_inputs_in_dygraph
(
self
):
mnist_data
=
MnistDataset
(
mode
=
'train'
)
paddle
.
disable_static
()
for
initial
in
[
"fit"
,
"train_batch"
,
"eval_batch"
,
"test_batch"
]:
save_dir
=
tempfile
.
mkdtemp
()
if
not
os
.
path
.
exists
(
save_dir
):
os
.
makedirs
(
save_dir
)
net
=
LeNet
()
model
=
Model
(
net
)
model
.
prepare
(
optimizer
=
optim
,
loss
=
CrossEntropyLoss
(
reduction
=
"sum"
))
if
initial
==
"fit"
:
model
.
fit
(
mnist_data
,
batch_size
=
64
,
verbose
=
0
)
else
:
img
=
np
.
array
(
np
.
random
.
random
((
1
,
1
,
28
,
28
)),
dtype
=
np
.
float32
)
label
=
np
.
array
(
np
.
random
.
rand
(
1
,
1
),
dtype
=
np
.
int64
)
if
initial
==
"train_batch"
:
model
.
train_batch
(
img
,
label
)
elif
initial
==
"eval_batch"
:
model
.
eval_batch
(
img
,
label
)
else
:
model
.
test_batch
(
img
)
model
.
save
(
save_dir
,
training
=
False
)
shutil
.
rmtree
(
save_dir
)
class
TestRaiseError
(
unittest
.
TestCase
):
def
test_input_without_name
(
self
):
...
...
@@ -562,13 +589,16 @@ class TestRaiseError(unittest.TestCase):
with
self
.
assertRaises
(
ValueError
):
model
=
Model
(
net
,
inputs
,
labels
)
def
test_input_without_input_spec
(
self
):
for
dynamic
in
[
True
,
False
]:
paddle
.
disable_static
()
if
dynamic
else
None
net
=
MyModel
(
classifier_activation
=
None
)
with
self
.
assertRaises
(
TypeError
):
model
=
Model
(
net
)
paddle
.
enable_static
()
def
test_export_deploy_model_without_inputs_and_run_in_dygraph
(
self
):
paddle
.
disable_static
()
net
=
MyModel
(
classifier_activation
=
None
)
save_dir
=
tempfile
.
mkdtemp
()
if
not
os
.
path
.
exists
(
save_dir
):
os
.
makedirs
(
save_dir
)
with
self
.
assertRaises
(
RuntimeError
):
model
=
Model
(
net
)
model
.
save
(
save_dir
,
training
=
False
)
paddle
.
enable_static
()
if
__name__
==
'__main__'
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录