我基本上都在玩复制AlphaZero。它适用于一些小游戏,但我试图将它扩展到更复杂的游戏。然而,现在我的网络经过2-10万次移动训练后才会填满NaN。不幸的是,由于它不是确定性的,并且使用调试器在如此宽的范围内发生故障点并不是非常有效。当我使用tfdbg检查“has_inf_or_nan”时,需要大约5分钟训练12000次移动。所以调试器对我没有任何作用,因为它需要很长时间才能发现错误。
在这篇文章的最底部,我将描述模型的样子。
以下是我如何使用某些常见的NaN来源:
损失函数(具有2个输出的单个网络:策略(选择移动的几率)和值(活动玩家的董事会位置质量)):
注意:move_result_placeholder会填充一组移动,这些移动是MonteCarlo树搜索的输出。由于大多数移动位置无效,因此通常为0,其中5-10为浮点数,表示选择该移动的几率。我有一个断言,验证它们总和为1.当运行训练时,我也有断言验证没有输入是NaN。在填充批次时,我从最后1,000,000(Board State,Move,Reward)的集合中随机选择。然后我将董事会状态,移动和奖励纳入培训步骤。
self.loss_policy = tf.losses.softmax_cross_entropy(self.move_result_placeholder, out_dense)
self.loss_value =
tf.losses.mean_squared_error(self.value_result_placeholder,
tf.reshape(self.out_value_layer, shape=[-1,]))
self.total_loss = self.loss_policy + self.loss_value
优化器(学习率1e-4):
self.train_step = tf.train.AdamOptimizer(learning_rate=self.learning_rate_placeholder).minimize(self.total_loss, name="optimizer")
使用SoftMax:
self.out_policy_layer = tf.nn.softmax(out_dense, name="out_policy_layer")
批量标准化(is_training是占位符,在训练时为1,在玩游戏时为0)batch_norm_decay为.999:
input_bn = tf.contrib.layers.batch_norm(input_conv, center=True, scale=True, is_training=self.is_training, decay=self._config.batch_norm_decay)
正则化(层中所有权重的L2为1e-4):
initializer=tf.contrib.layers.xavier_initializer()
if use_regularizer:
regularizer = tf.contrib.layers.l2_regularizer(scale=self._config.l2_regularizer_scale)
weights = tf.get_variable(name, shape=shape, initializer=initializer, regularizer=regularizer)
模特描述:
模型在tensorflow中创建,由4x8x3的输入图层组成(批量大小为1024)。这捕获了4x8棋盘的状态以及自从玩家得分以来已经进行了多少次移动以及在该特定游戏中看到该棋盘状态的次数。这将进入一个内核大小为3x3且strides = 1的conv2d层。然后,我应用BatchNormalization tf.contrib.layers.batch_norm(input_conv, center=True, scale=True, is_training=self.is_training, decay=self._config.batch_norm_decay)
并relu。在输入relu的末尾,大小为4x8x64。
之后有5个剩余块。残留块后,它分成两部分。第一个是策略网络输出,它通过另一个卷积层运行它,内核大小为1x1,步长为1,批量标准化和ReLU。此时它是4x8x2并且它变平并通过密集层然后到softmax输出256输出,表示它将选择任何给定移动的几率。 256个输出映射到4x8电路板,并带有用于移动方向的平面。因此,第一个4x8会告诉你选择一件并将其移动到西北的可能性。第二个会告诉你选择一件并将其移动到东北等的可能性
分割的另一面是值输出。在那一侧,它通过一个卷积层然后变平,然后通过一个密集的层,最后通过一个TanH,所以它输出一个值,告诉我们该板状态的质量。
所有层的权重都使用L2正则化(1e-4)。
损失是政策方面的交叉熵和价值方面的均方误差,我正在使用Adam Optimizer。
答案 0 :(得分:1)
这就是解决这个问题的过于宽泛的问题。通常,您需要考虑可以生成NaN
的内容并使用模块化禁用来解决此问题,即禁用或绕过模型中的内容并查看错误是否消失。一些可能出现问题的候选者:批量标准化,或某些边缘情况的softmax(全部为零输入),或者您可能会出现梯度爆炸(尝试限制学习率。)
例如,关闭批量规范化并运行模型,查看是否发生错误。如果是,请将学习率降低几个数量级。等等。
答案 1 :(得分:1)
如果我是你,我会研究tensorboard的tensorflow调试器插件。您会发现使用此工具可以很容易地通过图表跟踪问题。
您可以在图表中逐步执行计算,还可以跟踪弹出的NaN值的出现次数。
https://github.com/tensorflow/tensorboard/tree/master/tensorboard/plugins/debugger
答案 2 :(得分:0)
我正在做的事情有几个问题可能导致了我的问题。
我没有正确应用L2正则化。在计算损失时,我只使用了部分L2损失。
要在我创建所有图层或使用get_variable创建权重时修复它,我会传入L2丢失功能。 e.g:
weights = tf.get_variable(name, shape=shape, initializer=initializer, regularizer=tf.contrib.layers.l2_regularizer(scale=self._config.l2_regularizer_scale))
和
out_dense = tf.layers.dense(out_flat, self._config.output_width, activation=tf.nn.relu,
kernel_initializer=tf.contrib.layers.xavier_initializer(),
kernel_regularizer=tf.contrib.layers.l2_regularizer(scale=self._config.l2_regularizer_scale), name="out_policy_flat")
然后当我计算损失时,我使用了tf.losses.get_regularization_loss函数。 e.g。
l2_loss = tf.losses.get_regularization_loss()
tf.summary.scalar("reg_loss", l2_loss)
self.total_loss += l2_loss
我在张量板中添加了l2_loss作为摘要,以便我可以看到它对我的损失有多大影响,并使用tf.contrib.layers.l2_regularizer的可配置比例参数在后续运行中调整它。 / p>
此外,在我的一些密集层上,我没有应用ReLU激活,我使用的是默认的权重初始化程序。我在所有密集层中添加了ReLU激活和Xavier初始化器。
以上的某些组合解决了这个问题。