Tensor Flow MNIST Оценка прогнозов

Я работаю над этим учебник, и я обнаружил в этом следующем коде: при оценке прогнозов он проверяет точность, которая запускает правильную переменную, которая, в свою очередь, выполняет прогноз, который повторно инициализирует веса с помощью случайных чисел и реконструирует модель NN . Как это правильно? Что мне не хватает?

def neural_network_model(data):
    hidden_1_layer = {'weights':tf.Variable(tf.random_normal([784, n_nodes_hl1])),
                      'biases':tf.Variable(tf.random_normal([n_nodes_hl1]))}

    hidden_2_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])),
                      'biases':tf.Variable(tf.random_normal([n_nodes_hl2]))}

    hidden_3_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl2, n_nodes_hl3])),
                      'biases':tf.Variable(tf.random_normal([n_nodes_hl3]))}

    output_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl3, n_classes])),
                    'biases':tf.Variable(tf.random_normal([n_classes])),}


    l1 = tf.add(tf.matmul(data,hidden_1_layer['weights']), hidden_1_layer['biases'])
    l1 = tf.nn.relu(l1)

    l2 = tf.add(tf.matmul(l1,hidden_2_layer['weights']), hidden_2_layer['biases'])
    l2 = tf.nn.relu(l2)

    l3 = tf.add(tf.matmul(l2,hidden_3_layer['weights']), hidden_3_layer['biases'])
    l3 = tf.nn.relu(l3)

    output = tf.matmul(l3,output_layer['weights']) + output_layer['biases']

    return output

def train_neural_network(x):
    prediction = neural_network_model(x)
    cost = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(prediction,y) )
    optimizer = tf.train.AdamOptimizer().minimize(cost)

    hm_epochs = 10
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())

        for epoch in range(hm_epochs):
            epoch_loss = 0
            for _ in range(int(mnist.train.num_examples/batch_size)):
                epoch_x, epoch_y = mnist.train.next_batch(batch_size)
                _, c = sess.run([optimizer, cost], feed_dict={x: epoch_x, y: epoch_y})
                epoch_loss += c
            print('Epoch', epoch, 'completed out of',hm_epochs,'loss:',epoch_loss)

        correct = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1))

        accuracy = tf.reduce_mean(tf.cast(correct, 'float'))
        print('Accuracy:',accuracy.eval({x:mnist.test.images, y:mnist.test.labels}))

train_neural_network(x)

person Ahmed Mohamed    schedule 30.01.2017    source источник


Ответы (1)


Вы почти все поняли. Тензор accuracy косвенно зависит от тензора prediction, который зависит от тензора x. В вашем фрагменте кода вы не включили то, что на самом деле x; однако из связанного учебника:

x = tf.placeholder('float', [None, 784])
y = tf.placeholder('float')

Итак, x - это заполнитель, то есть тензор, который получает свое значение непосредственно от пользователя. Это не совсем ясно из последней строки

train_neural_network(x)

что он на самом деле не вызывает функцию преобразования train_neural_network(x), которая принимает x и обрабатывает его на лету, как вы ожидаете от обычной функции; скорее, функция использует ссылку на ранее определенные переменные-заполнители - на самом деле фиктивные - для определения графа вычислений, который затем выполняется непосредственно в сеансе. Однако график строится только один раз с использованием neural_network_model(x), а затем запрашивается для заданного количества эпох.

Вы пропустили следующее:

_, c = sess.run([optimizer, cost], feed_dict={x: epoch_x, y: epoch_y})

Это запрашивает результат операции optimizer и тензор cost, учитывая, что входными значениями являются epoch_x для x и epoch_y для y, протягивая данные через все определенные вычислительные узлы, полностью "вниз" до x. Для получения cost также требуется y. Оба предоставляются вызывающим абонентом. AdamOptimizer будет обновлять все обучаемые переменные как часть своего выполнения, изменяя веса сети.

После этого,

accuracy.eval({x: mnist.test.images, y: mnist.test.labels})

или, что то же самое

sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})

затем выдает еще одну оценку того же графика - без его изменения - но на этот раз с использованием входных данных mnist.test.images для x и mnist.test.labels для y. Это работает, потому что prediction сам зависит от x, который заменяется пользовательскими значениями при каждом вызове sess.run(...).

Вот как выглядит график в TensorBoard. Трудно сказать, но два узла-заполнителя находятся внизу слева, рядом с оранжевым узлом под названием «Переменная» и в центре справа под зеленым «Slice_1».

Вот как выглядит соответствующая часть графа сети; Я экспортировал это с помощью TensorBoard. Это немного сложно получить, поскольку узлы не помечены вручную (за исключением пары, которую я пометил сам), но здесь есть шесть важных моментов. Заполнители желтые: в правом нижнем углу вы найдете x, а y в центре слева. Зеленые - это промежуточные значения, которые имеют для нас смысл: слева - тензор prediction, справа - тензор, называемый correct. Синие части - это конечные точки графика: в верхнем левом углу есть тензор cost, а в правом верхнем углу вы найдете accuracy. По сути, данные идут снизу вверх.

Сетевой график

Итак, когда вы говорите «оценить prediction данный x», «оценить accuracy данный x и y» или «оптимизировать мою сеть с учетом x и y», вы на самом деле просто указываете значения на желтых концах и наблюдаете результат на зеленых или синих. .

person sunside    schedule 30.01.2017
comment
Я думаю, что не понял, вы сказали, что еще одна оценка того же графика, как, не меняя его, в то время как прогноз снова вызывает модель нейронной сети, которая должна вызываться один раз, когда она восстанавливает график, так как я знаю строку расчета, которая должна только называть, это то, что ты имеешь в виду? - person Ahmed Mohamed; 30.01.2017
comment
Я знаю, что он меняет X при вводе, но он также меняет веса скрытых слоев и снова рандомизирует их, это то, что он действительно сделал? - person Ahmed Mohamed; 31.01.2017
comment
Подумайте об этом так: сетевой граф определяется neural_network_model(x). Эта функция возвращает ссылку на тензор prediction, который так или иначе зависит от x; он ничего не делает, кроме определения того, как выглядит сеть. Как только вы оцениваете тензор с помощью sess.run() (или .evaluate), этот график создается, фиксируется на CPU или GPU. После этого, по сути, единственный, кто что-то меняет, - это Оптимизатор, в данном случае AdamOptimizer. Все остальное - это просто получение результатов того, что сеть производит если вы скармливаете ей x и y. Это поможет? - person sunside; 31.01.2017
comment
Веса и смещения скрытого слоя определены в руководстве через tf.Variable. Переменные - в отличие от заполнителей и констант - неявно помечаются как обучаемые, то есть они будут автоматически корректироваться при вызове .minimize() операции оптимизатора. - person sunside; 31.01.2017
comment
Хорошо, но когда он снова вызывает строительную сеть, у которой есть линии скрытых слоев, это не будет их снова рандомизировать? Вы имеете в виду только оптимизатор, который может изменять их после построения графика, независимо от того, вызывает он эту функцию или нет? - person Ahmed Mohamed; 31.01.2017
comment
Он больше не звонит. :) Это символично, всякий раз, когда вы меняете x, значение prediction изменяется (когда вы запускаете sess.run(prediction, feed_dict={x: ...}) на нем). На самом деле это черный ящик, и вам были даны местоположения входа (x) и выхода (prediction). sess.run() просто управляет механизмами, которые перемещают все, что вы укажете x, по сети, так что prediction может стать тем, чем он определен. - person sunside; 31.01.2017