pytorch-day02

1、基本数据类型

 Data type:

 Type check:

a = torch.randn(2, 3)
print(a.type())  # torch.FloatTensor
print(type(a))  # <class 'torch.Tensor'>
print(isinstance(a, torch.FloatTensor))  # True

print(isinstance(a, torch.cuda.FloatTensor))  # False
a = a.cuda()  # 搬运到cuda上
print(isinstance(a, torch.cuda.FloatTensor))  # True

2、维度

 2.1、标量(Dimension 0 / rank 0),例如loss

# 0维:没有[]
a = torch.tensor(1.0)
print(a)  # tensor(1.)
print(a.shape)  # torch.Size([])
print(len(a.shape))  # 0
print(a.size())  # torch.Size([])

 2.2、向量(Dim 1 / rank 1),例如bias

# 1维:最外层有1个[]
a = torch.tensor([1.1, 2.2])
print(a)  # tensor([1.1000, 2.2000])
print(a.shape)  # torch.Size([2])
print(len(a.shape))  # 1
print(a.size())  # torch.Size([2])

# 随机生成时,只需要指定维数(容易和0维时混淆)
b = torch.FloatTensor(1)
b = torch.FloatTensor(2)
# 使用numpy生成
c = np.ones(3)
d = torch.from_numpy(c)

 2.3、矩阵(Dim 2),例如带有batch的线性函数的输入

# 2维:最外层有2个[]
a = torch.randn(2, 3)  
print(a)
print(a.shape)  # torch.Size([2, 3])
print(a.shape[0])  # 2
print(a.shape[1])  # 3
print(a.size(0))  # 2
print(a.size(1))  # 3

 2.4、Dim 3,例如,RNN中,[10,20,100]:10句话(即batch为10);每句话有20个单词;每个单词用100维的向量表示

# 3维:最外层有3个[]
a = torch.randn(2, 3, 4)  
print(a)
print(a.shape)  # torch.Size([2, 3, 4])
print(list(a.shape))  # [2, 3, 4])
print(a.shape[0])  # 2
print(a.shape[1])  # 3
print(a.shape[2])  # 4
print(a.size(0))  # 2
print(a.size(1))  # 3
print(a.size(2))  # 4

 2.5、Dim 4,例如CNN中,图片[2,3,28,28]:2张图片;3彩色图(为1时是灰度图);28图片的像素

a = torch.randn(2, 3, 28, 28)

 2.6、补充

# 4维:最外层有4个[]
a = torch.randn(2, 3, 28, 28)
# 所占的内存大小,即2*3*28*28
print(a.numel())  # 4704
# 维度
print(a.dim())  # 4

3、创建Tensor

# 1、从Numpy引入
a = np.array([2, 3.3])
b = torch.from_numpy(a)

c = torch.tensor([5, 8.8])  # 小写的是接收现成的数据
print(c)
d = torch.Tensor([5, 8.8])  # 大写的可以接收现成的数据
print(d)
e = torch.Tensor(2, 3)  # 大写的也可以接受shape
print(e)

 3.1、创建未初始化的数据(不代表没有数据,而是其中的数据很random)

# 1、Torch.empty() 括号里给shape
a = torch.empty(2, 3)
print(a)
# 2、Torch.FloatTensor(d1, d2, d3) 数值会很大或很小,所有这种只适合做容器,后期需要把具体的数据写进来
b = torch.FloatTensor(2, 3)
print(b)
# 3、Torch.IntTensr(d1, d2, d3)
c = torch.IntTensor(2, 3)
print(c)

 3.2、设置默认类型

# torch.Tensor()默认与torch.FloatTensor()同类型
print(torch.Tensor(2, 3).type())  # torch.FloatTensor
print(torch.FloatTensor(2, 3).type())  # torch.FloatTensor

torch.set_default_tensor_type(torch.DoubleTensor)
print(torch.Tensor(2, 3).type())  # torch.DoubleTensor

  3.3、创建并初始化数据

# 1、rand:会随机产生0~1之间的数值,不包括1
a = torch.rand(3, 3)
print(a)
# 2、rand_like:把参数(tensor类型)的读出来,传给torch.rand()
b = torch.rand_like(a)
print(b)
# 在上面的基础上,可以均匀采样0~10的tensor
c = 10 * torch.rand(2, 3)
print(c)
# 3、randint只能采样整数(min,max,shape)
d = torch.randint(1, 10, [1, 2, 3])
print(d)
# 4、randn:正太分布N(0,1):均值为0,方差为1
e = torch.randn(3, 3)
print(e)
# normal:自定义正太分布的均值和方差
f = torch.normal(mean=torch.full([10], 0), std=torch.arange(1, 0, -0.1))
print(f)
# torch.full:第一个参数是shape,第二个参数是填充的数
g = torch.full([2, 3], 7)
print(g)
torch.full([], 7)
torch.full([1], 7)
# 5、arange/range(不建议使用):等差数列
h = torch.arange(0, 10, 2)  # 第三个参数默认是1
print(h)
# 6、linspace(0,10,step=4):取4个数
i = torch.linspace(0, 10, 11)
print(i)
# 7、logspace(a,b,c):从10^a到10^b中取c个数
j = torch.logspace(0, 1, steps=8)
print(j)
# 8、Ones/zeros/eye(对角线为1):参数是shape
# 9、randperm():随机打散
k = torch.randperm(10)
print(k)
# 两个tensor需要保持对应时
aa = torch.rand(2, 3)
bb = torch.rand(2, 2)
idx = torch.randperm(2)
print(aa[idx])
print(bb[idx])

4、切片和索引

 1 a = torch.rand(4, 3, 28, 28)
 2 print(a[0].shape)  # torch.Size([3, 28, 28])
 3 print(a[0][0].shape)  # torch.Size([28, 28])
 4 print(a[0][0][0].shape)  # torch.Size([28])
 5 print(a[0][0][2][4])  # tensor(0.0374)
 6 
 7 b = a[:2]  # 前两张图片
 8 print(b.shape)  # torch.Size([2, 3, 28, 28])
 9 c = a[:2, :1, :, :]  # 前两张图片的第1个通道上所有的数据
10 print(c.shape)  # torch.Size([2, 1, 28, 28])
11 d = a[:2, 1:, :, :]  # 前两张图片的除了第1个通道上所有的数据
12 print(d.shape)  # torch.Size([2, 2, 28, 28])
13 e = a[:2, -1:, :, :]  # 前两张图片的最后1个通道上所有的数据
14 print(e.shape)  # torch.Size([2, 1, 28, 28])
15 
16 # 隔行采样(start:end:steps)不包含end
17 f = a[:, :, 0:28:2, 0:28:2]  # 隔2行进行采样,默认行数是1
18 print(f.shape)  # torch.Size([4, 3, 14, 14])
19 h = a[:, :, 0:28:, 0:28:]
20 print(h.shape)  # torch.Size([4, 3, 28, 28])
21 g = a[:, :, ::2, ::2]
22 print(g.shape)  # torch.Size([4, 3, 14, 14])
 1 # index_select(a,torch.tensor([0,2])):a:表示要操作的通道,第二个参数表示取a通道的第0个数据和第3个数据
 2 a = torch.rand(4, 3, 28, 28)
 3 b = a.index_select(0, torch.tensor([0, 2]))
 4 print(b.shape)  # torch.Size([2, 3, 28, 28])
 5 
 6 # ...:任意多的维度
 7 print(a[...].shape)  # torch.Size([4, 3, 28, 28])
 8 print(a[0, ...].shape)  # torch.Size([3, 28, 28])
 9 
10 # ge(i):把大于i的数值置为True
11 x = torch.randn(2, 3)
12 c = x.ge(0.5)
13 print(c)
14 # 再把掩码为True的数取出来
15 d = torch.masked_select(x, c)
16 print(d)
17 
18 # 打平之后再取值
19 y = torch.tensor([[1, 2, 3], [4, 5, 6]])
20 z = torch.take(y, torch.tensor([0, 2, 5]))
21 print(z)  # tensor([1, 3, 6])

5、Tensor维度变换

 1 # 1、View/reshape
 2 a = torch.rand(4, 1, 28, 28)
 3 b = a.view(4, 1 * 28 * 28)  # 只要保持整个Tensor的a.numel()不变即可
 4 a.view(4 * 1, 28, 28)
 5 a.view(4 * 1 * 28, 28)
 6 # 弊端,在恢复原始数据维度时,容易丢失维度是“1”的维度信息
 7 
 8 # 2、Squeeze/unsqueeze(删减/增加维度),给数据新增加/减少一个组别,不改变数据
 9 print(a.unsqueeze(0).shape)  # torch.Size([1, 4, 1, 28, 28])
10 print(a.unsqueeze(-1).shape)  # torch.Size([4, 1, 28, 28, 1])
11 print(a.unsqueeze(4).shape)  # torch.Size([4, 1, 28, 28, 1])
12 print(a.unsqueeze(-4).shape)  # torch.Size([4, 1, 1, 28, 28])
13 print(a.unsqueeze(-5).shape)  # torch.Size([1, 4, 1, 28, 28])
14 # print(a.unsqueeze(5).shape)  # IndexError
15 # squeeze()的操作与unsqueeze()对应
16 # 注意1:squeeze()不给参数的话,会把所有维度为"1"的全挤压。
17 # 注意2:对于维度不为"1"即不能挤压的,返回原始数据
18 
19 # 3、Transpose/t/permute(矩阵的转置)
20 # 3.1、t():只适合于矩阵(2D)
21 e = torch.rand(2, 3)
22 e.t()
23 # 3.2、transpose(a,b):交换a,b维度
24 f = torch.rand(4, 3, 32, 32)
25 # a1=a.transpose(1,3).view(4,3*32*32).view(4,3,32,32) # RuntimeError
26 f1 = f.transpose(1, 3).contiguous().view(4, 3 * 32 * 32).view(4, 3, 32, 32)  # 错误用法,数据污染
27 f2 = f.transpose(1, 3).contiguous().view(4, 3 * 32 * 32).view(4, 32, 32, 3)  # 推荐用法
28 f3 = f.transpose(1, 3).contiguous().view(4, 3 * 32 * 32).view(4, 32, 32, 3).transpose(1, 3)
29 print(f1.shape)  # torch.Size([4, 3, 32, 32])
30 print(f3.shape)  # torch.Size([4, 3, 32, 32])
31 print(torch.all(torch.eq(f, f1)))  # tensor(False)
32 print(torch.all(torch.eq(f, f3)))  # tensor(True)
33 # 3.3、permute(a,b,c,d):参数表示维数的位置
34 g = f.permute(0, 2, 3, 1)
35 
36 # 4、Expand/repea(维度的扩展),两者效果一样,仅限于原来的维度是"1"
37 c = torch.rand(32)
38 c = c.unsqueeze(1).unsqueeze(2).unsqueeze(0)  # torch.Size([1, 32, 1, 1])
39 d = torch.rand(4, 32, 14, 14)
40 # 如果想让c和d相加,就要对c进行扩展
41 # 4.1、Expand: broadcasting(不会主动复制数据)推荐,速度快,节省内存
42 print(c.expand(4, 32, 14, 14).shape)  # torch.Size([4, 32, 14, 14])
43 print(c.expand(-1, 32, -1, -1).shape)  # torch.Size([1, 32, 1, 1]),-1表示不变
44 print(c.expand(-1, 32, -1, -4).shape)  # torch.Size([1, 32, 1, -4]) ,无意义
45 # 4.2、Repeat: memory copied(把所有扩展的数据按原数据拷贝一遍)
46 print(c.repeat(4, 32, 1, 1).shape)  # torch.Size([4, 1024, 1, 1]),每个参数表示对应维度拷贝的次数
47 print(c.repeat(4, 1, 14, 14).shape)  # torch.Size([4, 32, 14, 14])

6、Broadcasting(自动扩展)

 

 6.1、Why broadcasting

  

7、合并与分割

# 1、Cat除了指定的dim,其它维度要相同
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])
# 2、Stack
a1 = torch.rand(4, 3, 16, 16)
a2 = torch.rand(4, 3, 16, 16)
print(torch.cat([a1, a2], dim=2).shape)  # torch.Size([4, 3, 32, 16])
print(torch.stack([a1, a2], dim=2).shape)  # torch.Size([4, 3, 2, 16, 16])

b = torch.rand(32, 8)
c = torch.rand(30, 8)
print(torch.cat([b, c], dim=0).shape)  # torch.Size([62, 8])
# print(torch.stack([b,c],dim=0).shape) # RuntimeError
# 3、Split
b1 = torch.rand(32, 8)
c1 = torch.rand(32, 8)
d1 = torch.stack([b1, c1], dim=0)  # torch.Size([2, 32, 8])
bb, cc = d1.split([1, 1], dim=0)
print(bb.shape, cc.shape)  # torch.Size([1, 32, 8]) torch.Size([1, 32, 8])
bb, cc = d1.split(1, dim=0)
print(bb.shape, cc.shape)  # torch.Size([1, 32, 8]) torch.Size([1, 32, 8])
# bb,cc=d1.split(2,dim=0) #ValueError
# 4、Chunk
bb, cc = d1.chunk(2, dim=0)
print(bb.shape, cc.shape)  # torch.Size([1, 32, 8]) torch.Size([1, 32, 8])

8、基本运算

 

 1 # 1、Add/minus/multiply/divide
 2 a = torch.rand(3, 4)
 3 b = torch.rand(4)
 4 print(torch.all(torch.eq(a + b, torch.add(a, b))))  # tensor(True)
 5 
 6 # 2、矩阵相乘
 7 # 2.1、*:相同位置相乘
 8 # 2.1、torch.mm:只适合2Dtensor,所有不推荐
 9 # 2.2、torch.matmul
10 # 2.3、@:与torch.matmul一样
11 a = torch.rand(4, 3, 28, 64)
12 b = torch.rand(4, 3, 64, 32)
13 print(torch.matmul(a, b).shape)  # torch.Size([4, 3, 28, 32]) #前面的两维保持不变
14 # 3、pow次方
15 a = torch.full([2, 2], 3)
16 print(a.pow(2))
17 print(a ** 2)
18 # 4、sprt次方根
19 b = a.pow(2)
20 print(b.sqrt())
21 print(b ** 0.5)
22 # 5、rsqrt先开方,再求导数
23 a = torch.tensor([4., 4.])
24 print(a.rsqrt())
25 
26 a = torch.exp(torch.ones(2, 2))  # 全是e
27 print(torch.log(a))
28 print(torch.log2(a))
29 print(torch.log10(a))
30 # 6、round矩阵的近似运算
31 # 往下取整/往上取整/取整/取小数/四舍五入
32 a = torch.tensor(3.14)
33 print(a.floor(), a.ceil(), a.trunc(), a.frac(), a.round())  # tensor(3.) tensor(4.) tensor(3.) tensor(0.1400) tensor(3.)
34 
35 # 7、clamp裁剪(限制),例如gradient clipping
36 grad = torch.rand(2, 3) * 15
37 print(grad.max())
38 print(grad.median())
39 print(grad.clamp(10))  # 把数值限制在10以上
40 print(grad.clamp(0, 10))  # 把数值限制在0~10之间

9、Tensor统计

 

 

 

 

 


 

posted @ 2020-07-23 10:33  小吴的日常  阅读(274)  评论(0)    收藏  举报