Home Искусственный интеллект Q-цели, двойной DQN и дуэльный DQN | DeepTech

Q-цели, двойной DQN и дуэльный DQN | DeepTech

0
Q-цели, двойной DQN и дуэльный DQN
 | DeepTech

И снова здравствуйте,

Сегодняшняя тема… ну, такая же, как и предыдущая. Q Learning и Deep Q Networks. В прошлый раз мы объяснили, что такое Q Learning и как использовать уравнение Беллмана для нахождения Q-значений и, как следствие, оптимальной политики. Позже мы представили Deep Q Networks и то, как вместо того, чтобы вычислять все значения Q-таблицы, мы позволили Deep Neural Network научиться их аппроксимировать.

Сети Deep Q принимают в качестве входных данных состояние среды и выводят значение Q для каждого возможного действия. Максимальное значение Q определяет, какое действие выполнит агент. Обучение агентов использует в качестве потери Ошибка ТД, который представляет собой разницу между максимально возможным значением для следующего состояния и текущим прогнозом значения Q (как предлагает уравнение Беллмана). В результате нам удается аппроксимировать Q-таблицы с помощью нейронной сети.

Все идет нормально. Но, конечно, возникает несколько проблем. Просто так продвигаются научные исследования. И, конечно же, мы придумали несколько отличных решений.

Перемещение Q-целей

Первая проблема заключается в том, что называется движущимися Q-мишенями. Как мы видели, первым компонентом ошибки TD (TD означает Temporal Difference) является Q-Target, и он рассчитывается как немедленное вознаграждение плюс дисконтированное максимальное Q-значение для следующего состояния. Когда мы обучаем нашего агента, мы обновляем веса в соответствии с ошибкой TD. Но одни и те же веса применяются как к целевому, так и к прогнозируемому значению. Вы видите проблему?

Δж“=”α((р+γМаксаВопрос^(с,а,ж))Вопрос^(с,а,ж))жВопрос^(с,а,ж)\Delta w=\alpha\left(\left(R+\gamma \max _{a} \hat{Q}\left(s^{\prime}, a, w\right)\right)-\hat{Q }(s, a, w)\right) \nabla_{w} \hat{Q}(s, a, w)

Мы перемещаем вывод ближе к цели, но мы также перемещаем цель. Итак, мы в конечном итоге преследуем цель, и мы получаем сильно колеблющийся тренировочный процесс. Было бы неплохо оставить цель фиксированной, пока мы обучаем сеть. Что ж, DeepMind сделал именно это.

Вместо того, чтобы использовать одну нейронную сеть, он использует две. Да, вы не ослышались! (вроде бы одного уже не хватило).

Одна в качестве основной сети Deep Q, а вторая (называется Целевая сеть) для исключительного и периодического обновления весов цели. Эта техника называется Фиксированные Q-цели. На самом деле веса фиксированы для большей части тренировки и обновляются только время от времени.

class DQNAgent:

def __init__(self, state_size, action_size):

self.model = self._build_model()

self.target_model = self._build_model()

self.update_target_model()

def update_target_model(self):

self.target_model.set_weights(self.model.get_weights())

Предвзятость максимизации

Предвзятость максимизации — это склонность Deep Q Networks переоценивать функции ценности и действия-ценности (Q). Почему это происходит? Подумайте, что если по какой-то причине сеть завышает значение Q для действия, это действие будет выбрано в качестве действия для перехода к следующему шагу, и такое же завышенное значение будет использоваться в качестве целевого значения. Другими словами, невозможно оценить, действительно ли действие с максимальным значением является лучшим. Как это решить? Ответ очень интересный метод и называется:

Двойная глубокая сеть Q

Чтобы устранить предвзятость максимизации, мы используем две сети Deep Q.

  • С одной стороны, DQN отвечает за выбор следующего действия (с максимальным значением) как всегда.

  • С другой стороны, целевая сеть отвечает за оценка
    этого действия.

Хитрость заключается в том, что целевое значение автоматически создается не максимальным значением Q, а целевой сетью. Другими словами, мы вызываем целевую сеть для вычисления целевого значения Q для выполнения этого действия в следующем состоянии. И как побочный эффект, мы также решаем проблему с движущейся мишенью. Аккуратно, верно? Две птицы с одним камнем. Отделив выбор действия от генерации целевого значения Q, мы можем существенно уменьшить переоценку и тренироваться быстрее и надежнее.

def train_model(self):

if len(self.memory) < self.train_start:

return

batch_size = min(self.batch_size, len(self.memory))

mini_batch = random.sample(self.memory, batch_size)

update_input = np.zeros((batch_size, self.state_size))

update_target = np.zeros((batch_size, self.state_size))

action, reward, done = (), (), ()

for i in range(batch_size):

update_input(i) = mini_batch(i)(0)

action.append(mini_batch(i)(1))

reward.append(mini_batch(i)(2))

update_target(i) = mini_batch(i)(3)

done.append(mini_batch(i)(4))

target = self.model.predict(update_input)

target_next = self.model.predict(update_target)

target_val = self.target_model.predict(update_target)

for i in range(self.batch_size):

if done(i):

target(i)(action(i)) = reward(i)

else:

a = np.argmax(target_next(i))

target(i)(action(i)) = reward(i) + self.discount_factor * (target_val(i)(a))

self.model.fit(update_input, target, batch_size=self.batch_size,epochs=1, verbose=0)

Думаешь, это все? Извините, что подвел вас. Мы собираемся пойти еще дальше. Что теперь? Собираетесь ли вы добавить третью нейронную сеть? Ха-ха!!

Ну типа. Кто смеется сейчас?

Загрузите нашу бесплатную электронную книгу по глубокому обучению с подкреплением

Мы объединили все статьи по обучению с подкреплением в один PDF-файл. Поэтому, если у вас нет времени читать всю статью или вы хотите, чтобы pdf-версия читалась в автономном режиме, нажмите кнопку ниже.

* Мы стремимся к вашей конфиденциальности. AI Summer использует предоставленную вами информацию для отправки вам нашего информационного бюллетеня и связи с вами по поводу наших продуктов. Вы можете отказаться от подписки на эти сообщения в любое время. Для получения дополнительной информации ознакомьтесь с нашим Политика конфиденциальности.

Дуэли сетей Deep Q

Давайте сначала обновим основу Q Learning. Значения Q соответствуют метрике того, насколько хорошо действие для определенного состояния, верно? Вот почему это функция действия-ценности. Метрика — это не что иное, как ожидаемая отдача этого действия от состояния. Фактически значения Q можно разбить на две части: функцию ценности состояния V(s) и значение преимущества A(s, a). И да, мы просто вводим еще одну функцию:

Вопрос(с,а)“=”В(с)+А(с,а)Q(s, а)=V(s)+A(s, а)

Функция преимущества фиксирует, насколько лучше действие по сравнению с другими в данном состоянии, в то время как, как мы знаем, функция ценности фиксирует, насколько хорошо быть в этом состоянии. Вся идея Dueling Q Networks основана на представление функции Q в виде суммы ценности и функции преимущества. У нас просто есть две сети для изучения каждой части суммы, а затем мы объединяем их результаты.


ДДКН


Дуэль сетевых архитектур для глубокого обучения с подкреплением

Зарабатываем ли мы этим что-то? Конечно, мы делаем. Теперь агенты могут оценивать состояние, не заботясь о последствиях каждого действия из этого состояния. Это означает, что функции, определяющие, является ли состояние хорошим или нет, не обязательно совпадают с функциями, оценивающими действие. И, возможно, ему вообще не нужно заботиться о действиях. Нередки случаи, когда действия из состояния никак не влияют на окружающую среду. Так зачем их учитывать?

* Краткое примечание: если вы внимательно посмотрите на изображение, вы увидите, что для объединения выходных данных двух сетей мы не просто добавляем их. Причиной этого является проблема идентификации. Если у нас есть Q, мы не можем найти V и A. Таким образом, мы не можем выполнить обратное распространение. Вместо этого мы предпочитаем использовать среднее преимущество в качестве исходного уровня (вычитаемый термин).

def build_model(self):

input = Input(shape=self.state_size)

shared = Conv2D(32, (8, 8), strides=(4, 4), activation='relu')(input)

shared = Conv2D(64, (4, 4), strides=(2, 2), activation='relu')(shared)

shared = Conv2D(64, (3, 3), strides=(1, 1), activation='relu')(shared)

flatten = Flatten()(shared)

advantage_fc = Dense(512, activation='relu')(flatten)

advantage = Dense(self.action_size)(advantage_fc)

advantage = Lambda(lambda a: a(:, :) - K.mean(a(:, :), keepdims=True),

output_shape=(self.action_size,))(advantage)

value_fc = Dense(512, activation='relu')(flatten)

value = Dense(1)(value_fc)

value = Lambda(lambda s: K.expand_dims(s(:, 0), -1),

output_shape=(self.action_size,))(value)

q_value = merge((value, advantage), mode='sum')

model = Model(inputs=input, outputs=q_value)

model.summary()

return model

И последнее, но не менее важное: у нас есть еще одна проблема для обсуждения, и она связана с оптимизацией воспроизведения опыта.

Повтор приоритетного опыта

Вы помните, что воспроизведение опыта — это когда мы время от времени проигрываем агенту случайные прошлые переживания, чтобы он не забыл их? Если вы этого не сделаете, теперь вы это сделаете. Но некоторые переживания могут быть более значительными, чем другие. В результате мы должны расставить приоритеты для их воспроизведения. Для этого вместо случайной выборки (из равномерного распределения) мы используем выборку с приоритетом. В качестве приоритета мы определяем величину ошибки TD (плюс некоторая константа, чтобы избежать нулевой вероятности выбора опыта).

п“=”дельта+εр=|\дельта|+\варепсилон

Центральная идея: Чем выше ошибка между прогнозом и целью, тем актуальнее узнать об этом.

И чтобы гарантировать, что мы не всегда будем воспроизводить один и тот же опыт, мы добавляем некоторую стохастичность, и все готово. Кроме того, для снижения сложности мы сохраняем опыт в бинарном дереве под названием SumTree.

п(я)“=”пяαкпкαP (i) = \ frac {p_ {i} ^ {\ alpha}} {\ sum_ {k} p_ {k} ^ {\ alpha}}

from SumTree import SumTree

class PER:

e = 0.01

a = 0.6

def __init__(self, capacity):

self.tree = SumTree(capacity)

def _getPriority(self, error):

return (error + self.e) ** self.a

def add(self, error, sample):

p = self._getPriority(error)

self.tree.add(p, sample)

def sample(self, n):

batch = ()

segment = self.tree.total() / n

for i in range(n):

a = segment * i

b = segment * (i + 1)

s = random.uniform(a, b)

(idx, p, data) = self.tree.get(s)

batch.append((idx, data))

return batch

def update(self, idx, error):

p = self._getPriority(error)

self.tree.update(idx, p)

Это было много. Много новой информации, много новых улучшений. Но только подумайте, что мы можем объединить их все вместе. И мы делаем это.

Я попытался дать краткий обзор самых важных недавних усилий в этой области, опираясь на некоторые интуитивные мысли и немного математики. Вот почему обучение с подкреплением так важно для изучения. Существует так много потенциала и так много возможностей для улучшений, что вы просто не можете игнорировать тот факт, что он станет крупным игроком в области ИИ (если это уже не так). Но именно поэтому так трудно учиться и идти в ногу с этим.

Если вам нужно погрузиться глубже, я настоятельно рекомендую Продвинутый ИИ: курс глубокого обучения на Python на Удеми.

В следующий раз мы представим градиенты политик и алгоритм REINFORCE.

Нам остается только учиться…

Книга «Глубокое обучение в производстве» 📖

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

Узнать больше

* Раскрытие информации: Обратите внимание, что некоторые из приведенных выше ссылок могут быть партнерскими ссылками, и без дополнительной оплаты для вас мы будем получать комиссию, если вы решите совершить покупку после перехода по ссылке.

LEAVE A REPLY

Please enter your comment!
Please enter your name here