【问题标题】:Converting .npz model from ChainerRL to Keras model, or alternative methods?将 .npz 模型从 ChainerRL 转换为 Keras 模型,或替代方法?
【发布时间】:2020-07-29 19:53:14
【问题描述】:

我有一个 DQN 强化学习模型,它是使用 ChainerRL 在 Ms Pacman Atari 游戏环境上的内置 DQN 实验训练的,我们将此文件称为 model.npz。我有一些用 Keras 编写的分析软件,它使用 Keras 网络并将模型加载到该网络中。

我无法让从 ChainerRL 导出的 .npz 与 Keras 网络配合使用。

我已经弄清楚如何从 .npz 文件中加载权重。我想我知道如何确保 Keras 模型在内核大小、步幅和激活方面与 Chainer RL 模型相匹配。

下面是调用 ChainerRL 中构建网络的函数的代码:

return links.Sequence(
        links.NatureDQNHead(),
        L.Linear(512, n_actions),
        DiscreteActionValue)

由此调用并构建 Chainer DQN 网络的代码是:

class NatureDQNHead(chainer.ChainList):
"""DQN's head (Nature version)"""

def __init__(self, n_input_channels=4, n_output_channels=512,
             activation=F.relu, bias=0.1):
    self.n_input_channels = n_input_channels
    self.activation = activation
    self.n_output_channels = n_output_channels

    layers = [
        #L.Convolution2D(n_input_channels, out_channel=32, ksize=8, stride=4, pad=0, nobias=False, initialW=None, initial_bias=bias, *, dilate=1, groups=1),
        L.Convolution2D(n_input_channels, 32, 8, stride=4,
                        initial_bias=bias),
        #L.Convolution2D(n_input_channels=32, out_channel=64, ksize=4, stride=2, pad=0, nobias=False, initialW=None, initial_bias=bias, *, dilate=1, groups=1),
        L.Convolution2D(32, 64, 4, stride=2, initial_bias=bias),
        #L.Convolution2D(n_input_channels=64, out_channel=64, ksize=3, stride=1, pad=0, nobias=False, initialW=None, initial_bias=bias, *, dilate=1, groups=1),
        L.Convolution2D(64, 64, 3, stride=1, initial_bias=bias),
        #L.Convolution2D(in_size=3136, out_size=n_output_channels, nobias=False, initialW=None, initial_bias=bias),
        L.Linear(3136, n_output_channels, initial_bias=bias),
    ]

    super(NatureDQNHead, self).__init__(*layers)

def __call__(self, state):
    h = state
    for layer in self:
        h = self.activation(layer(h))
    return h

于是我编写了以下 Keras 代码,在 Keras 中构建了一个等效的网络:

# Keras Model
hidden = 512
#bias initializer to match the chainerRL one
initial_bias = tf.keras.initializers.Constant(0.1)

#matches default "channels_last" data format for Keras layers
inputs = Input(shape=(84, 84, 4))

#First call to Conv2D including all defaults for easy reference
x = Conv2D(filters=32, kernel_size=(8, 8), strides=4, padding='valid', data_format=None, dilation_rate=(1, 1), activation='relu', use_bias=True, kernel_initializer='glorot_uniform', bias_initializer=initial_bias, kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None, name='deepq/q_func/convnet/Conv')(inputs)
x1 = Conv2D(filters=64, kernel_size=(4, 4), strides=2, activation='relu', padding='valid', bias_initializer=initial_bias, name='deepq/q_func/convnet/Conv_1')(x)
x2 = Conv2D(filters=64, kernel_size=(3, 3), strides=1, activation='relu', padding='valid', bias_initializer=initial_bias, name='deepq/q_func/convnet/Conv_2')(x1)
#Flatten for move to linear layers
conv_out = Flatten()(x2)

action_out = Dense(hidden, activation='relu', name='deepq/q_func/action_value/fully_connected')(conv_out)
action_scores = Dense(units = 9, name='deepq/q_func/action_value/fully_connected_1', activation='linear', use_bias=True, kernel_initializer="glorot_uniform", bias_initializer=initial_bias, kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None,)(action_out)  # num_actions in {4, .., 18}

#Now create model using the above-defined layers
modelArchitecture = Model(inputs, action_scores)

我检查了 Keras 模型的初始权重的结构,发现它们如下:

  • 第 0 层:无权重
  • 第 1 层:(8,8,4,32)
  • 第 2 层:(4,4,32,64)
  • 第 3 层:(4,4,64,64)
  • 第 4 层:无权重
  • 第 5 层:(3136,512)
  • 第 6 层:(9,512)

然后,我检查了我尝试导入的 .npz 模型中的权重,发现它们如下:

  • 第 0 层:(32,4,8,8)
  • 第 1 层:(64,32,4,4)
  • 第 2 层:(64,64,4,4)
  • 第 3 层:(512,3136)
  • 第 4 层:(9,512)

因此,我使用 numpy.reshape 从 model.npz 的第 0 层重塑权重,并将它们应用到 Keras 网络的第 1 层。我对第 1 层的 model.npz 权重做了同样的事情,并将它们应用到 Keras 网络的第 2 层。然后,我从 model.npz 的第 2 层重塑权重,并将它们应用到 Keras 网络的第 3 层。我从 model.npz 转置了第 3 层的权重,并将它们应用到 Keras 模型的第 5 层。最后,我将model.npz第4层的权重转置,并应用到Keras模型的第6层。

我将模型保存为 .H5 格式,然后尝试在 Ms Pacman Atari 环境中的评估代码上运行它,并制作了一个视频。当我这样做时,吃豆人会沿着完全相同的短路径,脸先撞到墙上,然后继续尝试穿过墙,直到被鬼杀死。

因此,我在 Chainer DQN 网络和 Keras DQN 网络之间的转换似乎做错了什么。我不确定他们是否以不同的顺序处理颜色?

我还尝试将 ChainerRL model.npz 文件导出到 ONNX,但出现了几个错误,以至于如果不重写大量 ChainerRL 代码库,这似乎是不可能的。

任何帮助将不胜感激。

【问题讨论】:

    标签: python-3.x keras neural-network reinforcement-learning chainer


    【解决方案1】:

    我是 ChainerRL 的作者。我没有使用 Keras 的经验,但显然 Chainer 和 Keras 之间的权重参数格式似乎不同。您应该检查每个深度学习框架的权重参数的每个维度的含义。在Chainer中,在文档(https://docs.chainer.org/en/stable/reference/generated/chainer.functions.convolution_2d.html#chainer.functions.convolution_2d)中可以看到,Convolution2D的权重参数存储为(c_O, c_I, h_K, w_K)。

    一旦你找到每个维度的含义,我猜你需要的总是numpy.transpose,而不是numpy.reshape,重新排序维度以匹配 Keras 的顺序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-02
      • 2020-02-09
      • 2019-09-05
      • 2020-01-24
      • 2019-06-28
      • 2020-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多