我正在尝试使用Tensorflow创建一个程序,该程序可以将一个点分类为1
或0
。我试图在这个图的中心周围创建一个椭圆形状,蓝色点所在的位置如下:
椭圆内的所有内容都应被分类为1
,其余的应为0
。在上面的图表中,蓝色点是1
,红色x是0
。
然而,每次我尝试分类一个点时,它总是选择1
,即使这是一个我训练过的点,标记为0
。
我的问题很简单:为什么猜测总是1
,我做错了什么,或者应该做些什么来解决这个问题?这是我第一次尝试没有教程的机器学习问题,所以我对这些东西知之甚少。
我很感激你能提供的任何帮助,谢谢!
这是我的代码:
#!/usr/bin/env python3import tensorflow as tfimport numpyimport matplotlib.pyplot as plttraining_in = numpy.array([[0, 0], [1, 1], [2, 0], [-2, 0], [-1, -1], [-1, 1], [-1.5, 1], [3, 3], [3, 0], [-3, 0], [0, -3], [-1, 3], [1, -2], [-2, -1.5]])training_out = numpy.array([1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0])def transform_data(x): return [x[0], x[1], x[0]**2, x[1]**2, x[0]*x[1]]new_training_in = numpy.apply_along_axis(transform_data, 1, training_in)feature_count = new_training_in.shape[1]x = tf.placeholder(tf.float32, [None, feature_count])y = tf.placeholder(tf.float32, [None, 1])W = tf.Variable(tf.zeros([feature_count, 1]))b = tf.Variable(tf.zeros([1]))guess = tf.nn.softmax(tf.matmul(x, W) + b)cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(tf.matmul(x, W) + b, y))opti = tf.train.GradientDescentOptimizer(0.01).minimize(cost)init = tf.initialize_all_variables()sess = tf.Session()sess.run(init)for i in range(1000): for (item_x, item_y) in zip(new_training_in, training_out): sess.run(opti, feed_dict={ x: [item_x], y: [[item_y]]})print(sess.run(W))print(sess.run(b))plt.plot(training_in[:6, 0], training_in[:6, 1], 'bo')plt.plot(training_in[6:, 0], training_in[6:, 1], 'rx')results = sess.run(guess, feed_dict={ x: new_training_in })for i in range(training_in.shape[0]): xx = [training_in[i:,0]] yy = [training_in[i:,1]] res = results[i] # this always prints `[ 1.]` print(res) # uncomment these lines to see the guesses # if res[0] == 0: # plt.plot(xx, yy, 'c+') # else: # plt.plot(xx, yy, 'g+')plt.show()
回答:
当你使用softmax_cross_entropy_with_logits时会出现问题。在你的具体情况下,logits
和labels
的形状应该为[batch_size, number_of_labels=2]
。
请注意,你的张量logits=tf.matmul(x, W) + b
和labels=y
的形状为[batch_size, 1]
,因此Tensorflow假设number_of_labels=1
。这就是为什么你的猜测总是相同的。
A) 你可以通过将training_out
编码为一个热编码向量来解决这个问题。我推荐使用np.eye()
来实现这一点:
training_out = [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]training_out = numpy.eye(2)[training_out]
然后,你需要进行以下更改:
y = tf.placeholder(tf.float32, [None, 2])W = tf.Variable(tf.zeros([feature_count, 2]))b = tf.Variable(tf.zeros([2]))...for i in range(1000): for (item_x, item_y) in zip(new_training_in, training_out): sess.run(opti, feed_dict={x: [item_x], y: [item_y]})...results = sess.run(guess, feed_dict={x: new_training_in})[:,1]
B) 或者,你可以使用sparse_softmax_cross_entropy_with_logits,它允许labels
的形状为[batch_size]
。我已经调整了你的代码,使其以这种方式工作:
import tensorflow as tfimport numpyimport matplotlib.pyplot as plttraining_in = numpy.array( [[0, 0], [1, 1], [2, 0], [-2, 0], [-1, -1], [-1, 1], [-1.5, 1], [3, 3], [3, 0], [-3, 0], [0, -3], [-1, 3], [1, -2], [-2, -1.5]])training_out = numpy.array([1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0])def transform_data(x): return [x[0], x[1], x[0] ** 2, x[1] ** 2, x[0] * x[1]]new_training_in = numpy.apply_along_axis(transform_data, 1, training_in)feature_count = new_training_in.shape[1]x = tf.placeholder(tf.float32, [None, feature_count])y = tf.placeholder(tf.int32, [None])W = tf.Variable(tf.zeros([feature_count, 2]))b = tf.Variable(tf.zeros([2]))guess = tf.nn.softmax(tf.matmul(x, W) + b)cost = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(tf.matmul(x, W) + b, y))opti = tf.train.GradientDescentOptimizer(0.01).minimize(cost)init = tf.initialize_all_variables()sess = tf.Session()sess.run(init)for i in range(1000): for (item_x, item_y) in zip(new_training_in, training_out): sess.run(opti, feed_dict={x: [item_x], y: [item_y]})print(sess.run(W))print(sess.run(b))plt.plot(training_in[:6, 0], training_in[:6, 1], 'bo')plt.plot(training_in[6:, 0], training_in[6:, 1], 'rx')results = sess.run(guess, feed_dict={x: new_training_in})for i in range(training_in.shape[0]): xx = [training_in[i:, 0]] yy = [training_in[i:, 1]] res = results[i] # this always prints `[ 1.]` print(res) # uncomment these lines to see the guesses if res[0] == 0: plt.plot(xx, yy, 'c+') else: plt.plot(xx, yy, 'g+')plt.show()