Я пытаюсь реализовать градиент политики для проблемы контекстного бандита (https://medium.com/emergent-future/simple-reinforcement-learning-with-tensorflow-part-1-5-contextual-bandits-bff01d1aad9c).
Я определяю модель в тензорном потоке для решения этой проблемы, используя один полностью связанный слой.
Я пробую разные API-интерфейсы из tenorflow, но хочу избежать использования пакета contrib
, поскольку он не поддерживается Tenorflow. Я заинтересован в использовании keras
API, так как я уже знаком с функциональным интерфейсом, и теперь он реализован как tf.keras
. Тем не менее, мне кажется, что результаты могут работать только при использовании tf.contrib.slim.fully_connected
или tf.contrib.layers.fully_connected
(первое вызывает второе).
Следующие два фрагмента работают правильно (one_hot_encoded_state_input
и num_actions
оба придерживаются ожидаемых тензорных форм для слоев).
import tensorflow.contrib.slim as slim
action_probability_distribution = slim.fully_connected(
one_hot_encoded_state_input, \
num_actions, \
biases_initializer=None, \
activation_fn=tf.nn.sigmoid, \
weights_initializer=tf.ones_initializer())
и
from tensorflow.contrib.layers import fully_connected
action_probability_distribution = fully_connected(
one_hot_encoded_state_input,
num_actions,\
biases_initializer=None, \
activation_fn=tf.nn.sigmoid, \
weights_initializer=tf.ones_initializer())
С другой стороны, ни одна из следующих работ не работает:
action_probability_distribution = tf.layers.dense(
one_hot_encoded_state_input, \
num_actions, \
activation=tf.nn.sigmoid, \
bias_initializer=None, \
kernel_initializer=tf.ones_initializer())
ни
action_probability_distribution = tf.keras.layers.Dense(
num_actions, \
activation='sigmoid', \
bias_initializer=None, \
kernel_initializer = 'Ones')(one_hot_encoded_state_input)
В последних двух случаях используются высокоуровневые API-интерфейсы tenorflow layers
и keras
. В идеале я хотел бы знать, если я неправильно реализую первые два случая, используя последние два случая , и если единственная проблема, с которой я сталкиваюсь, это то, что последние два не эквивалентны первому два .
Для полноты здесь приведен весь код, необходимый для его запуска (Примечание: использовались python 3.5.6 и tenenflow 1.12.0).
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
num_states = 3
num_actions = 4
learning_rate = 1e-3
state_input = tf.placeholder(shape=(None,),dtype=tf.int32, name='state_input')
one_hot_encoded_state_input = tf.one_hot(state_input, num_states)
# DOESN'T WORK
action_probability_distribution = tf.keras.layers.Dense(num_actions, activation='sigmoid', bias_initializer=None, kernel_initializer = 'Ones')(one_hot_encoded_state_input)
# WORKS
# import tensorflow.contrib.slim as slim
# action_probability_distribution = slim.fully_connected(one_hot_encoded_state_input,num_actions,\
# biases_initializer=None,activation_fn=tf.nn.sigmoid,weights_initializer=tf.ones_initializer())
# WORKS
# from tensorflow.contrib.layers import fully_connected
# action_probability_distribution = fully_connected(one_hot_encoded_state_input,num_actions,\
# biases_initializer=None,activation_fn=tf.nn.sigmoid,weights_initializer=tf.ones_initializer())
# DOESN'T WORK
# action_probability_distribution = tf.layers.dense(one_hot_encoded_state_input,num_actions, activation=tf.nn.sigmoid, bias_initializer=None, kernel_initializer=tf.ones_initializer())
action_probability_distribution = tf.squeeze(action_probability_distribution)
action_chosen = tf.argmax(action_probability_distribution)
reward_input = tf.placeholder(shape=(None,), dtype=tf.float32, name='reward_input')
action_input = tf.placeholder(shape=(None,), dtype=tf.int32, name='action_input')
responsible_weight = tf.slice(action_probability_distribution, action_input, [1])
loss = -(tf.log(responsible_weight)*reward_input)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
update = optimizer.minimize(loss)
bandits = np.array([[0.2,0,-0.0,-5],
[0.1,-5,1,0.25],
[-5,5,5,5]])
assert bandits.shape == (num_states, num_actions)
def get_reward(state, action): # the lower the value of bandits[state][action], the higher the likelihood of reward
if np.random.randn() > bandits[state][action]:
return 1
return -1
max_episodes = 10000
epsilon = 0.1
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
rewards = np.zeros(num_states)
for episode in range(max_episodes):
state = np.random.randint(0,num_states)
action = sess.run(action_chosen, feed_dict={state_input:[state]})
if np.random.rand(1) < epsilon:
action = np.random.randint(0, num_actions)
reward = get_reward(state, action)
sess.run([update, action_probability_distribution, loss], feed_dict = {reward_input: [reward], action_input: [action], state_input: [state]})
rewards[state] += reward
if episode%500 == 0:
print(rewards)
При использовании чанков, прокомментированных # THIS WORKS
, агент изучает и максимизирует вознаграждение во всех трех состояниях. С другой стороны, те, кто прокомментировал # THIS DOESN'T WORK#
, не учатся и обычно очень быстро сходятся к выбору одного действия. Например, поведение работает должно выводить список reward
, который является положительным, растущими числами (хорошая совокупная награда за каждое состояние). нерабочее поведение выглядит как список reward
, который имеет только одно действие с увеличением совокупного вознаграждения, обычно жертвуя другим (отрицательное совокупное вознаграждение).