一些实验数据包含512个独立的布尔特征和一个布尔结果。
提供的数据集中大约有100万条真实实验记录。
在经典的XOR示例中,所有4种可能的状态都是训练神经网络所必需的。在我的案例中,只有2^(10-512) = 2^-505
,这接近于零。
我对数据的本质没有更多信息,只有这些(512 + 1) * 1e6
位的数据。
尝试在可用数据上使用一个隐藏层的NN进行训练。即使在训练集上的样本中,训练后的NN的输出始终接近0,没有一个接近“1”。尝试调整了权重初始化和梯度下降的学习率。
我的代码使用了TensorFlow 1.3和Python 3。模型摘录如下:
with tf.name_scope("Layer1"): #W1 = tf.Variable(tf.random_uniform([512, innerN], minval=-2/512, maxval=2/512), name="Weights_1") W1 = tf.Variable(tf.zeros([512, innerN]), name="Weights_1") b1 = tf.Variable(tf.zeros([1]), name="Bias_1") Out1 = tf.sigmoid( tf.matmul(x, W1) + b1)with tf.name_scope("Layer2"): W2 = tf.Variable(tf.random_uniform([innerN, 1], minval=-2/512, maxval=2/512), name="Weights_2") #W2 = tf.Variable(tf.zeros([innerN, 1]), name="Weights_2") b2 = tf.Variable(tf.zeros([1]), name="Bias_2") y = tf.nn.sigmoid( tf.matmul(Out1, W2) + b2)with tf.name_scope("Training"): y_ = tf.placeholder(tf.float32, [None,1]) cross_entropy = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits( labels = y_, logits = y) ) train_step = tf.train.GradientDescentOptimizer(0.005).minimize(cross_entropy) with tf.name_scope("Testing"): # Test trained model correct_prediction = tf.equal( tf.round(y), tf.round(y_))# ...# Trainfor step in range(500): batch_xs, batch_ys = Datasets.train.next_batch(300, shuffle=False) _, my_y, summary = sess.run([train_step, y, merged_summaries], feed_dict={x: batch_xs, y_: batch_ys})
我怀疑有两种情况:
- 我的错误 – 神经网络实现不当,架构错误;
- 数据质量差。与XOR示例相比,不完整的训练数据会导致神经网络失败。然而,训练后的神经网络应该能够对训练样本进行正确预测,对吗?
如何评估是否有可能在提供的数据上训练神经网络(两层感知器)来预测结果?一个可接受的示例是XOR示例。与某些随机噪声相反。
回答:
要判断是否有可能从数据集中学习一个可微分网络的函数,只能通过临时方法来确定。尽管如此,这些临时方法通常是有效的。例如,网络应该能够在没有正则化的前提下过拟合训练集。
一种常见的技术是只在数据集的一个子集上拟合网络。检查网络是否能过拟合该子集,然后增加子集的大小,同时也增加网络的大小。不幸的是,决定是否添加额外的层或在隐藏层中添加更多单元是一个你必须自己做出的任意决定。
然而,看你的代码,有几件事可能出错了:
- 你的输出是否平衡?我的意思是,数据集目标中1和0的数量是否相同?
- 你在第一层的初始化全部为零,对此的梯度将为零,因此它无法学习任何东西(尽管你在上面注释掉了实际的初始化)。
- Sigmoid非线性比更简单的非线性(如ReLU)更难优化。
我建议使用TensorFlow中的内置层定义来避免担心初始化,并在任何隐藏层中切换到ReLU(输出层需要sigmoid来处理你的布尔目标)。
最后,深度学习实际上并不擅长大多数“特征袋”机器学习问题,因为它们缺乏结构。例如,特征的顺序并不重要。其他方法通常效果更好,但如果你真的想使用深度学习,你可以参考这篇最近的论文,它展示了通过使用非常特定的非线性和权重初始化(只需更改上述代码中的4行)来提高性能的方法。