目录
5、生成所有数值都一样的tensor数值——full,传入形状参数和数值参数
7、linspace 传入三个参数,第三个是步长,前两个是起始值和终止值,左闭右开
8、logspace是以10位底的指数函数,传参进来的是10的指数值
(3)index_select 传入选中的维度,传入要取的索引值(必须以tensor格式传入)
2、unsqueeze(增加维度,一般来说增加的维度里只有一个值)
4、从最小维度开始匹配,我们默认越高维度越相似,而小维度上各有各的不同
2、mean——均值、sum——求和、prob累乘、max——最大值、min——最小值
3、argmin——最小值的位置;argmax——最大值的位置
一、pytorch数据类型
1、pytorch中的string类型如何表示?
(1)没有对string的支持内键
(2)how to denote string:
1>One-hot并不体现语义
2>Embedding—word2vec
2、核实数据类型
import torch
import numpy as np
a = torch.randn(2, 3)
#randn是随机建立一个2行3列的二维数组
print(a.type())
#torch.FloatTensor
print(type(a))
#<class 'torch.Tensor'>
#合法化检验
print(isinstance(a, torch.FloatTensor))
#True
3、维度介绍
(1)标量
一般用于最后的熵值计算结果的表示,只需要一个0维度的标量来表达
shape不需要加括号,size()需要加括号
a = torch.tensor(1.)
print(a)
#tensor(1.)
b = torch.tensor(1.3)
print(b)
#tensor(1.3000)
a = torch.tensor(2.2)
print(a.shape)
#torch.Size([])
print(len(a.shape))
#0零维的向量,也就是一个标量
print(a.size())
#torch.Size([])
(2)Dim1
一般会用在bias、线性层的输入
c = torch.tensor([1.1])
d = torch.tensor([1.1, 2.2])
print(c, d)
#tensor([1.1000]) tensor([1.1000, 2.2000])
e = torch.FloatTensor(2)
print(e)
#生成一个长度为2的dim1的tensor数据
#tensor([0., 0.])
f = torch.FloatTensor(1)
#生成一个长度为1的dim1的tensor数据
print(f)
#tensor([0.])
(3)Dim2
一般用在batch,当输入多张图片时,第一个数字是图片的个数,第二个是打平图片之后的一维点数
t1 = np.ones((2, 1))
print(t1)
'''
[[1.]
[1.]]
'''
k = torch.from_numpy(data)
print(k)
#tensor([1., 1.], dtype=torch.float64)
a = torch.randn(2, 3) #或者是torch.FloatTensor(2, 3)
print(a)
'''
tensor([[ 0.9476, 0.8075, -1.6457],
[-0.4735, -0.8509, -0.6772]])
'''
print(a.shape)
#torch.Size([2, 3])
print(a.size(0))
#第一维度的大小
#2
print(a.size(1))
#3
print(a.shape[1])
#3
(4)Dim3
适合RNN的文字处理
b = torch.rand(1, 2, 3)
#随机生成的数字在0-1之间均匀分布
print(b)
'''
tensor([[[0.7244, 0.2569, 0.2767],
[0.7456, 0.2834, 0.8144]]])
'''
print(b.shape)
#torch.Size([1, 2, 3])
print(b[0])
'''
tensor([[0.7244, 0.2569, 0.2767],
[0.7456, 0.2834, 0.8144]])
'''
print(list(b.shape))
#[1, 2, 3]
(5)Dim4
适合CNN
第一个数字是图片的个数,第二个数字是图片的通道,通道为1是灰色图像,通道为3的是菜色图像,后两位数字28*28是minis数据集的长和宽
numel()检测占用内存值
c = torch.rand(2, 1, 28, 28)
print(c)
'''
tensor([[[[0.8450, 0.4577, 0.0375, ..., 0.3396, 0.1341, 0.7081],
[0.6733, 0.3496, 0.7041, ..., 0.0523, 0.5972, 0.6742],
[0.0264, 0.6056, 0.7649, ..., 0.1025, 0.3801, 0.6365],
...,
[0.9703, 0.1519, 0.6940, ..., 0.9999, 0.6778, 0.3041],
[0.0407, 0.6849, 0.1991, ..., 0.4033, 0.1786, 0.9286],
[0.3482, 0.0666, 0.4701, ..., 0.7877, 0.5240, 0.0252]]],
[[[0.2246, 0.2970, 0.2059, ..., 0.9483, 0.2796, 0.0238],
[0.5209, 0.5017, 0.2875, ..., 0.3323, 0.4449, 0.5933],
[0.1048, 0.0413, 0.9015, ..., 0.4967, 0.1048, 0.6319],
...,
[0.6737, 0.9206, 0.9469, ..., 0.4061, 0.6017, 0.6666],
[0.7382, 0.7990, 0.3033, ..., 0.5636, 0.2971, 0.1573],
[0.8480, 0.7790, 0.9052, ..., 0.6815, 0.6486, 0.1487]]]])
'''
print(c.shape)
#torch.Size([2, 1, 28, 28])
print(c.numel())
#c占用的字节
#1568
print(c.dim())
#4
二、tensor数据的创建
1、从numpy进行导入
import torch
import numpy as np
#1、从numpy中导入
a = np.array([2, 3.3])
print(a)
#[2. 3.3]
b = torch.from_numpy(a)
print(b)
#tensor([2.0000, 3.3000], dtype=torch.float64)
c = np.ones((2, 3))
d = torch.from_numpy(c)
print(d)
'''
tensor([[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
'''
2、从list里面导入
小写的tensor括号里接收的是现有数据,而大写Terson、FloatTensor里面一般来说接受的是形状,也可以接受现成的数据,括号里用中括号时表示现成的数据,括号时输入的形状
#2、从list里面直接导入,当数据量不大的时候
a = torch.tensor([2, 3.2])
print(a)
#tensor([2.0000, 3.2000])
b = torch.FloatTensor([2, 3.2])
print(b)
#tensor([2.0000, 3.2000])
c = torch.tensor([[2, 3], [1, 4]])
print(c)
'''
tensor([[2, 3],
[1, 4]])
'''
3、未初始化
#3、未初始化,未初始化时一定要跟一个写入数据的步骤
a = torch.empty(2, 3)
print(a)
#数值是随机给出的
'''
tensor([[0.0000e+00, 0.0000e+00, 1.4013e-45],
[0.0000e+00, 1.4013e-45, 0.0000e+00]])
'''
b = torch.FloatTensor(1, 3, 4)
print(b)
#数据非常不规则
'''
nsor([[[0.0000, 1.8750, 0.0000, 1.8750],
[0.0000, 1.8750, 0.0000, 1.8750],
[0.0000, 1.8750, 0.0000, 1.8750]]])
'''
c = torch.IntTensor(1, 2, 3)
print(c)
'''
tensor([[[0, 0, 1],
[0, 1, 0]]], dtype=torch.int32)
'''
d = torch.FloatTensor(2, 3)
print(d)
'''
tensor([[1.6543e+22, 8.3798e-43, 8.4078e-45],
[0.0000e+00, 1.4013e-45, 0.0000e+00]])
'''
一般来说,tensor默认的数据类型是FloatTensor,在增强学习使用比较多的是doubleTensor类型,我们可以自定义默认类型
a = torch.tensor([1.3, 2])
print(a.type())
#torch.FloatTensor
torch.set_default_tensor_type(torch.DoubleTensor)
print(torch.tensor([1.3, 2]).type())
#torch.DoubleTensor
4、随机常见tensor数组
rand生成的数值分布在0-1之间
a = torch.rand(3, 3)
print(a)
'''
tensor([[0.3414, 0.9625, 0.9899],
[0.4586, 0.3740, 0.8750],
[0.7262, 0.5502, 0.9147]])
'''
b = torch.rand_like(a)
print(b)
'''
tensor([[0.9480, 0.1978, 0.4089],
[0.9161, 0.3314, 0.4368],
[0.1124, 0.8861, 0.9626]])
'''
randint随机生成整数值
c = torch.randint(1, 10, [3, 3])
print(c)
'''
#标准正太分布
a = torch.randn(3, 3)
print(a)
'''
tensor([[ 1.3423, 0.5951, -1.2756],
[-0.0795, -0.7977, 0.3281],
[-0.4175, -1.1260, -0.3014]])
'''
#标准正太分布
a = torch.randn(3, 3)
print(a)
'''
tensor([[ 1.3423, 0.5951, -1.2756],
[-0.0795, -0.7977, 0.3281],
[-0.4175, -1.1260, -0.3014]])
'''
tensor([[4, 4, 6],
[8, 4, 9],
[4, 7, 2]])
'''
5、生成所有数值都一样的tensor数值——full,传入形状参数和数值参数
#5、full,数组数字全部相同
a = torch.full([2, 3], 7)
print(a)
'''
tensor([[7., 7., 7.],
[7., 7., 7.]])
'''
b = torch.full([], 7)
print(b)
#tensor(7.)
c = torch.full([1], 7)
print(c)
#tensor([7.])
6、arange生成等差数组,一般不用range
#arange/range 生成等差数列,左闭右开,默认等差为1
a = torch.arange(0, 10)
print(a)
#tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b = torch.arange(0, 10, 2)
print(b)
#tensor([0, 2, 4, 6, 8])
#c = torch.range(0, 10)
#print(c)
#tensor([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
7、linspace 传入三个参数,第三个是步长,前两个是起始值和终止值,左闭右开
#linspace,需要传三个参数,第三个参数为步长,即排列几个数
a = torch.linspace(0, 10, steps=4)
print(a)
#tensor([ 0.0000, 3.3333, 6.6667, 10.0000])
b = torch.linspace(0, 10, steps=10)
print(b)
'''
tensor([ 0.0000, 1.1111, 2.2222, 3.3333, 4.4444, 5.5556, 6.6667, 7.7778,
8.8889, 10.0000])
'''
c = torch.linspace(0, 10, steps=11)
print(c)
#tensor([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
8、logspace是以10位底的指数函数,传参进来的是10的指数值
d = torch.logspace(0, -1, steps=10)
print(d)
#从10的0次方到10的负一次方进行等差排列,排列10个数
'''
tensor([1.0000, 0.7743, 0.5995, 0.4642, 0.3594, 0.2783, 0.2154, 0.1668, 0.1292,
0.1000])
'''
9、ones/zeros/eye
print(torch.ones(3, 3))
'''
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
'''
print(torch.zeros(3, 3))
'''
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
'''
print(torch.eye(3, 4))
#eye--单位矩阵
'''
tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
'''
10、randprem打散索引值,协同两组数据变化
#randperm协同打散
print("###############################")
ta = torch.rand(2, 3)
tb = torch.rand(2, 2)
idx = torch.randperm(2)
#长度为2的数据进行打散
print(idx)
#tensor([0, 1])
print(ta[idx])
'''
tensor([[0.5607, 0.0153, 0.3796],
[0.3243, 0.7399, 0.8882]])
'''
print(tb[idx])
'''
tensor([[0.6173, 0.7833],
[0.7570, 0.9795]])
'''
print(ta, tb)
'''
tensor([[0.3339, 0.2769, 0.5866],
[0.4238, 0.8009, 0.6605]])
tensor([[0.9526, 0.6434],
[0.8490, 0.8654]])
'''
三、索引和切片
1、索引
import torch
import numpy as np
a = torch.rand(4, 3, 28, 28)
print(a[0].shape)
#我们采用的是dim为4的tensor数据,第一个数表示batch,即第几张图片,查看第一张图片的属性值
#torch.Size([3, 28, 28])
print(a[0, 0].shape)
#torch.Size([28, 28])
print(a[0, 0, 2, 4].shape)
#当我们取一个图片具体的行和列,应该返回一个标量
#torch.Size([])
2、切片取值
(1)连续取值
#切片,连续取值
a = torch.rand(4, 3, 28, 28)
print(a.shape)
#torch.Size([4, 3, 28, 28])
print(a[:2].shape)
#取前两张图片的形状
#torch.Size([2, 3, 28, 28])
print(a[:2, 1:, :, :].shape)
#取前两张图片第一个通道的所有行和列
#torch.Size([2, 2, 28, 28])
print(a[:2, -1:, :, :].shape)
#取前两张图片的最后一个通道的所有行和列
#torch.Size([2, 1, 28, 28])
(2)隔段取值
#隔断取值
print(a[:, :, 0:28:2, 0:28:2].shape)
#torch.Size([4, 3, 14, 14])
print(a[:, :, ::2, ::2].shape)
#torch.Size([4, 3, 14, 14])
(3)index_select 传入选中的维度,传入要取的索引值(必须以tensor格式传入)
#selct by specific index
b = a.index_select(0, torch.tensor([1, 2]))
print(b.shape)
#torch.Size([2, 3, 28, 28]) 索引以tensor的形式写 在第一个维度上取索引为1和2的值,即取了两张照片的数据
c = a.index_select(1, torch.tensor([1, 2]))
print(c.shape)
#四张照片都取第2/3个通道上的行列数值
#torch.Size([4, 2, 28, 28])
d = a.index_select(2, torch.arange(28))
print(d.shape)
#torch.Size([4, 3, 28, 28])
e = a.index_select(3, torch.arange(28))
print(d.shape)
#torch.Size([4, 3, 28, 28])
(4)...省略号取值
#...省略号仅仅是为了方便
a = torch.rand(4, 3, 28, 28)
print(a.shape)
#torch.Size([4, 3, 28, 28])
print(a[...].shape)
#取所有维度的所有值
#torch.Size([4, 3, 28, 28])
print(a[0, ...].shape)
#取第一个维度上的所有值
#torch.Size([3, 28, 28])
print(a[:, 1, ...].shape)
#取第一个通道上的所有照片的所有行列值
#torch.Size([4, 28, 28])
print(a[..., :2].shape)
#前面的维度都取,列只取前两列的值
#torch.Size([4, 3, 28, 2])
(5)mask取值
#select by mask,不建议使用
x = torch.randn(3, 4)
print(x)
'''
tensor([[-1.5627, 0.3179, -0.1547, 1.1593],
[-0.7747, 0.1811, 2.0539, -0.2417],
[ 0.2367, -1.3491, 1.1154, 0.3998]])
'''
mask = x.ge(0.5)
#将数值大于0.5的数变为1,其余的值还是0
print(mask)
'''
tensor([[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 0, 1, 0]], dtype=torch.uint8)
'''
c = torch.masked_select(x, mask)
print(c)
'''
tensor([1.1593, 2.0539, 1.1154])
'''
print(c.shape)
#torch.Size([3]) 会把维度打平,只返回值大于0.5的数值的个数
(6)take取值
#select by flatten index
src = torch.tensor([[4, 3, 5], [6, 7, 8]])
x = torch.take(src, torch.tensor([0, 2, 5]))
#take函数把数组打平了,然后输入要取的索引值
print(x)
#tensor([4, 5, 8])
四、维度变换
1、view、reshape降维、升维
import torch
#view、reshape
a = torch.rand(4, 1, 28, 28)
print(a.shape)
#torch.Size([4, 1, 28, 28])
b = a.view(4, 28*28)
#把行和列的数据合并到一起
print(b.shape)
#torch.Size([4, 784])
c = a.view(4*28, 28)
print(c.shape)
#torch.Size([112, 28])
d = a.view(4*1*28, 28)
print(d.shape)
#torch.Size([112, 28])
e = a.view(4, 28, 28, 1)
print(e.shape)
#torch.Size([4, 28, 28, 1])
#破坏了数据本身的逻辑
2、unsqueeze(增加维度,一般来说增加的维度里只有一个值)
unsqueeze里面传入增加维度的位置(索引值)
#unsuqueeze
a = torch.rand(4, 1, 28, 28)
print(a.shape)
#torch.Size([4, 1, 28, 28])
b = a.unsqueeze(0)
print(b.shape)
#torch.Size([1, 4, 1, 28, 28])
c = a.unsqueeze(4)
print(c.shape)
#torch.Size([4, 1, 28, 28, 1])
a = torch.tensor([1.2, 2.3])
b = a.unsqueeze(-1)
print(b)
'''
tensor([[1.2000],
[2.3000]])
'''
c = a.unsqueeze(0)
print(c)
#tensor([[1.2000, 2.3000]])
实际案例
要给一个思维数据(图片数据)增加一个偏置
#案例
b = torch.rand(32)
f = torch.rand(4, 32, 14, 14)
b = b.unsqueeze(1).unsqueeze(2).unsqueeze(0)
print(b.shape)
#torch.Size([1, 32, 1, 1])
3、squeeze减少维度
b = torch.rand(32)
b = b.unsqueeze(1).unsqueeze(2).unsqueeze(0)
print(b.shape)
#torch.Size([1, 32, 1, 1])
print(b.squeeze().shape)
#如果不传参的话,是把能删的都删了
#torch.Size([32])
print(b.squeeze(-1).shape)
#torch.Size([1, 32, 1])
print(b.squeeze(0).shape)
#torch.Size([32, 1, 1])
4、expand——更加推荐的方法
#Expand
b = torch.rand(32)
b = b.unsqueeze(1).unsqueeze(2).unsqueeze(0)
#unsqueeze传入位置,增加维度的位置
b = b.expand(4, 32, 14, 14)
#expand传入的是形状——希望数组拓展成什么形状,expand只支持在1的位置进行扩展
print(b.shape)
torch.Size([4, 32, 14, 14])
b = b.expand(-1, 32, -1, -1)
-1的意思是对该维度不进行扩展
print(b.shape)
torch.Size([1, 32, 1, 1])
5、repeat——实实在在得发生了数据存储
expand传入的是形状,而repeat传入的是增加的倍数值
print(b.shape)
#torch.Size([1, 32, 1, 1])
#b = b.repeat(4, 1, 1, 1)
#print(b.shape)
#torch.Size([4, 32, 1, 1])
b = b.repeat(4, 1, 32, 32)
print(b.shape)
#torch.Size([4, 32, 32, 32])
6、transpose(交换两个维度值的位置)
transpose还需要contiguous一下,把数据连续一下再做变换
#transpose
a = torch.rand(4, 3, 32, 32)
print(a.shape)
#torch.Size([4, 3, 32, 32])
a1 = a.transpose(1, 3).contiguous().view(4, 3*32*32).view(4, 3, 32, 32)
#把1和3维度进行交换之后,变成了(4,32,32,3)然后将后面的三列进行了合并,最后拆分的时候1、3维度进行了交换,这样是不对的,数据遭到了破坏
a2 = a.transpose(1, 3).contiguous().view(4, 3*32*32).view(4, 32, 32, 3).transpose(1, 3)
print(a1.shape, a2.shape)
#torch.Size([4, 3, 32, 32]) torch.Size([4, 3, 32, 32])
#虽然形状是一样的,但是表示的含义却大不相同
print(torch.all(torch.eq(a, a1)))
#tensor(0, dtype=torch.uint8) 表示a和a1不相同
print(torch.all(torch.eq(a, a2)))
#tensor(1, dtype=torch.uint8) 表示a和a2相同
数据的存储、维度顺序非常重要,需要时刻谨记
7、permute
b = torch.rand(4, 3, 28, 32)
b = b.transpose(1, 3) #把1,3维度进行了交换,列在行前面了,这样图片的内容也发生了变化,我们进而将行和列进行一下变换
print(b.shape)
#orch.Size([4, 32, 28, 3])
b = b.transpose(1, 2)
print(b.shape)
#torch.Size([4, 28, 32, 3])
#这样的过程用permute一次性就可以完成
a = torch.rand(4, 3, 28, 31)
a = a.permute(0, 2, 3, 1)
#重新安排位置
print(a.shape)
#torch.Size([4, 28, 31, 3])
五、broadcasting机制
1、什么是broadcasting
(1)expand
(2)without copying data
主要思想
2、why broadcasting
(1)本身有现实意义;
(2)可以节省内存消耗
3、什么情况下使用broadcasting机制?
match from last dim!
·如果当前的dim维度上等于1,扩展在此维度上扩展数值量
·如果维度值为空, 可以自动生成维度并扩展维度值
·否则,则不能进行传播
4、从最小维度开始匹配,我们默认越高维度越相似,而小维度上各有各的不同
[32, 32]给每行每列加一个base基底;
[3, 1, 1]相等于是给每个通道都加个值;
[1, 1, 1, 1]像素点增加了一个值
六、拼接和拆分
1、拼接
stack和cat的区别
cat在指定维度上可以值不同,但是stack在指定维度上的值必须相同
(1)cat
import torch
#cat
a = torch.rand(4, 32, 8)
b = torch.rand(5, 32, 8)
c = torch.cat([a, b], dim=0) #以第一维度为准进行拼接
print(c.shape)
#torch.Size([9, 32, 8])
#现实意义可以理解为两个老师分别统计4/5个班的成绩,每个班有32个学生,每个学生有8门课的成绩,将两个老师统计的数据整合起来
a1 = torch.rand(4, 3, 32, 32)
a2 = torch.rand(5, 3, 32, 32)
d = torch.cat([a1, a2], dim=0)
print(d.shape)
#torch.Size([9, 3, 32, 32])
b1 = torch.rand(4, 1, 32, 32)
e = torch.cat([a1, b1], dim=1)
#在拼接的时候,只有传入的dim维度的那一维度可以不一样,其他维度的数值都必须相同
print(e.shape)
#torch.Size([4, 4, 32, 32])
a1 = torch.rand(4, 3, 16, 32)
a2 = torch.rand(4, 3, 16, 32)
b = torch.cat([a1, a2], dim=2)
print(b.shape)
#torch.Size([4, 3, 32, 32])
(2)stack
#stack
a1 = torch.rand(4, 3, 16, 32)
a2 = torch.rand(4, 3, 16, 32)
c = torch.stack([a1, a2], dim=2)
print(c.shape)
#torch.Size([4, 3, 2, 16, 32])
#stack会在dim=2的维度前增加一个维度
#现实意义是:两个老师分别统计两个班的成绩,一个班有32个人,每个人有8门课的成绩,将他们stack起来,可以表示(2,32,8)
#如果用cat的话,则表示为(64,8)则现实意义上来说不如stack好
2、拆分
(1)split按照长度进行拆分
b = torch.rand(32, 8)
a = torch.rand(32, 8)
c = torch.stack([a, b], dim=0)
print(c.shape)
#torch.Size([2, 32, 8])
aa, bb = c.split(1, dim=0)
print(aa.shape, bb.shape)
#torch.Size([1, 32, 8]) torch.Size([1, 32, 8])
d = torch.rand(5, 32, 8)
a1, a2, a3 = d.split([1, 2, 2], dim=0)
print(a1.shape, a2.shape, a3.shape)
#torch.Size([1, 32, 8]) torch.Size([2, 32, 8]) torch.Size([2, 32, 8])
#把5个班级的成绩进行拆分,拆分成3的模块,一个模块1个班级,两个模块两个班级
#split是按照拆分的长度进行传参的
(2)chunk按照数量进行拆分
#chunk,传参传入的是拆分模块的数量,会自动均匀分配
b = torch.rand(32, 8)
a = torch.rand(32, 8)
c = torch.stack([a, b], dim=0)
print(c.shape)
aa, bb = c.chunk(2, dim=0)
#把两个班级的成绩拆分成两个模块进行比较,split传入的是拆分的长度,拆成长度为1等同于拆成2个模块
print(aa.shape, bb.shape)
#torch.Size([1, 32, 8]) torch.Size([1, 32, 8])
七、数学运算
1、加减乘除
在torch里面,a+b = add(a,b); a - b = sub(a, b); a*b = mul(a, b); a / b=div(a, b)
import torch
a = torch.rand(3, 4)
b = torch.rand(4)
#这两个tensor数组可以直接运算,因为根据broading机制来说,它会自动把b数组转换为跟a数组一样的形状进行运算
print(a+b)
'''
tensor([[1.6960, 1.1914, 1.1556, 1.4485],
[1.6178, 1.0697, 1.1246, 1.1632],
[1.5524, 0.5618, 0.9049, 1.3834]])
'''
print(torch.add(a, b))
'''
tensor([[1.0804, 0.9328, 1.1746, 0.9296],
[0.8897, 0.6246, 1.3664, 0.5070],
[1.2556, 0.3952, 1.2464, 0.7305]])
'''
print(torch.all(torch.eq(a+b, torch.add(a, b))))
#tensor(1, dtype=torch.uint8)
print(torch.all(torch.eq(a-b, torch.sub(a, b))))
#tensor(1, dtype=torch.uint8)
print(torch.all(torch.eq(a*b, torch.mul(a, b))))
#tensor(1, dtype=torch.uint8)
print(torch.all(torch.eq(a/b, torch.div(a, b))))
#tensor(1, dtype=torch.uint8)
2、矩阵相乘 matmul 是按照矩阵的方式相乘
·Torch.mm(只适用于二维矩阵,不建议使用)
·Torch.matmul
·@
#矩阵相乘运算
a = torch.full([2, 2], 3)
b = torch.ones(2, 2)
c = torch.mm(a, b)
print(c)
'''
tensor([[6., 6.],
[6., 6.]])
'''
d = torch.matmul(a, b)
print(d)
'''
tensor([[6., 6.],
[6., 6.]])
'''
e = a@b
print(e)
'''
tensor([[6., 6.],
[6., 6.]])
'''
案例:降维
#一个案例,降维
x = torch.rand(4, 748)
w = torch.rand(512, 748)
#这里的传参的标注是,前面是我们降维的目标,希望降低到多少维度,后面是我们原本的维度
k = x@w.t()
#在这里t()是只适合二维矩阵的转置函数,二维即以上的用transpose
print(k.shape)
#torch.Size([4, 512])
二维即以上的数组进行矩阵相乘:matmul
默认后面两个维度进行矩阵相乘计算
当前面的维度数值相同,直接计算,当么有维度或维度为1时,根据广播机制进行计算,但是当维度的数值个数不为1的时候,没有办法计算,如下案例a与b2无法进行矩阵相乘
a = torch.rand(4, 3, 28, 64)
b = torch.rand(4, 3, 64, 32)
c = torch.matmul(a, b)
print(c.shape)
#torch.Size([4, 3, 28, 32])
b1 = torch.rand(4, 1, 64, 32)
c1 = torch.matmul(a, b1)
#这里的a 和 b1在第二个维度上不一致,但是根据broadcasting机制,它会自动把1的地方扩充为a的维度值,然后进行运算
print(c.shape)
#torch.Size([4, 3, 28, 32])
'''
b2 = torch.rand(4, 64, 32)
#此时的b2和a没办法进行矩阵相乘,因为他们都没有1这个维度值,所以没办法进行扩充
c2 = torch.matmul(a, b2)
print(c2.shape)
#RuntimeError: The size of tensor a (3) must match the size of tensor b (4) at non-singleton dimension 1
'''
3、次方、开方根、开方根倒数
a = torch.full([2, 2], 3)
b = a.pow(2)
print(b)
'''
tensor([[9., 9.],
[9., 9.]])
'''
b1 = a ** 2
print(b1)
'''
tensor([[9., 9.],
[9., 9.]])
'''
c = b1.sqrt()
#对c取平方根
print(c)
'''
tensor([[3., 3.],
[3., 3.]])
'''
d = b1.rsqrt()
#取平方根的倒数
print(d)
'''
tensor([[0.3333, 0.3333],
[0.3333, 0.3333]])
'''
d1 = b1 ** (0.5)
print(d1)
'''
tensor([[3., 3.],
[3., 3.]])
4、指数运算
#e的指数函数tensor数据
a = torch.exp(torch.ones(2, 2))
print(a)
'''
tensor([[2.7183, 2.7183],
[2.7183, 2.7183]])
'''
b = torch.log(a)
#log函数默认以e为底
print(b)
'''
tensor([[1.0000, 1.0000],
[1.0000, 1.0000]])
'''
5、取近似值
floor()取小
ceil()取大
round()四舍五入
trunc()取整数
frac()取小数
裁剪——clamp
打印参数w的梯度:w.grad.norm(2)
torch里面的clamp类似于numpy里面的climp把数值范围进行裁剪
#approximation
a = torch.tensor(3.14)
print(a.floor())
#tensor(3.)
print(a.ceil())
#tensor(4.)
print(a.round())
#tensor(3.)
print(torch.tensor(3.5).round())
#tensor(4.)
print(a.trunc())
#tensor(3.)
print(a.frac())
#tensor(0.1400)
#clamp——裁剪
grad = torch.rand(2, 3) * 15
print(grad.max())
#tensor(9.3662)
print(grad.median())
#tensor(5.9054)
print(grad.clamp(10))
#梯度的最小限定是10
'''
tensor([[10., 10., 10.],
[10., 10., 10.]])
'''
print(grad.clamp(0, 10))
#给出限定范围,0-10之间,大于10的部分都变为10
'''
tensor([[ 0.2897, 3.3792, 6.4364],
[ 3.5287, 10.0000, 8.6903]])
'''
八、统计属性
1、norm——范数
注意:norm不等于normalize(正则化)
vector norm 不等同于 matrix norm
第一范数
第二范数
import torch
#范式
a = torch.full([8], 1)
b = a.reshape(2, 4)
c = a.reshape(2, 2, 2)
print(b)
'''
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.]])
'''
print(c)
'''
tensor([[[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.]]])
'''
#求a,b,c的第一范式
print(a.norm(1))
#tensor(8.)
print(b.norm(1))
#tensor(8.)
print(c.norm(1))
#tensor(8.)
x1 = b.norm(1, dim=1)
#以行为标准,对列进行操作,求每一行的第一范式
print(x1)
#tensor([4., 4.])
x2 = b.norm(2, dim=1)
#以行位标准,对每一列进行操作,求每一行的第二范式
print(x2)
#tensor([2., 2.])
print(c.norm(1, dim=0))
#以第一维度为标准,对每行每列的对应数值进行操作,求第一范数
'''
tensor([[2., 2.],
[2., 2.]])
'''
print(c.norm(2, dim=0))
'''
tensor([[1.4142, 1.4142],
[1.4142, 1.4142]])
'''
2、mean——均值、sum——求和、prob累乘、max——最大值、min——最小值
a = torch.arange(8).view(2, 4).float()
print(a)
'''
tensor([[0., 1., 2., 3.],
[4., 5., 6., 7.]])
'''
print(a.min())
#tensor(0.)
print(a.max())
#tensor(7.)
print(a.prod())
#prod是累乘的意思
#tensor(0.)
print(a.sum())
#tensor(28.)
3、argmin——最小值的位置;argmax——最大值的位置
a = torch.arange(8).view(2, 4).float()
print(a)
#当我们没有指定维度的时候,返回的位置是把数组打平之后的位置索引
print(a.argmax())
#tensor(7)
print(a.argmin())
#tensor(0)
a = a.view(1, 2, 4)
print(a.argmax())
#tensor(7)
print(a.argmin())
#tensor(0)
a = torch.rand(2, 3, 4)
print(a.argmax())
#tensor(10)
a = torch.randn(4, 10)
print(a[0])
'''
tensor([-2.2259, -0.3194, -0.2529, -1.2658, 0.0792, 0.5460, -1.9197, 0.2636,
-0.0684, -1.4274])
'''
print(a.argmax())
#tensor(31)
print(a.argmax(dim=1))
#tensor([6, 8, 0, 1])
#以dim=1为标准是取dim=0的维度上的每张照片(这里仅仅是举了一个应用场景)的最大值
#以列为标准,取每一行上的最大值
print(a.argmax(dim=0))
#tensor([2, 3, 1, 1, 0, 3, 1, 1, 0, 1])
#以行为标准,取每一列上的最大值
dim,keepdim
a = torch.randn(4, 10).float()
print(a)
'''
tensor([[-0.5399, 2.2001, 1.2691, 0.9019, 0.6524, -0.7588, -0.2862, -0.8736,
0.2056, 0.3449],
[-0.1167, 2.1540, -0.2391, -1.2638, 0.2705, -0.7601, 0.8635, -1.4094,
0.4610, -0.4595],
[-1.6827, 0.8954, 0.2086, -0.8916, 0.4781, -0.0702, 1.0478, 1.4631,
1.3250, -0.7159],
[ 0.6034, 0.7537, -0.4327, -0.6153, 0.6938, 0.2003, 0.9891, 0.2207,
-1.4104, -0.1738]])
'''
print(a.max(dim=1))
'''
torch.return_types.max(
values=tensor([2.2001, 2.1540, 1.4631, 0.9891]),
indices=tensor([1, 1, 7, 6]))
'''
#max返回的是最大值的数值和索引位置
print(a.max(dim=1, keepdim=True))
'''
torch.return_types.max(
values=tensor([[2.2001],
[2.1540],
[1.4631],
[0.9891]]),
indices=tensor([[1],
[1],
[7],
[6]]))
'''
print(a.argmax(dim=1, keepdim=True))
'''
tensor([[4],
[4],
[4],
[6]])
'''
a = torch.randn(4, 10).float()
print(a.topk(3, dim=1))
#以列为标准,找每一行的前三大的值
'''
torch.return_types.topk(
values=tensor([[1.1169, 0.4949, 0.4045],
[3.1041, 1.2796, 0.8438],
[0.9410, 0.6610, 0.4236],
[1.7050, 0.2118, 0.1091]]),
indices=tensor([[7, 1, 9],
[9, 8, 6],
[3, 7, 0],
[5, 2, 3]]))
'''
5、比较大小
#基本比较运算
a = torch.randn(4, 10).float()
print(a > 0)
#由于pytorch里面没有string类型,所以判断值返回的是0和1
'''
tensor([[1, 0, 1, 1, 1, 1, 1, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 1, 0, 1]], dtype=torch.uint8)
'''
print(torch.gt(a, 0))
#其功能同上
'''
tensor([[1, 0, 1, 1, 1, 1, 1, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 1, 0, 1]], dtype=torch.uint8)
'''
print(a != 0)
'''
tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=torch.uint8)
'''
b = torch.ones(2, 3)
b1 = torch.randn(2, 3)
print(torch.eq(b, b1))
'''
tensor([[0, 0, 0],
[0, 0, 0]], dtype=torch.uint8)
'''
print(torch.eq(b, b))
'''
tensor([[1, 1, 1],
[1, 1, 1]], dtype=torch.uint8)
'''
print(torch.equal(b, b))
#True
拓展:where、gather
where
#where
cond = torch.rand(2, 2)
print(cond)
'''
tensor([[0.3904, 0.8854],
[0.7794, 0.7720]])
'''
a = torch.zeros(2, 2)
b = torch.ones(2, 2)
x = torch.where(cond > 0.5, a, b)
#大于0.5的地方用a来代替,否则用b来赋值,赋值是在对应的位置赋对应数组的值
print(x)
'''
tensor([[1., 1.],
[0., 1.]])
'''
gather
#gather
prob = torch.randn(4, 10)
idx = prob.topk(dim=1, k=3)
print(idx)
'''
torch.return_types.topk(
values=tensor([[1.2111, 1.0892, 1.0405],
[2.6614, 0.9915, 0.9800],
[0.9517, 0.5465, 0.4751],
[2.0146, 0.2789, 0.0141]]),
indices=tensor([[6, 3, 1],
[2, 8, 9],
[6, 1, 8],
[4, 3, 2]]))
'''
idx = idx[1]
label = torch.arange(10) + 100
print(label)
#tensor([100, 101, 102, 103, 104, 105, 106, 107, 108, 109])
x = torch.gather(label.expand(4, 10), dim=1, index=idx.long())
print(x)
'''
ensor([[105, 108, 107],
[106, 100, 108],
[108, 107, 100],
[107, 101, 105]])
'''
5、kthvalue——第几个的数值和位置
a = torch.randn(4, 10).float()
print(a.kthvalue(8, dim=1))
#kthvalue默认取第k小的值,且只能是取第k小的值,第8小的值就是第三大的值
'''
torch.return_types.kthvalue(
values=tensor([0.4045, 0.8438, 0.4236, 0.1091]),
indices=tensor([9, 6, 0, 3]))
'''
6、topk——top几的位置和数值
a = torch.randn(4, 10).float()
print(a.topk(3, dim=1, largest=False))
#largest=False表示改变排序方式,从小到大排列,取最小的三个值
'''
torch.return_types.topk(
values=tensor([[-0.6322, -0.4538, 0.0437],
[-1.9131, -1.8761, -0.9199],
[-0.8112, -0.6957, -0.5263],
[-0.6981, -0.6127, -0.4714]]),
indices=tensor([[6, 0, 3],
[4, 3, 0],
[1, 2, 9],
[6, 4, 7]]))
'''