目录
1、Tensor中统计学相关函数
2、Tensor中的矩阵分解
3、Tensor搭建网络相关运算
3.1 张量裁剪
3.2 张量索引与数据筛选
3.3 张量组合和拼接
3.4 张量切片与变形
范数(Norm)是用来衡量向量大小的函数,它将向量映射到非负实数,在机器学习中体现的作用有:
编程示例:
import torch
# 范数
a = torch.rand(2, 1)
b = torch.rand(2, 1)
print(a, b)
print(torch.dist(a, b, p = 1)) # 一范式
print(torch.dist(a, b, p = 2)) # 二范式
print(torch.dist(a, b, p = 3)) # 三范式
print(torch.norm(a))
print(torch.norm(a, p=3))
print(torch.norm(a, p='fro')) # 计算张量a的Frobenius范数
print('==== 统计函数 ====')
a = torch.rand(2,3)
print(a)
print(torch.mean(a,dim=0)) # 对维度0进行求均值
print(torch.sum(a)) # 累和
print(torch.prod(a)) # 累积
print(torch.argmax(a,dim=0)) # 打印最大值对应维度索引
print(torch.argmin(a,dim=0)) # 打印最小值对应维度索引
print(torch.std(a)) # 标准差
print(torch.var(a)) # 方差
print(torch.median(a)) # 中位数
print(torch.mode(a)) # 众数
# 直方图
print('==== 直方图 ====')
a = torch.rand(2,2) * 10
print(torch.histc(a,6,0,0)) # 首先传入a,第二个参数为统计多少个区间,最后两个参数就是定义最大值和最小值,
# 可以直接定义,也可采用默认0,0。 如果取0,0 就是取当前tensor的最大值最小值进行统计
# histc函数结果可以让我们判断出每个tensor的值在哪个区间里
# 频数
print('==== 频数 ====')
a = torch.randint(0, 10, [10])
print(a)
print(torch.bincount(a)) # 返回一个n+1维的tensor,分别代表0-n这n+1个数字分别出现的频次
# 利用bincount()我们可以用来统计某一类样本的个数
# 随机抽样
print('==== 随机抽样 ====')
torch.manual_seed(1) #定义随机种子 1
mean = torch.rand(1, 2)
std = torch.rand(1, 2)
print(torch.normal(mean, std)) # 正态分布函数,传入均值和标准差,生成随机结果
# 定义随机种子的意义能够用来约束当前的随机抽样,保证随机抽样结果一致
除了上面示例的统计函数,pytorch通过distribute还定义了多个分布函数,利用分布函数可以进行深度学习相关运算。比如,利用分布函数完成得分函数定义(反馈机制),得分函数能够强化学习中策略梯度方法的基础。同时,还可以完成pathwise derivative估计器,能够变分自动编码器中重新参数化技巧。
在机器学习中,可以使用矩阵分解来将一个张量或矩阵表示为较低秩的分量的组合。矩阵分解的目的是降低数据的维度、提取关键特征或简化计算。常见的矩阵分解方法有:
EVD(特征值分解):将一个方阵分解为特征向量和特征值的组合。即A = VΛV^(-1),其中,V是一个由A的特征向量组成的矩阵,Λ是一个对角矩阵,对角线上的元素是A的特征值。V^(-1)是V的逆矩阵。
SVD(奇异值分解):将一个矩阵分解为三个矩阵的乘积,即,其中U和V是正交矩阵,Σ是对角矩阵。
QR分解:QR分解将一个矩阵分解为一个正交矩阵Q和一个上三角矩阵R的乘积,即A = QR。
LU分解:LU分解将一个矩阵分解为一个下三角矩阵L和一个上三角矩阵U的乘积,即A = LU。
此外,与EVD相关的PCA分解,就是将n维特征映射到k维上,这k维是全新的正交特征,也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。PCA算法的优化目标是将原始数据降维后同一维度的方差最大(特征最丰富),并且不同维度之间的相关性为0(信息冗余最低)。因此可以通过协方差矩阵来反映方差和相关性。
与SVD相关的LDA分解,就是将数据投影到一个新的低维子空间,使得投影后的样本在同一类别内尽可能紧密,不同类别之间尽可能分开。LDA分解的目标是将原始高维数据投影到一个低维空间,同时最大化类间的差异和最小化类内的差异。
裁剪运算就是对Tensor中元素进行范围过滤,解空间被约束后,网络会更加稳定,因此可以达到正则化和防止过拟合的效果。同时还可以防止梯度离散或者梯度爆炸。
import torch
print("==== 裁剪 ====")
a = torch.rand(2,2) * 10
print(a)
a = a.clamp(2,5) # 裁剪范围为2-5,对于小于2的直接取2,对于大于5的直接取5,中间值保持不变
print(a)
# 数据筛选、聚合、索引函数
# torch.where
print("==== torch.where ====")
a = torch.rand(4,4)
b = torch.rand(4,4)
print(a)
print(b)
out = torch.where(a>0.5,a,b) # 如果a大于0.5,则选择a,否则选择b
print(out)
# torch.index_select
print("==== torch.index_select ====")
a = torch.rand(4,4)
print(a)
out = torch.index_select(a,dim=0,index=torch.tensor([0,3,2])) # 在第0维上进行,然后按照第0维、第3维、第2维来输出一个3x4的矩阵
print(out,out.shape)
# torch.gather
print("==== torch.gather ====")
a = torch.linspace(1,16,16).view(4,4) # 定义一个序列,然后通过view改变当前向量的shape成4x4的矩阵
print(a)
torch.gather(a,dim=0,index=torch.tensor([[0,1,1,1],
[0,1,2,2],
[0,1,3,3]])) # 在第0维上开始进行索引,然后按照指定维度输出该列上的值
print(out)
# torch.masked_select
print("==== torch.masked_select ====")
a = torch.linspace(1,16,16).view(4,4)
print(a)
mask = torch.gt(a,8)
print(mask)
out = torch.masked_select(a,mask) # 输出大于8的值
print(out)
# torch.take
print("==== torch.take ====")
a = torch.linspace(1,16,16).view(4,4)
print(a)
b = torch.take(a,index=torch.tensor([0,15,13,10])) # 输出对于索引值
print(b)
# torch.nonzero
print("==== torch.nonzero ====")
a = torch.tensor([[0,1,2,0],
[2,3,0,1]])
out = torch.nonzero(a) # 输出非零的行列坐标
print(out)
import torch
a = torch.zeros((2,4))
b = torch.ones((2,4))
out = torch.cat((a,b),dim=0) # 输出4x4维矩阵
print(out)
out = torch.cat((a,b),dim=1) # 输出2x8维矩阵
print(out)
print("==== torch.stack ====")
a = torch.linspace(1, 6, 6).view(2, 3)
b = torch.linspace(7, 12, 6).view(2, 3)
print(a, b)
out = torch.stack((a, b), dim=2) # 增加一个维度
print(out)
print(out.shape)
print(out[:, :, 0])
print(out[:, :, 1]
import torch
print("==== 张量切分 ====")
print("==== 1、chunk ====")
a = torch.rand((3, 4))
print(a)
out = torch.chunk(a, 2, dim=0) # 平均切片,切片的数量2
print(out[0], out[0].shape)
print(out[1], out[1].shape)
print("==== 2、split ====")
a = torch.rand((10, 4))
print(a)
out = torch.split(a, 3, dim=0) # 10/3=3余1,最终拿到4个tensor
for t in out: # 循环输出
print(t, t.shape)
print(len(out))
out = torch.split(a, [1, 3, 6], dim=0) # 在list中指定当前切分尺寸——按照1、3、6三个size进行切分
for t in out:
print(t, t.shape) # 1x4、3x4、6x4
# 张量变形
print("==== 张量变形 ====")
a = torch.rand(2,3)
print(a)
out = torch.reshape(a,(3,2)) # 改变形状
print(torch.t(out)) # 转置
a = torch.rand(1,2,3)
out = torch.transpose(out,0,1) # 将0维和1维进行交换
print(out)
print(out.shape)
out = torch.squeeze(a) # 删除大小为1的维度
print(out)
print(out.shape)
out = torch.unsqueeze(a,-1) # 添加维度
print(out.shape)
out = torch.unbind(a,dim=1) # 删除某个维度
print(out)
print(a)
print(torch.flip(a, dims=[2, 1])) # 翻转指定维度,先翻转维度1,再翻转维度2
print(a)
out = torch.rot90(a, -1, dims=[0, 2]) # 翻转90°,-1表示顺时针旋转(默认逆时针),先旋转0维,再旋转2维维度
print(out)
print(out.shape)