Вот код:
Код: Выделить всё
Trainer::Trainer(int64_t input_channels, int64_t num_actions, int64_t capacity) : buffer(capacity),
network1(input_channels, num_actions),
target_network1(input_channels, num_actions),
dqn_optimizer(network1.parameters(), torch::optim::AdamOptions(0.001).betas({ 0.9, 0.999 })) {}
Код: Выделить всё
torch::Tensor Trainer::compute_td_loss(int64_t batch_size, float gamma) {
std::vector batch =
buffer.sample_queue(batch_size);
std::vector states;
std::vector new_states;
std::vector actions;
std::vector rewards;
for (auto i : batch) {
states.push_back(std::get(i).to(torch::kCPU));
new_states.push_back(std::get(i).to(torch::kCPU));
actions.push_back(std::get(i).to(torch::kCPU));
rewards.push_back(std::get(i).to(torch::kCPU));
}
torch::Tensor states_tensor;
torch::Tensor new_states_tensor;
torch::Tensor actions_tensor;
torch::Tensor rewards_tensor;
states_tensor = torch::cat(states, 0);
new_states_tensor = torch::cat(new_states, 0);
rewards_tensor = torch::cat(rewards, 0);
actions_tensor = torch::cat(actions, 0);
torch::Tensor q_values = network1.forward(states_tensor);
torch::Tensor next_target_q_values = target_network1.forward(new_states_tensor);
torch::Tensor next_q_values = network1.forward(new_states_tensor);
actions_tensor = actions_tensor.to(torch::kInt64);
for (int i = 0; i < batch_size; ++i) {
// Extraire l'indice de l'action pour l'élément i
int action_index = actions_tensor[i][0].item();
// Afficher action_index
int j;
if (action_index == 0) j = 0;
else if (action_index == 12) j = 1;
else if (action_index == 25) j = 2;
else if (action_index == 50) j = 3;
else if (action_index == 75) j = 4;
else if (action_index == 88) j = 5;
else j = 6;
// Extraire la valeur Q correspondante de q_values pour l'indice d'action spécifié
q_value[i] = q_values[i][j];
}
torch::Tensor maximum = std::get(next_q_values.max(1));
torch::Tensor next_q_value = torch::empty({ batch_size }, torch::kCPU);
// Parcourir chaque élément du batch
for (int i = 0; i < batch_size; ++i) {
// Extraire l'indice de l'action pour l'élément i
int action_index = maximum[i].item();
// Afficher action_index
// Extraire la valeur Q correspondante de q_values pour l'indice d'action spécifié
next_q_value[i] = next_target_q_values[i][action_index];
}
torch::Tensor expected_q_value = rewards_tensor.squeeze(1) + gamma * next_q_value;
torch::Tensor loss = torch::mse_loss(q_value, expected_q_value);
for (const auto& param : network1.parameters()) {
if (!param.requires_grad()) {
::MessageBox(NULL, L"Paramètre n'a pas requires_grad défini sur true", L"compute_td_loss", MB_OK);
}
}
dqn_optimizer.zero_grad();
loss.backward();
dqn_optimizer.step();
return loss;
}
Код: Выделить всё
struct LinearModel : torch::nn::Module {
torch::nn::Linear linear;
LinearModel(int64_t input_size, int64_t output_size)
: linear(register_module("linear", torch::nn::Linear(input_size, output_size))) {
// Setting requires_grad=True for all parameters
for (auto& param : linear->parameters()) {
param.requires_grad_(true);
}
}
torch::Tensor forward(torch::Tensor input) {
torch::DeviceType device_type;
device_type = torch::kCPU;
torch::Device device(device_type);
input = torch::relu(linear(input));
return input;
}
Код: Выделить всё
class Trainer {
private: ExperienceReplay buffer;
private: LinearModel network1, target_network1;
private: torch::optim::Adam dqn_optimizer;
private: double epsilon_start = 1.0;
private: double epsilon_final = 0.01;
private: int64_t epsilon_decay = 30000;
private: int64_t batch_size = 32;
private: float gamma = 0.99;
public:
Trainer(int64_t input_channels, int64_t num_actions, int64_t capacity);
torch::Tensor compute_td_loss(int64_t batch_size, float gamma);
double epsilon_by_frame(int64_t frame_id);
void loadstatedict(torch::nn::Module& model,
torch::nn::Module& target_model);
void Trainer::ddqn(struct_matrix* state, int indice, struct_matrix* nb_pos, struct_matrix* data, sortie* sortie0);
};
Подробнее здесь: https://stackoverflow.com/questions/786 ... s-backward