Несоответствия между tf.contrib.layer.fully_connected, tf.layers.dense, tf.contrib.slim.fully_connected, tf.keras.layers.Dense - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь реализовать градиент политики для проблемы контекстного бандита (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, который имеет только одно действие с увеличением совокупного вознаграждения, обычно жертвуя другим (отрицательное совокупное вознаграждение).

1 Ответ

0 голосов
/ 17 января 2019

Для тех, кто сталкивается с этой проблемой, особенно учитывая, что для его реализации имеется много API-интерфейсов, в отличие от инициализации и значений по умолчанию.Для tf.contrib и tf.slim использование biases_initializer = None означает, что смещение не используется.Для репликации с использованием tf.layers и tf.keras требуется use_bias=False.

...