Python 二元交叉熵损失计算中np.dot与np.multiply与np.sum的差异

Python 二元交叉熵损失计算中np.dot与np.multiply与np.sum的差异,python,numpy,neural-network,sum,difference,Python,Numpy,Neural Network,Sum,Difference,我尝试了以下代码,但没有发现np.dot和np.multiply with 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

我尝试了以下代码,但没有发现np.dotnp.multiply with 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 ]]
()
-2.07917628312
()
<class 'numpy.float64'>
0.693058761039
<class 'numpy.ndarray'>
0.6930587610394646
它的产量是

(1, 1)
[[-2.07917628]]
(1, 1)
<class 'numpy.ndarray'>
[[ 0.693058761039 ]]
()
-2.07917628312
()
<class 'numpy.float64'>
0.693058761039
<class 'numpy.ndarray'>
0.6930587610394646
输出为

(1, 1)
[[-2.07917628]]
(1, 1)
<class 'numpy.ndarray'>
[[ 0.693058761039 ]]
()
-2.07917628312
()
<class 'numpy.float64'>
0.693058761039
<class 'numpy.ndarray'>
0.6930587610394646

0.6930587610394646

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|
|A B| ⊙ |E F| = |A*E B*F|
|C D|   |G H|   |C*G D*H|
然而,
np.乘法
对两个矩阵进行运算

|A B| . |E F| = |A*E+B*G A*F+B*H|
|C D|   |G H|   |C*E+D*G C*F+D*H|
|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

如果
Y
A2
是(1,N)数组,则
np.dot(Y,A.T)
将产生(1,1)结果。它是将a(1,N)与a(N,1)进行矩阵乘法。将
N的
相加,留下(1,1)

使用
乘法
的结果是(1,N)。对所有值求和,结果为标量


如果
Y
A2
为(N,)形(元素数相同,但为1d),则
np.dot(Y,A2)
(no
.T
)也将产生标量。从
np.dot
文档:

对于二维数组,它等价于矩阵乘法,对于一维数组,它等价于向量的内积

返回a和b的点积。如果a和b都是标量或都是一维数组,则返回标量;否则将返回一个数组


挤压
减少所有大小为1的维度,但仍返回数组。在
numpy
中,数组可以有任意数量的维度(从0到32)。因此,0d阵列是可能的。比较
np.array(3)
np.array([3])
np.array([[3]])
您所做的是计算模型的形状,当与真实输出(此处:
Y
)进行比较时,这些形状衡量模型的预测(此处:
A2
)有多差

下面是一个可重复的例子,可以解释为什么在第二种情况下使用
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
请注意,沿着此处匹配的内部尺寸的总和
(1x8)和(8x1)
。因此,
8
s将在点乘或矩阵乘法过程中消失,产生的结果为
(1x1)
,它只是一个标量,但作为形状的2D数组返回
(1,1)


另外,最重要的是注意,这里的输入是2D数组(即矩阵)


以标量值形式返回结果 或返回基于输入数组的结果数组形状。即使使用
out=
参数,如果输入是二维数组,也不可能返回标量。但是,如果结果数组的形状为
(1,1)
(或者更一般地说,是封装在nD数组中的标量值),则可以对结果使用


大小为1到标量值的数据数组


np.sum
返回标量,
np.dot
不返回标量。要获得具体答案,您可能需要提供输入数组的形状。通常,您会看到默认情况下,
np.sum
总是对整个输入求和并返回标量
np.dot
仅在一个轴上求和(在您的例子中,它似乎是唯一的一个轴)并保留维度。您所做的是计算
二进制交叉熵损失
,您尝试的两种方法都是等效的,这就是为什么您得到相同的结果。不清楚你的实际问题是关于什么的。实际上,我在寻找np.dot答案中的标量值要获得标量值,你需要使用1d数组,而不是2d数组。在这种情况下,我们不能仅使用
np.dot()
来获得标量值吗?因为它给出的答案与
np.multiply()
np.sum()
@AsadShakeel添加了一个将结果转换为标量的技巧:)谢谢!如果可以的话,我会不止一次地投票给你:)很好的解释。节省了很多时间。使用
*
乘法两个矩阵怎么样?使用
*
乘法矩阵也可以进行元素乘法,如⊙ 和
np.multiply
操作符。嘿,你能解释一下np.matmul()是什么吗does@Avnishkumar它执行矩阵乘法。请看我的答案上面有更多的解释!