带你从入门到精通——深度学习(二. PyTorch中的类型转换、运算和索引)
例如,获取张量t中第0行全部列的数据可以使用t[0,:]或者t[0]。
建议先阅读我之前的深度学习博客,掌握一定的深度学习前置知识后再阅读本文,链接如下:
带你从入门到精通——深度学习(一. 深度学习简介和PyTorch入门)-CSDN博客
目录
二. PyTorch中的类型转换、运算和索引
2.1 类型转换
2.1.1 张量元素类型转换
可以使用如下方法转换张量的dtype属性:
import torch
# 方法一:统一使用type()函数
t1 = torch.rand(3, 3)
t2 = t1.type(torch.ShortTensor)
t3 = t1.type(torch.IntTensor) # dtype为int64
t4 = t1.type(torch.LongTensor)
t5 = t1.type(torch.FloatTensor) # dtype为float32
t6 = t1.type(torch.DoubleTensor)
print(t2, t3, t4, t5, t6, sep='\n')
'''
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]], dtype=torch.int16)
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]], dtype=torch.int32)
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
tensor([[0.2954, 0.8667, 0.4989],
[0.4912, 0.0715, 0.1602],
[0.8600, 0.3063, 0.4580]])
tensor([[0.2954, 0.8667, 0.4989],
[0.4912, 0.0715, 0.1602],
[0.8600, 0.3063, 0.4580]], dtype=torch.float64)
'''
# 方法二:使用各自对应的函数
t1 = torch.randn(3, 3)
t2 = t1.short()
t3 = t1.int() # dtype为int64
t4 = t1.long()
t5 = t1.float() # dtype为float32
t6 = t1.double()
print(t2, t3, t4, t5, t6, sep='\n')
'''
tensor([[ 0, 0, -1],
[ 0, 0, 0],
[ 0, 0, -1]], dtype=torch.int16)
tensor([[ 0, 0, -1],
[ 0, 0, 0],
[ 0, 0, -1]], dtype=torch.int32)
tensor([[ 0, 0, -1],
[ 0, 0, 0],
[ 0, 0, -1]])
tensor([[-5.2128e-01, 2.4985e-01, -1.8288e+00],
[-1.1770e-03, -9.7328e-01, 3.0126e-01],
[-8.1348e-01, -2.8600e-01, -1.0277e+00]])
tensor([[-5.2128e-01, 2.4985e-01, -1.8288e+00],
[-1.1770e-03, -9.7328e-01, 3.0126e-01],
[-8.1348e-01, -2.8600e-01, -1.0277e+00]], dtype=torch.float64)
'''
2.1.2 数组和张量的转换
NumPy中的ndarray数组与PyTorch中的Tensor张量可以相互转换,具体方法如下:
import torch
import numpy as np
# tensor转numpy
t = torch.tensor([2, 4, 6])
arr1 = t.numpy() # 共享内存
arr2 = t.numpy().copy() # 不共享内存
# numpy转tensor
arr = np.array([1, 2, 3])
t1 = torch.from_numpy(arr) # 共享内存
t2 = torch.from_numpy(arr.copy()) # 不共享内存
t3 = torch.tensor(arr) # 不共享内存
注意:共享内存是指如果修改一方里的数据,另一方里的数据也会被修改。
标量张量(即内部只有一个元素的张量)也可以使用如下方法转换为数字:
t_scalar1 = torch.tensor(1)
t_scalar2 = torch.tensor([[6]])
print(t_scalar1.item()) # 输出1
print(t_scalar2.item()) # 输出6
2.2 数值运算
2.2.1 加减乘除运算
张量的加减乘除运算的方法如下:
import torch
# 加法运算的四种方法
t1 = torch.tensor([[1, 2], [3, 4]])
t2 = t1 + 1
t3 = torch.add(t1, 2)
t4 = t1.add(t1)
t1.add_(3) # 此方法不返回新的tensor,而是直接修改原tensor(即t1张量)
print(t2, t3, t4, t1, sep='\n')
'''
tensor([[2, 3],
[4, 5]])
tensor([[3, 4],
[5, 6]])
tensor([[2, 4],
[6, 8]])
tensor([[4, 5],
[6, 7]])
'''
# 减法运算的四种方法
t1 = torch.tensor([[1, 2], [3, 4]])
t2 = t1 - 1
t3 = torch.sub(t1, 2)
t4 = t1.sub(t1)
t1.sub_(3) # 此方法不返回新的tensor,而是直接修改原tensor(即t1张量)
print(t2, t3, t4, t1, sep='\n')
'''
tensor([[0, 1],
[2, 3]])
tensor([[-1, 0],
[ 1, 2]])
tensor([[0, 0],
[0, 0]])
tensor([[-2, -1],
[ 0, 1]])
'''
# 乘法运算的四种方法
t1 = torch.tensor([[1, 2], [3, 4]])
t2 = t1 * 2
t3 = torch.mul(t1, 3)
t4 = t1.mul(t1)
t1.mul_(2) # 此方法不返回新的tensor,而是直接修改原tensor(即t1张量)
print(t2, t3, t4, t1, sep='\n')
'''
tensor([[2, 4],
[6, 8]])
tensor([[ 3, 6],
[ 9, 12]])
tensor([[ 1, 4],
[ 9, 16]])
tensor([[2, 4],
[6, 8]])
'''
# 除法运算的四种方法
t1 = torch.tensor([[2, 4], [6, 8]], dtype=torch.float32)
t2 = t1 / 2
t3 = torch.div(t1, 3)
t4 = t1.div(t1)
t1.div_(2) # 此方法不返回新的tensor,而是直接修改原tensor(即t1张量)
print(t2, t3, t4, t1, sep='\n') # 输出的dtype均为float32
'''
tensor([[1., 2.],
[3., 4.]])
tensor([[0.6667, 1.3333],
[2.0000, 2.6667]])
tensor([[1., 1.],
[1., 1.]])
tensor([[1., 2.],
[3., 4.]])
'''
注意:上述方法的乘法运算中,如果两个乘数均为矩阵,被称为矩阵的点乘,也叫哈达玛积(Hadamard product)。
注意:上述方法的除法运算中,如果原张量的dtype为整数类型,则无法使用div_方法直接修改原张量,需要先将原张量的dtype转换为浮点类型。
2.2.2 矩阵乘法运算
矩阵乘法运算要求第一个矩阵列数等于第二个矩阵的行数,又被称为矩阵的叉乘,也叫点积,其使用方法如下:
import torch
# 矩阵乘法运算的三种方法
t1 = torch.tensor([[2, 4], [6, 8], [10, 12]])
t2 = torch.tensor([[2, 3, 4], [2, 3, 4]])
t3 = t1 @ t2
t4 = t1.matmul(t2)
t5 = torch.matmul(t1, t2)
print(t3, t4, t5, sep='\n')
'''
tensor([[12, 18, 24],
[28, 42, 56],
[44, 66, 88]])
tensor([[12, 18, 24],
[28, 42, 56],
[44, 66, 88]])
tensor([[12, 18, 24],
[28, 42, 56],
[44, 66, 88]])
'''
2.2.3 取反运算
张量的取反运算的使用方法如下:
import torch
# 张量取反运算的三种方法
t1 = torch.tensor([[2, 4], [6, 8], [10, 12]])
t2 = t1.neg()
t3 = torch.neg(t1)
t1.neg_() # 此方法不返回新的tensor,而是直接修改原tensor(即t1张量)
print(t2, t3, t1, sep='\n')
'''
tensor([[ -2, -4],
[ -6, -8],
[-10, -12]])
tensor([[ -2, -4],
[ -6, -8],
[-10, -12]])
tensor([[ -2, -4],
[ -6, -8],
[-10, -12]])
'''
2.3 常用运算函数
常用运算函数的使用方法如下:
import torch
torch.random.manual_seed(0)
t = torch.randint(2, 9, (3, 4), dtype=torch.float32)
print(t)
'''
tensor([[6., 5., 2., 4.],
[3., 4., 8., 5.],
[6., 7., 4., 2.]])
'''
# 计算平均值
print(t.mean()) # 计算张量全部元素的平均值
# tensor(4.6667)
print(t.mean(dim=0)) # 计算张量按行的平均值(将行的长度收缩为1)
# tensor([5.0000, 5.3333, 4.6667, 3.6667])
print(t.mean(dim=1)) # 计算张量按列的平均值(将列的长度收缩为1)
# tensor([4.2500, 5.0000, 4.7500])
# 计算总和
print(t.sum()) # 计算张量全部元素的总和
# tensor(56.)
print(t.sum(dim=0)) # 计算张量按行的总和(将行的长度收缩为1)
# tensor([15., 16., 14., 11.])
print(t.sum(dim=1)) # 计算张量按列的总和(将列的长度收缩为1)
# tensor([17., 20., 19.])
# 计算平方
print(t.pow(2))
'''
tensor([[36., 25., 4., 16.],
[ 9., 16., 64., 25.],
[36., 49., 16., 4.]])
'''
# 计算平方根
print(t.sqrt())
'''
tensor([[2.4495, 2.2361, 1.4142, 2.0000],
[1.7321, 2.0000, 2.8284, 2.2361],
[2.4495, 2.6458, 2.0000, 1.4142]])
'''
# 计算指数, 即计算以e为底数,以张量中的元素为指数的结果
print(t.exp())
'''
tensor([[ 403.4288, 148.4132, 7.3891, 54.5981],
[ 20.0855, 54.5981, 2980.9580, 148.4132],
[ 403.4288, 1096.6332, 54.5981, 7.3891]])
'''
# 计算对数
print(t.log()) # 计算以e为底数,以张量中的元素为真数的结果
'''
tensor([[1.7918, 1.6094, 0.6931, 1.3863],
[1.0986, 1.3863, 2.0794, 1.6094],
[1.7918, 1.9459, 1.3863, 0.6931]])
'''
print(t.log2()) # 计算以2为底数,以张量中的元素为真数的结果
'''
tensor([[2.5850, 2.3219, 1.0000, 2.0000],
[1.5850, 2.0000, 3.0000, 2.3219],
[2.5850, 2.8074, 2.0000, 1.0000]])
'''
print(t.log10()) # 计算以10为底数,以张量中的元素为真数的结果
'''
tensor([[0.7782, 0.6990, 0.3010, 0.6021],
[0.4771, 0.6021, 0.9031, 0.6990],
[0.7782, 0.8451, 0.6021, 0.3010]])
'''
# 其他常用方法如下:(下述方法均可以通过dim参数指定函数作用的维度)
print(torch.median(t)) # 计算张量全部元素的中位数, tensor(4.)
print(torch.var(t)) # 计算张量全部元素的方差. tensor(3.5152)
print(torch.std(t)) # 计算张量全部元素的标准差. tensor(1.8749)
print(torch.argmax(t)) # 计算张量全部元素的最大值索引, tensor(6)
print(torch.argmin(t)) # 计算张量全部元素的最小值索引, tensor(2)
print(torch.max(t)) # 计算张量全部元素的最大值, tensor(8.)
print(torch.min(t)) # 计算张量全部元素的最小值, tensor(2.)
注意:上述方法均有torch.func(data,dim=None)和data.func(dim=None)两种使用形式。
2.4 索引和切片操作
在操作张量时,经常要去获取张量中的某些元素进行处理或者修改,此时就需要进行索引和切片操作,常用的索引和切片操作如下:
import torch
torch.random.manual_seed(0)
t = torch.randint(1, 9, (4, 5))
print(t)
'''
tensor([[5, 8, 6, 1, 4],
[4, 4, 8, 2, 4],
[6, 3, 5, 8, 7],
[1, 1, 5, 3, 2]])
'''
# 1. 直接索引
# 1.1 指定单个索引, 即两个离散索引
print(t[0, 1]) # 获取第0行、第1列的值
'''
tensor(8)
'''
# 1.2 指定范围索引, 即两个连续索引
print(t[0:2, 1:3]) # 获取第0行到第1行、第1列到第2列的值
'''
tensor([[8, 6],
[4, 8]])
'''
# 1.3 指定单一范围索引, 即一个连续索引和一个离散索引
print(t[0:2, 1]) # 获取第0行到第1行、第1列的值
'''
tensor([8, 4])
'''
# 2. 列表索引
# 2.1 指定两组离散索引
print(t[[0, 1], [1, 3]]) # 获取第0行、第1列和第1行、第3列的值
'''
tensor([8, 2])
'''
# 2.2 指定一个连续索引,一组离散索引
print(t[0:2, [1, 3]]) # 获取第0行到第1行的第1列和第3列的值
'''
tensor([[8, 1],
[4, 2]])
'''
# 2.3 指定一组列表离散索引, 一组离散索引
print(t[[[0], [2]], [0, 3]]) # 获取第0行和第2行的第0列和第3列的值
'''
tensor([[5, 1],
[6, 8]])
'''
# 3. 布尔索引
print(t[t[:, 0] >= 5, 2:]) # 获取第0列的值大于等于5的行中第2列到最后一列的值
'''
tensor([[6, 1, 4],
[5, 8, 7]])
'''
print(t[:, t[3] > 2]) # 获取第3行的值大于2的列中全部行的值
'''
tensor([[6, 1],
[8, 2],
[5, 8],
[5, 3]])
'''
注意:最后一维的全体切片操作(即':')可以省略不写,例如,获取张量t中第0行全部列的数据可以使用t[0,:]或者t[0]。
更多推荐



所有评论(0)