В чем разница между np.mean и tf.reduce_mean?

92

В руководстве для начинающих MNIST есть утверждение

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

tf.castв основном меняет тип тензора объекта, но в чем разница между tf.reduce_meanи np.mean?

Вот документ tf.reduce_mean:

reduce_mean(input_tensor, reduction_indices=None, keep_dims=False, name=None)

input_tensor: Уменьшаемый тензор. Должен иметь числовой тип.

reduction_indices: Размеры для уменьшения. Если None(по умолчанию), уменьшает все размеры.

# 'x' is [[1., 1. ]]
#         [2., 2.]]
tf.reduce_mean(x) ==> 1.5
tf.reduce_mean(x, 0) ==> [1.5, 1.5]
tf.reduce_mean(x, 1) ==> [1.,  2.]

Для одномерного вектора это выглядит так np.mean == tf.reduce_mean, но я не понимаю, что в нем происходит tf.reduce_mean(x, 1) ==> [1., 2.]. tf.reduce_mean(x, 0) ==> [1.5, 1.5]вроде имеет смысл, так как mean of [1, 2]and [1, 2]is [1.5, 1.5], но что с этим происходит tf.reduce_mean(x, 1)?

O.rka
источник
они дают разные результаты для целочисленных значений из-за деления в питоне
Сальвадор Дали
Одно важное отличие для новичков в tenorflow: tf.reduce_meanмногопоточность, обычно вычисляется на вашем графическом процессоре, тогда np.meanкак вычисляется на одном процессоре. Кроме того, tfон предназначен для обработки пакета данных, в то время как npработает с одним экземпляром данных.
drevicko

Ответы:

114

Функциональные возможности numpy.meanи tensorflow.reduce_meanтакие же. Они делают то же самое. Из документации для numpy и tensorflow вы можете это увидеть. Давайте посмотрим на пример,

c = np.array([[3.,4], [5.,6], [6.,7]])
print(np.mean(c,1))

Mean = tf.reduce_mean(c,1)
with tf.Session() as sess:
    result = sess.run(Mean)
    print(result)

Вывод

[ 3.5  5.5  6.5]
[ 3.5  5.5  6.5]

Здесь вы можете видеть, что когда axis(numpy) или reduction_indices(tensorflow) равно 1, он вычисляет среднее по (3,4), (5,6) и (6,7), поэтому 1определяет, по какой оси вычисляется среднее значение. Когда он равен 0, вычисляется среднее значение по (3,5,6) и (4,6,7) и так далее. Надеюсь, вы уловили идею.

В чем разница между ними?

Вы можете вычислить операцию numpy где угодно на Python. Но чтобы выполнить операцию тензорного потока, она должна выполняться внутри тензорного потока Session. Вы можете прочитать об этом здесь . Поэтому, когда вам нужно выполнить какие-либо вычисления для вашего графа тензорного потока (или структуры, если хотите), это должно быть сделано внутри тензорного потока Session.

Давайте посмотрим на другой пример.

npMean = np.mean(c)
print(npMean+1)

tfMean = tf.reduce_mean(c)
Add = tfMean + 1
with tf.Session() as sess:
    result = sess.run(Add)
    print(result)

Мы могли бы увеличить среднее значение на 1in, numpyкак это было бы естественно, но для того, чтобы сделать это в тензорном потоке, вам нужно выполнить это внутри Session, без использования Sessionвы не можете этого сделать. Другими словами, когда вы вычисляете tfMean = tf.reduce_mean(c), тензорный поток не вычисляет его. Он только вычисляет это в файле Session. Но numpy вычисляет это мгновенно, когда вы пишете np.mean().

Надеюсь, это имеет смысл.

Шубхаши
источник
23
но что уменьшить часть значит здесь?
rsht
22
@Roman это термин из функционального программирования. вы можете прочитать об этом здесь: python-course.eu/lambda.php
Данияр
1
@rsht REDUCE = уменьшение чисел путем их суммирования до 1 значения. MEAN = усреднение этой суммы.
Meghna Natraj
1
@rsht Представьте, что у вас есть N элементов, и вы хотите вычислить среднее значение (M) этих N чисел. Способ увидеть эту проблему состоит в том, что у нас есть вектор размера (1, N) и по оси = 0 мы уменьшаем элементы (здесь у нас есть N элементов). Редукция (или агрегация) имеет функциональные возможности, и в нашем примере функция - это функция среднего.
alift
23

Ключевым моментом здесь является слово «сокращение», концепция из функционального программирования, которая позволяет reduce_meanв TensorFlow сохранять текущее среднее результатов вычислений из пакета входных данных.

Если вы не знакомы с функциональным программированием, это может показаться загадочным. Итак, сначала давайте посмотрим, что reduceделает. Если вам дали список вроде [1,2,5,4] и попросили вычислить среднее значение, это легко - просто передайте весь массив в, np.meanи вы получите среднее значение. Однако что, если бы вам пришлось вычислить среднее значение потока чисел? В этом случае вам нужно сначала собрать массив, прочитав из потока, а затем вызвать np.meanполученный массив - вам придется написать еще код.

Альтернативой является использование парадигмы сокращения. В качестве примера рассмотрим, как мы можем использовать сократить в питона , чтобы вычислить сумму чисел: reduce(lambda x,y: x+y, [1,2,5,4]).

Это работает так:

  1. Шаг 1: Считайте из списка 2 цифры - 1,2. Оцените лямбда 1,2. reduce сохраняет результат 3. Примечание - это единственный шаг, на котором из списка считываются 2 цифры.
  2. Шаг 2: Считайте следующую цифру из списка - 5. Вычислите лямбда 5, 3 (3 - результат шага 1, который уменьшает сохраненное значение). reduce сохраняет результат 8.
  3. Шаг 3: Считайте следующую цифру из списка - 4. Вычислите лямбда 8,4 (8 - результат шага 2, который уменьшает сохраненное значение). уменьшить сохраняет результат 12
  4. Шаг 4: Прочтите следующую цифру из списка - ее нет, поэтому верните сохраненный результат 12.

Подробнее здесь Функциональное программирование на Python

Чтобы увидеть, как это применимо к TensorFlow, взгляните на следующий блок кода, который определяет простой график, который принимает значение с плавающей запятой и вычисляет среднее значение. Однако входными данными для графа является не одно число с плавающей запятой, а массив чисел с плавающей запятой. reduce_meanВычисляет среднее значение по всем этим поплавков.

import tensorflow as tf


inp = tf.placeholder(tf.float32)
mean = tf.reduce_mean(inp)

x = [1,2,3,4,5]

with tf.Session() as sess:
    print(mean.eval(feed_dict={inp : x}))

Этот шаблон пригодится при вычислении значений по пакетам изображений. Посмотрите на пример Deep MNIST, где вы видите такой код:

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
Нихил Георгий
источник
4

В новой документации указано, что tf.reduce_mean()дает те же результаты, что и np.mean:

Эквивалентен np.mean

Также он имеет абсолютно те же параметры, что и np.mean . Но вот важное отличие: они дают одинаковые результаты только для значений с плавающей запятой :

import tensorflow as tf
import numpy as np
from random import randint

num_dims = 10
rand_dim = randint(0, num_dims - 1)
c = np.random.randint(50, size=tuple([5] * num_dims)).astype(float)

with tf.Session() as sess:
    r1 = sess.run(tf.reduce_mean(c, rand_dim))
    r2 = np.mean(c, rand_dim)
    is_equal = np.array_equal(r1, r2)
    print is_equal
    if not is_equal:
        print r1
        print r2

Если вы удалите преобразование типов, вы увидите другие результаты


В дополнение к этому, многие другие tf.reduce_функции , такие как reduce_all, reduce_any, reduce_min,reduce_max , reduce_prodпроизводят одни и те же значения, что и там Numpy аналогов. Очевидно, поскольку это операции, они могут выполняться только изнутри сеанса.

Сальвадор Дали
источник
было бы полезно, если бы вы объяснили, в чем разница, помимо примера. После запуска вашего примера у меня сложилось впечатление, tf.reduce_meanчто результат dtypeсоответствует вводу dtype. Результат np.mean()всегда является плавающим. Это правильно?
craq
-1

1обычно относится к строкам и 2обычно относится к столбцам. Уменьшение индекса «сверх» 1означает уменьшение по строкам.

[1., 2.]просто [ <row 1 mean> , <row 2 mean> ].

Это соглашение о нумерации индексов типично для программного обеспечения статистики, особенно R.

Shadowtalker
источник
1
Я считаю, что 0 относится к столбцу, а не 2
hfz