使用 TensorFlow 的训练和预测出了什么问题?
What is going wrong with the training and predictions using TensorFlow?
请看下面写的代码
x = tf.placeholder("float", [None, 80])
W = tf.Variable(tf.zeros([80,2]))
b = tf.Variable(tf.zeros([2]))
y = tf.nn.softmax(tf.matmul(x,W) + b)
y_ = tf.placeholder("float", [None,2])
所以这里我们看到数据中有 80 个特征,只有 2 个可能的输出。我这样设置 cross_entropy
和 train_step
。
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.matmul(x, W) + b, y_)
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
初始化所有变量。
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
然后我将此代码用于 "train" 我的神经网络。
g = 0
for i in range(len(x_train)):
_, w_out, b_out = sess.run([train_step, W, b], feed_dict={x: [x_train[g]], y_: [y_train[g]]})
g += 1
print "...Trained..."
训练网络后,无论我训练多少次,它总是产生相同的准确率。该准确率是 0.856067
我用这段代码达到了那个准确率-
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print sess.run(accuracy, feed_dict={x: x_test, y_: y_test})
0.856067
问题来了,是不是我尺寸太小了?也许我应该将这些特征分解为 10x8 矩阵?也许是 4x20 矩阵?等等
然后我尝试获取实际测试数据产生 0 或 1 的概率,就像这样-
test_data_actual = genfromtxt('clean-test-actual.csv',delimiter=',') # Actual Test data
x_test_actual = []
for i in test_data_actual:
x_test_actual.append(i)
x_test_actual = np.array(x_test_actual)
ans = sess.run(y, feed_dict={x: x_test_actual})
并打印出概率:
print ans[0:10]
[[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]]
(注意:它有时会产生 [ 0. 1.]
。)
然后我尝试看看应用专家方法是否会产生更好的结果。请看下面的代码。
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 1, 1, 1],
strides=[1, 1, 1, 1], padding='SAME')
(请注意我是如何更改 strides
以避免错误的)。
W_conv1 = weight_variable([1, 80, 1, 1])
b_conv1 = bias_variable([1])
问题又来了。我将张量(vector/matrix,如果你愿意的话)定义为 80x1(所以 1 行有 80 个特征);我在其余代码中继续这样做(请参见下文)。
x_ = tf.reshape(x, [-1,1,80,1])
h_conv1 = tf.nn.relu(conv2d(x_, W_conv1) + b_conv1)
第二个卷积层
h_pool1 = max_pool_2x2(h_conv1)
W_conv2 = weight_variable([1, 80, 1, 1])
b_conv2 = bias_variable([1])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
密集连接层
W_fc1 = weight_variable([80, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 80])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
辍学
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
读数
W_fc2 = weight_variable([1024, 2])
b_fc2 = bias_variable([2])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
在上面你会看到我将输出定义为 2 个可能的答案(也是为了避免错误)。
然后 cross_entropy
和 train_step
.
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.matmul(h_fc1_drop, W_fc2) + b_fc2, y_)
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
开始会话。
sess.run(tf.initialize_all_variables())
"Train" 神经网络。
g = 0
for i in range(len(x_train)):
if i%100 == 0:
train_accuracy = accuracy.eval(session=sess, feed_dict={x: [x_train[g]], y_: [y_train[g]], keep_prob: 1.0})
train_step.run(session=sess, feed_dict={x: [x_train[g]], y_: [y_train[g]], keep_prob: 0.5})
g += 1
print "test accuracy %g"%accuracy.eval(session=sess, feed_dict={
x: x_test, y_: y_test, keep_prob: 1.0})
test accuracy 0.929267
而且,再一次,它总是产生 0.929267
作为输出。
实际数据出现0或1的概率如下:
[[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.96712834 0.03287172]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]]
如您所见,这些概率存在 一些 差异,但通常只是相同的结果。
我知道这不是深度学习问题。这显然是一个训练问题。我知道每次重新初始化变量和重新训练网络时,训练精度应该总是有一些差异,但我只是不知道为什么或哪里出错了。
答案是2折。
dimensions/parameters 有一个问题。另一个问题是特征被放置在错误的位置。
W_conv1 = weight_variable([1, 2, 1, 80])
b_conv1 = bias_variable([80])
注意 weight_variable
中的前两个数字对应于输入的维度。后两个数字对应于特征张量的维度。 bias_variable
始终取 weight_variable
中的最后一个数字。
第二个卷积层
W_conv2 = weight_variable([1, 2, 80, 160])
b_conv2 = bias_variable([160])
这里前两个数字仍然对应于输入的维度。后两个数字对应于特征的数量和由先前 80 个特征产生的加权网络。在这种情况下,我们将加权网络加倍。 80x2=160。 bias_variable
然后取 weight_variable
中的最后一个数字。如果您此时要完成代码,weight_variable
中的最后一个数字将是 1,以防止由于输入张量和输出张量的形状而导致尺寸错误。但是,相反,为了更好的预测,让我们添加第三个卷积层。
第三个卷积层
W_conv3 = weight_variable([1, 2, 160, 1])
b_conv3 = bias_variable([1])
再一次,weight_variable
中的前两个数字采用输入的形状。第三个数字对应于我们在第二个卷积层中建立的加权变量的数量。 weight_variable
中的最后一个数字现在变为 1,因此我们不会 运行 预测输出的任何维度错误。在这种情况下,输出的维度为 1, 2
.
W_fc2 = weight_variable([80, 1024])
b_fc2 = bias_variable([1024])
在这里,神经元的数量是 1024
,这是完全任意的,但是 weight_variable
中的第一个数字需要是我们的特征矩阵的维度需要被其整除的东西。在这种情况下,它可以是任何数字(例如 2, 4, 10, 20, 40, 80
)。再一次,bias_variable
取 weight_variable
中的最后一个数字。
此时,请确保 h_pool3_flat = tf.reshape(h_pool3, [-1, 80])
中的最后一个数字对应于 W_fc2
weight_variable
中的第一个数字。
现在,当您 运行 训练计划时,您会注意到结果各不相同,不会总是猜测全 1 或全 0。
当你想预测概率时,你必须将 x
提供给 softmax
变量-> y_conv=tf.nn.softmax(tf.matmul(h_fc2_drop, W_fc3) + b_fc3)
就像这样-
ans = sess.run(y_conv, feed_dict={x: x_test_actual, keep_prob: 1.0})
您可以更改 keep_prob
变量,但将其保持在 1.0
始终会产生最佳结果。现在,如果你打印出 ans
你会得到类似这样的东西-
[[ 0.90855026 0.09144982]
[ 0.93020624 0.06979381]
[ 0.98385173 0.0161483 ]
[ 0.93948185 0.06051811]
[ 0.90705943 0.09294061]
[ 0.95702559 0.04297439]
[ 0.95543593 0.04456403]
[ 0.95944828 0.0405517 ]
[ 0.99154049 0.00845954]
[ 0.84375167 0.1562483 ]
[ 0.98449463 0.01550537]
[ 0.97772813 0.02227189]
[ 0.98341942 0.01658053]
[ 0.93026513 0.06973486]
[ 0.93376994 0.06623009]
[ 0.98026556 0.01973441]
[ 0.93210858 0.06789146]
注意概率是如何变化的。您的训练现已正常进行。
请看下面写的代码
x = tf.placeholder("float", [None, 80])
W = tf.Variable(tf.zeros([80,2]))
b = tf.Variable(tf.zeros([2]))
y = tf.nn.softmax(tf.matmul(x,W) + b)
y_ = tf.placeholder("float", [None,2])
所以这里我们看到数据中有 80 个特征,只有 2 个可能的输出。我这样设置 cross_entropy
和 train_step
。
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.matmul(x, W) + b, y_)
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
初始化所有变量。
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
然后我将此代码用于 "train" 我的神经网络。
g = 0
for i in range(len(x_train)):
_, w_out, b_out = sess.run([train_step, W, b], feed_dict={x: [x_train[g]], y_: [y_train[g]]})
g += 1
print "...Trained..."
训练网络后,无论我训练多少次,它总是产生相同的准确率。该准确率是 0.856067
我用这段代码达到了那个准确率-
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print sess.run(accuracy, feed_dict={x: x_test, y_: y_test})
0.856067
问题来了,是不是我尺寸太小了?也许我应该将这些特征分解为 10x8 矩阵?也许是 4x20 矩阵?等等
然后我尝试获取实际测试数据产生 0 或 1 的概率,就像这样-
test_data_actual = genfromtxt('clean-test-actual.csv',delimiter=',') # Actual Test data
x_test_actual = []
for i in test_data_actual:
x_test_actual.append(i)
x_test_actual = np.array(x_test_actual)
ans = sess.run(y, feed_dict={x: x_test_actual})
并打印出概率:
print ans[0:10]
[[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]
[ 1. 0.]]
(注意:它有时会产生 [ 0. 1.]
。)
然后我尝试看看应用专家方法是否会产生更好的结果。请看下面的代码。
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 1, 1, 1],
strides=[1, 1, 1, 1], padding='SAME')
(请注意我是如何更改 strides
以避免错误的)。
W_conv1 = weight_variable([1, 80, 1, 1])
b_conv1 = bias_variable([1])
问题又来了。我将张量(vector/matrix,如果你愿意的话)定义为 80x1(所以 1 行有 80 个特征);我在其余代码中继续这样做(请参见下文)。
x_ = tf.reshape(x, [-1,1,80,1])
h_conv1 = tf.nn.relu(conv2d(x_, W_conv1) + b_conv1)
第二个卷积层
h_pool1 = max_pool_2x2(h_conv1)
W_conv2 = weight_variable([1, 80, 1, 1])
b_conv2 = bias_variable([1])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
密集连接层
W_fc1 = weight_variable([80, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 80])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
辍学
keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
读数
W_fc2 = weight_variable([1024, 2])
b_fc2 = bias_variable([2])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
在上面你会看到我将输出定义为 2 个可能的答案(也是为了避免错误)。
然后 cross_entropy
和 train_step
.
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(tf.matmul(h_fc1_drop, W_fc2) + b_fc2, y_)
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
开始会话。
sess.run(tf.initialize_all_variables())
"Train" 神经网络。
g = 0
for i in range(len(x_train)):
if i%100 == 0:
train_accuracy = accuracy.eval(session=sess, feed_dict={x: [x_train[g]], y_: [y_train[g]], keep_prob: 1.0})
train_step.run(session=sess, feed_dict={x: [x_train[g]], y_: [y_train[g]], keep_prob: 0.5})
g += 1
print "test accuracy %g"%accuracy.eval(session=sess, feed_dict={
x: x_test, y_: y_test, keep_prob: 1.0})
test accuracy 0.929267
而且,再一次,它总是产生 0.929267
作为输出。
实际数据出现0或1的概率如下:
[[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.96712834 0.03287172]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]
[ 0.92820859 0.07179145]]
如您所见,这些概率存在 一些 差异,但通常只是相同的结果。
我知道这不是深度学习问题。这显然是一个训练问题。我知道每次重新初始化变量和重新训练网络时,训练精度应该总是有一些差异,但我只是不知道为什么或哪里出错了。
答案是2折。
dimensions/parameters 有一个问题。另一个问题是特征被放置在错误的位置。
W_conv1 = weight_variable([1, 2, 1, 80])
b_conv1 = bias_variable([80])
注意 weight_variable
中的前两个数字对应于输入的维度。后两个数字对应于特征张量的维度。 bias_variable
始终取 weight_variable
中的最后一个数字。
第二个卷积层
W_conv2 = weight_variable([1, 2, 80, 160])
b_conv2 = bias_variable([160])
这里前两个数字仍然对应于输入的维度。后两个数字对应于特征的数量和由先前 80 个特征产生的加权网络。在这种情况下,我们将加权网络加倍。 80x2=160。 bias_variable
然后取 weight_variable
中的最后一个数字。如果您此时要完成代码,weight_variable
中的最后一个数字将是 1,以防止由于输入张量和输出张量的形状而导致尺寸错误。但是,相反,为了更好的预测,让我们添加第三个卷积层。
第三个卷积层
W_conv3 = weight_variable([1, 2, 160, 1])
b_conv3 = bias_variable([1])
再一次,weight_variable
中的前两个数字采用输入的形状。第三个数字对应于我们在第二个卷积层中建立的加权变量的数量。 weight_variable
中的最后一个数字现在变为 1,因此我们不会 运行 预测输出的任何维度错误。在这种情况下,输出的维度为 1, 2
.
W_fc2 = weight_variable([80, 1024])
b_fc2 = bias_variable([1024])
在这里,神经元的数量是 1024
,这是完全任意的,但是 weight_variable
中的第一个数字需要是我们的特征矩阵的维度需要被其整除的东西。在这种情况下,它可以是任何数字(例如 2, 4, 10, 20, 40, 80
)。再一次,bias_variable
取 weight_variable
中的最后一个数字。
此时,请确保 h_pool3_flat = tf.reshape(h_pool3, [-1, 80])
中的最后一个数字对应于 W_fc2
weight_variable
中的第一个数字。
现在,当您 运行 训练计划时,您会注意到结果各不相同,不会总是猜测全 1 或全 0。
当你想预测概率时,你必须将 x
提供给 softmax
变量-> y_conv=tf.nn.softmax(tf.matmul(h_fc2_drop, W_fc3) + b_fc3)
就像这样-
ans = sess.run(y_conv, feed_dict={x: x_test_actual, keep_prob: 1.0})
您可以更改 keep_prob
变量,但将其保持在 1.0
始终会产生最佳结果。现在,如果你打印出 ans
你会得到类似这样的东西-
[[ 0.90855026 0.09144982]
[ 0.93020624 0.06979381]
[ 0.98385173 0.0161483 ]
[ 0.93948185 0.06051811]
[ 0.90705943 0.09294061]
[ 0.95702559 0.04297439]
[ 0.95543593 0.04456403]
[ 0.95944828 0.0405517 ]
[ 0.99154049 0.00845954]
[ 0.84375167 0.1562483 ]
[ 0.98449463 0.01550537]
[ 0.97772813 0.02227189]
[ 0.98341942 0.01658053]
[ 0.93026513 0.06973486]
[ 0.93376994 0.06623009]
[ 0.98026556 0.01973441]
[ 0.93210858 0.06789146]
注意概率是如何变化的。您的训练现已正常进行。