在没有高级 API 的情况下重新训练 CNN
Retraining a CNN without a high-level API
总结:我试图在不使用高级 API 的情况下为 MNIST 重新训练一个简单的 CNN。我已经通过重新训练整个网络成功地做到了这一点,但我目前的目标是只重新训练最后一两个全连接层。
目前工作:
假设我有一个具有以下结构的 CNN
- 卷积层
- RELU
- 池化层
- 卷积层
- RELU
- 池化层
- 全连接层
- RELU
- 丢弃层
- 全连接层到 10 个输出 类
我的目标是重新训练最后一个全连接层或最后两个全连接层。
一个卷积层的例子:
W_conv1 = tf.get_variable("W", [5, 5, 1, 32],
initializer=tf.truncated_normal_initializer(stddev=np.sqrt(2.0 / 784)))
b_conv1 = tf.get_variable("b", initializer=tf.constant(0.1, shape=[32]))
z = tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='SAME')
z += b_conv1
h_conv1 = tf.nn.relu(z + b_conv1)
全连接层示例:
input_size = 7 * 7 * 64
W_fc1 = tf.get_variable("W", [input_size, 1024], initializer=tf.truncated_normal_initializer(stddev=np.sqrt(2.0/input_size)))
b_fc1 = tf.get_variable("b", initializer=tf.constant(0.1, shape=[1024]))
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
我的假设:在新数据集上执行反向传播时,我只是确保我的权重 W 和 b(来自 W*x+b)固定在非- 全连接层。
首先想到怎么做:保存W和b,进行一次反向传播步骤,在I层用旧的替换新的W和b不想改变。
我对第一种方法的看法:
- 这是计算密集型的并且浪费内存。只做最后一层的全部好处是不必做其他的
- 如果不应用于所有层,反向传播的功能可能会有所不同?
我的问题:
- 如何在不使用高级 API 时正确地重新训练神经网络中的特定层。欢迎提供概念和编码答案。
P.S. 充分了解如何使用高级 APIs 来做到这一点。示例:https://towardsdatascience.com/how-to-train-your-model-dramatically-faster-9ad063f0f718。只是不想让神经网络变得神奇,我想知道到底发生了什么
优化器的最小化函数有一个可选参数,用于选择要训练的变量,例如:
optimizer_step = tf.train.MomentumOptimizer(learning_rate, momentum, name='MomentumOptimizer').minimize(loss, var_list=training_variables)
您可以使用 tf.trainable_variables():
获取要训练的层的变量
vars1 = tf.trainable_variables()
# FC Layer
input_size = 7 * 7 * 64
W_fc1 = tf.get_variable("W", [input_size, 1024], initializer=tf.truncated_normal_initializer(stddev=np.sqrt(2.0/input_size)))
b_fc1 = tf.get_variable("b", initializer=tf.constant(0.1, shape=[1024]))
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
vars2 = tf.trainable_variables()
training_variables = list(set(vars2) - set(vars1))
编辑:实际上,在这种情况下使用 tf.trainable_variables 可能有点矫枉过正,因为您直接有 W_fc1 和 b_fc1。这将很有用,例如,如果您使用 tf.layers.dense 创建一个密集层,您不会在其中显式拥有变量。
总结:我试图在不使用高级 API 的情况下为 MNIST 重新训练一个简单的 CNN。我已经通过重新训练整个网络成功地做到了这一点,但我目前的目标是只重新训练最后一两个全连接层。
目前工作: 假设我有一个具有以下结构的 CNN
- 卷积层
- RELU
- 池化层
- 卷积层
- RELU
- 池化层
- 全连接层
- RELU
- 丢弃层
- 全连接层到 10 个输出 类
我的目标是重新训练最后一个全连接层或最后两个全连接层。
一个卷积层的例子:
W_conv1 = tf.get_variable("W", [5, 5, 1, 32],
initializer=tf.truncated_normal_initializer(stddev=np.sqrt(2.0 / 784)))
b_conv1 = tf.get_variable("b", initializer=tf.constant(0.1, shape=[32]))
z = tf.nn.conv2d(x_image, W_conv1, strides=[1, 1, 1, 1], padding='SAME')
z += b_conv1
h_conv1 = tf.nn.relu(z + b_conv1)
全连接层示例:
input_size = 7 * 7 * 64
W_fc1 = tf.get_variable("W", [input_size, 1024], initializer=tf.truncated_normal_initializer(stddev=np.sqrt(2.0/input_size)))
b_fc1 = tf.get_variable("b", initializer=tf.constant(0.1, shape=[1024]))
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
我的假设:在新数据集上执行反向传播时,我只是确保我的权重 W 和 b(来自 W*x+b)固定在非- 全连接层。
首先想到怎么做:保存W和b,进行一次反向传播步骤,在I层用旧的替换新的W和b不想改变。
我对第一种方法的看法:
- 这是计算密集型的并且浪费内存。只做最后一层的全部好处是不必做其他的
- 如果不应用于所有层,反向传播的功能可能会有所不同?
我的问题:
- 如何在不使用高级 API 时正确地重新训练神经网络中的特定层。欢迎提供概念和编码答案。
P.S. 充分了解如何使用高级 APIs 来做到这一点。示例:https://towardsdatascience.com/how-to-train-your-model-dramatically-faster-9ad063f0f718。只是不想让神经网络变得神奇,我想知道到底发生了什么
优化器的最小化函数有一个可选参数,用于选择要训练的变量,例如:
optimizer_step = tf.train.MomentumOptimizer(learning_rate, momentum, name='MomentumOptimizer').minimize(loss, var_list=training_variables)
您可以使用 tf.trainable_variables():
获取要训练的层的变量vars1 = tf.trainable_variables()
# FC Layer
input_size = 7 * 7 * 64
W_fc1 = tf.get_variable("W", [input_size, 1024], initializer=tf.truncated_normal_initializer(stddev=np.sqrt(2.0/input_size)))
b_fc1 = tf.get_variable("b", initializer=tf.constant(0.1, shape=[1024]))
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
vars2 = tf.trainable_variables()
training_variables = list(set(vars2) - set(vars1))
编辑:实际上,在这种情况下使用 tf.trainable_variables 可能有点矫枉过正,因为您直接有 W_fc1 和 b_fc1。这将很有用,例如,如果您使用 tf.layers.dense 创建一个密集层,您不会在其中显式拥有变量。