【问题标题】:Normalization VS. numpy way to normalize?归一化VS。 numpy的方式来规范化?
【发布时间】:2018-04-05 13:03:52
【问题描述】:

我应该规范化一个数组。我已经阅读了规范化并遇到了一个公式:

我为它写了以下函数:

def normalize_list(list):
    max_value = max(list)
    min_value = min(list)
    for i in range(0, len(list)):
        list[i] = (list[i] - min_value) / (max_value - min_value)

这应该是对元素数组进行规范化。

然后我遇到了这个:https://stackoverflow.com/a/21031303/6209399 这表示您可以通过简单地执行以下操作来规范化数组:

def normalize_list_numpy(list):
    normalized_list = list / np.linalg.norm(list)
    return normalized_list

如果我用我自己的函数和 numpy 方法规范化这个测试数组test_array = [1, 2, 3, 4, 5, 6, 7, 8, 9],我会得到这些答案:

My own function: [0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]
The numpy way: [0.059234887775909233, 0.11846977555181847, 0.17770466332772769, 0.23693955110363693, 0.29617443887954614, 0.35540932665545538, 0.41464421443136462, 0.47387910220727386, 0.5331139899831830

为什么函数给出不同的答案?还有其他方法来规范化数据数组吗? numpy.linalg.norm(list) 是做什么的?我怎么了?

【问题讨论】:

  • 请注意,这不是传统的标准化公式,通常表示为 (x - x_mean) / stdev(x),它将 x 标准化为正态分布。 (stdev 是标准差。)
  • 同意布拉德。您的公式将值缩放到区间 [0, 1],而“归一化”通常意味着转换为具有均值 0 和方差 1(在统计中),或者缩放向量以具有相对于某个范数的单位长度(通常是 L2 )。
  • 那不是叫“标准化”吗? @phg
  • @OuuGiii 不,没有官方引用可以引用我会说“标准化”和“标准化”都是指减去平均值并除以标准差以使数据具有N~(0,1) 分布。也许规范化可以采用您在线性代数上下文中提到的含义,但我会说 phg 是主要用法。
  • @OuuGiii 是的,至少根据this answernormalization 指的是 [0,1] 范围,standardization 指的是均值 0 方差 1。

标签: python numpy normalization


【解决方案1】:

有不同类型的标准化。您正在使用最小-最大标准化。 scikit learn 的 min-max 归一化如下。

import numpy as np
from sklearn.preprocessing import minmax_scale

# your function
def normalize_list(list_normal):
    max_value = max(list_normal)
    min_value = min(list_normal)
    for i in range(len(list_normal)):
        list_normal[i] = (list_normal[i] - min_value) / (max_value - min_value)
    return list_normal

#Scikit learn version 
def normalize_list_numpy(list_numpy):
    normalized_list = minmax_scale(list_numpy)
    return normalized_list

test_array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
test_array_numpy = np.array(test_array)

print(normalize_list(test_array))
print(normalize_list_numpy(test_array_numpy))

输出:

[0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]    
[0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0]

MinMaxscaler 完全使用您的规范化/缩放公式: http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.minmax_scale.html

@OuuGiii:注意:使用 Python 内置函数名称作为变量名称不是一个好主意。 list() 是 Python 内置函数,因此应避免将其用作变量。

【讨论】:

  • 不知道这存在,+1。 @OuuGii 直接来自此函数的文档,“此转换通常用作零均值、单位方差缩放的替代方法。”
  • @BradSolomon 它经常在 sklearn 中用于特征缩放,然后再馈送到各种敏感分类器,如 svm 或 knn 等。
【解决方案2】:

您引用的问题/答案并未明确将您自己的公式与您在此处使用的 np.linalg.norm(list) 版本相关联。

一个 NumPy 解决方案是这样的:

import numpy as np
def normalize(x):
    x = np.asarray(x)
    return (x - x.min()) / (np.ptp(x))

print(normalize(test_array))    
# [ 0.     0.125  0.25   0.375  0.5    0.625  0.75   0.875  1.   ]

这里np.ptp 是峰到峰,即

沿轴的值范围(最大值 - 最小值)。

这种方法将值缩放到@phg 指出的区间 [0, 1]。

归一化的更传统定义是缩放到 0 均值和单位方差:

x = np.asarray(test_array)
res = (x - x.mean()) / x.std()
print(res.mean(), res.std())
# 0.0 1.0

或者使用sklearn.preprocessing.normalize作为预装函数。

使用test_array / np.linalg.norm(test_array) 创建一个单位长度的结果;你会看到np.linalg.norm(test_array / np.linalg.norm(test_array)) 等于 1。所以你在这里谈论两个不同的领域,一个是统计数据,另一个是线性代数。

【讨论】:

  • 谢谢,但是函数 normalize_list_numpy() 有什么作用呢?
  • @OuuGiii 它使向量的长度为 1。
  • @OuuGiii 查看np.linalg.norm(test_array / np.linalg.norm(test_array)) 的结果以了解@phg 的评论。
【解决方案3】:

python 的强大之处在于它的broadcasting 属性,它允许您在不显式循环的情况下进行向量化数组操作。因此,您无需使用显式 for 循环编写函数,这既慢又耗时,尤其是当您的数据集太大时。

min-max normalization 的 Pythonic 方式是

test_array = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
normalized_test_array = (test_array - min(test_array)) / (max(test_array) - min(test_array)) 

输出 >> [ 0., 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1. ]

【讨论】:

    猜你喜欢
    • 2012-04-04
    • 2021-02-16
    • 2017-09-26
    • 1970-01-01
    • 2017-11-03
    • 2020-07-09
    • 1970-01-01
    • 2015-10-04
    • 2014-04-22
    相关资源
    最近更新 更多