torch.nn.functional.normalize详解

torch.nn.functional.normalize详解,第1张


一、 函数分析

函数的默认情况:
torch.nn.functional.normalize(input, p=2, dim=1, eps=1e-12, out=None)
含义:返回在指定维度上的输入数据inputL-p范数的标准化后的数据。


(在指定维度上,该数据的每个元素除以其L-p范数)
L-p范数:数学上的范数是指一个向量 x = ( x 1 , x 2 , . . . , x n ) x=(x_1,x_2,...,x_n) x=(x1,x2,...,xn)的模。


公式如下。


如果数学概念不理解的话:

  • 每个向量(1维还是多维)都具有“方向”和“长度”两个特征。


    在实数空间内,正负性表示“方向”,实数的绝对值 ∣ a ∣ |a| a表示“长度”,该长度成为数学上的模(或者范数)。


  • 对于二维向量(a,b)来说,同样具有一个“方向”[比如,向量与x轴的夹角,可以用内积表示],以及“长度”[通常用 ( a 2 + b 2 ) 2 \sqrt[2] {(a^2+b^2)} 2(a2+b2) 表示,即为L-2范数。


    ]

  • 同理在三维或者多维向量下,类推得到L-p范数。



    ∣ ∣ x ∣ ∣ = ∑ 1 n ( ( ∣ x i ∣ ) p ) 1 p ||x||=\sum_1^n ((|x_i|)^p)^{\frac{1}{p}} x=1n((xi)p)p1

    思维误区:不表示,L-2空间内的二维向量只能用L-2范数,也是可以用L-1范数的。


    当然高于L-2的范数也能说,只是毫无意义。


    因此,往往在L-p空间内使用 ≤ p \leq p p的范数。



    此外,L-2范数其实类似于机器学习上的RSME,L-1范数类似于MAE.

参数解析:

  • input:输入任何形式的torch.tensor
  • p :理解了L-p范数的定义,显然这里的p是用来指代L-p范数的。


  • eps: 因为要除以L-p范数,为避免分母过于小,因此设定了一个阈值,其默认为1e-12

二、 案例讲解 2.1 p的栗子

import math
a = torch.Tensor([1,2,3])
# a的L1范数为 6=1+2+3;L2的范数为 sqrt(14)=sqrt(1^2+2^2+3^2)
a1 =torch.nn.functional.normalize(a, p=1,dim=0)
a2=torch.nn.functional.normalize(a, dim=0)#p默认为2
print(a1,a2) 
print(torch.div(a,6),torch.div(a,math.sqrt(14))) 

out:

tensor([0.1667, 0.3333, 0.5000]) tensor([0.2673, 0.5345, 0.8018])
tensor([0.1667, 0.3333, 0.5000]) tensor([0.2673, 0.5345, 0.8018])
2.2 dim的栗子
b = torch.Tensor([[1,2,3], [4,5,6]]) # shape=(2,3)
b0=torch.nn.functional.normalize(b,p=1, dim=0)
b1=torch.nn.functional.normalize(b,p=1, dim=1)
print("dim=0 outset's shape:",b0.shape)
print(b0)
print("dim=1 outset's shape:",b1.shape)
print(b1) 

在理解dim的时候,为方便运算和验证,我这里设置的是L-1范数。



out:

dim=0 outset's shape: torch.Size([2, 3])
tensor([[0.2000, 0.2857, 0.3333],
        [0.8000, 0.7143, 0.6667]])
dim=1 outset's shape: torch.Size([2, 3])
tensor([[0.1667, 0.3333, 0.5000],
        [0.2667, 0.3333, 0.4000]])

解析
对于轴的理解可以参考:https://mathpretty.com/12065.html
我的规律,不明白看图(左侧是一维扩展到二维的情况。


右侧是具体轴维度的运算情况):

规律:

  1. 判断:确定好轴方向(dim为哪个维度)
  2. 简化:沿轴方向的(一堆)数据看作一个新数据,不妨取一堆的第一个命名为新数据
  3. 运算:对新数据们进行当前的运算
  4. 扩维:沿轴方向进行逐一运算


验证

b00 = torch.div(b,torch.Tensor([5,7,9])) #有广播机制
b11 = torch.div(b,torch.Tensor([[6,6,6],[15,15,15]]))
print(b0==b00)
print(b1==b11) 

out:

tensor([[True, True, True],
        [True, True, True]])
tensor([[True, True, True],
        [True, True, True]])

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/578630.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存