我有一个性能良好的 TensorFlow CNN 模型,我们想在硬件中实现这个模型;即FPGA。这是一个相对较小的网络,但如果它更小,那将是理想的。带着这个目标,我检查了内核,发现有些内核的权重非常强,有些则根本没有做太多(内核值都接近于零)。这特别发生在第 2 层,对应于名为“W_conv2”的 tf.Variable()。W_conv2 的形状为 [3, 3, 32, 32]。我想冻结/锁定 W_conv2[:, :, 29, 13] 的值并将它们设置为零,以便可以训练网络的其余部分进行补偿。将此内核的值设置为零有效地从硬件实现中删除/修剪内核,从而实现上述目标。
我发现了类似的问题,建议通常围绕两种方法之一进行;
建议#1:
tf.Variable(some_initial_value, trainable = False)
实施此建议会冻结整个变量。我只想冻结一个切片,特别是 W_conv2[:, :, 29, 13]。
建议2:
Optimizer = tf.train.RMSPropOptimizer(0.001).minimize(loss, var_list)
同样,实施此建议不允许使用切片。例如,如果我尝试与我的既定目标相反(仅优化单个变量的单个内核),如下所示:
Optimizer = tf.train.RMSPropOptimizer(0.001).minimize(loss, var_list = W_conv2[:,:,0,0]))
我收到以下错误:
NotImplementedError: ('Trying to optimize unsupported type ', <tf.Tensor 'strided_slice_2228:0' shape=(3, 3) dtype=float32>)
以我在这里尝试的方式切片 tf.Variables() 是不可能的。我尝试过的唯一接近做我想做的事情是使用 .assign() 但这非常低效、繁琐且像穴居人,因为我已按如下方式实现它(在模型训练后):
for _ in range(10000):
# get a new batch of data
# reset the values of W_conv2[:,:,29,13]=0 each time through
for m in range(3):
for n in range(3):
assign_op = W_conv2[m,n,29,13].assign(0)
sess.run(assign_op)
# re-train the rest of the network
_, loss_val = sess.run([optimizer, loss], feed_dict = {
dict_stuff_here
})
print(loss_val)
该模型在 Keras 中启动,然后转移到 TensorFlow,因为 Keras 似乎没有实现预期结果的机制。我开始认为 TensorFlow 不允许修剪,但很难相信;它只需要正确的实现。