使用 Numpy 与硬编码进行规范化

Normalization using Numpy vs hard coded

import numpy as np
import math

def normalize(array):
    mean = sum(array) / len(array)
    deviation = [(float(element) - mean)**2 for element in array]
    std = math.sqrt(sum(deviation) / len(array))
    normalized = [(float(element) - mean)/std for element in array]

    numpy_normalized = (array - np.mean(array)) / np.std(array)

    print normalized
    print numpy_normalized
    print ""

normalize([2, 4, 4, 4, 5, 5, 7, 9])
normalize([1, 2])
normalize(range(5))

输出:

[-1.5, -0.5, -0.5, -0.5, 0.0, 0.0, 1.0, 2.0]
[-1.5 -0.5 -0.5 -0.5  0.   0.   1.   2. ]

[0.0, 1.414213562373095]
[-1.  1.]

[-1.414213562373095, -0.7071067811865475, 0.0, 0.7071067811865475, 1.414213562373095]
[-1.41421356 -0.70710678  0.          0.70710678  1.41421356]

有人可以向我解释为什么此代码在第二个示例中的行为不同,但在其他两个示例中的行为相似吗?

我在硬编码示例中做错了什么吗? NumPy 做了什么以 [-1, 1] 结束?

计算平均值时,您没有将数组中的数字转换为浮点数。对于您的第二个或第三个输入,这不是问题,因为它们恰好可以很好地计算出来(正如@abarnert 所解释的),但是由于第二个输入没有,并且完全由整数组成,您最终计算的平均值为1 应该是 1.5。这会传播,导致您与使用 NumPy 函数的结果不一致。

如果用此替换计算平均值的行,这会强制 Python 使用浮点除法:

mean = sum(array) / float(len(array))

你最终会得到 [-1, 1] 作为第二组输入的结果,就像 NumPy 一样。

作为 ,您使用的是整数。在 Python 2 中(除非你 from __future__ import division),一个整数除以一个整数得到一个整数。

那么,为什么三个都没有错呢?好吧,看看价值观。在第一个中,总和为 40,len 为 8,因此 40 / 8 = 5。在第三个中,10 / 5 = 2。但在第二个中,3 / 2 = 1.5。这就是为什么当你做整数除法时只有那个人得到错误的答案。

那么,为什么 NumPy 不会也弄错第二个呢? NumPy 不会将整数数组视为浮点数,而是将它们视为整数——print np.array(array).dtype,你会看到 int64。但是,正如 np.mean 的文档所解释的那样,"float64 intermediate and return values are used for integer inputs"。而且,虽然我不确定这一点,但我猜他们是专门这样设计的,以避免这样的问题。


附带说明一下,如果您对采用浮点数的平均值感兴趣,那么仅使用 sum / div 还存在其他问题。例如,[1, 2, 1e200, -1e200] 的均值实际上应该是 0.75,但如果您只执行 sum / div,您将得到 0。 (为什么?好吧,1 + 2 + 1e200 == 1e200。)您可能想要查看一个简单的统计库,即使您没有使用 NumPy,也可以避免所有这些问题。在 Python 3(一开始就可以避免你的问题)中,stdlib 中有一个,叫做 statistics;在 Python 2,你必须去 PyPI。