Python Numpy | Разница между np.dot и np.multiply с np.sum
Я пробовал следующий код, но не нашел разницы между np.dot и np.multiply с np.sum
Вот код np.dot
logprobs = np.dot(Y, (np.log(A2)).T) + np.dot((1.0-Y),(np.log(1 - A2)).T)
print(logprobs.shape)
print(logprobs)
cost = (-1/m) * logprobs
print(cost.shape)
print(type(cost))
print(cost)
Его выход
(1, 1)
[[-2.07917628]]
(1, 1)
<class 'numpy.ndarray'>
[[ 0.693058761039 ]]
Вот код для np.multiply с np.sum
logprobs = np.sum(np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2)))
print(logprobs.shape)
print(logprobs)
cost = - logprobs / m
print(cost.shape)
print(type(cost))
print(cost)
Его выход
()
-2.07917628312
()
<class 'numpy.float64'>
0.693058761039
Я не могу понять разницу типов и форм, тогда как значение результата одинаково в обоих случаях
Даже в случае сжимания прежнего значения стоимости кода становятся такими же, как и позже, но тип остается таким же
cost = np.squeeze(cost)
print(type(cost))
print(cost)
выход
<class 'numpy.ndarray'>
0.6930587610394646
Ответы
Ответ 1
То, что вы делаете, это вычисление двоичной кросс-энтропийной потери, которая измеряет, насколько плохи прогнозы (здесь: A2
) модели по сравнению с истинными результатами (здесь: Y
).
Вот воспроизводимый пример для вашего случая, который должен объяснить, почему вы получаете скаляр во втором случае, используя np.sum
In [88]: Y = np.array([[1, 0, 1, 1, 0, 1, 0, 0]])
In [89]: A2 = np.array([[0.8, 0.2, 0.95, 0.92, 0.01, 0.93, 0.1, 0.02]])
In [90]: logprobs = np.dot(Y, (np.log(A2)).T) + np.dot((1.0-Y),(np.log(1 - A2)).T)
# 'np.dot' returns 2D array since its arguments are 2D arrays
In [91]: logprobs
Out[91]: array([[-0.78914626]])
In [92]: cost = (-1/m) * logprobs
In [93]: cost
Out[93]: array([[ 0.09864328]])
In [94]: logprobs = np.sum(np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2)))
# np.sum returns scalar since it sums everything in the 2D array
In [95]: logprobs
Out[95]: -0.78914625761870361
Обратите внимание, что np.dot
суммирует только те внутренние размеры, которые соответствуют здесь (1x8) and (8x1)
. Итак, 8
будет отсутствовать во время умножения скалярного произведения или матрицы, что даст результат в виде (1x1)
который является просто скаляром, но возвращается как двумерный массив формы (1,1)
.
Также, самое главное, обратите внимание, что здесь np.dot
точно такой же, как и np.matmul
поскольку входные данные являются двумерными массивами (то есть матрицами).
In [107]: logprobs = np.matmul(Y, (np.log(A2)).T) + np.matmul((1.0-Y),(np.log(1 - A2)).T)
In [108]: logprobs
Out[108]: array([[-0.78914626]])
In [109]: logprobs.shape
Out[109]: (1, 1)
Вернуть результат как скалярное значение
np.dot
или np.matmul
возвращает любую форму результирующего массива на основе входных массивов. Даже с аргументом out=
невозможно вернуть скаляр, если входные данные являются двумерными массивами. Однако мы можем использовать np.asscalar()
для результата, чтобы преобразовать его в скаляр, если результирующий массив имеет форму (1,1)
(или, в более общем случае, скалярное значение, заключенное в массив nD)
In [123]: np.asscalar(logprobs)
Out[123]: -0.7891462576187036
In [124]: type(np.asscalar(logprobs))
Out[124]: float
ndarray от размера 1 до скалярного значения
In [127]: np.asscalar(np.array([[[23.2]]]))
Out[127]: 23.2
In [128]: np.asscalar(np.array([[[[23.2]]]]))
Out[128]: 23.2
Ответ 2
np.dot
является точечным произведением двух матриц.
|A B| . |E F| = |A*E+B*G A*F+B*H|
|C D| |G H| |C*E+D*G C*F+D*H|
В то время как np.multiply
выполняет умножение по элементам двух матриц.
|A B| ⊙ |E F| = |A*E B*F|
|C D| |G H| |C*G D*H|
При использовании с np.sum
результат, равный, является просто совпадением.
>>> np.dot([[1,2], [3,4]], [[1,2], [2,3]])
array([[ 5, 8],
[11, 18]])
>>> np.multiply([[1,2], [3,4]], [[1,2], [2,3]])
array([[ 1, 4],
[ 6, 12]])
>>> np.sum(np.dot([[1,2], [3,4]], [[1,2], [2,3]]))
42
>>> np.sum(np.multiply([[1,2], [3,4]], [[1,2], [2,3]]))
23
Ответ 3
Если Y
и A2
являются (1, N) массивами, то np.dot(Y,AT)
будет давать результат (1,1). Он выполняет матричное умножение a (1, N) с a (N, 1). N's
суммируются, оставляя (1,1).
При multiply
результат равен (1, N). Суммируйте все значения, а результат - скаляр.
Если бы Y
и A2
были (N) сформированы (одинаковое количество элементов, но 1d), то np.dot(Y,A2)
(no .T
) также произведет скаляр. Из документации np.dot
:
Для двумерных массивов это эквивалентно матричному умножению, а для 1-D массивов - скалярному произведению векторов
Возвращает точечный продукт a и b. Если a и b являются скалярами или обоими 1-D массивами, тогда возвращается скаляр; в противном случае массив возвращается.
squeeze
уменьшает размеры всех размеров 1, но все равно возвращает массив. В numpy
массив может иметь любое количество измерений (от 0 до 32). Таким образом, возможен массив 0d. Сравните форму np.array(3)
, np.array([3])
и np.array([[3]])
.
Ответ 4
In this example it just not a coincidence. Lets take an example we have two (1,3) and (1,3) matrices.
// Lets code
import numpy as np
x1=np.array([1, 2, 3]) // first array
x2=np.array([3, 4, 3]) // second array
//Then
X_Res=np.sum(np.multiply(x1,x2))
// will result 20 as it will be calculated as - (1*3)+(2*4)+(3*3) , i.e element wise
// multiplication followed by sum.
Y_Res=np.dot(x1,x2.T)
// in order to get (1,1) matrix) from a dot of (1,3) matrix and //(1,3) matrix we need to //transpose second one.
//Hence|1 2 3| * |3|
// |4| = |1*3+2*4+3*3| = |20|
// |3|
// will result 20 as it will be (1*3)+(2*4)+(3*3) , i.e. dot product of two matrices
print X_Res //20
print Y_Res //20