4

这是一段神经网络代码示例:

def forward_step(X, W, b, W2, b2):
    hidden_layer = np.maximum(0, np.dot(X, W) + b)
    scores = np.dot(hidden_layer, W2) + b2
    exp_scores = np.exp(scores)
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
    ...

上面显示的代码的最后一行引发了错误:

<ipython-input-49-d97cff51c360> in forward_step(X, W, b, W2, b2)
     14     scores = np.dot(hidden_layer, W2) + b2
     15     exp_scores = np.exp(scores)
---> 16     probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
     17     corect_logprobs = -np.log(probs[range(X.shape[0]), y])

/Users/###/anaconda/lib/python3.6/site-packages/numpy/core/fromnumeric.py in sum(a, axis, dtype, out, keepdims)
   1810             pass
   1811         else:
-> 1812             return sum(axis=axis, dtype=dtype, out=out, **kwargs)
   1813     return _methods._sum(a, axis=axis, dtype=dtype,
   1814                          out=out, **kwargs)

TypeError: sum() got an unexpected keyword argument 'keepdims'

有一个类似的问题Numpy sum keepdims error说 numpy 的版本应该大于 1.7。我检查了我的 numpy 版本:

import numpy
numpy.version.version
>> 1.12.1

现在我对这个错误是如何发生的感到困惑。

4

1 回答 1

8

请注意,在它的文档中keepdims的参数下:numpy.sum()

keepdims : bool,可选
如果设置为 True,则缩小的轴作为尺寸为 1 的尺寸留在结果中。使用此选项,结果将针对输入数组正确广播。
如果传递了默认值,那么keepdims将不会传递给 的sum子类的方法ndarray,但是任何非默认值都会传递。如果子类sum方法没有实现keepdims ,则会引发任何异常。

所以它在这里声明,如果你使用 的子类,那么如果子类的相应函数没有用它定义,numpy.ndarray你会得到这个错误。sum

请注意,在您的错误中,它引用1812numpy/core/fromnumeric.py. 看看实际numpy1.12.x 源代码中的上下文:

kwargs = {}
if keepdims is not np._NoValue:
    kwargs['keepdims'] = keepdims
if isinstance(a, _gentype):
    res = _sum_(a)
    if out is not None:
        out[...] = res
        return out
    return res
if type(a) is not mu.ndarray:
    try:
        sum = a.sum
    except AttributeError:
        pass
    else:
        return sum(axis=axis, dtype=dtype, out=out, **kwargs)
return _methods._sum(a, axis=axis, dtype=dtype,
                     out=out, **kwargs)

这里需要注意两件事:该sum函数确实解析了您的keepdims变量,因为它把它拉到线上1812并试图把它放在另一个函数中,所以您知道错误不是您使用变量的方式。另一件重要的事情是,1812您出错的行仅在执行if 时 type(a) is not mu.ndarray,即,如果您使用的类与ndarray. 这正是文档所引用的内容。如果你有一个不同的类,那么他们需要使用 keepdims 参数sum来实现这个函数,如果他们不这样做会引发错误。

例如,其他类np.matrix将具有不同的 sum 函数,而且似乎即使在numpy 1.13.x, sumfornp.matrix类型中也不支持keepdim参数(因为在 中numpy,矩阵总是二维的)。例如,它适用于np.array

>>> import numpy as np
>>> A = np.eye(4)
>>> A
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])
>>> np.sum(A, axis=1, keepdims=True)
array([[ 1.],
       [ 1.],
       [ 1.],
       [ 1.]])

但是对于 a np.matrix,它不会:

>>> import numpy.matlib
>>> B = np.matlib.eye(4)
>>> np.sum(B, axis=1, keepdims=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".../numpy/core/fromnumeric.py", line 1832, in sum
    return sum(axis=axis, dtype=dtype, out=out, **kwargs)
TypeError: sum() got an unexpected keyword argument 'keepdims'

numpy但是,大多数数组/矩阵类型的对象可以很容易地转换为with中的数组np.array(<object>),这应该可以解决大多数子类对象的问题,numpy并且可能是您的问题。np.matrix如果需要,您也可以简单地将结果包装回 a中。

>>> B = np.matlib.eye(4)
>>> B = np.array(B)
>>> np.sum(B, axis=1, keepdims=True)
array([[ 1.],
       [ 1.],
       [ 1.],
       [ 1.]])

但是,如果您的对象类一种np.matrix类型,那么该keepdims参数是没有意义的。矩阵总是二维的,所以sum函数不会减少维度,因此参数不会做任何事情。这就是为什么它没有为矩阵实现。

于 2017-09-26T10:22:03.353 回答