我正在努力在存在故障的情况下模拟神经网络操作。我想在推理期间访问权重数据以破坏权重中的位,并且我希望在每次新激活时以不同方式破坏它们,因此无法脱机完成。在推理期间如何访问和写入权重?
我正在使用models
repo中的vgg16模型,该模型是使用TF-Slim API(https://github.com/tensorflow/models/blob/master/research/slim/nets/vgg.py)编写的,我在这里复制了一个片段:
with tf.variable_scope(scope, 'vgg_a', [inputs]) as sc:
end_points_collection = sc.original_name_scope + '_end_points'
# Collect outputs for conv2d, fully_connected and max_pool2d.
with slim.arg_scope([slim.conv2d, slim.max_pool2d],
outputs_collections=end_points_collection):
net = slim.repeat(inputs, 1, slim.conv2d, 64, [3, 3], scope='conv1')
net = slim.max_pool2d(net, [2, 2], scope='pool1')
例如,我想通过访问可训练和不可训练的变量,对其值进行一些修改并将其写回来在slim.conv2d
层中注入错误。
如何在处理输入之前访问conv2d
图层的实例?
我可以阅读layer.variables
,修改它们,然后将新值设置回layer.variables
吗?
或者是正确的方法来继承slim.conv2d
并添加允许我写入layer.variables
属性的访问器?
我想通过访问可训练和不可训练的变量来注入错误,对它们的值进行一些修改,然后将它们写回来。
看一下名为tf.get_variable
:documentation的这个函数
tf.get_variable
获取具有指定参数的现有变量或创建一个新变量。
首先,在Tensorflow中使用变量时,命名很重要。在范围内声明变量时,如示例中的代码:
with tf.variable_scope(scope, 'vgg_a', [inputs]) as sc:
[...]
变量的名称取决于范围vgg_a
。
例如:
def conv_relu(input, kernel_shape, bias_shape):
# Create variable named "weights".
weights = tf.get_variable("weights", kernel_shape,
initializer=tf.random_normal_initializer())
# Create variable named "biases".
biases = tf.get_variable("biases", bias_shape,
initializer=tf.constant_initializer(0.0))
conv = tf.nn.conv2d(input, weights,
strides=[1, 1, 1, 1], padding='SAME')
return tf.nn.relu(conv + biases)
如果我有一个辅助方法正在创建类似上面代码的变量,并在范围层次结构中调用此方法,如下所示:
def my_image_filter(input_images):
with tf.variable_scope("conv1"):
relu1 = conv_relu(input_images, [5, 5, 32, 32], [32])
这里创建的变量将命名为conv1/weights
,conv1/biases
。
with tf.variable_scope("conv2"):
return conv_relu(relu1, [5, 5, 32, 32], [32])
这里创建的变量将命名为conv2/weights
,conv2/biases
。
考虑到这一点,让我们深入了解Tensorflow中的变量:
import numpy as np
import tensorflow as tf
with tf.variable_scope("foo", reuse=tf.AUTO_REUSE):
a = tf.get_variable(name='a', shape=[1, 10], initializer=tf.constant_initializer(5))
print(a)
with tf.variable_scope("foo", reuse=True):
b = tf.get_variable(name='a', shape=[1, 10])
print(b)
这打印以下行:
<tf.Variable 'foo/a:0' shape=(1, 10) dtype=float32_ref>
<tf.Variable 'foo/a:0' shape=(1, 10) dtype=float32_ref>
嗯,有趣。两个变量都具有相同的名称。
现在让我们试着看看它们包含什么:
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
val_a = sess.run(a)
val_b = sess.run(b)
print("val_a:", val_a)
print("val_b:", val_b)
我们得到以下输出:
val_a: [[5. 5. 5. 5. 5. 5. 5. 5. 5. 5.]]
val_b: [[5. 5. 5. 5. 5. 5. 5. 5. 5. 5.]]
太好了!当我们为tf.get_variable(name='a', shape=[1, 10])
调用b
时,我们没有指定任何初始化器,但是我们得到的值与a
相同。
现在,只是要仔细检查a
和b
引用相同的变量,让我们添加以下代码:
new_val = np.array([[2., 2., 2., 2., 2., 2., 2., 2., 2., 2.]])
assign_op = b.assign(new_val)
with tf.Session() as sess:
sess.run(assign_op)
val_a = sess.run(a)
val_b = sess.run(b)
print("val_a:", val_a)
print("val_b:", val_b)
打印:
val_a: [[2. 2. 2. 2. 2. 2. 2. 2. 2. 2.]]
val_b: [[2. 2. 2. 2. 2. 2. 2. 2. 2. 2.]]
大!我们现在知道如何使用其范围和名称来查找变量,就像您按目录和文件名查找文件一样。然后我们可以使用任一变量来操纵值。
同样,对于您的问题,您可以检索已初始化的变量并根据需要进行更改。只需确保在您的范围内设置reuse=True
或致电scope.reuse_variables()
。
Here是一个关于在Tensorflow中使用变量的好教程。