Sklearn中与特征缩放有关的五个函数和类,全部位于sklearn.preprocessing包内。作为一个系列文章,我们将逐一讲解Sklearn中提供的标准化和归一化方法,以下是本系列已发布的文章列表:

  • Sklearn标准化和归一化方法汇总(1):标准化 / 标准差归一化 / Z-Score归一化
  • Sklearn标准化和归一化方法汇总(2):Min-Max归一化
  • Sklearn标准化和归一化方法汇总(3):范数归一化

以下是Sklearn中的五种与特征缩放相关的函数和类,我们的研究也是为围绕这些函数和类展开的:

名称 方法名 类名
标准化 / Z-Score 归一化 / 标准差归一化 sklearn.preprocessing.scale sklearn.preprocessing.StandardScaler
Min-Max 归一化 sklearn.preprocessing.minmax_scale sklearn.preprocessing.MinMaxScaler
范数归一化 sklearn.preprocessing.normalize sklearn.preprocessing.Normalizer
Robust Scaler(无常用别名) sklearn.preprocessing.robust_scale sklearn.preprocessing.RobustScaler
Power Transformer (无常用别名) sklearn.preprocessing.power_transform sklearn.preprocessing.PowerTransformer

关于各种关于标准化和归一化的概念和分类,我们已经在此前一篇文章《标准化和归一化概念澄清与梳理》中做了详细的梳理和澄清,不清楚的读者可以先阅读一下此文。本文我们研究第三种归一化手段:范数归一化。本文地址:https://laurence.blog.csdn.net/article/details/128723321,转载请注明出处!

1. 算法

范数归一化的计算逻辑是:先计算出一个向量(通常是一行)的范数(如无特殊说明,通常都是指L-2范数),然后让向量中的每一个元素除以这个范数,得到的新向量就是范数归一化后的结果。所以,理解范数归一化的关键是要理解:范数。我们已经在此前一篇文章中专门做了介绍,请参考《范数的意义与计算方法》一文。

由于范数表示一个向量的“长度”,一个向量除以了自己的“范数”后,就等于把自己的“长度”缩放成了单位长度:1,所以可以想象:在一个二维的向量空间中,范数为1的向量都会分布在以原点为圆心,半径为1的圆上,如果是三维的向量空间,会分布在以原点为圆心,半径为1的圆球上。。

范数归一化与此前介绍的标准差归一化和Min-Max归一化有本质的不同,它是面向向量或矩阵的,所以默认也是按行(即向量形式)进行运算的。应用范数归一化的前提是:当前操作的多维数组是一个有意义的向量或矩阵,或者说是需要准备拿它去进行向量或矩阵运算(这在机器学习算法中很常见),在此前提下,当我们使用范数归一化时,是将一个向量(通常是二维数组中的一行)作为一个整体去运算的,通俗地说就是:此时的一行数据才是一个数(一个向量)。

“范数归一化是应用在向量(或矩阵)上”这一点也体现在了API层面上,第一点是:你可能会发现像scale()minmax_scale()这类归一化函数还可以接受一维数组,但到了normalize()就不会再接受一维数组了,需要至少要二维以上的数组(否则会报“Expected 2D array, got 1D array instead”错误),这在暗示:针对一维数组(非向量)应用范数归一化是无意义的;第二点是:像scale()minmax_scale()这类归一化函数默认是“列”向操作,而normalize()默认则是“行”向操作,这在暗示它是操作向量的,这都是根据它的实际应用场景设置的默认参数,所以能反映出它的一些本质特征。

总结一下:范数归一化是面向向量(或矩阵)的运算,所以默认也是按行(即向量形式)进行处理。

2. 示例

2.1 一个“无意义”的示例

有很多刚接触范数归一化的人会沿袭对其他归一化方法的理解来试图理解范数归一化,包括使用的测试数据也是一样的单列数据,就如同我们在本系列前面两篇文章中使用到的身高数据一样,于是,在初学者那里我们会常常看到类似下面的归一化结果以及数据分布图,我们要说的是:虽然计算上没有错误,但这种处理是没有意义的,也就不会出现在实际应用中,因为我们试图处理的数据根本不是一个有意义的向量数据,所以处理结果也是无意义的。那就让我们使用此前的身高数据看一下非向量(一维数组)到底会被处理成什么样子:

# 范数归一化 (在非向量上的无意义应用)import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import Normalizer
from sklearn.preprocessing import normalize
# author: https://laurence.blog.csdn.net/%matplotlib inline
np.random.seed(42)
fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize=(13,5))heights = np.random.normal(loc=170, scale=170*0.15, size=1000)
print("1. 原始数据")
print(f"heights (first 3 elements) = {heights[:3]}")# 不同于scale()和minmax_scale()还能接受一维数组,normalize()已不接受一维数组了,至少要二维以上。
# 否则就会报错:Expected 2D array, got 1D array instead, 这暗示:范数归一化是面向向量或整个矩阵的
# 所以从API层面就作出了限制,因此我必须一开始将heights转置为二维(单列)数组
heights = heights.reshape(-1,1)
print(f"reshaped heights (first 3 elements) = {heights[:3].tolist()}")ax1.hist(heights, bins=50)
ax1.set_title("raw data")
ax1.annotate(f"σ = {heights.std()}", (0.5, 0.95), xycoords='axes fraction', va='center', ha='center')print("--------------------------------------------------------------------------------------------------------------")print("2. 使用normalize按行进”行“范数归一化")
# 不指定axis参数,默认也是按行, 这也体现了normalize是面向向量运算的设计意图
normalized_heights = normalize(heights, axis=1)
print(f"normalized_heights(first 3 elements) = {normalized_heights[:3, :].tolist()}")
ax2.hist(normalized_heights, bins=50)
ax2.set_title("normalize() by row")
ax2.annotate(f"σ = {normalized_heights.std()}", (0.5, 0.95), xycoords='axes fraction', va='center', ha='center')print("--------------------------------------------------------------------------------------------------------------")print("3. 使用normalize按”列“进行范数归一化")
# 列向操作并不是normalize的默认操作轴向,必须显式设置!
normalized_heights = normalize(heights, axis=0)
print(f"normalized_heights(first 3 elements) = {normalized_heights[:3, :].tolist()}")
ax3.hist(normalized_heights, bins=50)
ax3.set_title("normalize() by col")
ax3.annotate(f"σ = {normalized_heights.std()}", (0.5, 0.95), xycoords='axes fraction', va='center', ha='center')print("--------------------------------------------------------------------------------------------------------------")print("4. 使用Normalizer进行范数归一化")
# Normalizer不可设置轴向,只能按“行”
normalized_heights = Normalizer().fit_transform(heights)
print(f"normalized_heights(first 3 elements) = {normalized_heights[:3, :].tolist()}")
ax4.hist(normalized_heights, bins=50)
ax4.set_title("Normalizer")
ax4.annotate(f"σ = {normalized_heights.std()}", (0.5, 0.95), xycoords='axes fraction', va='center', ha='center')plt.show()

输出数据:

1. 原始数据
heights (first 3 elements) = [182.6662109  166.47426032 186.51605772]
reshaped heights (first 3 elements) = [[182.66621090178643], [166.4742603201348], [186.51605772156765]]
--------------------------------------------------------------------------------------------------------------
2. 使用normalize按行进”行“范数归一化
normalized_heights(first 3 elements) = [[1.0], [1.0], [1.0]]
--------------------------------------------------------------------------------------------------------------
3. 使用normalize按”列“进行范数归一化
normalized_heights(first 3 elements) = [[0.03352337883141376], [0.030551789884073692], [0.03422991274781404]]
--------------------------------------------------------------------------------------------------------------
4. 使用Normalizer进行范数归一化
normalized_heights(first 3 elements) = [[1.0], [1.0], [1.0]]

输出图表:

现在我们来解读一下程序输出的数据和图表。我们准备的身高数据并不是一个向量,在还没有认识到这个问题的情况下,为了能够进行范数归一化,我们把它强行转置为一个二维(单列)数组:

[[182.66621090178643], [166.47426032013480], [186.51605772156765],...[165.84179242457762]]

在此基础上,我们有两种选择,也是看待数据的两种方式:

  • 按“行”范数归一化

如果我们打算按“行”进行范数归一化,则每一行会被视为一个向量,由于我们的数据一行只有一个元素,即一个向量只有一个分量,套用范数归一化的计算公式可知,不管是什么值,计算出的结果都为1,所以1000行数据就被转置为了:

[[1.0], [1.0], [1.0],...[1.0]]

此时数据分布就变为图中第2和第4两个子图的样子,这种转换毫无意义。

  • 按“列”范数归一化

如果我们打算按“列”进行范数归一化,则每一列会被视为一个向量,此时,我们只有一个向量,这个向量包含1000个维度的分量,经归一化处理后,得到的结果是:

[[0.03352337883141376], [0.030551789884073692], [0.03422991274781404],...[0.03123451354323424]]

对应的数据分布就是图3所示的样子,看上去已经“有那味”了,数据被缩放了,分布还保持与原始数据一样,很多介绍范数的文章就到此结束了。然而实际的情况是:这个由1000个身高数据组成的向量是一个“怪物”,根本不是一个有意义的向量,完全体现不出范数归一化的作用。

2.2 一个“有意义”的示例

由于我们准备的身高数据不是一组有意义的向量,这导致上面的示例不管是按行还是按列,都无法展示范数归一化的真正效果,问题的关键就是:身高数据是一个单维数据,我们需要准备至少包含两个维度的向量来演示范数归一化,才能看到它的转换效果。所以,我们应该再引入一个维度:体重,组成一个由身高和体重构成的二维向量,然后对其进行范数归一化:

# 范数归一化 (在向量上的有意义应用)import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import normalize
from sklearn.preprocessing import StandardScaler
# author: https://laurence.blog.csdn.net/%matplotlib inline
np.random.seed(42)
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15,5))# 我们不能再用身高数据演示范数归一化了,因为从数据的意义上讲它是一”列“数据,而范数归一化是面向向量(或矩阵)的,也就是一行数据
# 如果我们把这组身高数据当成”行“进行范数归一化,可以计算,但没有任何意义,因为这组数据不是一个向量;
# 如果我们把这组身高数据当成”列“进行范数归一化,则每一行只有一个元素,所以归一化的结果是:所有的身高数据都被缩放成了1,这也没有意义# 使用有意义的二维向量
heights_weights = np.random.normal(loc=(170, 60), scale=(170*0.15, 60*0.15), size=(1000, 2))print("1. 原始数据")
print(f"heights_weights (first 2 elements) = {heights_weights[:2, :].tolist()}")
ax1.scatter(x=heights_weights[:,0], y=heights_weights[:,1])
ax1.set_title("raw data")print("-------------------------------------------------------------------------------------------------------------------------------------")print("2. 使用normalize范数归一化")
# 默认按行向量进行范数归一化,也符合我们的期望,针对本数据按“列”无意义,不演示
normalized_heights_weights = normalize(heights_weights)
print(f"normalized_heights_weights (first 2 elements) = {normalized_heights_weights[:2, :].tolist()}")
ax2.scatter(x=normalized_heights_weights[:,0], y=normalized_heights_weights[:,1])
ax2.set_title("normalize()")print("-------------------------------------------------------------------------------------------------------------------------------------")print("3. 使用Normalizer范数归一化")
# 只能按行向量进行范数归一化,也符合我们的期望,针对本数据按“列”无意义,不演示
normalized_heights_weights = Normalizer().fit_transform(heights_weights)
print(f"normalized_heights_weights (first 2 elements) = {normalized_heights_weights[:2, :].tolist()}")
ax3.scatter(x=normalized_heights_weights[:,0], y=normalized_heights_weights[:,1])
ax3.set_title("Normalizer (center view)")
ax3.set(xlim=(-1, 1),ylim=(-1, 1))
ax3.axvline(x=0, c='grey')
ax3.axhline(y=0, c='grey')plt.show()# 调研数据分布变化fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15,5))
ax1.hist(heights_weights, bins=50)
ax1.set_title("raw data")
# 经过范数归一化后,每一行元素(向量分量)除以的范数都是不一样的,所以每一列元素实际上是进行了
# 无规律的缩放,所以如果观察列数据的分布,其经过范数归一化后,分布一定改变了。但这是在用非向量
# 的视角看待数据,使用范数归一化的场景不会受此影响,也不关注这个问题。
ax2.hist(normalized_heights_weights, bins=50)
ax2.set_title("normalize data")plt.show()

输出数据:

1. 原始数据
heights_weights (first 2 elements) = [[182.66621090178643, 58.75562128945934], [186.51605772156765, 73.70726870767223]]
-------------------------------------------------------------------------------------------------------------------------------------
2. 使用normalize范数归一化
normalized_heights_weights (first 2 elements) = [[0.9519655603640547, 0.30620511406694606], [0.9300146475620354, 0.3675224555317171]]
-------------------------------------------------------------------------------------------------------------------------------------
3. 使用Normalizer范数归一化
normalized_heights_weights (first 2 elements) = [[0.9519655603640547, 0.30620511406694606], [0.9300146475620354, 0.3675224555317171]]

输出图表:

改用二维向量数据后,我们能就能从图表中发现范数归一化的真正效果。左一图中的每一个点可以视为一个向量,经过范数归一化后,数据呈现出图二的分布状态,所有向量的“长度”(范数)全部变成了1,表现到图表上就是它们被缩放到了以原点为圆心,1为半径的圆上!同时,可以看到正态分布对点位在圆上的分布影响,而图三是为了凸显归一化后数据是分布在单位圆上,特意将坐标系居中显示,从中可以观察到那是单位园上的一小段圆弧。最后,我们再看一下数据分布:

由于数据是按行处理的,所以从列向角度看,同一个列(例如身高)中的每个元素都除以了不同的数(所在行的范数),所以列的数据分布必然会发生改变,上图显示的非常明显。但同样的道理,因为现在的场景是向量运算,所以也不会考察列向数据的分布。这就是我们在介绍范数归一化时反复强调的:范数归一化和标准差归一化、Min-Max归一化等其他归一化方法是完全不同的缩放手段,它缩放的是向量。

Sklearn标准化和归一化方法汇总(3):范数归一化相关推荐

  1. Sklearn标准化和归一化方法汇总(2):Min-Max归一化

    Sklearn中与特征缩放有关的五个函数和类,全部位于sklearn.preprocessing包内.作为一个系列文章,我们将逐一讲解Sklearn中提供的标准化和归一化方法,以下是本系列已发布的文章 ...

  2. java归一化方法_Java之Normalizer(归一化)

    什么是归一化? 归一化的概念在人工智能领域会普通看到, 比如使用TensorFlow框架编码时,就会出现数据归一化的步骤或函数. 简单来说, 归一化就是对一组数据进行转换,使这组数据具备相同的格式或特 ...

  3. 【深度学习/机器学习】为什么要归一化?归一化方法详解

    [深度学习/机器学习]为什么要归一化?归一化方法详解 文章目录 1. 介绍 1.1 什么是归一化 1.2 归一化的好处 2. 归一化方法 2.1 最大最小标准化(Min-Max Normalizati ...

  4. 机器学习中常见的几种归一化方法以及原因

    在机器学习中,数据归一化是非常重要,它可能会导致模型坏掉或者训练出一个很奇怪的模型,为了让机器学习的模型更加适合实际情况,需要对数据进行归一化处理. 1.机器学习中常用的归一化方法: 2. 不同归一化 ...

  5. 机器学习常见归一化方法及实现

    归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为标量. 在多种计算中都经常用到这种方法.在对数据进行算法训练时,由于数据的问题可能导致算法的效果并不理想,这时候可以考 ...

  6. 机器学习中数据预处理——标准化/归一化方法(scaler)

    由于工作问题比较忙,有两周没有总结一下工作学习中遇到的问题. 这篇主要是关于机器学习中的数据预处理的scaler变化. 工作中遇到的问题是:流量预测问题,拿到的数据差距非常大,凌晨的通话流量很少几乎为 ...

  7. 数据处理之标准化/归一化方法

    数据处理之标准化/归一化方法 归一化方法(Normalization Method) 1.把数变为(0,1)之间的小数 主要是为了数据处理方便提出来的,把数据映射到0-1范围之内处理,更加便捷快速,应 ...

  8. 归一化的好处及归一化,标准化的处理方法

    归一化后有两个好处 1. 提升模型的收敛速度 如下图,x1的取值为0-2000,而x2的取值为1-5,假如只有这两个特征,对其进行优化时,会得到一个窄长的椭圆形,导致在梯度下降时,梯度的方向为垂直等高 ...

  9. 数据归归一化方法(标准化)

    数据归一化方法 数据标准化(normalization)数据标准化处理主要包括数据同趋化处理和无量纲化处理两个方面. 数据同趋化处理主要解决不同性质数据问题,对不同性质指标直接加总不能正确反映不同作用 ...

最新文章

  1. Spring Security 源码分析:Spring Security 授权过程
  2. Javascript:必须知道的Javascript知识点之“字面量和对应类型”
  3. 使用PHP读取和创建txt,doc,xls,pdf类型文件
  4. UA OPTI512R 傅立叶光学导论11 卷积的性质
  5. python—web页面操作之3种等待方式
  6. 禁止复制的网页怎么复制
  7. avws扫描出来的漏洞怎么利用_漏洞扫描利用
  8. 音视频技术开发周刊 60期
  9. ssm使用全注解实现增删改查案例——applicationContext.xml
  10. 生成器作为(快速失败)状态机
  11. 论文笔记(eTrust: Understanding Trust Evolution in an Online World)
  12. 1英寸大底手机来了 是索尼的营销噱头吗?
  13. [RK3399][Android7.1] Pinctrl的默认配置
  14. java计算机毕业设计校园点餐系统源程序+mysql+系统+lw文档+远程调试
  15. 对前端构建工具的一些理解
  16. 征信的用途以及提升途径
  17. 初步使用计算机教学设计,【教资笔试——科目三】信息技术教学设计范例
  18. 树莓派浏览网页,显示无法打开此网址
  19. 大学期间能考的计算机证书,大学期间可以考哪些证书?过来人告诉你这3大类最有用!...
  20. 拉勾教育java高薪训练营课程怎么样_[拉勾教育-大前端高薪训练营]这可能是迄今为止对大前端最好的解释...

热门文章

  1. Python 数据挖掘(三) matplotlib模块 简单使用
  2. 钉钉在线表格下载后子表内容空白无数据
  3. 关于三星SSD的固态优化
  4. 在两个高程点之间如何生成加密点_等高线加密高程点
  5. 【SPSS】数据预处理基础教程(附案例实战)
  6. VC操作EXCEL2003
  7. 如何在你的WordPress网站上添加成本计算器
  8. 微雪树莓派PICO笔记——4. ADC(模拟数字转换器)
  9. 【STM32CubeMx】学习记录(基于微雪教程)(2019/2/16——2019/2/23完结)
  10. 如何获取linux源码