我刚开始学习TensorFlow,并构建了我的第一个非常小的网络!!我的代码可以运行,但准确率始终不变;它在训练过程中没有变化。我的数据有15个特征和6个类别。如果增加更多特征可以使其更容易和更好的话,我可能会添加更多的特征。简而言之,我的疑问是:
调试TensorFlow代码的一般程序是什么?
我的网络架构是随意确定的,所以也许我应该改变每层的neurons数量,我不太确定。
sess1 = tf.Session()num_predictors = len(training_predictors_tf.columns)num_classes = len(training_classes_tf.columns)feature_data = tf.placeholder(tf.float32, [None, num_predictors])actual_classes = tf.placeholder(tf.float32, [None, num_classes])weights1 = tf.Variable(tf.truncated_normal([num_predictors, 50], stddev=0.0001))biases1 = tf.Variable(tf.ones([50]))weights2 = tf.Variable(tf.truncated_normal([50, 45], stddev=0.0001))biases2 = tf.Variable(tf.ones([45])) weights3 = tf.Variable(tf.truncated_normal([45, 25], stddev=0.0001))biases3 = tf.Variable(tf.ones([25]))weights4 = tf.Variable(tf.truncated_normal([25, num_classes], stddev=0.0001))biases4 = tf.Variable(tf.ones([num_classes]))hidden_layer_1 = tf.nn.relu(tf.matmul(feature_data, weights1) + biases1)hidden_layer_2 = tf.nn.relu(tf.matmul(hidden_layer_1, weights2) + biases2)hidden_layer_3 = tf.nn.relu(tf.matmul(hidden_layer_2, weights3) + biases3)out = tf.matmul(hidden_layer_3, weights4) + biases4model = tf.nn.softmax_cross_entropy_with_logits(labels=actual_classes, logits=out)# cost = -tf.reduce_sum(actual_classes*tf.log(model))cross_entropy = tf.reduce_mean( model)train_step = tf.train.GradientDescentOptimizer(0.05).minimize(cross_entropy)# train_step = tf.train.AdamOptimizer(learning_rate=0.0001).minimize(cross_entropy)sess1.run(tf.global_variables_initializer())correct_prediction = tf.equal(tf.argmax(out, 1), tf.argmax(actual_classes, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))for i in range(1, 30001): sess1.run( train_step, feed_dict={ feature_data: training_predictors_tf.values, actual_classes: training_classes_tf.values.reshape(len(training_classes_tf.values), num_classes) } ) if i%5000 == 0: print(i, sess1.run( accuracy, feed_dict={ feature_data: training_predictors_tf.values, actual_classes: training_classes_tf.values.reshape(len(training_classes_tf.values), num_classes) } ))
这是我的输出结果:
5000 0.362710000 0.362715000 0.362720000 0.362725000 0.362730000 0.3627
编辑:我按照这里的说明对数据进行了缩放,范围在[-5;0]之间,但仍然没有更好地训练网络 🙁
未缩放数据的片段(前6列为one-hot编码):
2017-06-27 0 0 0 1 0 0 20120.0 20080.0 20070.0 20090.0 ... 20050.0 20160.0 20130.0 20160.0 20040.0 20040.0 20040.0 31753.0 36927.0 41516.02017-06-28 0 0 1 0 0 0 20150.0 20120.0 20080.0 20150.0 ... 20060.0 20220.0 20160.0 20130.0 20130.0 20040.0 20040.0 39635.0 31753.0 36927.02017-06-29 0 0 0 1 0 0 20140.0 20150.0 20120.0 20140.0 ... 20090.0 20220.0 20220.0 20160.0 20100.0 20130.0 20040.0 50438.0 39635.0 31753.02017-06-30 0 1 0 0 0 0 20210.0 20140.0 20150.0 20130.0 ... 20150.0 20270.0 20220.0 20220.0 20050.0 20100.0 20130.0 58983.0 50438.0 39635.02017-07-03 0 0 0 1 0 0 20020.0 20210.0 20140.0 20210.0 ... 20140.0 20250.0 20270.0 20220.0 19850.0 20050.0 20100.0 88140.0 58983.0 50438.0
回答:
调试你的网络和改进它是两件不同的事情。要改进它,一旦你选择了一种分类器类型(例如神经网络),你应该使用训练和验证的准确率,并根据这两个准确率调整你的超参数。例如,可以参考Goodfellow等人的书中的实用方法论章节,了解如何调整超参数(内容有点长,但非常有价值!)。
至于调试,这是更难的部分。你通常通过定期打印一些“关键张量”的值来进行调试。你显然在某个地方有bug,否则你的准确率在训练过程中至少会有所变化。导致这种情况的一个常见问题是梯度爆炸,这会导致训练初期很快出现Nan
(有时是无穷大或奇怪位置的0),这基本上会停止网络的任何更新。我建议你打印你的损失值,也许还可以打印梯度范数,这应该能告诉你是否是这个问题。如果是的话,快速而粗糙的解决方案是开始时使用较小的学习率,然后逐渐增加。真正的解决方案是使用梯度裁剪。
打印多个张量值的示例:
if i%5000 == 0: acc_val, loss_val, predictions = sess1.run( [accuracy, cross_entropy, tf.argmax(out, 1)], feed_dict={ feature_data: training_predictors_tf.values, actual_classes: training_classes_tf.values.reshape(len(training_classes_tf.values), num_classes) }) print(i, acc_val, loss_val) # 你也可以打印predictions,但它会很大,所以更难看到其他值。这样做可以让你检查模型是否总是预测类别0...