Tensorflow——迁移学习实现(语义分割)
Tensorflow - transfer learning implementation (semantic segmentation)
我正在努力实现一个 CNN 架构(FCN-8s 模型,带有预训练的 VGG16 模型),用于对我自己的数据进行语义分割(2 类,因此,每像素二进制分类)
我打算如何解决这个问题:
- 加载带有权重的预训练模型
- Add/remove 额外的更高层转换为 FCN
- 冻结预训练模型的较低层(在训练阶段不更新)
- 在特定数据集上训练网络
假设这是正确的,我该如何冻结我的 tensorflow 模型的较低层? (我正在寻找具体的实施细节)我看过 TensorFlow 上的 Inception 再培训教程,但我还不太确定。
这是我心目中的工作流程:
运行我的数据通过现有的预训练模型,并提取特征输出,没有训练它。 (如何?)
将这些特征输出馈送到另一个包含更高层的网络 - 并开始训练它。
任何建议都会有所帮助!
否则,如果我错了,我该怎么想?
更新:
我使用 chasep255's suggestion below, and tried to use tf.stop_gradient 以便 "freeze" 我模型中的较低层。显然,我的实现有问题。可能 alternatives/suggestions?
该模型基于FCN(用于语义分割)论文构建。我从模型架构中提取 logits
,即我的特征,我最初将其直接输入到 loss
函数中,以使用 softmax 分类器将其最小化。 (每像素分类)deconv_1
是我的 logits 张量,形状为 [batch, h, w, num_classes] = [1, 750, 750, 2]
实现:
logits = vgg_fcn.deconv_1
stopper = tf.stop_gradient(logits, 'stop_gradients')
loss = train_func.loss(stopper, labels_placeholder, 2)
with tf.name_scope('Optimizer'):
train_op = train_func.training(loss, FLAGS.learning_rate)
with tf.name_scope('Accuracy'):
eval_correct = train_func.accuracy_eval(logits, labels_placeholder)
accuracy_summary = tf.scalar_summary('Accuracy', eval_correct)
然后我运行这些图形操作如下:
_, acc, loss_value = sess.run([train_op,eval_correct, loss], feed_dict=feed_dict)
当我 运行 这样的训练周期时,没有优化损失值,这肯定是因为我如何引入 tf.stop_gradient
Op。
更多细节,我的损失函数如下:
def loss(logits, labels, num_classes):
logits = tf.reshape(logits, [-1, num_classes])
#epsilon = tf.constant(value=1e-4)
#logits = logits + epsilon
labels = tf.to_int64(tf.reshape(labels, [-1]))
print ('shape of logits: %s' % str(logits.get_shape()))
print ('shape of labels: %s' % str(labels.get_shape()))
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits, labels, name='Cross_Entropy')
cross_entropy_mean = tf.reduce_mean(cross_entropy, name='xentropy_mean')
tf.add_to_collection('losses', cross_entropy_mean)
loss = tf.add_n(tf.get_collection('losses'), name='total_loss')
return loss
您可以将预训练模型的输出传递给 sess.run(pretrained_output, ...) 并捕获预训练模型的输出。保存输出后,您可以将其输入到模型中。在这种情况下,优化器将无法将梯度传播到预训练模型。
您还可以将预训练模型正常附加到您的模型,然后通过 tf.stop_graidents() 传递预训练输出,这将阻止优化器将梯度传播回预训练模型。
最后,您可以遍历预训练模型中的所有变量,并将它们从可训练变量列表中删除。
我正在努力实现一个 CNN 架构(FCN-8s 模型,带有预训练的 VGG16 模型),用于对我自己的数据进行语义分割(2 类,因此,每像素二进制分类)
我打算如何解决这个问题:
- 加载带有权重的预训练模型
- Add/remove 额外的更高层转换为 FCN
- 冻结预训练模型的较低层(在训练阶段不更新)
- 在特定数据集上训练网络
假设这是正确的,我该如何冻结我的 tensorflow 模型的较低层? (我正在寻找具体的实施细节)我看过 TensorFlow 上的 Inception 再培训教程,但我还不太确定。
这是我心目中的工作流程:
运行我的数据通过现有的预训练模型,并提取特征输出,没有训练它。 (如何?)
将这些特征输出馈送到另一个包含更高层的网络 - 并开始训练它。
任何建议都会有所帮助!
否则,如果我错了,我该怎么想?
更新:
我使用 chasep255's suggestion below, and tried to use tf.stop_gradient 以便 "freeze" 我模型中的较低层。显然,我的实现有问题。可能 alternatives/suggestions?
该模型基于FCN(用于语义分割)论文构建。我从模型架构中提取 logits
,即我的特征,我最初将其直接输入到 loss
函数中,以使用 softmax 分类器将其最小化。 (每像素分类)deconv_1
是我的 logits 张量,形状为 [batch, h, w, num_classes] = [1, 750, 750, 2]
实现:
logits = vgg_fcn.deconv_1
stopper = tf.stop_gradient(logits, 'stop_gradients')
loss = train_func.loss(stopper, labels_placeholder, 2)
with tf.name_scope('Optimizer'):
train_op = train_func.training(loss, FLAGS.learning_rate)
with tf.name_scope('Accuracy'):
eval_correct = train_func.accuracy_eval(logits, labels_placeholder)
accuracy_summary = tf.scalar_summary('Accuracy', eval_correct)
然后我运行这些图形操作如下:
_, acc, loss_value = sess.run([train_op,eval_correct, loss], feed_dict=feed_dict)
当我 运行 这样的训练周期时,没有优化损失值,这肯定是因为我如何引入 tf.stop_gradient
Op。
更多细节,我的损失函数如下:
def loss(logits, labels, num_classes):
logits = tf.reshape(logits, [-1, num_classes])
#epsilon = tf.constant(value=1e-4)
#logits = logits + epsilon
labels = tf.to_int64(tf.reshape(labels, [-1]))
print ('shape of logits: %s' % str(logits.get_shape()))
print ('shape of labels: %s' % str(labels.get_shape()))
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits, labels, name='Cross_Entropy')
cross_entropy_mean = tf.reduce_mean(cross_entropy, name='xentropy_mean')
tf.add_to_collection('losses', cross_entropy_mean)
loss = tf.add_n(tf.get_collection('losses'), name='total_loss')
return loss
您可以将预训练模型的输出传递给 sess.run(pretrained_output, ...) 并捕获预训练模型的输出。保存输出后,您可以将其输入到模型中。在这种情况下,优化器将无法将梯度传播到预训练模型。
您还可以将预训练模型正常附加到您的模型,然后通过 tf.stop_graidents() 传递预训练输出,这将阻止优化器将梯度传播回预训练模型。
最后,您可以遍历预训练模型中的所有变量,并将它们从可训练变量列表中删除。