AdamOptimizer и GradientDescentOptimizer из тензорного потока не могут вместить простые данные

Подобный вопрос: здесь

Я пробую 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()

1 ответ

Решение

TLDR; ваша потеря неверна. Потери сводятся к нулю без снижения точности.

Проблема в том, что ваши вероятности не нормированы. Если вы посмотрите на свою потерю, она идет вниз, но вероятности для обоих y[:0] а также y[:1] собираются в 1, поэтому argmax не имеет смысла.

Традиционное решение состоит в том, чтобы использовать только 1 степень свободы вместо 2, поэтому ваша вероятность для первого класса sigmoid(y)и для второго класса 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: вы можете поделиться кодом, который вы использовали для создания графиков выше?

Другие вопросы по тегам