Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
hapi
提交
c4289fd7
H
hapi
项目概览
PaddlePaddle
/
hapi
通知
11
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
4
列表
看板
标记
里程碑
合并请求
7
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
H
hapi
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
4
Issue
4
列表
看板
标记
里程碑
合并请求
7
合并请求
7
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
c4289fd7
编写于
5月 07, 2020
作者:
L
LielinJiang
提交者:
GitHub
5月 07, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #74 from LielinJiang/move-mnist-to-example
Move mnist to examples
上级
701a823e
ba1a0a9f
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
154 addition
and
405 deletion
+154
-405
examples/handwritten_number_recognition/README.md
examples/handwritten_number_recognition/README.md
+55
-0
examples/handwritten_number_recognition/mnist.py
examples/handwritten_number_recognition/mnist.py
+97
-0
hapi/callbacks.py
hapi/callbacks.py
+2
-1
resnet.py
resnet.py
+0
-404
未找到文件。
examples/handwritten_number_recognition/README.md
0 → 100644
浏览文件 @
c4289fd7
# MNIST
当我们学习编程的时候,编写的第一个程序一般是实现打印"Hello World"。而机器学习(或深度学习)的入门教程,一般都是 MNIST 数据库上的手写识别问题。原因是手写识别属于典型的图像分类问题,比较简单,同时MNIST数据集也很完备。
本页将介绍如何使用PaddlePaddle高级API(hapi)实现MNIST,包括
[
安装
](
#installation
)
、
[
训练
](
#training-a-model
)
、
[
输出
](
#log
)
、
[
参数保存
](
#save
)
、
[
模型评估
](
#evaluation
)
。
## 安装
在当前目录下运行样例代码需要PadddlePaddle的v2.0.0或以上的版本。如果你的运行环境中的PaddlePaddle低于此版本,请根据安装文档中的说明来更新PaddlePaddle。
## 训练
可以通过如下的方式启动训练:
```
python mnist.py
```
上面的方式默认使用的静态图模式,切换动态图模式训练可以加
```--dynamic```
```
python mnist.py --dynamic
```
多卡进行模型训练,启动训练的方式:
```
python -m paddle.distributed.launch mnist.py
```
## 输出
执行训练开始后,将得到类似如下的输出。
```
Epoch 1/10
step 10/469 - loss: 2.4547 - acc_top1: 0.1273 - acc_top2: 0.2305 - 94ms/step
step 20/469 - loss: 1.2578 - acc_top1: 0.3063 - acc_top2: 0.4316 - 48ms/step
step 30/469 - loss: 0.7918 - acc_top1: 0.4344 - acc_top2: 0.5638 - 33ms/step
step 40/469 - loss: 0.6947 - acc_top1: 0.5148 - acc_top2: 0.6412 - 25ms/step
step 50/469 - loss: 0.5452 - acc_top1: 0.5731 - acc_top2: 0.6959 - 20ms/step
step 60/469 - loss: 0.4184 - acc_top1: 0.6133 - acc_top2: 0.7314 - 17ms/step
step 70/469 - loss: 0.5143 - acc_top1: 0.6423 - acc_top2: 0.7595 - 15ms/step
step 80/469 - loss: 0.5688 - acc_top1: 0.6658 - acc_top2: 0.7808 - 13ms/step
...
```
## 参数保存
训练好的模型默认会保存在
```mnist_checkpoint/```
文件加下,可以通过
```--output-dir```
命令来指定你想要保存的文件夹位置。
## 模型评估
执行如下命令进行评估,
```--resume```
后面指定训练好的模型路径
```
python mnist.py --resume mnist_checkpoint/final.pdparams --eval-only
```
切换动态图模式评估:
```
python mnist.py --resume mnist_checkpoint/final.pdparams --eval-only --dynamic
```
多卡评估
```
python -m paddle.distributed.launch mnist.py --resume mnist_checkpoint/final.pdparams --eval-only
```
mnist.py
→
examples/handwritten_number_recognition/
mnist.py
浏览文件 @
c4289fd7
# Copyright (c) 20
19
PaddlePaddle Authors. All Rights Reserved.
# Copyright (c) 20
20
PaddlePaddle Authors. All Rights Reserved.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# you may not use this file except in compliance with the License.
...
@@ -16,94 +16,15 @@ from __future__ import division
...
@@ -16,94 +16,15 @@ from __future__ import division
from
__future__
import
print_function
from
__future__
import
print_function
import
argparse
import
argparse
import
contextlib
import
os
import
numpy
as
np
from
paddle
import
fluid
from
paddle
import
fluid
from
paddle.fluid.optimizer
import
Momentum
from
paddle.fluid.optimizer
import
Momentum
from
paddle.fluid.dygraph.nn
import
Conv2D
,
Pool2D
,
Linear
from
hapi.datasets.mnist
import
MNIST
as
MnistDataset
from
hapi.datasets.mnist
import
MNIST
as
MnistDataset
from
hapi.model
import
Model
,
Input
,
set_device
from
hapi.model
import
Input
,
set_device
from
hapi.loss
import
CrossEntropy
from
hapi.loss
import
CrossEntropy
from
hapi.metrics
import
Accuracy
from
hapi.metrics
import
Accuracy
from
hapi.vision.models
import
LeNet
class
SimpleImgConvPool
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
filter_size
,
pool_size
,
pool_stride
,
pool_padding
=
0
,
pool_type
=
'max'
,
global_pooling
=
False
,
conv_stride
=
1
,
conv_padding
=
0
,
conv_dilation
=
1
,
conv_groups
=
None
,
act
=
None
,
use_cudnn
=
False
,
param_attr
=
None
,
bias_attr
=
None
):
super
(
SimpleImgConvPool
,
self
).
__init__
(
'SimpleConv'
)
self
.
_conv2d
=
Conv2D
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
filter_size
,
stride
=
conv_stride
,
padding
=
conv_padding
,
dilation
=
conv_dilation
,
groups
=
conv_groups
,
param_attr
=
None
,
bias_attr
=
None
,
use_cudnn
=
use_cudnn
)
self
.
_pool2d
=
Pool2D
(
pool_size
=
pool_size
,
pool_type
=
pool_type
,
pool_stride
=
pool_stride
,
pool_padding
=
pool_padding
,
global_pooling
=
global_pooling
,
use_cudnn
=
use_cudnn
)
def
forward
(
self
,
inputs
):
x
=
self
.
_conv2d
(
inputs
)
x
=
self
.
_pool2d
(
x
)
return
x
class
MNIST
(
Model
):
def
__init__
(
self
):
super
(
MNIST
,
self
).
__init__
()
self
.
_simple_img_conv_pool_1
=
SimpleImgConvPool
(
1
,
20
,
5
,
2
,
2
,
act
=
"relu"
)
self
.
_simple_img_conv_pool_2
=
SimpleImgConvPool
(
20
,
50
,
5
,
2
,
2
,
act
=
"relu"
)
pool_2_shape
=
50
*
4
*
4
SIZE
=
10
scale
=
(
2.0
/
(
pool_2_shape
**
2
*
SIZE
))
**
0.5
self
.
_fc
=
Linear
(
800
,
10
,
param_attr
=
fluid
.
param_attr
.
ParamAttr
(
initializer
=
fluid
.
initializer
.
NormalInitializer
(
loc
=
0.0
,
scale
=
scale
)),
act
=
"softmax"
)
def
forward
(
self
,
inputs
):
inputs
=
fluid
.
layers
.
reshape
(
inputs
,
[
-
1
,
1
,
28
,
28
])
x
=
self
.
_simple_img_conv_pool_1
(
inputs
)
x
=
self
.
_simple_img_conv_pool_2
(
x
)
x
=
fluid
.
layers
.
flatten
(
x
,
axis
=
1
)
x
=
self
.
_fc
(
x
)
return
x
def
main
():
def
main
():
...
@@ -113,10 +34,10 @@ def main():
...
@@ -113,10 +34,10 @@ def main():
train_dataset
=
MnistDataset
(
mode
=
'train'
)
train_dataset
=
MnistDataset
(
mode
=
'train'
)
val_dataset
=
MnistDataset
(
mode
=
'test'
)
val_dataset
=
MnistDataset
(
mode
=
'test'
)
inputs
=
[
Input
([
None
,
784
],
'float32'
,
name
=
'image'
)]
inputs
=
[
Input
([
None
,
1
,
28
,
28
],
'float32'
,
name
=
'image'
)]
labels
=
[
Input
([
None
,
1
],
'int64'
,
name
=
'label'
)]
labels
=
[
Input
([
None
,
1
],
'int64'
,
name
=
'label'
)]
model
=
MNIST
()
model
=
LeNet
()
optim
=
Momentum
(
optim
=
Momentum
(
learning_rate
=
FLAGS
.
lr
,
momentum
=
.
9
,
parameter_list
=
model
.
parameters
())
learning_rate
=
FLAGS
.
lr
,
momentum
=
.
9
,
parameter_list
=
model
.
parameters
())
...
@@ -127,14 +48,19 @@ def main():
...
@@ -127,14 +48,19 @@ def main():
inputs
,
inputs
,
labels
,
labels
,
device
=
FLAGS
.
device
)
device
=
FLAGS
.
device
)
if
FLAGS
.
resume
is
not
None
:
if
FLAGS
.
resume
is
not
None
:
model
.
load
(
FLAGS
.
resume
)
model
.
load
(
FLAGS
.
resume
)
if
FLAGS
.
eval_only
:
model
.
evaluate
(
val_dataset
,
batch_size
=
FLAGS
.
batch_size
)
return
model
.
fit
(
train_dataset
,
model
.
fit
(
train_dataset
,
val_dataset
,
val_dataset
,
epochs
=
FLAGS
.
epoch
,
epochs
=
FLAGS
.
epoch
,
batch_size
=
FLAGS
.
batch_size
,
batch_size
=
FLAGS
.
batch_size
,
save_dir
=
'mnist_checkpoint'
)
save_dir
=
FLAGS
.
output_dir
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
...
@@ -144,7 +70,7 @@ if __name__ == '__main__':
...
@@ -144,7 +70,7 @@ if __name__ == '__main__':
parser
.
add_argument
(
parser
.
add_argument
(
"-d"
,
"--dynamic"
,
action
=
'store_true'
,
help
=
"enable dygraph mode"
)
"-d"
,
"--dynamic"
,
action
=
'store_true'
,
help
=
"enable dygraph mode"
)
parser
.
add_argument
(
parser
.
add_argument
(
"-e"
,
"--epoch"
,
default
=
2
,
type
=
int
,
help
=
"number of epoch"
)
"-e"
,
"--epoch"
,
default
=
10
,
type
=
int
,
help
=
"number of epoch"
)
parser
.
add_argument
(
parser
.
add_argument
(
'--lr'
,
'--lr'
,
'--learning-rate'
,
'--learning-rate'
,
...
@@ -155,12 +81,17 @@ if __name__ == '__main__':
...
@@ -155,12 +81,17 @@ if __name__ == '__main__':
parser
.
add_argument
(
parser
.
add_argument
(
"-b"
,
"--batch_size"
,
default
=
128
,
type
=
int
,
help
=
"batch size"
)
"-b"
,
"--batch_size"
,
default
=
128
,
type
=
int
,
help
=
"batch size"
)
parser
.
add_argument
(
parser
.
add_argument
(
"-n"
,
"--num_devices"
,
default
=
1
,
type
=
int
,
help
=
"number of devices"
)
"--output-dir"
,
type
=
str
,
default
=
'mnist_checkpoint'
,
help
=
"checkpoint save dir"
)
parser
.
add_argument
(
parser
.
add_argument
(
"-r"
,
"-r"
,
"--resume"
,
"--resume"
,
default
=
None
,
default
=
None
,
type
=
str
,
type
=
str
,
help
=
"checkpoint path to resume"
)
help
=
"checkpoint path to resume"
)
parser
.
add_argument
(
"--eval-only"
,
action
=
'store_true'
,
help
=
"only evaluate the model"
)
FLAGS
=
parser
.
parse_args
()
FLAGS
=
parser
.
parse_args
()
main
()
main
()
hapi/callbacks.py
浏览文件 @
c4289fd7
...
@@ -311,7 +311,8 @@ class ProgBarLogger(Callback):
...
@@ -311,7 +311,8 @@ class ProgBarLogger(Callback):
def
on_eval_end
(
self
,
logs
=
None
):
def
on_eval_end
(
self
,
logs
=
None
):
logs
=
logs
or
{}
logs
=
logs
or
{}
if
self
.
_is_print
()
and
(
self
.
steps
is
not
None
):
if
self
.
_is_print
()
and
(
self
.
eval_steps
is
not
None
):
self
.
_updates
(
logs
,
'eval'
)
self
.
_updates
(
logs
,
'eval'
)
print
(
'Eval samples: %d'
%
(
self
.
evaled_samples
))
print
(
'Eval samples: %d'
%
(
self
.
evaled_samples
))
...
...
resnet.py
已删除
100644 → 0
浏览文件 @
701a823e
# Copyright (c) 2019 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
division
from
__future__
import
print_function
import
argparse
import
contextlib
import
math
import
os
import
random
import
time
import
cv2
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
from
paddle.fluid.layer_helper
import
LayerHelper
from
paddle.fluid.dygraph.nn
import
Conv2D
,
Pool2D
,
BatchNorm
,
Linear
from
paddle.fluid.dygraph.container
import
Sequential
from
model
import
Model
,
CrossEntropy
class
ConvBNLayer
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
filter_size
,
stride
=
1
,
groups
=
1
,
act
=
None
):
super
(
ConvBNLayer
,
self
).
__init__
()
self
.
_conv
=
Conv2D
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
filter_size
,
stride
=
stride
,
padding
=
(
filter_size
-
1
)
//
2
,
groups
=
groups
,
act
=
None
,
bias_attr
=
False
)
self
.
_batch_norm
=
BatchNorm
(
num_filters
,
act
=
act
)
def
forward
(
self
,
inputs
):
x
=
self
.
_conv
(
inputs
)
x
=
self
.
_batch_norm
(
x
)
return
x
class
BottleneckBlock
(
fluid
.
dygraph
.
Layer
):
def
__init__
(
self
,
num_channels
,
num_filters
,
stride
,
shortcut
=
True
):
super
(
BottleneckBlock
,
self
).
__init__
()
self
.
conv0
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
,
filter_size
=
1
,
act
=
'relu'
)
self
.
conv1
=
ConvBNLayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
,
filter_size
=
3
,
stride
=
stride
,
act
=
'relu'
)
self
.
conv2
=
ConvBNLayer
(
num_channels
=
num_filters
,
num_filters
=
num_filters
*
4
,
filter_size
=
1
,
act
=
None
)
if
not
shortcut
:
self
.
short
=
ConvBNLayer
(
num_channels
=
num_channels
,
num_filters
=
num_filters
*
4
,
filter_size
=
1
,
stride
=
stride
)
self
.
shortcut
=
shortcut
self
.
_num_channels_out
=
num_filters
*
4
def
forward
(
self
,
inputs
):
x
=
self
.
conv0
(
inputs
)
conv1
=
self
.
conv1
(
x
)
conv2
=
self
.
conv2
(
conv1
)
if
self
.
shortcut
:
short
=
inputs
else
:
short
=
self
.
short
(
inputs
)
x
=
fluid
.
layers
.
elementwise_add
(
x
=
short
,
y
=
conv2
)
layer_helper
=
LayerHelper
(
self
.
full_name
(),
act
=
'relu'
)
return
layer_helper
.
append_activation
(
x
)
class
ResNet
(
Model
):
def
__init__
(
self
,
depth
=
50
,
num_classes
=
1000
):
super
(
ResNet
,
self
).
__init__
()
layer_config
=
{
50
:
[
3
,
4
,
6
,
3
],
101
:
[
3
,
4
,
23
,
3
],
152
:
[
3
,
8
,
36
,
3
],
}
assert
depth
in
layer_config
.
keys
(),
\
"supported depth are {} but input layer is {}"
.
format
(
layer_config
.
keys
(),
depth
)
layers
=
layer_config
[
depth
]
num_in
=
[
64
,
256
,
512
,
1024
]
num_out
=
[
64
,
128
,
256
,
512
]
self
.
conv
=
ConvBNLayer
(
num_channels
=
3
,
num_filters
=
64
,
filter_size
=
7
,
stride
=
2
,
act
=
'relu'
)
self
.
pool
=
Pool2D
(
pool_size
=
3
,
pool_stride
=
2
,
pool_padding
=
1
,
pool_type
=
'max'
)
self
.
layers
=
[]
for
idx
,
num_blocks
in
enumerate
(
layers
):
blocks
=
[]
shortcut
=
False
for
b
in
range
(
num_blocks
):
block
=
BottleneckBlock
(
num_channels
=
num_in
[
idx
]
if
b
==
0
else
num_out
[
idx
]
*
4
,
num_filters
=
num_out
[
idx
],
stride
=
2
if
b
==
0
and
idx
!=
0
else
1
,
shortcut
=
shortcut
)
blocks
.
append
(
block
)
shortcut
=
True
layer
=
self
.
add_sublayer
(
"layer_{}"
.
format
(
idx
),
Sequential
(
*
blocks
))
self
.
layers
.
append
(
layer
)
self
.
global_pool
=
Pool2D
(
pool_size
=
7
,
pool_type
=
'avg'
,
global_pooling
=
True
)
stdv
=
1.0
/
math
.
sqrt
(
2048
*
1.0
)
self
.
fc_input_dim
=
num_out
[
-
1
]
*
4
*
1
*
1
self
.
fc
=
Linear
(
self
.
fc_input_dim
,
num_classes
,
act
=
'softmax'
,
param_attr
=
fluid
.
param_attr
.
ParamAttr
(
initializer
=
fluid
.
initializer
.
Uniform
(
-
stdv
,
stdv
)))
def
forward
(
self
,
inputs
):
x
=
self
.
conv
(
inputs
)
x
=
self
.
pool
(
x
)
for
layer
in
self
.
layers
:
x
=
layer
(
x
)
x
=
self
.
global_pool
(
x
)
x
=
fluid
.
layers
.
reshape
(
x
,
shape
=
[
-
1
,
self
.
fc_input_dim
])
x
=
self
.
fc
(
x
)
return
x
def
make_optimizer
(
parameter_list
=
None
):
total_images
=
1281167
base_lr
=
FLAGS
.
lr
momentum
=
0.9
weight_decay
=
1e-4
step_per_epoch
=
int
(
math
.
floor
(
float
(
total_images
)
/
FLAGS
.
batch_size
))
boundaries
=
[
step_per_epoch
*
e
for
e
in
[
30
,
60
,
80
]]
values
=
[
base_lr
*
(
0.1
**
i
)
for
i
in
range
(
len
(
boundaries
)
+
1
)]
learning_rate
=
fluid
.
layers
.
piecewise_decay
(
boundaries
=
boundaries
,
values
=
values
)
learning_rate
=
fluid
.
layers
.
linear_lr_warmup
(
learning_rate
=
learning_rate
,
warmup_steps
=
5
*
step_per_epoch
,
start_lr
=
0.
,
end_lr
=
base_lr
)
optimizer
=
fluid
.
optimizer
.
Momentum
(
learning_rate
=
learning_rate
,
momentum
=
momentum
,
regularization
=
fluid
.
regularizer
.
L2Decay
(
weight_decay
),
parameter_list
=
parameter_list
)
return
optimizer
def
accuracy
(
pred
,
label
,
topk
=
(
1
,
)):
maxk
=
max
(
topk
)
pred
=
np
.
argsort
(
pred
)[:,
::
-
1
][:,
:
maxk
]
correct
=
(
pred
==
np
.
repeat
(
label
,
maxk
,
1
))
batch_size
=
label
.
shape
[
0
]
res
=
[]
for
k
in
topk
:
correct_k
=
correct
[:,
:
k
].
sum
()
res
.
append
(
100.0
*
correct_k
/
batch_size
)
return
res
def
center_crop_resize
(
img
):
h
,
w
=
img
.
shape
[:
2
]
c
=
int
(
224
/
256
*
min
((
h
,
w
)))
i
=
(
h
+
1
-
c
)
//
2
j
=
(
w
+
1
-
c
)
//
2
img
=
img
[
i
:
i
+
c
,
j
:
j
+
c
,
:]
return
cv2
.
resize
(
img
,
(
224
,
224
),
0
,
0
,
cv2
.
INTER_LINEAR
)
def
random_crop_resize
(
img
):
height
,
width
=
img
.
shape
[:
2
]
area
=
height
*
width
for
attempt
in
range
(
10
):
target_area
=
random
.
uniform
(
0.08
,
1.
)
*
area
log_ratio
=
(
math
.
log
(
3
/
4
),
math
.
log
(
4
/
3
))
aspect_ratio
=
math
.
exp
(
random
.
uniform
(
*
log_ratio
))
w
=
int
(
round
(
math
.
sqrt
(
target_area
*
aspect_ratio
)))
h
=
int
(
round
(
math
.
sqrt
(
target_area
/
aspect_ratio
)))
if
w
<=
width
and
h
<=
height
:
i
=
random
.
randint
(
0
,
height
-
h
)
j
=
random
.
randint
(
0
,
width
-
w
)
img
=
img
[
i
:
i
+
h
,
j
:
j
+
w
,
:]
return
cv2
.
resize
(
img
,
(
224
,
224
),
0
,
0
,
cv2
.
INTER_LINEAR
)
return
center_crop_resize
(
img
)
def
random_flip
(
img
):
return
img
[:,
::
-
1
,
:]
def
normalize_permute
(
img
):
# transpose and convert to RGB from BGR
img
=
img
.
astype
(
np
.
float32
).
transpose
((
2
,
0
,
1
))[::
-
1
,
...]
mean
=
np
.
array
([
123.675
,
116.28
,
103.53
],
dtype
=
np
.
float32
)
std
=
np
.
array
([
58.395
,
57.120
,
57.375
],
dtype
=
np
.
float32
)
invstd
=
1.
/
std
for
v
,
m
,
s
in
zip
(
img
,
mean
,
invstd
):
v
.
__isub__
(
m
).
__imul__
(
s
)
return
img
def
compose
(
functions
):
def
process
(
sample
):
img
,
label
=
sample
for
fn
in
functions
:
img
=
fn
(
img
)
return
img
,
label
return
process
def
image_folder
(
path
,
shuffle
=
False
):
valid_ext
=
(
'.jpg'
,
'.jpeg'
,
'.png'
,
'.ppm'
,
'.bmp'
,
'.webp'
)
classes
=
[
d
for
d
in
os
.
listdir
(
path
)
if
os
.
path
.
isdir
(
os
.
path
.
join
(
path
,
d
))]
classes
.
sort
()
class_map
=
{
cls
:
idx
for
idx
,
cls
in
enumerate
(
classes
)}
samples
=
[]
for
dir
in
sorted
(
class_map
.
keys
()):
d
=
os
.
path
.
join
(
path
,
dir
)
for
root
,
_
,
fnames
in
sorted
(
os
.
walk
(
d
)):
for
fname
in
sorted
(
fnames
):
p
=
os
.
path
.
join
(
root
,
fname
)
if
os
.
path
.
splitext
(
p
)[
1
].
lower
()
in
valid_ext
:
samples
.
append
((
p
,
class_map
[
dir
]))
def
iterator
():
if
shuffle
:
random
.
shuffle
(
samples
)
for
s
in
samples
:
yield
s
return
iterator
def
run
(
model
,
loader
,
mode
=
'train'
):
total_loss
=
0.
total_acc1
=
0.
total_acc5
=
0.
total_time
=
0.
start
=
time
.
time
()
device_ids
=
list
(
range
(
FLAGS
.
num_devices
))
start
=
time
.
time
()
for
idx
,
batch
in
enumerate
(
loader
()):
outputs
,
losses
=
getattr
(
model
,
mode
)(
batch
[
0
],
batch
[
1
],
device
=
'gpu'
,
device_ids
=
device_ids
)
top1
,
top5
=
accuracy
(
outputs
[
0
],
batch
[
1
],
topk
=
(
1
,
5
))
total_loss
+=
np
.
sum
(
losses
)
total_acc1
+=
top1
total_acc5
+=
top5
if
idx
>
1
:
# skip first two steps
total_time
+=
time
.
time
()
-
start
if
idx
%
10
==
0
:
print
((
"{:04d} loss: {:0.3f} top1: {:0.3f}% top5: {:0.3f}% "
"time: {:0.3f}"
).
format
(
idx
,
total_loss
/
(
idx
+
1
),
total_acc1
/
(
idx
+
1
),
total_acc5
/
(
idx
+
1
),
total_time
/
max
(
1
,
(
idx
-
1
))))
start
=
time
.
time
()
def
main
():
@
contextlib
.
contextmanager
def
null_guard
():
yield
epoch
=
FLAGS
.
epoch
batch_size
=
FLAGS
.
batch_size
guard
=
fluid
.
dygraph
.
guard
()
if
FLAGS
.
dynamic
else
null_guard
()
train_dir
=
os
.
path
.
join
(
FLAGS
.
data
,
'train'
)
val_dir
=
os
.
path
.
join
(
FLAGS
.
data
,
'val'
)
train_loader
=
fluid
.
io
.
xmap_readers
(
lambda
batch
:
(
np
.
array
([
b
[
0
]
for
b
in
batch
]),
np
.
array
([
b
[
1
]
for
b
in
batch
]).
reshape
(
-
1
,
1
)),
paddle
.
batch
(
fluid
.
io
.
xmap_readers
(
compose
([
cv2
.
imread
,
random_crop_resize
,
random_flip
,
normalize_permute
]),
image_folder
(
train_dir
,
shuffle
=
True
),
process_num
=
8
,
buffer_size
=
4
*
batch_size
),
batch_size
=
batch_size
,
drop_last
=
True
),
process_num
=
2
,
buffer_size
=
4
)
val_loader
=
fluid
.
io
.
xmap_readers
(
lambda
batch
:
(
np
.
array
([
b
[
0
]
for
b
in
batch
]),
np
.
array
([
b
[
1
]
for
b
in
batch
]).
reshape
(
-
1
,
1
)),
paddle
.
batch
(
fluid
.
io
.
xmap_readers
(
compose
([
cv2
.
imread
,
center_crop_resize
,
normalize_permute
]),
image_folder
(
val_dir
),
process_num
=
8
,
buffer_size
=
4
*
batch_size
),
batch_size
=
batch_size
),
process_num
=
2
,
buffer_size
=
4
)
if
not
os
.
path
.
exists
(
'resnet_checkpoints'
):
os
.
mkdir
(
'resnet_checkpoints'
)
with
guard
:
model
=
ResNet
()
optim
=
make_optimizer
(
parameter_list
=
model
.
parameters
())
model
.
prepare
(
optim
,
CrossEntropy
())
if
FLAGS
.
resume
is
not
None
:
model
.
load
(
FLAGS
.
resume
)
for
e
in
range
(
epoch
):
print
(
"======== train epoch {} ========"
.
format
(
e
))
run
(
model
,
train_loader
)
model
.
save
(
'resnet_checkpoints/{:02d}'
.
format
(
e
))
print
(
"======== eval epoch {} ========"
.
format
(
e
))
run
(
model
,
val_loader
,
mode
=
'eval'
)
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
(
"Resnet Training on ImageNet"
)
parser
.
add_argument
(
'data'
,
metavar
=
'DIR'
,
help
=
'path to dataset '
'(should have subdirectories named "train" and "val"'
)
parser
.
add_argument
(
"-d"
,
"--dynamic"
,
action
=
'store_true'
,
help
=
"enable dygraph mode"
)
parser
.
add_argument
(
"-e"
,
"--epoch"
,
default
=
90
,
type
=
int
,
help
=
"number of epoch"
)
parser
.
add_argument
(
'--lr'
,
'--learning-rate'
,
default
=
0.1
,
type
=
float
,
metavar
=
'LR'
,
help
=
'initial learning rate'
)
parser
.
add_argument
(
"-b"
,
"--batch_size"
,
default
=
256
,
type
=
int
,
help
=
"batch size"
)
parser
.
add_argument
(
"-n"
,
"--num_devices"
,
default
=
4
,
type
=
int
,
help
=
"number of devices"
)
parser
.
add_argument
(
"-r"
,
"--resume"
,
default
=
None
,
type
=
str
,
help
=
"checkpoint path to resume"
)
FLAGS
=
parser
.
parse_args
()
assert
FLAGS
.
data
,
"error: must provide data path"
main
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录