最近下决心要好好学习一下,从11月4日开始学习《Tensorflow实战》这本书,跟着书上一句句敲代码并调试,中间遇到了如下一些常见问题:
1.tensorflow首先通过定义好计算图,然后再把真实的数据喂进图中来得到一个结果。有点像形参和实参的意味。喂进数据的时候也就是先获得输入,然后获得输出:
image_batch, label_batch = sess.run([train_image, train_label])
loss_, pred_, logits_, top_k_op_ = sess.run([loss, pred, logits, top_k_op], feed_dict={x:image_batch, y:label_batch})
跑第一个代码时以为这样就完了,然后在迭代的时候发现每次的logits_都是一样的,说明参数没有更新,经过查阅才知道原来在每次计算完输出后,需要添加一行代码来保证参数更新:
sess.run(train_step, feed_dict={x:image_batch, y:label_batch})
其中,train_step就是
train_step = optimizer.minimize(loss)
2.说到这里就要提到后面遇到的一个问题了。我在训练的时候发现,训练集上的准确率随着迭代次数增加是在不断增加,但是在测试集上却很低,我怀疑是batch_normalization中参数的问题,可是我在训练和测试时分别设置了is_training这两个参数,在设置为False的时候依旧没有好的结果,并且观察prediction,发现每一类的概率都是0.2左右(这里我用的数据集时5类花朵分类)。后来经过查阅,发现是因为自己在训练时没有在优化器前加入如下语句:
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=LEARNING_RATE)
with tf.control_dependencies(update_ops):
train_step = optimizer.minimize(loss)
3.在利用一个多层感知机训练mnist数据集时,我使用的是自己写的损失函数label*(log(pred)),训练时loss出现了nan的情况,这是因为pred出现了0,因此需要在使用自己的损失函数时,要注意是否会出现这种情况。
4.训练时发现loss老是降不下去,这时可以考虑一下是否和学习率、迭代次数和优化器有关。出现这个情况时我一度以为是自己的网络设计有问题,于是把结果单独输出来看,中间增减了几次batch_norm,发现确实如果不适用batch_norm,就很容易出现died node的情况,我的每类pred都全部变成0了!Σ(っ °Д °;)っ
5.一开始用mnist数据集分类,使用的是one-hot编码,后来使用5类花朵数据集,在计算Loss的时候,可以直接使用
tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits))
这个函数来计算loss。
6.要定义参数正则化项的loss时,可以使用如下语句,先对每个loss使用:
tf.add_to_collection('loss', loss_i),最后把这些loss全部取出来相加:tf.add_n(tf.get_collection('loss'))
7.调参:学习率可以初始时使用e-2~e-4,微调时使用e-4~e-7左右,注意图像尺寸的影响,优化器工程中常用SGD和Momentum,据说是和训练出来的参数量有关?
8.我在读自己生成的tfrecord数据时,出现了读到那儿就卡住不动了的情况,这时应在读数据前加入:
coord = tf.train.Coordinator()
thread = tf.train.start_queue_runners(sess, coord)
9.我们在训练初始时应该初始化网络参数,而在读取保存的参数时就不需要了:
saver = tf.train.Saver(tf.global_variables())
latest_ckpt = tf.train.latest_checkpoint(Config.train_log_dir)
graph = tf.get_default_graph()
if latest_ckpt is not None:
saver.restore(sess, latest_ckpt)
else:
init = tf.global_variables_initializer()
sess.run(init)
10.在训练时需要打乱数据的顺序,通常使用这个函数来实现:
tf.train.shuffle_batch([image, label],batch_size=batch_size,num_threads= 64,
capacity=capacity,
min_after_dequeue=min_after_dequeue)
当你的tfrecord在制作时是根据类别一个文件夹一个文件夹放进去的时候, 就要注意这个min_after_dequeue这个参数的设置了,它的意思大概是队列中后面的最小空间?这个值如果设置小了,它就只会在前面的那些图片里面打乱顺序,假设有3000张图片,一共5类每类600张,如果这个参数设置为1000,那就只会取到前面的2类数据再在里面选出来打乱,所以这里设置这个参数的时候需要把值设置为总的样本数。我在想如果这个值设置得特别大,会不会造成存储负担?所以在制作数据集时其实可以先把顺序打乱一下。
11.vgg网络使用了串联的卷积层,可以避免使用大的卷积核,减小了参数量,但是计算量是没有减少的甚至有所增加,吧?
以上就是目前遇到的一些问题和解决方法,目前的5类分类器准确率只有78%左右,但是至少出结果了,希望后面能够更加的优化吧~若有大佬路过希望帮忙指正呀~