未验证 提交 7160d704 编写于 作者: C ceci3 提交者: GitHub

Fix docs (#230)

* fix

* update docs

* update
上级 d21b2c6b
import sys
sys.path.append('..')
import numpy as np
import argparse
import ast
import time
import argparse
import ast
import logging
import paddle
import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr
from paddleslim.nas import RLNAS
from paddleslim.common import get_logger
from optimizer import create_optimizer
import imagenet_reader
_logger = get_logger(__name__, level=logging.INFO)
def create_data_loader(image_shape):
data_shape = [None] + image_shape
data = fluid.data(name='data', shape=data_shape, dtype='float32')
label = fluid.data(name='label', shape=[None, 1], dtype='int64')
data_loader = fluid.io.DataLoader.from_generator(
feed_list=[data, label],
capacity=1024,
use_double_buffer=True,
iterable=True)
return data_loader, data, label
def build_program(main_program,
startup_program,
image_shape,
archs,
args,
is_test=False):
with fluid.program_guard(main_program, startup_program):
with fluid.unique_name.guard():
data_loader, data, label = create_data_loader(image_shape)
output = archs(data)
output = fluid.layers.fc(input=output, size=args.class_dim)
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)
acc_top5 = fluid.layers.accuracy(
input=softmax_out, label=label, k=5)
if is_test == False:
optimizer = create_optimizer(args)
optimizer.minimize(avg_cost)
return data_loader, avg_cost, acc_top1, acc_top5
def search_mobilenetv2(config, args, image_size, is_server=True):
if is_server:
### start a server and a client
rl_nas = RLNAS(
key='lstm',
configs=config,
is_sync=False,
server_addr=(args.server_address, args.port),
controller_batch_size=1,
lstm_num_layers=1,
hidden_size=100,
temperature=1.0)
else:
### start a client
rl_nas = RLNAS(
key='lstm',
configs=config,
is_sync=False,
server_addr=(args.server_address, args.port),
lstm_num_layers=1,
hidden_size=10,
temperature=1.0,
is_server=False)
image_shape = [3, image_size, image_size]
for step in range(args.search_steps):
archs = rl_nas.next_archs(1)[0][0]
train_program = fluid.Program()
test_program = fluid.Program()
startup_program = fluid.Program()
train_loader, avg_cost, acc_top1, acc_top5 = build_program(
train_program, startup_program, image_shape, archs, args)
test_loader, test_avg_cost, test_acc_top1, test_acc_top5 = build_program(
test_program,
startup_program,
image_shape,
archs,
args,
is_test=True)
test_program = test_program.clone(for_test=True)
place = fluid.CUDAPlace(0) if args.use_gpu else fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(startup_program)
if args.data == 'cifar10':
train_reader = paddle.batch(
paddle.reader.shuffle(
paddle.dataset.cifar.train10(cycle=False), buf_size=1024),
batch_size=args.batch_size,
drop_last=True)
test_reader = paddle.batch(
paddle.dataset.cifar.test10(cycle=False),
batch_size=args.batch_size,
drop_last=False)
elif args.data == 'imagenet':
train_reader = paddle.batch(
imagenet_reader.train(),
batch_size=args.batch_size,
drop_last=True)
test_reader = paddle.batch(
imagenet_reader.val(),
batch_size=args.batch_size,
drop_last=False)
train_loader.set_sample_list_generator(
train_reader,
places=fluid.cuda_places() if args.use_gpu else fluid.cpu_places())
test_loader.set_sample_list_generator(test_reader, places=place)
build_strategy = fluid.BuildStrategy()
train_compiled_program = fluid.CompiledProgram(
train_program).with_data_parallel(
loss_name=avg_cost.name, build_strategy=build_strategy)
for epoch_id in range(args.retain_epoch):
for batch_id, data in enumerate(train_loader()):
fetches = [avg_cost.name]
s_time = time.time()
outs = exe.run(train_compiled_program,
feed=data,
fetch_list=fetches)[0]
batch_time = time.time() - s_time
if batch_id % 10 == 0:
_logger.info(
'TRAIN: steps: {}, epoch: {}, batch: {}, cost: {}, batch_time: {}ms'.
format(step, epoch_id, batch_id, outs[0], batch_time))
reward = []
for batch_id, data in enumerate(test_loader()):
test_fetches = [
test_avg_cost.name, test_acc_top1.name, test_acc_top5.name
]
batch_reward = exe.run(test_program,
feed=data,
fetch_list=test_fetches)
reward_avg = np.mean(np.array(batch_reward), axis=1)
reward.append(reward_avg)
_logger.info(
'TEST: step: {}, batch: {}, avg_cost: {}, acc_top1: {}, acc_top5: {}'.
format(step, batch_id, batch_reward[0], batch_reward[1],
batch_reward[2]))
finally_reward = np.mean(np.array(reward), axis=0)
_logger.info(
'FINAL TEST: avg_cost: {}, acc_top1: {}, acc_top5: {}'.format(
finally_reward[0], finally_reward[1], finally_reward[2]))
rl_nas.reward(np.float32(finally_reward[1]))
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='RL NAS MobileNetV2 cifar10 argparase')
parser.add_argument(
'--use_gpu',
type=ast.literal_eval,
default=True,
help='Whether to use GPU in train/test model.')
parser.add_argument(
'--batch_size', type=int, default=256, help='batch size.')
parser.add_argument(
'--class_dim', type=int, default=1000, help='classify number.')
parser.add_argument(
'--data',
type=str,
default='cifar10',
choices=['cifar10', 'imagenet'],
help='server address.')
parser.add_argument(
'--is_server',
type=ast.literal_eval,
default=True,
help='Whether to start a server.')
parser.add_argument(
'--search_steps',
type=int,
default=100,
help='controller server number.')
parser.add_argument(
'--server_address', type=str, default="", help='server ip.')
parser.add_argument('--port', type=int, default=8881, help='server port')
parser.add_argument(
'--retain_epoch', type=int, default=5, help='epoch for each token.')
parser.add_argument('--lr', type=float, default=0.1, help='learning rate.')
args = parser.parse_args()
print(args)
if args.data == 'cifar10':
image_size = 32
block_num = 3
elif args.data == 'imagenet':
image_size = 224
block_num = 6
else:
raise NotImplementedError(
'data must in [cifar10, imagenet], but received: {}'.format(
args.data))
config = [('MobileNetV2Space')]
search_mobilenetv2(config, args, image_size, is_server=args.is_server)
......@@ -91,7 +91,7 @@ make html
sphinx-apidoc -M -o api_en/ ../../paddleslim
```
如果有新增`package`,请将其天剑`./api_en/index_en.rst`文件中。
如果有新增`package`,请将其添加`./api_en/index_en.rst`文件中。
### 2.2.2 编译文档
......
early-stop
早停算法
========
早停算法接口在实验中如何使用
......@@ -7,7 +7,7 @@ MedianStop
.. py:class:: paddleslim.nas.early_stop.MedianStop(strategy, start_epoch, mode)
`源代码 <>`_
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/nas/early_stop/median_stop/median_stop.py>`_
MedianStop是利用历史较好实验的中间结果来判断当前实验是否有运行完成的必要,如果当前实验在中间步骤的结果差于历史记录的实验列表中相同步骤的结果的中值,则代表当前实验是较差的实验,可以提前终止。参考 `Google Vizier: A Service for Black-Box Optimization <https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46180.pdf>`_.
......@@ -30,44 +30,35 @@ MedianStop是利用历史较好实验的中间结果来判断当前实验是否
sanas = SANAS(config, server_addr=("", 8732), save_checkpoint=None)
earlystop = MedianStop(sanas, start_epoch = 2)
.. py:method:: get_status(step, result, epochs):
.. py:method:: get_status(step, result, epochs):
获取当前实验当前result的状态。
获取当前实验当前result的状态。
**参数:**
- **step<int>** - 当前实验是当前client中的第几个实验。
- **result<float>** - 当前实验的中间步骤的result,可以为损失值,也可以为准确率等指标,只要和`mode`对应即可。
- **epochs<int>** - 在搜索过程中每个实验需要运行的总得epoch数量。
**参数:**
- **step<int>** - 当前实验是当前client中的第几个实验。
- **result<float>** - 当前实验的中间步骤的result,可以为损失值,也可以为准确率等指标,只要和`mode`对应即可。
- **epochs<int>** - 在搜索过程中每个实验需要运行的总得epoch数量。
**返回:**
返回当前实验在当前epoch的状态,为`GOOD`或者`BAD`,如果为`BAD`,则代表当前实验可以早停。
**返回:**
返回当前实验在当前epoch的状态,为`GOOD`或者`BAD`,如果为`BAD`,则代表当前实验可以早停。
**示例代码:**
**示例代码:**
.. code-block:: python
.. code-block:: python
import paddle
from paddleslim.nas import SANAS
from paddleslim.nas.early_stop import MedianStop
steps = 10
epochs = 7
config = [('MobileNetV2Space')]
sanas = SANAS(config, server_addr=("", 8732), save_checkpoint=None)
earlystop = MedianStop(sanas, 2)
### 假设网络中计算出来的loss是1.0,实际使用时需要获取真实的loss或者rewards。
avg_loss = 1.0
for step in range(steps):
archs = sanas.next_archs()[0]
for epoch in range(epochs):
for data in train_reader():
loss = archs(data)
for data in test_reader():
loss = archs(data)
avg_cost = np.mean(loss)
status = earlystop.get_status(step, avg_cost, epochs)
if status == 'BAD':
break;
sanas.reward(avg_cost)
### 假设我们要获取的是当前实验第7个epoch的状态,实际使用时需要传入真实要获取的steps和实验真实所处的epochs。
status = earlystop.get_status(steps, avg_loss, epochs)
print(status)
......@@ -18,3 +18,4 @@ API文档
single_distiller_api.rst
search_space.md
table_latency.md
early_stop.rst
......@@ -167,11 +167,13 @@ RLNAS
.. py:class:: paddleslim.nas.RLNAS(key, configs, use_gpu=False, server_addr=("", 8881), is_server=True, is_sync=False, save_controller=None, load_controller=None, **kwargs)
`源代码 <> `_
`源代码 <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/nas/rl_nas.py>`_
RLNAS (Reinforcement Learning Neural Architecture Search)是基于强化学习算法进行模型结构搜索的算法。
- **key<str>** - 使用的强化学习Controller名称,目前paddleslim支持的有`LSTM`和`DDPG`,自定义强化学习Controller请参考 ` 自定义强化学习Controller <> `_
**参数:**
- **key<str>** - 使用的强化学习Controller名称,目前paddleslim支持的有`LSTM`和`DDPG`,自定义强化学习Controller请参考 `自定义强化学习Controller <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/docs/zh_cn/api_cn/custom_rl_controller.md>`_
- **configs(list<tuple>)** - 搜索空间配置列表,格式是 ``[(key, {input_size, output_size, block_num, block_mask})]`` 或者 ``[(key)]`` (MobileNetV2、MobilenetV1和ResNet的搜索空间使用和原本网络结构相同的搜索空间,所以仅需指定 ``key`` 即可), ``input_size`` 和 ``output_size`` 表示输入和输出的特征图的大小, ``block_num`` 是指搜索网络中的block数量, ``block_mask`` 是一组由0和1组成的列表,0代表不进行下采样的block,1代表下采样的block。 更多paddleslim提供的搜索空间配置可以参考[Search Space](../search_space.md)。
- **use_gpu(bool)** - 是否使用GPU来训练Controller。默认:False。
- **server_addr(tuple)** - RLNAS中Controller的地址,包括server的ip地址和端口号,如果ip地址为None或者为""的话则默认使用本机ip。默认:("", 8881)。
......@@ -183,7 +185,7 @@ RLNAS (Reinforcement Learning Neural Architecture Search)是基于强化学习
.. note::
`LSTM`算法的附加参数:
- **`LSTM`算法的附加参数:**
- lstm_num_layers(int, optional): - Controller中堆叠的LSTM的层数。默认:1.
- hidden_size(int, optional): - LSTM中隐藏层的大小。默认:100.
......@@ -191,14 +193,15 @@ RLNAS (Reinforcement Learning Neural Architecture Search)是基于强化学习
- tanh_constant(float, optional): 是否在计算每个token过程中做tanh激活,并乘上`tanh_constant`值。 默认:None。
- decay(float, optional): LSTM中记录rewards的baseline的平滑率。默认:0.99.
- weight_entropy(float, optional): 在更新controller参数时是否为接收到的rewards加上计算token过程中的带权重的交叉熵值。默认:None。
- controller_batch_size(int, optional): controller的batch_size,即每运行一次controller可以拿到几个token。默认:1.
- controller_batch_size(int, optional): controller的batch_size,即每运行一次controller可以拿到几组token。默认:1.
`DDPG`算法的附加参数:
注意:使用`DDPG`算法的话必须安装parl。安装方法: pip install parl
- **`DDPG`算法的附加参数:**
**注意:** 使用`DDPG`算法的话必须安装parl。安装方法: `pip install parl`
- obs_dim(int): observation的维度。
- model(class,optional): DDPG算法中使用的具体的模型,一般是个类,包含actor_model和critic_model,需要实现两个方法,一个是policy用来获得策略,另一个是value,需要获得Q值。可以参考默认的model` <>_`实现您自己的model。默认:`default_ddpg_model`.
- model(class,optional): DDPG算法中使用的具体的模型,一般是个类,包含actor_model和critic_model,需要实现两个方法,一个是policy用来获得策略,另一个是value,需要获得Q值。可以参考默认的 `default_model <https://github.com/PaddlePaddle/PaddleSlim/blob/develop/paddleslim/common/RL_controller/DDPG/ddpg_model.py>`_ 实现您自己的model。默认:`default_ddpg_model`.
- actor_lr(float, optional): actor网络的学习率。默认:1e-4.
- critic_lr(float, optional): critic网络的学习率。默认:1e-3.
- gamma(float, optional): 接收到rewards之后的折扣因子。默认:0.99.
......@@ -221,42 +224,45 @@ RLNAS (Reinforcement Learning Neural Architecture Search)是基于强化学习
rlnas = RLNAS(key='lstm', configs=config)
.. py:method:: next_archs(obs=None)
获取下一组模型结构。
.. py:method:: next_archs(obs=None)
**参数:**
获取下一组模型结构。
- **obs<int|np.array>** - 需要获取的模型结构数量或者当前模型的observations。
**参数:**
**返回:**
返回模型结构实例的列表,形式为list。
- **obs<int|np.array>** - 需要获取的模型结构数量或者当前模型的observations。
**示例代码:**
**返回:**
返回模型结构实例的列表,形式为list。
**示例代码:**
.. code-block:: python
.. code-block:: python
import paddle.fluid as fluid
from paddleslim.nas import RLNAS
config = [('MobileNetV2Space')]
rlnas = RLNAS(key='lstm', configs=config)
input = fluid.data(name='input', shape=[None, 3, 32, 32], dtype='float32')
archs = rlnas.next_archs(1)
archs = rlnas.next_archs(1)[0]
for arch in archs:
output = arch(input)
input = output
print(output)
.. py:method:: reward(rewards, **kwargs):
.. py:method:: reward(rewards, **kwargs):
把当前模型结构的rewards回传。
把当前模型结构的rewards回传。
**参数:**
**参数:**
- **rewards<float|list<float>>:** - 当前模型的rewards,分数越大越好。
- **\*\*kwargs:** - 附加的参数,取决于具体的强化学习算法。
- **rewards<float|list<float>>:** - 当前模型的rewards,分数越大越好。
- **\*\*kwargs:** - 附加的参数,取决于具体的强化学习算法。
**示例代码:**
**示例代码:**
.. code-block:: python
.. code-block:: python
import paddle.fluid as fluid
from paddleslim.nas import RLNAS
config = [('MobileNetV2Space')]
......@@ -264,51 +270,53 @@ RLNAS (Reinforcement Learning Neural Architecture Search)是基于强化学习
rlnas.next_archs(1)
rlnas.reward(1.0)
.. note::
.. note::
reward这一步必须在`next_token`之后执行。
..
.. py:method:: final_archs(batch_obs):
.. py:method:: final_archs(batch_obs):
获取最终的模型结构。一般在controller训练完成之后会获取几十个模型结构进行完整的实验。
获取最终的模型结构。一般在controller训练完成之后会获取几十个模型结构进行完整的实验。
**参数:**
**参数:**
- **obs<int|np.array>** - 需要获取的模型结构数量或者当前模型的observations。
- **obs<int|np.array>** - 需要获取的模型结构数量或者当前模型的observations。
**返回:**
返回模型结构实例的列表,形式为list。
**返回:**
返回模型结构实例的列表,形式为list。
**示例代码:**
**示例代码:**
.. code-block:: python
.. code-block:: python
import paddle.fluid as fluid
from paddleslim.nas import RLNAS
config = [('MobileNetV2Space')]
rlnas = RLNAS(key='lstm', configs=config)
archs = rlnas.final_archs(10)
archs = rlnas.final_archs(1)
print(archs)
.. py:methd:: tokens2arch(tokens)
.. py:method:: tokens2arch(tokens):
通过一组tokens得到实际的模型结构,一般用来把搜索到最优的token转换为模型结构用来做最后的训练。tokens的形式是一个列表,tokens映射到搜索空间转换成相应的网络结构,一组tokens对应唯一的一个网络结构。
通过一组tokens得到实际的模型结构,一般用来把搜索到最优的token转换为模型结构用来做最后的训练。tokens的形式是一个列表,tokens映射到搜索空间转换成相应的网络结构,一组tokens对应唯一的一个网络结构。
**参数:**
**参数:**
- **tokens(list):** - 一组tokens。tokens的长度和范围取决于搜索空间。
- **tokens(list):** - 一组tokens。tokens的长度和范围取决于搜索空间。
**返回:**
根据传入的token得到一个模型结构实例列表。
**返回:**
根据传入的token得到一个模型结构实例列表。
**示例代码:**
**示例代码:**
.. code-block:: python
.. code-block:: python
import paddle.fluid as fluid
from paddleslim.nas import SANAS
from paddleslim.nas import RLNAS
config = [('MobileNetV2Space')]
rlnas = RLNAS(key='lstm', configs=config)
input = fluid.data(name='input', shape=[None, 3, 32, 32], dtype='float32')
tokens = ([0] * 25)
archs = sanas.tokens2arch(tokens)[0]
archs = rlnas.tokens2arch(tokens)[0]
print(archs(input))
......@@ -19,7 +19,11 @@ import socket
import logging
import time
import threading
import cloudpickle
import six
if six.PY2:
import cPickle as pickle
else:
import pickle
from .log_helper import get_logger
from .RL_controller.utils import compute_grad, ConnectMessage
......@@ -77,7 +81,7 @@ class Client(object):
"CANNOT recv params from server in next_archs, Please check whether the server is alive!!! {}".
format(e))
os._exit(0)
self._params_dict = cloudpickle.loads(message[0])
self._params_dict = pickle.loads(message[0])
tokens = self._controller.next_tokens(
obs, params_dict=self._params_dict, is_inference=is_inference)
_logger.debug("Client: client_name is {}, current token is {}".format(
......@@ -92,7 +96,7 @@ class Client(object):
_logger.debug("Client: update weight {}".format(self._client_name))
self._client_socket.send_multipart([
ConnectMessage.UPDATE_WEIGHT, self._client_name,
cloudpickle.dumps(params_grad)
pickle.dumps(params_grad)
])
_logger.debug("Client: update done {}".format(self._client_name))
......@@ -107,7 +111,7 @@ class Client(object):
if message[0] == ConnectMessage.WAIT:
_logger.debug("Client: self.init_wait: {}".format(self.init_wait))
if not self.init_wait:
wait_port = cloudpickle.loads(message[1])
wait_port = pickle.loads(message[1])
wait_signal = self._connect_wait_socket(wait_port)
self.init_wait = True
else:
......
......@@ -24,7 +24,6 @@ else:
import logging
import time
import threading
import cloudpickle
from .log_helper import get_logger
from .RL_controller.utils import add_grad, ConnectMessage
......@@ -141,13 +140,13 @@ class Server(object):
_logger.debug("Server: get weight {}".format(
client_name))
self._server_socket.send_multipart(
[cloudpickle.dumps(self._params_dict)])
[pickle.dumps(self._params_dict)])
_logger.debug("Server: send params done {}".format(
client_name))
self._lock.release()
elif cmd == ConnectMessage.UPDATE_WEIGHT:
_logger.info("Server: update {}".format(client_name))
params_dict_grad = cloudpickle.loads(message[2])
params_dict_grad = pickle.loads(message[2])
if self._is_sync:
if not sum_params_dict:
sum_params_dict = self._params_dict
......@@ -163,7 +162,7 @@ class Server(object):
self._server_socket.send_multipart([
ConnectMessage.WAIT,
cloudpickle.dumps(self._wait_port)
pickle.dumps(self._wait_port)
])
else:
self._lock.acquire()
......@@ -203,9 +202,10 @@ class Server(object):
os.makedirs(self._save_controller)
output_dir = self._save_controller
else:
if not os.path.exists('./.rlnas_controller'):
os.makedirs('./.rlnas_controller')
output_dir = './.rlnas_controller'
with open(os.path.join(output_dir, 'rlnas.params'), 'wb') as f:
pickle.dump(self._params_dict, f)
_logger.info("Save params done")
_logger.debug("Save params done")
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册