未验证 提交 6d23261a 编写于 作者: B Bo Zhou 提交者: GitHub

update code format to meet icode requirement (#243)

* update code format to meet icode requirement

* update torch code
上级 53da94b8
......@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ADAM_OPTIMIZER_H
#define ADAM_OPTIMIZER_H
......@@ -20,7 +19,7 @@
#include <cmath>
#include "optimizer.h"
namespace DeepES{
namespace deep_es {
/*@brief AdamOptimizer.
* Implements Adam algorithm.
......@@ -33,7 +32,8 @@ namespace DeepES{
*/
class AdamOptimizer: public Optimizer {
public:
AdamOptimizer(float base_lr, float beta1=0.9, float beta2=0.999, float epsilon=1e-8):Optimizer(base_lr), \
AdamOptimizer(float base_lr, float beta1 = 0.9, float beta2 = 0.999,
float epsilon = 1e-8): Optimizer(base_lr), \
_beta1(beta1), _beta2(beta2), _epsilon(epsilon) {}
~AdamOptimizer();
......
......@@ -23,7 +23,7 @@
#include "utils.h"
#include <glog/logging.h>
namespace DeepES{
namespace deep_es {
class CachedGaussianSampling: public SamplingMethod {
......
......@@ -22,7 +22,7 @@
#include "sampling_method.h"
#include "utils.h"
namespace DeepES{
namespace deep_es {
class GaussianSampling: public SamplingMethod {
......
......@@ -18,8 +18,7 @@
#include <map>
#include <glog/logging.h>
namespace DeepES{
namespace deep_es {
/*@brief Optimizer. Base class for optimizers.
*
......@@ -41,7 +40,7 @@ public:
}
template<typename T>
bool update(T weights, float* gradient, int size, std::string param_name="") {
bool update(T weights, float* gradient, int size, std::string param_name = "") {
/*@ Performs a single optimization step (parameter update) at the parameter level.
*
*@Args:
......@@ -53,21 +52,23 @@ public:
if (_params_size.count(param_name) == 0) {
_params_size[param_name] = size;
} else if (_params_size[param_name] != size) {
LOG(WARNING) << "[Warning] Update times: "<< int(_update_times / _params_size.size()) \
LOG(WARNING) << "[Warning] Update times: " << int(_update_times / _params_size.size()) \
<< ". Size of weights[" << param_name << "] is " << _params_size[param_name] << ", not " << size;
return false;
}
++_update_times;
compute_step(gradient, size, param_name);
for (int i = 0; i < size; ++i) {
weights[i] -= _base_lr * gradient[i];
}
return true;
} // template function
protected:
virtual void compute_step(float* graident, int size, std::string param_name="") = 0;
virtual void compute_step(float* graident, int size, std::string param_name = "") = 0;
float _base_lr;
float _update_times;
std::map<std::string, int> _params_size;
......
......@@ -23,7 +23,7 @@
#include "deepes.pb.h"
#include <glog/logging.h>
namespace DeepES{
namespace deep_es {
/* @brief: create an optimizer according to the configuration"
* @args:
* config: configuration for the optimizer
......
......@@ -23,7 +23,7 @@
#include "deepes.pb.h"
#include <glog/logging.h>
namespace DeepES{
namespace deep_es {
/* @brief: create an sampling_method according to the configuration"
* @args:
* config: configuration for the DeepES
......
......@@ -19,7 +19,7 @@
#include <random>
#include "deepes.pb.h"
namespace DeepES{
namespace deep_es {
/*Base class for sampling algorithms. All algorithms are required to override the following functions:
*
......@@ -30,7 +30,7 @@ namespace DeepES{
* View an demostrative algorithm in gaussian_sampling.h
* */
class SamplingMethod{
class SamplingMethod {
public:
......@@ -44,7 +44,7 @@ public:
Usally you won't have to modify the configuration items of other algorithms
if you are not using them.
*/
virtual bool load_config(const DeepESConfig& config)=0;
virtual bool load_config(const DeepESConfig& config) = 0;
/*@brief generate Gaussian noise and the related key.
*
......@@ -56,7 +56,7 @@ public:
*@return:
* success: generate Gaussian successfully or not.
*/
virtual bool sampling(int* key, float* noise, int64_t size)=0;
virtual bool sampling(int* key, float* noise, int64_t size) = 0;
/*@brief reconstruct the Gaussion noise given the key.
* This function is often used for updating the neuron network parameters in the offline environment.
......@@ -69,7 +69,7 @@ public:
*@return:
* success: reconstruct Gaussian successfully or not.
*/
virtual bool resampling(int key, float* noise, int64_t size)=0;
virtual bool resampling(int key, float* noise, int64_t size) = 0;
bool set_seed(int seed) {
_seed = seed;
......
......@@ -19,7 +19,7 @@
#include <cmath>
#include "optimizer.h"
namespace DeepES{
namespace deep_es {
/*@brief SGDOptimizer.
* Implements stochastic gradient descent (optionally with momentum).
......@@ -30,7 +30,7 @@ namespace DeepES{
*/
class SGDOptimizer: public Optimizer {
public:
SGDOptimizer(float base_lr, float momentum=0.9):Optimizer(base_lr), _momentum(momentum) {}
SGDOptimizer(float base_lr, float momentum = 0.9): Optimizer(base_lr), _momentum(momentum) {}
~SGDOptimizer();
protected:
......
......@@ -23,13 +23,13 @@
#include <google/protobuf/text_format.h>
#include <fstream>
namespace DeepES{
namespace deep_es {
/*Return ranks that is normliazed to [-0.5, 0.5] with the rewards as input.
Args:
reward: an array of rewards
*/
bool compute_centered_ranks(std::vector<float> &reward);
bool compute_centered_ranks(std::vector<float>& reward);
std::string read_file(const std::string& filename);
......@@ -43,6 +43,7 @@ template<typename T>
bool load_proto_conf(const std::string& config_file, T& proto_config) {
bool success = true;
std::ifstream fin(config_file);
if (!fin || fin.fail()) {
LOG(ERROR) << "open prototxt config failed: " << config_file;
success = false;
......@@ -55,31 +56,38 @@ bool load_proto_conf(const std::string& config_file, T& proto_config) {
fin.read(file_content_buffer, file_size);
std::string proto_str(file_content_buffer, file_size);
if (!google::protobuf::TextFormat::ParseFromString(proto_str, &proto_config)) {
LOG(ERROR) << "Failed to load config: " << config_file;
success = false;
}
delete[] file_content_buffer;
fin.close();
}
return success;
}
template<typename T>
bool save_proto_conf(const std::string& config_file, T&proto_config) {
bool save_proto_conf(const std::string& config_file, T& proto_config) {
bool success = true;
std::ofstream ofs(config_file, std::ofstream::out);
if (!ofs || ofs.fail()) {
LOG(ERROR) << "open prototxt config failed: " << config_file;
success = false;
} else {
std::string config_str;
success = google::protobuf::TextFormat::PrintToString(proto_config, &config_str);
if (!success) {
return success;
}
ofs << config_str;
}
return success;
}
......
......@@ -14,7 +14,7 @@
syntax = "proto2";
package DeepES;
package deep_es;
message DeepESConfig {
//sampling configuration
......
......@@ -14,33 +14,40 @@
#include "adam_optimizer.h"
namespace DeepES {
namespace deep_es {
AdamOptimizer::~AdamOptimizer() {
for (auto iter = _momentum.begin(); iter != _momentum.end(); iter++) {
delete[] iter->second;
}
for (auto iter = _velocity.begin(); iter != _velocity.end(); iter++) {
delete[] iter->second;
}
_momentum.clear();
_velocity.clear();
}
void AdamOptimizer::compute_step(float* gradient, int size, std::string param_name="") {
void AdamOptimizer::compute_step(float* gradient, int size, std::string param_name = "") {
if (_momentum.count(param_name) == 0) {
_momentum[param_name] = new float [size];
memset(_momentum[param_name], 0, size * sizeof(float));
}
if (_velocity.count(param_name) == 0) {
_velocity[param_name] = new float [size];
memset(_velocity[param_name], 0, size * sizeof(float));
}
int true_update_times = int(_update_times / _velocity.size());
float alpha = std::sqrt(1 - std::pow(_beta2, _update_times)) / (1 - std::pow(_beta1, _update_times));
float alpha = std::sqrt(1 - std::pow(_beta2, _update_times)) / (1 - std::pow(_beta1,
_update_times));
for (int i = 0; i < size; ++i) {
_momentum[param_name][i] = _beta1 * _momentum[param_name][i] + (1 - _beta1) * gradient[i];
_velocity[param_name][i] = _beta2 * _velocity[param_name][i] + (1 - _beta2) * gradient[i] * gradient[i];
_velocity[param_name][i] = _beta2 * _velocity[param_name][i] + (1 - _beta2) * gradient[i] *
gradient[i];
gradient[i] = alpha * _momentum[param_name][i] / (std::sqrt(_velocity[param_name][i]) + _epsilon);
}
}
......
......@@ -14,7 +14,7 @@
#include "cached_gaussian_sampling.h"
namespace DeepES{
namespace deep_es {
CachedGaussianSampling::CachedGaussianSampling() {}
......@@ -37,66 +37,83 @@ bool CachedGaussianSampling::load_config(const DeepESConfig& config) {
bool CachedGaussianSampling::sampling(int* key, float* noise, int64_t size) {
bool success = true;
if (_noise_cache == nullptr) {
LOG(ERROR) << "[DeepES] Please use load_config() first.";
success = false;
return success;
}
if (noise == nullptr) {
LOG(ERROR) << "[DeepES] Input noise array cannot be nullptr.";
success = false;
return success;
}
if ((size >= _cache_size) || (size < 0)) {
LOG(ERROR) << "[DeepES] Input size " << size << " is out of bounds [0, " << _cache_size << "), cache_size: " << _cache_size;
LOG(ERROR) << "[DeepES] Input size " << size << " is out of bounds [0, " << _cache_size <<
"), cache_size: " << _cache_size;
success = false;
return success;
}
int rand_key = rand();
std::default_random_engine generator(rand_key);
std::uniform_int_distribution<unsigned int> uniform(0, _cache_size - size);
int index = uniform(generator);
*key = index;
for (int64_t i = 0; i < size; ++i) {
*(noise + i) = *(_noise_cache + index + i);
}
return success;
}
bool CachedGaussianSampling::resampling(int key, float* noise, int64_t size) {
bool success = true;
if (_noise_cache == nullptr) {
LOG(ERROR) << "[DeepES] Please use load_config() first.";
success = false;
return success;
}
if (noise == nullptr) {
LOG(ERROR) << "[DeepES] Input noise array cannot be nullptr.";
success = false;
return success;
}
if ((size >= _cache_size) || (size < 0)) {
LOG(ERROR) << "[DeepES] Input size " << size << " is out of bounds [0, " << _cache_size << "), cache_size: " << _cache_size;
LOG(ERROR) << "[DeepES] Input size " << size << " is out of bounds [0, " << _cache_size <<
"), cache_size: " << _cache_size;
success = false;
return success;
}
if ((key > _cache_size - size) || (key < 0)) {
LOG(ERROR) << "[DeepES] Resampling key " << key << " is out of bounds [0, " << _cache_size - size << "], cache_size: " << _cache_size << ", size: " << size;
LOG(ERROR) << "[DeepES] Resampling key " << key << " is out of bounds [0, " << _cache_size - size <<
"], cache_size: " << _cache_size << ", size: " << size;
success = false;
return success;
}
for (int64_t i = 0; i < size; ++i) {
*(noise + i) = *(_noise_cache + key + i);
}
return success;
}
bool CachedGaussianSampling::_create_noise_cache() {
std::default_random_engine generator(_seed);
std::normal_distribution<float> norm;
for (int64_t i = 0; i < _cache_size; ++i) {
*(_noise_cache + i) = norm(generator) * _std;
}
return true;
}
......
......@@ -14,7 +14,7 @@
#include "gaussian_sampling.h"
namespace DeepES{
namespace deep_es {
bool GaussianSampling::load_config(const DeepESConfig& config) {
bool success = true;
......@@ -25,33 +25,40 @@ bool GaussianSampling::load_config(const DeepESConfig& config) {
bool GaussianSampling::sampling(int* key, float* noise, int64_t size) {
bool success = true;
if (noise == nullptr) {
LOG(ERROR) << "[DeepES] Input noise array cannot be nullptr.";
success = false;
return success;
}
int rand_key = rand();
*key = rand_key;
std::default_random_engine generator(rand_key);
std::normal_distribution<float> norm;
for (int64_t i = 0; i < size; ++i) {
*(noise + i) = norm(generator) * _std;
}
return success;
}
bool GaussianSampling::resampling(int key, float* noise, int64_t size) {
bool success = true;
if (noise == nullptr) {
LOG(ERROR) << "[DeepES] Input noise array cannot be nullptr.";
success = false;
} else {
std::default_random_engine generator(key);
std::normal_distribution<float> norm;
for (int64_t i = 0; i < size; ++i) {
*(noise + i) = norm(generator) * _std;
}
}
return success;
}
......
......@@ -14,13 +14,13 @@
#include "optimizer_factory.h"
namespace DeepES{
namespace deep_es {
std::shared_ptr<Optimizer> create_optimizer(const OptimizerConfig& optimizer_config) {
std::shared_ptr<Optimizer> optimizer;
std::string opt_type = optimizer_config.type();
std::transform(opt_type.begin(), opt_type.end(), opt_type.begin(), ::tolower);
if (opt_type == "sgd") {
optimizer = std::make_shared<SGDOptimizer>(optimizer_config.base_lr(), \
optimizer_config.momentum());
......@@ -32,6 +32,7 @@ std::shared_ptr<Optimizer> create_optimizer(const OptimizerConfig& optimizer_con
} else {
LOG(ERROR) << "type of OptimizerConfig must be SGD or Adam."; // NotImplementedError
}
return optimizer;
}
......
......@@ -14,12 +14,13 @@
#include "sampling_factory.h"
namespace DeepES{
namespace deep_es {
std::shared_ptr<SamplingMethod> create_sampling_method(const DeepESConfig& config) {
std::shared_ptr<SamplingMethod> sampling_method;
bool cached = config.gaussian_sampling().cached();
if (cached) {
sampling_method = std::make_shared<CachedGaussianSampling>();
} else {
......@@ -27,7 +28,8 @@ std::shared_ptr<SamplingMethod> create_sampling_method(const DeepESConfig& confi
}
bool success = sampling_method->load_config(config);
if(success) {
if (success) {
return sampling_method;
} else {
LOG(ERROR) << "[DeepES] Fail to create sampling_method";
......
......@@ -14,20 +14,22 @@
#include "sgd_optimizer.h"
namespace DeepES {
namespace deep_es {
SGDOptimizer::~SGDOptimizer() {
for (auto iter = _velocity.begin(); iter != _velocity.end(); iter++) {
delete[] iter->second;
}
_velocity.clear();
}
void SGDOptimizer::compute_step(float* gradient, int size, std::string param_name="") {
void SGDOptimizer::compute_step(float* gradient, int size, std::string param_name = "") {
if (_velocity.count(param_name) == 0) {
_velocity[param_name] = new float [size];
memset(_velocity[param_name], 0, size * sizeof(float));
}
for (int i = 0; i < size; ++i) {
_velocity[param_name][i] = _momentum * _velocity[param_name][i] + (1 - _momentum) * gradient[i];
gradient[i] = _velocity[param_name][i];
......
......@@ -15,52 +15,65 @@
#include "utils.h"
#include <dirent.h>
namespace DeepES {
namespace deep_es {
bool compute_centered_ranks(std::vector<float> &reward) {
bool compute_centered_ranks(std::vector<float>& reward) {
std::vector<std::pair<float, int>> reward_index;
float gap = 1.0 / (reward.size() - 1);
float normlized_rank = -0.5;
int id = 0;
for (auto& rew: reward) {
for (auto& rew : reward) {
reward_index.push_back(std::make_pair(rew, id));
++id;
}
std::sort(reward_index.begin(), reward_index.end());
for (int i = 0; i < reward.size(); ++i) {
id = reward_index[i].second;
reward[id] = normlized_rank;
normlized_rank += gap;
}
return true;
}
std::vector<std::string> list_all_model_dirs(std::string path) {
std::vector<std::string> model_dirs;
DIR *dpdf;
struct dirent *epdf;
DIR* dpdf;
struct dirent* epdf;
dpdf = opendir(path.data());
if (dpdf != NULL){
while (epdf = readdir(dpdf)){
if (dpdf != NULL) {
while (epdf = readdir(dpdf)) {
std::string dir(epdf->d_name);
if (dir.find("model_iter_id") != std::string::npos) {
model_dirs.push_back(path + "/" + dir);
}
}
}
closedir(dpdf);
return model_dirs;
}
std::string read_file(const std::string& filename) {
std::ifstream ifile(filename.c_str());
if (!ifile.is_open()) {
LOG(ERROR) << "Open file: [" << filename << "] failed.";
return "";
}
std::ostringstream buf;
char ch;
while (buf && ifile.get(ch)) buf.put(ch);
char ch = '\n';
while (buf && ifile.get(ch)) {
buf.put(ch);
}
ifile.close();
return buf.str();
}
......
seed: 1024
gaussian_sampling {
std: 0.5
cached: true
cache_size : 100000
}
optimizer {
type: "Adam"
base_lr: 0.05
......@@ -12,6 +14,7 @@ optimizer {
beta2: 0.999
epsilon: 1e-08
}
async_es {
model_iter_id: 0
}
......@@ -19,7 +19,7 @@
#include "async_es_agent.h"
#include "paddle_api.h"
using namespace DeepES;
using namespace deep_es;
using namespace paddle::lite_api;
const int ITER = 10;
......@@ -59,24 +59,32 @@ float evaluate(CartPole& env, std::shared_ptr<AsyncESAgent> agent) {
float reward = env.getReward();
bool done = env.isDone();
total_reward += reward;
if (done) break;
if (done) {
break;
}
obs = env.getState();
}
return total_reward;
}
int main(int argc, char* argv[]) {
std::vector<CartPole> envs;
for (int i = 0; i < ITER; ++i) {
envs.push_back(CartPole());
}
std::shared_ptr<AsyncESAgent> agent = std::make_shared<AsyncESAgent>("../demo/paddle/cartpole_init_model",
"../demo/cartpole_config.prototxt");
std::shared_ptr<AsyncESAgent> agent =
std::make_shared<AsyncESAgent>("./demo/paddle/cartpole_init_model",
"./demo/cartpole_config.prototxt");
// Clone agents to sample (explore).
std::vector< std::shared_ptr<AsyncESAgent> > sampling_agents;
for (int i = 0; i < ITER; ++i) {
sampling_agents.push_back(agent->clone());
}
......@@ -88,16 +96,20 @@ int main(int argc, char* argv[]) {
noisy_info.resize(ITER);
omp_set_num_threads(10);
for (int epoch = 0; epoch < 100; ++epoch) {
last_noisy_info.clear();
last_noisy_rewards.clear();
if (epoch != 0) {
for (int i = 0; i < ITER; ++i){
for (int i = 0; i < ITER; ++i) {
last_noisy_info.push_back(noisy_info[i]);
last_noisy_rewards.push_back(noisy_rewards[i]);
}
}
#pragma omp parallel for schedule(dynamic, 1)
#pragma omp parallel for schedule(dynamic, 1)
for (int i = 0; i < ITER; ++i) {
std::shared_ptr<AsyncESAgent> sampling_agent = sampling_agents[i];
SamplingInfo info;
......@@ -108,7 +120,7 @@ int main(int argc, char* argv[]) {
noisy_rewards[i] = reward;
}
for (int i = 0; i < ITER; ++i){
for (int i = 0; i < ITER; ++i) {
last_noisy_info.push_back(noisy_info[i]);
last_noisy_rewards.push_back(noisy_rewards[i]);
}
......
......@@ -19,7 +19,7 @@
#include "es_agent.h"
#include "paddle_api.h"
using namespace DeepES;
using namespace deep_es;
using namespace paddle::lite_api;
const int ITER = 10;
......@@ -59,24 +59,31 @@ float evaluate(CartPole& env, std::shared_ptr<ESAgent> agent) {
float reward = env.getReward();
bool done = env.isDone();
total_reward += reward;
if (done) break;
if (done) {
break;
}
obs = env.getState();
}
return total_reward;
}
int main(int argc, char* argv[]) {
std::vector<CartPole> envs;
for (int i = 0; i < ITER; ++i) {
envs.push_back(CartPole());
}
std::shared_ptr<ESAgent> agent = std::make_shared<ESAgent>("../demo/paddle/cartpole_init_model",
"../demo/cartpole_config.prototxt");
std::shared_ptr<ESAgent> agent = std::make_shared<ESAgent>("./demo/paddle/cartpole_init_model",
"./demo/cartpole_config.prototxt");
// Clone agents to sample (explore).
std::vector< std::shared_ptr<ESAgent> > sampling_agents;
for (int i = 0; i < ITER; ++i) {
sampling_agents.push_back(agent->clone());
}
......@@ -86,8 +93,9 @@ int main(int argc, char* argv[]) {
noisy_keys.resize(ITER);
omp_set_num_threads(10);
for (int epoch = 0; epoch < 100; ++epoch) {
#pragma omp parallel for schedule(dynamic, 1)
#pragma omp parallel for schedule(dynamic, 1)
for (int i = 0; i < ITER; ++i) {
std::shared_ptr<ESAgent> sampling_agent = sampling_agents[i];
SamplingInfo key;
......
......@@ -19,7 +19,7 @@
#include <map>
#include <stdlib.h>
namespace DeepES{
namespace deep_es {
/* DeepES agent with PaddleLite as backend. This agent supports asynchronous update.
* Users mainly focus on the following functions:
* 1. clone: clone an agent for multi-thread evaluation
......@@ -27,7 +27,7 @@ namespace DeepES{
* 3. update: update parameters given data collected during evaluation.
*/
class AsyncESAgent: public ESAgent {
public:
public:
AsyncESAgent() {}
~AsyncESAgent();
......@@ -58,7 +58,7 @@ class AsyncESAgent: public ESAgent {
std::vector<SamplingInfo>& noisy_info,
std::vector<float>& noisy_rewards);
private:
private:
std::map<int, std::shared_ptr<PaddlePredictor>> _previous_predictors;
std::map<int, float*> _param_delta;
std::string _config_path;
......
......@@ -22,11 +22,13 @@
#include "deepes.pb.h"
#include <vector>
using namespace paddle::lite_api;
namespace deep_es {
namespace DeepES {
typedef paddle::lite_api::PaddlePredictor PaddlePredictor;
typedef paddle::lite_api::CxxConfig CxxConfig;
typedef paddle::lite_api::Tensor Tensor;
int64_t ShapeProduction(const shape_t& shape);
int64_t ShapeProduction(const paddle::lite_api::shape_t& shape);
/**
* @brief DeepES agent with PaddleLite as backend.
......@@ -37,7 +39,7 @@ int64_t ShapeProduction(const shape_t& shape);
*
*/
class ESAgent {
public:
public:
ESAgent() {}
~ESAgent();
......@@ -79,9 +81,7 @@ class ESAgent {
return _param_size;
}
protected:
protected:
int64_t _calculate_param_size();
std::shared_ptr<PaddlePredictor> _predictor;
......
......@@ -13,7 +13,7 @@
// limitations under the License.
#include "async_es_agent.h"
namespace DeepES {
namespace deep_es {
AsyncESAgent::AsyncESAgent(
const std::string& model_dir,
......@@ -21,29 +21,32 @@ AsyncESAgent::AsyncESAgent(
_config_path = config_path;
}
AsyncESAgent::~AsyncESAgent() {
for(const auto kv: _param_delta) {
for (const auto kv : _param_delta) {
float* delta = kv.second;
delete[] delta;
}
}
bool AsyncESAgent::_save() {
using namespace paddle::lite_api;
bool success = true;
if (_is_sampling_agent) {
LOG(ERROR) << "[DeepES] Cloned AsyncESAgent cannot call `save`.Please use original AsyncESAgent.";
success = false;
return success;
}
int model_iter_id = _config->async_es().model_iter_id() + 1;
//current time
time_t rawtime;
struct tm * timeinfo;
struct tm* timeinfo;
char buffer[80];
time (&rawtime);
time(&rawtime);
timeinfo = localtime(&rawtime);
std::string model_name = "model_iter_id-"+ std::to_string(model_iter_id);
std::string model_name = "model_iter_id-" + std::to_string(model_iter_id);
std::string model_path = _config->async_es().model_warehouse() + "/" + model_name;
LOG(INFO) << "[save]model_path: " << model_path;
_predictor->SaveOptimizedModel(model_path, LiteModelType::kProtobuf);
......@@ -51,11 +54,13 @@ bool AsyncESAgent::_save() {
auto async_es = _config->mutable_async_es();
async_es->set_model_iter_id(model_iter_id);
success = save_proto_conf(_config_path, *_config);
if (!success) {
LOG(ERROR) << "[]unable to save config for AsyncESAgent";
success = false;
return success;
}
int max_to_keep = _config->async_es().max_to_keep();
success = _remove_expired_model(max_to_keep);
return success;
......@@ -66,11 +71,14 @@ bool AsyncESAgent::_remove_expired_model(int max_to_keep) {
std::string model_path = _config->async_es().model_warehouse();
std::vector<std::string> model_dirs = list_all_model_dirs(model_path);
int model_iter_id = _config->async_es().model_iter_id() + 1;
for (const auto& dir: model_dirs) {
for (const auto& dir : model_dirs) {
int dir_model_iter_id = _parse_model_iter_id(dir);
if (model_iter_id - dir_model_iter_id >= max_to_keep) {
std::string rm_command = std::string("rm -rf ") + dir;
int ret = system(rm_command.c_str());
if (ret == 0) {
LOG(INFO) << "[DeepES] remove expired Model: " << dir;
} else {
......@@ -80,30 +88,37 @@ bool AsyncESAgent::_remove_expired_model(int max_to_keep) {
}
}
}
return success;
}
bool AsyncESAgent::_compute_model_diff() {
bool success = true;
for (const auto& kv: _previous_predictors) {
for (const auto& kv : _previous_predictors) {
int model_iter_id = kv.first;
std::shared_ptr<PaddlePredictor> old_predictor = kv.second;
float* diff = new float[_param_size];
memset(diff, 0, _param_size * sizeof(float));
int offset = 0;
for (const std::string& param_name: _param_names) {
for (const std::string& param_name : _param_names) {
auto des_tensor = old_predictor->GetTensor(param_name);
auto src_tensor = _predictor->GetTensor(param_name);
const float* des_data = des_tensor->data<float>();
const float* src_data = src_tensor->data<float>();
int64_t tensor_size = ShapeProduction(src_tensor->shape());
for (int i = 0; i < tensor_size; ++i) {
diff[i + offset] = des_data[i] - src_data[i];
}
offset += tensor_size;
}
_param_delta[model_iter_id] = diff;
}
return success;
}
......@@ -111,35 +126,45 @@ bool AsyncESAgent::_load() {
bool success = true;
std::string model_path = _config->async_es().model_warehouse();
std::vector<std::string> model_dirs = list_all_model_dirs(model_path);
if (model_dirs.size() == 0) {
int model_iter_id = _config->async_es().model_iter_id();
success = model_iter_id == 0 ? true: false;
success = model_iter_id == 0 ? true : false;
if (!success) {
LOG(WARNING) << "[DeepES] current_model_iter_id is nonzero, but no model is \
found at the dir: " << model_path;
}
return success;
}
for(auto &dir: model_dirs) {
for (auto& dir : model_dirs) {
int model_iter_id = _parse_model_iter_id(dir);
if (model_iter_id == -1) {
LOG(WARNING) << "[DeepES] fail to parse model_iter_id: " << dir;
success = false;
return success;
}
std::shared_ptr<PaddlePredictor> predictor = _load_previous_model(dir);
if (predictor == nullptr) {
success = false;
LOG(WARNING) << "[DeepES] fail to load model: " << dir;
return success;
}
_previous_predictors[model_iter_id] = predictor;
}
success = _compute_model_diff();
return success;
}
std::shared_ptr<PaddlePredictor> AsyncESAgent::_load_previous_model(std::string model_dir) {
using namespace paddle::lite_api;
// 1. Create CxxConfig
CxxConfig config;
config.set_model_file(model_dir + "/model");
......@@ -161,7 +186,7 @@ std::shared_ptr<AsyncESAgent> AsyncESAgent::clone() {
float* noise = new float [_param_size];
new_agent->_predictor = _predictor;
new_agent->_sampling_predictor = CreatePaddlePredictor<CxxConfig>(*_cxx_config);
new_agent->_sampling_predictor = paddle::lite_api::CreatePaddlePredictor<CxxConfig>(*_cxx_config);
new_agent->_is_sampling_agent = true;
new_agent->_sampling_method = _sampling_method;
new_agent->_param_names = _param_names;
......@@ -183,9 +208,11 @@ bool AsyncESAgent::update(
CHECK(success) << "[DeepES] fail to load previous models.";
int current_model_iter_id = _config->async_es().model_iter_id();
// validate model_iter_id for each sample before the update
for (int i = 0; i < noisy_info.size(); ++i) {
int model_iter_id = noisy_info[i].model_iter_id();
if (model_iter_id != current_model_iter_id
&& _previous_predictors.count(model_iter_id) == 0) {
LOG(WARNING) << "[DeepES] The sample with model_dir_id: " << model_iter_id \
......@@ -205,6 +232,7 @@ bool AsyncESAgent::update(
bool success = _sampling_method->resampling(key, _noise, _param_size);
CHECK(success) << "[DeepES] resampling error occurs at sample: " << i;
float* delta = _param_delta[model_iter_id];
// compute neg_gradients
if (model_iter_id == current_model_iter_id) {
for (int64_t j = 0; j < _param_size; ++j) {
......@@ -216,6 +244,7 @@ bool AsyncESAgent::update(
}
}
}
for (int64_t j = 0; j < _param_size; ++j) {
_neg_gradients[j] /= -1.0 * noisy_info.size();
}
......@@ -223,13 +252,14 @@ bool AsyncESAgent::update(
//update
int64_t counter = 0;
for (std::string param_name: _param_names) {
for (std::string param_name : _param_names) {
std::unique_ptr<Tensor> tensor = _predictor->GetMutableTensor(param_name);
float* tensor_data = tensor->mutable_data<float>();
int64_t tensor_size = ShapeProduction(tensor->shape());
_optimizer->update(tensor_data, _neg_gradients + counter, tensor_size, param_name);
counter += tensor_size;
}
success = _save();
CHECK(success) << "[DeepES] fail to save model.";
return true;
......@@ -238,15 +268,20 @@ bool AsyncESAgent::update(
int AsyncESAgent::_parse_model_iter_id(const std::string& model_path) {
int model_iter_id = -1;
int pow = 1;
for (int i = model_path.size() - 1; i >= 0; --i) {
if (model_path[i] >= '0' && model_path[i] <= '9') {
if (model_iter_id == -1) model_iter_id = 0;
if (model_iter_id == -1) {
model_iter_id = 0;
}
} else {
break;
}
model_iter_id += pow * (model_path[i] - '0');
pow *= 10;
}
return model_iter_id;
}
......
......@@ -15,21 +15,28 @@
#include "es_agent.h"
#include <ctime>
namespace DeepES {
namespace deep_es {
int64_t ShapeProduction(const shape_t& shape) {
int64_t ShapeProduction(const paddle::lite_api::shape_t& shape) {
int64_t res = 1;
for (auto i : shape) res *= i;
for (auto i : shape) {
res *= i;
}
return res;
}
ESAgent::~ESAgent() {
delete[] _noise;
if (!_is_sampling_agent)
if (!_is_sampling_agent) {
delete[] _neg_gradients;
}
}
ESAgent::ESAgent(const std::string& model_dir, const std::string& config_path) {
using namespace paddle::lite_api;
// 1. Create CxxConfig
_cxx_config = std::make_shared<CxxConfig>();
std::string model_path = model_dir + "/model";
......@@ -68,11 +75,12 @@ std::shared_ptr<ESAgent> ESAgent::clone() {
LOG(ERROR) << "[DeepES] only original ESAgent can call `clone` function.";
return nullptr;
}
std::shared_ptr<ESAgent> new_agent = std::make_shared<ESAgent>();
float* noise = new float [_param_size];
new_agent->_sampling_predictor = CreatePaddlePredictor<CxxConfig>(*_cxx_config);
new_agent->_sampling_predictor = paddle::lite_api::CreatePaddlePredictor<CxxConfig>(*_cxx_config);
new_agent->_predictor = _predictor;
new_agent->_cxx_config = _cxx_config;
new_agent->_is_sampling_agent = true;
......@@ -96,15 +104,18 @@ bool ESAgent::update(
compute_centered_ranks(noisy_rewards);
memset(_neg_gradients, 0, _param_size * sizeof(float));
for (int i = 0; i < noisy_info.size(); ++i) {
int key = noisy_info[i].key(0);
float reward = noisy_rewards[i];
bool success = _sampling_method->resampling(key, _noise, _param_size);
CHECK(success) << "[DeepES] resampling error occurs at sample: " << i;
for (int64_t j = 0; j < _param_size; ++j) {
_neg_gradients[j] += _noise[j] * reward;
}
}
for (int64_t j = 0; j < _param_size; ++j) {
_neg_gradients[j] /= -1.0 * noisy_info.size();
}
......@@ -112,20 +123,23 @@ bool ESAgent::update(
//update
int64_t counter = 0;
for (std::string param_name: _param_names) {
for (std::string param_name : _param_names) {
std::unique_ptr<Tensor> tensor = _predictor->GetMutableTensor(param_name);
float* tensor_data = tensor->mutable_data<float>();
int64_t tensor_size = ShapeProduction(tensor->shape());
_optimizer->update(tensor_data, _neg_gradients + counter, tensor_size, param_name);
counter += tensor_size;
}
return true;
}
bool ESAgent::add_noise(SamplingInfo& sampling_info) {
bool success = true;
if (!_is_sampling_agent) {
LOG(ERROR) << "[DeepES] Original ESAgent cannot call add_noise function, please use cloned ESAgent.";
LOG(ERROR) <<
"[DeepES] Original ESAgent cannot call add_noise function, please use cloned ESAgent.";
success = false;
return success;
}
......@@ -138,13 +152,15 @@ bool ESAgent::add_noise(SamplingInfo& sampling_info) {
sampling_info.set_model_iter_id(model_iter_id);
int64_t counter = 0;
for (std::string param_name: _param_names) {
for (std::string param_name : _param_names) {
std::unique_ptr<Tensor> sample_tensor = _sampling_predictor->GetMutableTensor(param_name);
std::unique_ptr<const Tensor> tensor = _predictor->GetTensor(param_name);
int64_t tensor_size = ShapeProduction(tensor->shape());
for (int64_t j = 0; j < tensor_size; ++j) {
sample_tensor->mutable_data<float>()[j] = tensor->data<float>()[j] + _noise[counter + j];
}
counter += tensor_size;
}
......@@ -157,10 +173,12 @@ std::shared_ptr<PaddlePredictor> ESAgent::get_predictor() {
int64_t ESAgent::_calculate_param_size() {
int64_t param_size = 0;
for (std::string param_name: _param_names) {
for (std::string param_name : _param_names) {
std::unique_ptr<const Tensor> tensor = _predictor->GetTensor(param_name);
param_size += ShapeProduction(tensor->shape());
}
return param_size;
}
......
......@@ -36,7 +36,7 @@ else
fi
#----------------protobuf-------------#
cp ./core/src/proto/deepes.proto ./
cp ./core/proto/deepes.proto ./
protoc deepes.proto --cpp_out ./
mv deepes.pb.h core/include
mv deepes.pb.cc core/src
......@@ -49,6 +49,7 @@ mkdir build
cd build
cmake ../ ${FLAGS}
make -j10
cd -
#-----------------run----------------#
./parallel_main
./build/parallel_main
......@@ -12,7 +12,7 @@ echo "Cannot find the torch library: ../libtorch"
fi
#----------------protobuf-------------#
cp ./core/src/proto/deepes.proto ./
cp ./core/proto/deepes.proto ./
protoc deepes.proto --cpp_out ./
mv deepes.pb.h core/include
mv deepes.pb.cc core/src
......
......@@ -17,7 +17,7 @@
#include "optimizer_factory.h"
#include <memory>
namespace DeepES {
namespace deep_es {
TEST(SGDOptimizersTest, Method_update) {
......
......@@ -19,7 +19,7 @@
#include "cached_gaussian_sampling.h"
#include <memory>
namespace DeepES {
namespace deep_es {
class SamplingTest : public ::testing::Test {
......
......@@ -26,7 +26,7 @@
#include <random>
#include <math.h>
namespace DeepES {
namespace deep_es {
// The fixture for testing class Foo.
......
......@@ -16,7 +16,7 @@
#include <vector>
#include "utils.h"
namespace DeepES {
namespace deep_es {
// Tests that the Utils::compute_centered_rank() method.
TEST(UtilsTest, Method_compute_centered_ranks) {
......
......@@ -22,7 +22,7 @@
#include "utils.h"
#include "deepes.pb.h"
namespace DeepES{
namespace deep_es{
/**
* @brief DeepES agent for Torch.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册