Так что такое A3C? Расчёт A3C был недавно выполнен группой DeepMind компании Google, и он сделал разбрызгивание… по сути, устаревшего DQN. Он был более быстрым, легким, все более энергичным и готов к достижению гораздо лучших результатов на стандартной батарее Profound RL предприятий. В целом, он мог работать в последовательном режиме, так же как и дискретные пространства деятельности. Учитывая это, это стало погружением в вычисление Deep RL для новых вопросов тестирования со сложными состояниями и пространствами деятельности. По правде говоря, OpenAI только что разрядил визуализацию A3C как своего “специалиста по общему запуску” для работы с новым (и крайне отличающимся) набором вселенских ситуаций.

The 3 As of A3C

Долгосрочный бит отставания Entertainer Pundit – это серьезный кусок. Как насчет того, чтобы начать с разгрузки имени, а с этого момента начать разгружать механику самого вычисления.

Nonconcurrent: Совсем не похоже на DQN, где одиночный оператор, с которым разговаривает одиночная нейронная система, взаимодействует с одиночной нейронной ситуацией, A3C использует различные проявления вышеперечисленного, чтобы адаптироваться тем более продуктивно. В A3C существует мировая система и различные специализированные операторы, каждый из которых имеет свое собственное расположение параметров системы. Каждый из этих операторов соединяется со своим собственным дубликатом земли одновременно, так как различные специалисты общаются со своим окружением. Объяснение этому выше, чем наличие отдельного специалиста (после ускорения выполнения большего объема работы), заключается в том, что опыт каждого оператора свободен от опыта других. В связи с этим общий опыт, доступный для подготовки, оказывается все более и более разнообразным.

Пандит-развлекатель: До сих пор эта схема была сосредоточена на стратегиях с акцентом на уважение, например, Q-обучение, или методиках циклического подхода, например, Strategy Slope. Экранный персонаж Пандит объединяет преимущества этих двух методик. Благодаря A3C, наша система будет оценивать как ценность V(s) (насколько велика вероятность того, что определенное состояние будет в), так и стратегию π(s) (много вероятностных результатов деятельности). Каждый из них будет независимым, полностью связанным между собой слоем, расположенным в самой высокой точке системы. В основном, оператор использует измеритель стоимости (пандит), чтобы обновить стратегию (эстрадный исполнитель) более умно, чем обычные стратегии наклона аранжировки.

Реализация алгоритма

https://miro.medium.com/max/1316/1*Hzql_1t0-wwDxiz0C97AcQ.png

За время, проведенное в структуре, это использование вычисления A3C, я использовал в качестве эталона качественные исполнения DennyBritz и OpenAI. Два из них я глубоко прописываю в том случае, если вы захотите увидеть здесь опции, отличающиеся от моего кода. Каждый сегмент, вставленный здесь, в учебных целях выводится за рамки любого соответствующего подключения к рассматриваемому вопросу и не будет выполняться в одиночку. Чтобы просмотреть и запустить полное, полезное выполнение A3C, смотрите мое хранилище Github.

Общая схема разработки кода:

AC_Network – этот класс содержит все операции Tensorflow для создания самих систем.

Specialist – Этот класс содержит дубликат AC_Network, класса домена, так же как и все обоснования сотрудничества с природой и обновления мировой системы.

Код повышенного уровня для построения специализированных вхождений и их параллельного запуска.

Расчет A3C начинается с разработки всемирной системы. Эта система будет состоять из конволюционных слоев для обработки пространственных условий, привязанных слоем LSTM к обработке мимолетных условий, и, наконец, слоев стоимости и стратегии выхода. Ниже приведен код модели для настройки самой схемы системы.

класс AC_Network():

Def __init__(self,s_size,a_size,scope,trainer):

с помощью tf.variable_scope(scope):

#Входные и визуальные слои кодирования

self.inputs = tf.placeholder(shape=[None,s_size],dtype=tf.float32)

self.imageIn = tf.reshape(self.inputs,shape=[-1,84,84,1])

self.conv1 = slim.conv2d(activation_fn=tf.nn.elu,

input=self.imageIn,num_outputs=16,

kernel_size=[8,8],stride=[4,4],padding=’VALID”)

self.conv2 = slim.conv2d(activation_fn=tf.nn.elu,

input=self.conv1,num_outputs=32,

kernel_size=[4,4],stride=[2,2],padding=’VALID”)

hidden = slim.fully_connected(slim.flatten(self.conv2),256,activation_fn=tf.nn.elu)

#Повторяющаяся сеть для временных зависимостей

lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(256,state_is_tuple=True)

c_init = np.zeros((1, lstm_cell.state_size.c), np.float32)

h_init = np.zeros((1, lstm_cell.state_size.h), np.float32)

self.state_init = [c_init, h_init]

c_in = tf.placeholder(tf.float32, [1, lstm_cell.state_size.c]))

h_in = tf.placeholder(tf.float32, [1, lstm_cell.state_size.h]))

self.state_in = (c_in, h_in)

rnn_in = tf.expand_dims(hidden, [0])

step_size = tf.shape(self.imageIn)[:1]

state_in = tf.nn.rnn_cell.LSTMStateTuple(c_in, h_in)

lstm_outputs, lstm_state = tf.nn.dynamic_rnn(

lstm_cell, rnn_in, initial_state=state_in, sequence_length=step_size,

time_major=False)

lstm_c, lstm_h = lstm_state

self.state_out = (lstm_c[:1, :], lstm_h[:1, :])

rnn_out = tf.reshape(lstm_outputs, [-1, 256])

#Выходные слои для оценки политики и стоимости.

self.policy = slim.fully_connected(rnn_out,a_size),

activation_fn=tf.nn.softmax,

weights_initializer=normalized_columns_initializer(0.01),

biases_initializer=Нет)

self.value = slim.full_connected(rnn_out,1,

activation_fn=None,

weights_initializer=normalized_columns_initializer(1.0),

biases_initializer=Нет)

Далее производится множество операторов-рабочих, каждый из которых имеет свою систему и состояние. Каждый из этих операторов выполняется на отдельной строке процессора, поэтому их должно быть не больше, чем строк на вашем процессоре.

с помощью tf.device(“/cpu:0”):

master_network = AC_Network(s_size,a_size,’global’,None) # Генерация глобальной сети

num_workers = multiprocessing.cpu_count() # Установка рабочих от количества доступных потоков процессора

работники = []

# Создать рабочие классы

для i в диапазоне(num_workers):

works.append(Worker(DoomGame(),i,s_size,a_size,trainer,saver,model_path)):)

с tf.Session() как сесс:

coord = tf.train.Coordinator()

если load_model == Верно:

распечатать ‘Загрузка модели…’

ckpt = tf.train.get_checkpoint_state(model_path)

saver.restore(sess,ckpt.model_checkpoint_path)

Иначе:

sess.run(tf.global_variables_initializer()))

# Здесь происходит асинхронная магия.

# Запустите процесс “работы” для каждого рабочего в отдельной угрозе.

worker_threads = []

для рабочих:

worker_work = lambda: worker.work(max_episode_length, gamma, master_network, sess, coord)

t = threading.Thread(target=(worker_work)))

t.start()

work_threads.append(t)

coord.join(work_threads)

Каждый работник начинает с настройки своих системных параметров по всему миру. Мы можем сделать это, разработав операцию Tensorflow, которая устанавливает каждый фактор в соседней специализированной системе на равные переменные стимулы в мировой системе.

Каждый специалист в этот момент ассоциируется со своим собственным дубликатом природы и собирает понимание. Каждый держит в руках сводку переживаний (восприятие, активность, вознаграждение, дела, уважение), которые постоянно добавляются из общения с землей.

lass Worker():

….

….

….

… … … def work(self,max_episode_length,gamma,global_AC,sess,coord):

эпизод_счёт = 0

total_step_count = 0

распечатать “Начинающий работник” + str(self.number)

с помощью sess.as_default(), sess.graph.as_default():

пока не coord.should_stop():

sess.run(self.update_local_ops)

episode_buffer = []

эпизод_значения = []

episode_frame = []

эпизод_возвращение = 0

эпизод_степ_счёт = 0

d = Ложный

self.env.new_episode()

s = self.env.get_state().screen_buffer

episode_frames.append(s)

s = process_frame(s)

rnn_state = self.local_AC.state_init

while self.env.is_episode_finished() == False:

#Сделать действие, используя вероятности из вывода сети политики.

a_dist,v,rnn_state = sess.run([self.local_AC.policy,self.local_AC.value,self.local_AC.state_out],

feed_dict={self.local_AC.inputs:[s],

self.local_AC.state_in[0]:rnn_state[0],

self.local_AC.state_in[1]:rnn_state[1]})

a = np.random.choice(a_dist[0],p=a_dist[0])

a = np.argmax(a_dist == a)

r = self.env.make_action(self.actions[a]) / 100.0

d = self.env.is_episode_finished()

если d == Ложь:

s1 = self.env.get_state().screen_buffer

episode_frames.append(s1)

s1 = process_frame(s1)

Иначе:

1 = s

episode_buffer.append([s,a,r,s1,d,v[0,0]]))

episode_values.append(v[0,0]))

эпизод_возвращение += r

s = s1

total_steps += 1

эпизод_шаг_счет += 1

#Специально для VizDoom. Мы спим игру на определенное время.

если self.sleep_time>0:

sleep(self.sleep_time)

# Если эпизод не закончился, но буфер опыта полон, то мы

# сделайте шаг обновления, используя этот опыт развертывания.

если len(episode_buffer) == 30 и d != True и episode_step_count != max_episode_length – 1:

# Так как мы не знаем, что такое истинный конечный возврат, то мы “bootstrap” из нашего текущего

# оценка стоимости.

v1 = sess.run(self.local_AC.value,

feed_dict={self.local_AC.inputs:[s],

self.local_AC.state_in[0]:rnn_state[0],

self.local_AC.state_in[1]:rnn_state[1]})[0,0]

v_l,p_l,e_l,g_n,v_n = self.train(global_AC,episode_buffer,sess,gamma,v1)

episode_buffer = []

sess.run(self.update_local_ops)

если d == Правда:

сломать

self.episode_rewards.append(episode_reward)

self.episode_lengths.append(episode_step_count)

self.episode_mean_values.append(np.mean(episode_values)))

# Обновите сеть, используя буфер опыта в конце эпизода.

v_l,p_l,e_l,g_n,v_n = self.train(global_AC,episode_buffer,sess,gamma,0.0)

Когда история опыта лаборанта достаточно огромна, мы используем ее для определения ограниченной отдачи и бита отставания, и используем ее для вычисления стоимости и приближения несчастий. Дополнительно мы устанавливаем энтропию (H) подхода. Это сравнивается с распространением вероятностей активности. Если вероятность того, что стратегия приведет к деятельности с умеренными сравнительными вероятностями, то в этот момент энтропия будет высокой, но если в рамках этой стратегии будет рекомендована одиночная деятельность с огромной вероятностью, то в этот момент энтропия будет низкой. Мы используем энтропию как метод для улучшения исследования, призывая модель быть традиционалистской с точки зрения ее осведомленности о правильной деятельности.

Потеря стоимости: L = Σ(R – V(s))²

Потеря политики: L = -лог(π(s)). * A(s) – β*H(π)

Рабочий в этот момент использует эти неудачи, чтобы получить углы относительно параметров своей системы. Каждый из этих углов обычно обрезается, чтобы предвидеть чрезмерно большое обновление параметров, которое может дестабилизировать подход.

Специалист в этой точке использует наклоны для обновления параметров системы по всему миру. В соответствии с этим каждый из специалистов постоянно освежает мировую систему, так как они работают в соответствии со своим состоянием.

класс AC_Network():

Def __init__(self,s_size,a_size,scope,trainer):

….

….

….

if scope != ‘global’:

self.actions = tf.placeholder(shape=[None],dtype=tf.int32)

self.actions_onehot = tf.one_hot(self.actions,a_size,dtype=tf.float32)

self.target_v = tf.placeholder(shape=[None],dtype=tf.float32)

self.benefits = tf.placeholder(shape=[None],dtype=tf.float32)

self.responsible_outputs = tf.reduce_sum(self.policy * self.actions_onehot, [1])

#Потерянные функции

self.value_loss = 0.5 * tf.reduce_sum(tf.square(self.target_v – tf.reshape(self.value,[-1])))))

self.entropy = – tf.reduce_sum(self.policy * tf.log(self.policy))

self.policy_loss = -tf.reduce_sum(tf.log(self.responsible_outputs)*self.advantage)

self.loss = 0.5 * self.value_loss + self.policy_loss – self.entropy * 0.01

#Получить градиенты из локальной сети, используя локальные потери

local_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope)

self.gradients = tf.gradients(self.loss,local_vars)

self.var_norms = tf.global_norm(local_vars)

grads,self.grad_norms = tf.cli_by_global_norm(self.gradients,40.0)

#Примените локальные градиенты к глобальной сети

global_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, ‘global’)

self.apply_grads = trainer.apply_gradients(zip(grads,global_vars)))

класс Worker():

….

….

….

def train(self,global_AC,rollout,sess,gamma,bootstrap_value):

rollout = np.array(rollout)

наблюдения = rollout[:,0]

действия = rollout[:,1]

награды = rollout[:,2]

next_observations = rollout[:,3]

значения = rollout[:,5]

# Здесь мы берем награды и ценности из развертывания, и используем их для того.

# генерируют преимущество и скидку на возврат.

# функция преимущества использует “Обобщенную оценку преимущества”.

self.rewards_plus = np.asarray(rewards.tolist() + [boottstrap_value]))

discounted_rewards = discount(self.rewards_plus,gamma)[:-1]

self.value_plus = np.asarray(values.tolist() + [bootstrap_value]))

преимущества = награды + гамма * self.value_plus[1:] – self.value_plus[:-1]

преимущества = скидка(преимущества, гамма)

# Обновите глобальную сеть, используя градиенты от потерь.

# Сгенерировать статистику сети для периодического сохранения

rnn_state = self.local_AC.state_init

feed_dict = {self.local_AC.target_v:discounted_rewards,

self.local_AC.inputs:np.vstack(наблюдения),

self.local_AC.actions:actions,

self.local_AC.benefits:benefits,

self.local_AC.state_in[0]:rnn_state[0],

self.local_AC.state_in[1]:rnn_state[1]}

v_l,p_l,e_l,g_n,v_n,_ = sess.run([self.local_AC.value_loss,

self.local_AC.policy_loss,

self.local_AC.enropy,

self.local_AC.grad_norms,

self.local_AC.var_norms,

self.local_AC.apply_grads],

feed_dict=feed_dict)

возвращать v_l / len(rollout),p_l / len(rollout),e_l / len(rollout),g_n,v_n

Когда производится эффективное обновление системы по всему миру, вся процедура перепрофилируется! Рабочий в этот момент сбрасывает свои собственные системные параметры в мировую систему, и процедура начинается еще раз.