来自tensorflow的AdamOptimizer和GradientDescentOptimizer无法适应简单数据
AdamOptimizer and GradientDescentOptimizer from tensorflow not able to fit simple data
类似问题:
我正在试用 TensorFlow。我生成了可线性分离的简单数据,并尝试对其拟合线性方程。这是代码。
np.random.seed(2010)
n = 300
x_data = np.random.random([n, 2]).tolist()
y_data = [[1., 0.] if v[0]> 0.5 else [0., 1.] for v in x_data]
x = tf.placeholder(tf.float32, [None, 2])
W = tf.Variable(tf.zeros([2, 2]))
b = tf.Variable(tf.zeros([2]))
y = tf.sigmoid(tf.matmul(x , W) + b)
y_ = tf.placeholder(tf.float32, [None, 2])
cross_entropy = -tf.reduce_sum(y_ * tf.log(tf.clip_by_value(y, 1e-9, 1)))
train_step = tf.train.AdamOptimizer(0.01).minimize(cross_entropy)
correct_predict = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_predict, tf.float32))
s = tf.Session()
s.run(tf.initialize_all_variables())
for i in range(10):
s.run(train_step, feed_dict = {x: x_data, y_: y_data})
print(s.run(accuracy, feed_dict = {x: x_data, y_: y_data}))
print(s.run(accuracy, feed_dict = {x: x_data, y_: y_data}), end=",")
我得到以下输出:
0.536667, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46
在第一次迭代之后,它在 0.46
处被击中。
剧情如下:
然后我更改了代码以使用梯度下降:
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
现在我得到以下值:0.54、0.54、0.63、0.70、0.75、0.8、0.84、0.89、0.92、0.94、0.94
剧情如下:
我的问题:
1) 为什么 AdamOptimizer 会失败?
2) 如果问题出在学习率或其他我需要调整的参数上,我通常如何调试它们?
3) 我 运行 梯度下降 50 次迭代(我 运行 上面的 10 次)并每 5 次迭代打印一次精度,这是输出:
0.54, 0.8, 0.95, 0.96, 0.92, 0.89, 0.87, 0.84, 0.81, 0.79, 0.77.
很明显它开始发散,看起来问题出在固定的学习率上(它在一个点后超调)。我说得对吗?
4) 在这个玩具示例中,可以做些什么来获得更好的配合。理想情况下,它应该具有 1.0 的精度,因为数据是线性可分的。
[编辑]
应@Yaroslav 的要求,这里是用于绘图的代码
xx = [v[0] for v in x_data]
yy = [v[1] for v in x_data]
x_min, x_max = min(xx) - 0.5, max(xx) + 0.5
y_min, y_max = min(yy) - 0.5, max(yy) + 0.5
xxx, yyy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))
pts = np.c_[xxx.ravel(), yyy.ravel()].tolist()
# ---> Important
z = s.run(tf.argmax(y, 1), feed_dict = {x: pts})
z = np.array(z).reshape(xxx.shape)
plt.pcolormesh(xxx, yyy, z)
plt.scatter(xx, yy, c=['r' if v[0] == 1 else 'b' for v in y_data], edgecolor='k', s=50)
plt.show()
TLDR;你的损失是错误的。在不降低准确性的情况下损失变为零。
问题是你的概率没有标准化。如果你看看你的损失,它正在下降,但是 y[:0]
和 y[:1]
的概率都将变为 1,所以 argmax 是没有意义的。
传统的解决方案是只使用 1 个自由度而不是 2 个,所以第一个 class 的概率是 sigmoid(y)
,第二个 class 的概率是 1-sigmoid(y)
所以交叉熵类似于 -y[0]log(sigmoid(y0)) - y[1]log(1-sigmoid(y0))
或者您可以更改您的代码,使用 tf.nn.softmax
而不是 tf.sigmoid
。这除以概率之和,因此优化器无法通过同时将两个概率都驱动为 1 来减少损失。
以下达到 0.99666673
准确度。
tf.reset_default_graph()
np.random.seed(2010)
n = 300
x_data = np.random.random([n, 2]).tolist()
y_data = [[1., 0.] if v[0]> 0.5 else [0., 1.] for v in x_data]
x = tf.placeholder(tf.float32, [None, 2])
W = tf.Variable(tf.zeros([2, 2]))
b = tf.Variable(tf.zeros([2]))
y = tf.nn.softmax(tf.matmul(x , W) + b)
y_ = tf.placeholder(tf.float32, [None, 2])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
regularizer = tf.reduce_sum(tf.square(y))
train_step = tf.train.AdamOptimizer(1.0).minimize(cross_entropy+regularizer)
correct_predict = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_predict, tf.float32))
s = tf.Session()
s.run(tf.initialize_all_variables())
for i in range(30):
s.run(train_step, feed_dict = {x: x_data, y_: y_data})
cost1,cost2=s.run([cross_entropy,accuracy], feed_dict = {x: x_data, y_: y_data})
print(cost1, cost2)
PS:你能分享一下你用来制作上面的图的代码吗?
类似问题:
我正在试用 TensorFlow。我生成了可线性分离的简单数据,并尝试对其拟合线性方程。这是代码。
np.random.seed(2010)
n = 300
x_data = np.random.random([n, 2]).tolist()
y_data = [[1., 0.] if v[0]> 0.5 else [0., 1.] for v in x_data]
x = tf.placeholder(tf.float32, [None, 2])
W = tf.Variable(tf.zeros([2, 2]))
b = tf.Variable(tf.zeros([2]))
y = tf.sigmoid(tf.matmul(x , W) + b)
y_ = tf.placeholder(tf.float32, [None, 2])
cross_entropy = -tf.reduce_sum(y_ * tf.log(tf.clip_by_value(y, 1e-9, 1)))
train_step = tf.train.AdamOptimizer(0.01).minimize(cross_entropy)
correct_predict = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_predict, tf.float32))
s = tf.Session()
s.run(tf.initialize_all_variables())
for i in range(10):
s.run(train_step, feed_dict = {x: x_data, y_: y_data})
print(s.run(accuracy, feed_dict = {x: x_data, y_: y_data}))
print(s.run(accuracy, feed_dict = {x: x_data, y_: y_data}), end=",")
我得到以下输出:
0.536667, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46, 0.46
在第一次迭代之后,它在 0.46
处被击中。
剧情如下:
然后我更改了代码以使用梯度下降:
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
现在我得到以下值:0.54、0.54、0.63、0.70、0.75、0.8、0.84、0.89、0.92、0.94、0.94
剧情如下:
我的问题:
1) 为什么 AdamOptimizer 会失败?
2) 如果问题出在学习率或其他我需要调整的参数上,我通常如何调试它们?
3) 我 运行 梯度下降 50 次迭代(我 运行 上面的 10 次)并每 5 次迭代打印一次精度,这是输出:
0.54, 0.8, 0.95, 0.96, 0.92, 0.89, 0.87, 0.84, 0.81, 0.79, 0.77.
很明显它开始发散,看起来问题出在固定的学习率上(它在一个点后超调)。我说得对吗?
4) 在这个玩具示例中,可以做些什么来获得更好的配合。理想情况下,它应该具有 1.0 的精度,因为数据是线性可分的。
[编辑]
应@Yaroslav 的要求,这里是用于绘图的代码
xx = [v[0] for v in x_data]
yy = [v[1] for v in x_data]
x_min, x_max = min(xx) - 0.5, max(xx) + 0.5
y_min, y_max = min(yy) - 0.5, max(yy) + 0.5
xxx, yyy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))
pts = np.c_[xxx.ravel(), yyy.ravel()].tolist()
# ---> Important
z = s.run(tf.argmax(y, 1), feed_dict = {x: pts})
z = np.array(z).reshape(xxx.shape)
plt.pcolormesh(xxx, yyy, z)
plt.scatter(xx, yy, c=['r' if v[0] == 1 else 'b' for v in y_data], edgecolor='k', s=50)
plt.show()
TLDR;你的损失是错误的。在不降低准确性的情况下损失变为零。
问题是你的概率没有标准化。如果你看看你的损失,它正在下降,但是 y[:0]
和 y[:1]
的概率都将变为 1,所以 argmax 是没有意义的。
传统的解决方案是只使用 1 个自由度而不是 2 个,所以第一个 class 的概率是 sigmoid(y)
,第二个 class 的概率是 1-sigmoid(y)
所以交叉熵类似于 -y[0]log(sigmoid(y0)) - y[1]log(1-sigmoid(y0))
或者您可以更改您的代码,使用 tf.nn.softmax
而不是 tf.sigmoid
。这除以概率之和,因此优化器无法通过同时将两个概率都驱动为 1 来减少损失。
以下达到 0.99666673
准确度。
tf.reset_default_graph()
np.random.seed(2010)
n = 300
x_data = np.random.random([n, 2]).tolist()
y_data = [[1., 0.] if v[0]> 0.5 else [0., 1.] for v in x_data]
x = tf.placeholder(tf.float32, [None, 2])
W = tf.Variable(tf.zeros([2, 2]))
b = tf.Variable(tf.zeros([2]))
y = tf.nn.softmax(tf.matmul(x , W) + b)
y_ = tf.placeholder(tf.float32, [None, 2])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
regularizer = tf.reduce_sum(tf.square(y))
train_step = tf.train.AdamOptimizer(1.0).minimize(cross_entropy+regularizer)
correct_predict = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_predict, tf.float32))
s = tf.Session()
s.run(tf.initialize_all_variables())
for i in range(30):
s.run(train_step, feed_dict = {x: x_data, y_: y_data})
cost1,cost2=s.run([cross_entropy,accuracy], feed_dict = {x: x_data, y_: y_data})
print(cost1, cost2)
PS:你能分享一下你用来制作上面的图的代码吗?