Numpy sum() 出现 'keepdims' 错误

Numpy sum() got an 'keepdims' error

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

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

现在我很困惑这个错误是怎么发生的。

请注意,在 docs for numpy.sum() 中的 keepdims 参数下,它指出:

keepdims : bool, optional
If this is set to True, the axes which are reduced are left in the result as dimensions with size one. With this option, the result will broadcast correctly against the input array.
If the default value is passed, then keepdims will not be passed through to the sum method of sub-classes of ndarray, however any non-default value will be. If the sub-classes sum method does not implement keepdims any exceptions will be raised.

所以它在这里声明,如果你正在使用 numpy.ndarray 的子 class,那么如果相应的 sum 函数用于子 - class 尚未用它定义。

请注意,在您的错误中,它引用了 numpy/core/fromnumeric.py 中的行 1812。在实际 numpy 1.12.x source:

的上下文中看一下
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 函数 did 解析了你的 keepdims 变量,因为它将它拉到了 [=21= 行上方] 并尝试将其放入另一个函数中,因此您知道错误不是您使用变量的方式。另一件重要的事情是,您出错的行 1812 仅执行 if type(a) is not mu.ndarray,即,如果您使用不同的 class 比 ndarray。这正是文档所引用的内容。如果您有不同的 class,那么他们需要使用 keepdims 参数 实现此 sum 函数 ,如果他们不这样做,则会引发错误。

其他class例如np.matrix会有不同的求和函数,而且看起来,即使在numpy 1.13.xsum对于np.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.]])

但是对于 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'

但是,大多数 array/matrix 类型的对象都可以使用 np.array(<object>) 轻松地转换为 numpy 中的数组,这应该可以解决大多数子 class 的问题在 numpy 中编辑对象,很可能是您的问题。如果需要,您也可以简单地将结果包装回 np.matrix

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

但是,如果对象 的 class 是 一个 np.matrix 类型,那么 keepdims 参数就毫无意义.矩阵是 always 2D,所以 sum 函数不会减少维度,因此参数不会做任何事情。这就是它没有为矩阵实现的原因。