Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
PaddleSlim
提交
1ceffac5
P
PaddleSlim
项目概览
PaddlePaddle
/
PaddleSlim
大约 1 年 前同步成功
通知
51
Star
1434
Fork
344
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
53
列表
看板
标记
里程碑
合并请求
16
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
PaddleSlim
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
53
Issue
53
列表
看板
标记
里程碑
合并请求
16
合并请求
16
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
1ceffac5
编写于
12月 13, 2019
作者:
C
ceci3
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add search space doc
上级
47461da0
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
168 addition
and
0 deletion
+168
-0
demo/nas/README.md
demo/nas/README.md
+70
-0
demo/nas/search_space_doc.md
demo/nas/search_space_doc.md
+98
-0
未找到文件。
demo/nas/README.md
0 → 100644
浏览文件 @
1ceffac5
# 网络结构搜索示例
本示例介绍如何使用网络结构搜索接口,搜索到一个更小或者精度更高的模型,该文档仅介绍paddleslim中SANAS的使用及如何利用SANAS得到模型结构,完整示例代码请参考sa_nas_mobilenetv2.py或者block_sa_nas_mobilenetv2.py。
## 接口介绍
请参考。
### 1. 配置搜索空间
详细的搜索空间配置可以参考
<a
href=
'../../../paddleslim/nas/nas_api.md'
>
神经网络搜索API文档
</a>
。
```
config = [('MobileNetV2Space')]
```
### 2. 利用搜索空间初始化SANAS实例
```
from paddleslim.nas import SANAS
sa_nas = SANAS(
config,
server_addr=("", 8881),
init_temperature=10.24,
reduce_rate=0.85,
search_steps=300,
is_server=True)
```
### 3. 根据实例化的NAS得到当前的网络结构
```
archs = sa_nas.next_archs()
```
### 4. 根据得到的网络结构和输入构造训练和测试program
```
import paddle.fluid as fluid
train_program = fluid.Program()
test_program = fluid.Program()
startup_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
data = fluid.data(name='data', shape=[None, 3, 32, 32], dtype='float32')
label = fluid.data(name='label', shape=[None, 1], dtype='int64')
for arch in archs:
data = arch(data)
output = fluid.layers.fc(data, 10)
softmax_out = fluid.layers.softmax(input=output, use_cudnn=False)
cost = fluid.layers.cross_entropy(input=softmax_out, label=label)
avg_cost = fluid.layers.mean(cost)
acc_top1 = fluid.layers.accuracy(input=softmax_out, label=label, k=1)
test_program = train_program.clone(for_test=True)
sgd = fluid.optimizer.SGD(learning_rate=1e-3)
sgd.minimize(avg_cost)
```
### 5. 根据构造的训练program添加限制条件
```
from paddleslim.analysis import flops
if flops(train_program) > 321208544:
continue
```
### 6. 回传score
```
sa_nas.reward(score)
```
demo/nas/search_space_doc.md
0 → 100644
浏览文件 @
1ceffac5
# paddleslim.nas 提供的搜索空间:
## 1. 根据原本模型结构构造搜索空间:
### 1.1 MobileNetV2Space
### 1.2 MobileNetV1Space
### 1.3 ResNetSpace
## 2. 根据相应模型的block构造搜索空间
### 2.1 MobileNetV1BlockSpace
### 2.2 MobileNetV2BlockSpace
### 2.3 ResNetBlockSpace
### 2.4 InceptionABlockSpace
### 2.5 InceptionCBlockSpace
# 自定义搜索空间(search space)
自定义搜索空间类需要继承搜索空间基类并重写以下几部分:
1.
初始化的tokens(
`init_tokens`
函数),可以设置为自己想要的tokens列表, tokens列表中的每个数字指的是当前数字在相应的搜索列表中的索引。例如本示例中若tokens=[0, 3, 5],则代表当前模型结构搜索到的通道数为[8, 40, 128]。
2.
token中每个数字的搜索列表长度(
`range_table`
函数),tokens中每个token的索引范围。
3.
根据token产生模型结构(
`token2arch`
函数),根据搜索到的tokens列表产生模型结构。
以新增reset block为例说明如何构造自己的search space。自定义的search space不能和已有的search space同名。
```
python
### 引入搜索空间基类函数和search space的注册类函数
from
.search_space_base
import
SearchSpaceBase
from
.search_space_registry
import
SEARCHSPACE
import
numpy
as
np
### 需要调用注册函数把自定义搜索空间注册到space space中
@
SEARCHSPACE
.
register
### 定义一个继承SearchSpaceBase基类的搜索空间的类函数
class
ResNetBlockSpace2
(
SearchSpaceBase
):
def
__init__
(
self
,
input_size
,
output_size
,
block_num
,
block_mask
):
### 定义一些实际想要搜索的内容,例如:通道数、每个卷积的重复次数、卷积核大小等等
### self.filter_num 代表通道数的搜索列表
self
.
filter_num
=
np
.
array
([
8
,
16
,
32
,
40
,
64
,
128
,
256
,
512
])
### 定义初始化token,初始化token的长度根据传入的block_num或者block_mask的长度来得到的
def
init_tokens
(
self
):
return
[
0
]
*
3
*
len
(
self
.
block_mask
)
### 定义
def
range_table
(
self
):
return
[
len
(
self
.
filter_num
)]
*
3
*
len
(
self
.
block_mask
)
def
token2arch
(
self
,
tokens
=
None
):
if
tokens
==
None
:
tokens
=
self
.
init_tokens
()
self
.
bottleneck_params_list
=
[]
for
i
in
range
(
len
(
self
.
block_mask
)):
self
.
bottleneck_params_list
.
append
(
self
.
filter_num
[
tokens
[
i
*
3
+
0
]],
self
.
filter_num
[
tokens
[
i
*
3
+
1
]],
self
.
filter_num
[
tokens
[
i
*
3
+
2
]],
2
if
self
.
block_mask
[
i
]
==
1
else
1
)
def
net_arch
(
input
):
for
i
,
layer_setting
in
enumerate
(
self
.
bottleneck_params_list
):
channel_num
,
stride
=
layer_setting
[:
-
1
],
layer_setting
[
-
1
]
input
=
self
.
_resnet_block
(
input
,
channel_num
,
stride
,
name
=
'resnet_layer{}'
.
format
(
i
+
1
))
return
input
return
net_arch
### 构造具体block的操作
def
_resnet_block
(
self
,
input
,
channel_num
,
stride
,
name
=
None
):
shortcut_conv
=
self
.
_shortcut
(
input
,
channel_num
[
2
],
stride
,
name
=
name
)
input
=
self
.
_conv_bn_layer
(
input
=
input
,
num_filters
=
channel_num
[
0
],
filter_size
=
1
,
act
=
'relu'
,
name
=
name
+
'_conv0'
)
input
=
self
.
_conv_bn_layer
(
input
=
input
,
num_filters
=
channel_num
[
1
],
filter_size
=
3
,
stride
=
stride
,
act
=
'relu'
,
name
=
name
+
'_conv1'
)
input
=
self
.
_conv_bn_layer
(
input
=
input
,
num_filters
=
channel_num
[
2
],
filter_size
=
1
,
name
=
name
+
'_conv2'
)
return
fluid
.
layers
.
elementwise_add
(
x
=
shortcut_conv
,
y
=
input
,
axis
=
0
,
name
=
name
+
'_elementwise_add'
)
def
_shortcut
(
self
,
input
,
channel_num
,
stride
,
name
=
None
):
channel_in
=
input
.
shape
[
1
]
if
channel_in
!=
channel_num
or
stride
!=
1
:
return
self
.
conv_bn_layer
(
input
,
num_filters
=
channel_num
,
filter_size
=
1
,
stride
=
stride
,
name
=
name
+
'_shortcut'
)
else
:
return
input
def
_conv_bn_layer
(
self
,
input
,
num_filters
,
filter_size
,
stride
=
1
,
padding
=
'SAME'
,
act
=
None
,
name
=
None
):
conv
=
fluid
.
layers
.
conv2d
(
input
,
num_filters
,
filter_size
,
stride
,
name
=
name
+
'_conv'
)
bn
=
fluid
.
layers
.
batch_norm
(
conv
,
act
=
act
,
name
=
name
+
'_bn'
)
return
bn
```
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录