У чому різниця між np.mean та tf.reduce_mean?


90

У підручнику для початківців 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]це має сенс, оскільки середнє значення [1, 2]і [1, 2]є [1.5, 1.5], але що відбувається tf.reduce_mean(x, 1)?



Одна важлива відмінність для тих, хто новачок у tensorflow: tf.reduce_meanбагатопотоковість, як правило, обчислюється на вашому графічному процесорі, тоді np.meanяк обчислюється на одному процесорі. Крім того, tfпризначений для обробки партії даних, тоді як npдіє на одному екземплярі даних.
drevicko

Відповіді:


110

Функціональність 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)

Ми могли б збільшити середню по 1в , numpyяк ви б , природно, але для того , щоб зробити це в tensorflow, вам необхідно виконати , що Session, без використання Sessionви не можете зробити це. Іншими словами, коли ви обчислюєте tfMean = tf.reduce_mean(c), tensorflow тоді цього не обчислює. Він лише обчислює, що в a Session. Але numpy обчислює це миттєво, коли ви пишете np.mean().

Сподіваюся, це має сенс.


21
але що зменшити частину значить тут?
rsht

20
@Roman - це термін із функціонального програмування. Ви можете прочитати про це тут: python-course.eu/lambda.php
Даніяр

1
@rsht ЗНИЖИТИ = зменшити числа, підсумувавши їх до 1 значення. MEAN = усереднення цієї суми.
Мегна

1
@rsht Уявіть, що у вас N елементів, і ви хочете обчислити середнє значення (M) цих N чисел. Спосіб побачити цю проблему полягає в тому, що ми маємо вектор розміру (1, N), а над віссю = 0, ми зменшуємо елементи (тут ми маємо N елементів). Скорочення (або агрегування) поставляється з функціоналом, і в нашому прикладі функція є середньою функцією.
Alift

22

Ключовим тут є слово зменшення, концепція функціонального програмування, яка дозволяє методу reduce_mean у TensorFlow зберігати середнє значення результатів обчислень з партії входів.

Якщо ви не знайомі з функціональним програмуванням, це може здатися таємничим. Тож спочатку давайте подивимося, що робить зменшення. Якщо вам дали такий список, як [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. зменшити зберігає результат 3. Примітка - це єдиний крок, коли 2 цифри зчитуються зі списку
  2. Крок 2: Прочитайте наступну цифру зі списку - 5. Оцініть лямбда-значення 5, 3 (3 є результатом кроку 1, що зменшує кількість збережених). зменшити зберігає результат 8.
  3. Крок 3: Прочитайте наступну цифру зі списку - 4. Оцініть лямбду 8,4 (8 - результат кроку 2, який зменшує кількість збережених). зменшити зберігає результат 12
  4. Крок 4: Прочитайте наступну цифру зі списку - їх немає, тому поверніть збережений результат 12.

Детальніше читайте тут Функціональне програмування на Python

Щоб побачити, як це стосується TensorFlow, подивіться на наступний блок коду, який визначає простий графік, який приймає float і обчислює середнє значення. Вхідні дані для графіка, однак, не є одним плаваючим словом, а масивом плаваючих знаків. Redu_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))

3

У новій документації зазначено, що 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.


1
Я вважаю, що 0 стосується стовпця, а не 2
hfz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.