张量的创建
张量(Tensors)类似于NumPy的ndarrays,但张量可以在GPU上进行计算。 所以从本质上来说,PyTorch是一个处理张量的库。一个张量是一个数字、向量、矩阵或任何n维数组。
下面分别展示了0维张量到n位张量:
import torch
import numpy
torch.manual_seed(7) # 固定随机数种子
'''
<torch._C.Generator at 0x7f168427f780>
'''
一、直接创建
- torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
- 功能:从data创建tensor
data: 数据,可以是list,numpy
dtype: 数据类型,默认与data的一致
device: 所在设备,cuda/cpu
requires_grad: 是否需要梯度
pin_memory: 是否存于锁页内存
torch.tensor([[0.1, 1.2], [2.2, 3.1], [4.9, 5.2]])
'''
tensor([[0.1000, 1.2000],
, [2.2000, 3.1000],
, [4.9000, 5.2000]])
'''
- torch.from_numpy(ndarray)
- 功能:从numpy创建tensor
注意事项:从torch.from_numpy创建的tensor于原ndarray共享内存,当修改其中一个数据,另一个也将会被改动。
a = numpy.array([1, 2, 3])
t = torch.from_numpy(a)
二、依据数值创建
- torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:依size创建全0张量
size: 张量的形状,如(3, 3)、(3, 224, 224)
out: 输出的张量
layout: 内存中布局形式,有strided, sparse_coo等
device: 所在设备,gpu/cpu
requires_grad: 是否需要梯度
torch.zeros(2, 3)
'''
tensor([[0., 0., 0.],
, [0., 0., 0.]])
'''
- torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False)
- 功能:依input形状创建全0张量
input: 创建与input同形状的全0张量
dtype: 数据类型
layout: 内存中布局形式
input = torch.empty(2, 3)
torch.zeros_like(input)
'''
tensor([[0., 0., 0.],
, [0., 0., 0.]])
'''
torch.ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.ones(2, 3)
'''
tensor([[1., 1., 1.],
, [1., 1., 1.]])
'''
- torch.ones_like(input, dtype=None, layout=None, device=None, requires_grad=False)
- 功能:依input形状创建全1张量
size: 张量的形状,如(3, 3)、(3, 224, 224)
dtype: 数据类型
layout: 内存中布局形式
device: 所在设备,gpu/cpu
requires_grad: 是否需要梯度
input = torch.empty(2, 3)
torch.ones_like(input)
'''
tensor([[1., 1., 1.],
, [1., 1., 1.]])
'''
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.full((2, 3), 3.141592)
'''
tensor([[3.1416, 3.1416, 3.1416],
, [3.1416, 3.1416, 3.1416]])
'''
- torch.full_like(input, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能: 依input形状创建指定数据的张量
size: 张量的形状,如(3, 3)
fill_value: 张量的值 - torch.arange(start=0, end. step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:创建等差的1维张量
start: 数列起始值
end: 数列“结束值”
step: 数列公差,默认为1 - 注意事项:数值区间为 [start, end)
torch.arange(1, 2.5, 0.5)
'''
tensor([1.0000, 1.5000, 2.0000])
'''
- torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:创建均分的1维张量
start: 数列起始值
end: 数列结束值
steps: 数列长度
torch.linspace(start=-10, end=10, steps=5)
'''
tensor([-10., -5., 0., 5., 10.])
'''
- torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能: 创建对数均分的1维张量
- 注意事项:长度为steps,底为base
start: 数列起始值
end: 数列结束值
steps: 数列长度
base: 对数函数的底,默认为10
torch.logspace(start=0.1, end=1.0, steps=5)
'''
tensor([ 1.2589, 2.1135, 3.5481, 5.9566, 10.0000])
'''
- torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能: 创建单位对角矩阵(2维张量)
- 注意事项:默认为方阵
n:矩阵行数
m:矩阵列数
torch.eye(3)
'''
tensor([[1., 0., 0.],
, [0., 1., 0.],
, [0., 0., 1.]])
'''
三、依概率分布创建张量
- torch.normal(mean, std, out=None)
- 功能:生成正态分布(高斯分布)
mean: 均值
std: 标准差 - 四种模式:
mean为标量,std为标量
mean为标量,std为张量
mean为张量,std为标量
mean为张量,std为张量
# mean为张量, std为张量
torch.normal(mean=torch.arange(1., 11.), std=torch.arange(1, 0, -0.1))
'''
tensor([0.8532, 2.7075, 3.7575, 3.2200, 6.0145, 5.5526, 6.8577, 8.3697, 9.0276,
, 9.8318])
'''
- torch.normal(mean, std, size, out=None)
- 功能:生成一定大小的生成正态分布(高斯分布)
torch.normal(2, 3, size=(1, 4))
'''
tensor([[2.9530, 2.3984, 2.4120, 2.7216]])
'''
- torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:生成标准正态分布
size: 张量的形状
torch.randn(2, 3)
'''
tensor([[1.3955, 1.3470, 2.4382],
, [0.2028, 2.4505, 2.0256]])
'''
- torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:在区间 [0,1)上,生成均匀分布
torch.rand(2, 3)
'''
tensor([[0.7405, 0.2529, 0.2332],
, [0.9314, 0.9575, 0.5575]])
'''
- torch.randint(low=0, high, size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:区间 [low,high)生成整数均匀分布
size:张量的形状
torch.randint(3, 10, (2, 2))
'''
tensor([[4, 8],
, [7, 8]])
'''
- torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False)
- 功能:生成从0到n-1的随机排列
n:张量的长度
torch.randperm(4)
'''
tensor([1, 3, 0, 2])
'''
- torch.bernoulli(input, *, generator=None, out=None)
- 功能:以input为概率,生成伯努利分布(0-1分布,两点分布)
input:概率值
a = torch.empty(3, 3).uniform_(0, 1)
torch.bernoulli(a)
'''
tensor([[0., 0., 1.],
, [0., 1., 1.],
, [1., 0., 1.]])
'''
张量的操作
一、张量拼接与切分
- torch.cat(tensors, dim=0, out=None)
- 功能:将张量按维度dim进行拼接
tensors:张量序列
dim:要拼接的维度
x = torch.randn(2, 3)
torch.cat((x, x, x), 1)
'''
tensor([[-1.7038, 0.6248, 0.1196, -1.7038, 0.6248, 0.1196, -1.7038, 0.6248,
, 0.1196],
, [-0.8049, 1.6162, 0.2516, -0.8049, 1.6162, 0.2516, -0.8049, 1.6162,
, 0.2516]])
'''
- torch.stack(tensors, dim=0, out=None)
- 功能:在新创建的维度dim上进行拼接
tensors:张量序列
dim:要拼接的维度 - torch.chunk(input, chunks, dim=0)
- 功能:将张量按维度dim进行平均切分
- 返回值:张量列表
- 注意事项:若不能整除,最后一份张量小于其他张量
input:要切分的张量
chunks:要切分的份数
dim:要切分的维度 - torch.split(tensor, split_size_or_sections, dim=0)
- 功能:将张量按维度dim进行切分
- 返回值:张量列表
tensor:要切分的张量
split_size_or_sections:为int时,表示每一份的长度;为list时,按list元素切分
dim:要切分的维度
a = torch.arange(10).reshape(5,2)
torch.split(a, 2)
'''
(tensor([[0, 1],
, [2, 3]]), tensor([[4, 5],
, [6, 7]]), tensor([[8, 9]]))
'''
张量索引
- torch.index_select(input, dim, index, out=None)
- 功能:在维度dim上,按index索引数据
- 返回值:依index索引数据拼接的张量
index:要索引的张量
dim:要索引的维度
index:要索引数据的序号
x = torch.randn(3, 4)
indices = torch.tensor([0, 2])
torch.index_select(x, 0, indices)
'''
tensor([[-0.0510, 0.1323, 0.3916, 1.0830],
, [ 0.3809, 0.2569, -1.0273, 0.4999]])
'''
- torch.masked_select(input, mask, out=None)
- 功能:按mask中的True进行索引
- 返回值:一维张量
input:要索引的张量
mask:与input同形状的布尔类型张量
x = torch.randn(3, 4)
mask = x.ge(0.5)
torch.masked_select(x, mask)
'''
tensor([0.5054, 0.8079])
'''
三、张量变换
- torch.reshape(input, shape)
- 功能:变换张量形状
- 注意事项:当张量在内存中是连续时,新张量与input共享数据内存
input:要变换的张量
shape:新张量的形状
a = torch.arange(4.)
torch.reshape(a, (2, 2))
'''
tensor([[0., 1.],
, [2., 3.]])
'''
- torch.transpose(input, dim0, dim1)
- 功能:交换张量的两个维度
input:要交换的张量
dim0:要交换的维度
dim1:要交换的维度
x = torch.randn(2, 3)
torch.transpose(x, 0, 1)
'''
tensor([[ 0.0096, 0.4506],
, [-0.5704, 0.4101],
, [-0.1722, 0.8957]])
'''
- torch.t(input)
- 功能:2维张量转置,对矩阵而言,等价于torch.transpose(input, 0, 1)
x = torch.randn(())
torch.t(x)
'''
tensor(-0.2882)
'''
- torch.squeeze(input, dim=None, out=None)
- 功能:压缩长度为1的维度(轴)
dim:若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除
x = torch.zeros(2, 1, 2, 1, 2)
y = torch.squeeze(x)
- torch.unsqueeze(input, dim, out=None)
- 功能:依据dim扩展维度
dim:扩展的维度
x = torch.tensor([1, 2, 3, 4])
torch.unsqueeze(x, 0)
'''
tensor([[1, 2, 3, 4]])
'''
线性回归模型实例
下面我们开始写一个线性回归模型:
# 首先我们得有训练样本X,Y, 这里我们随机生成
x = torch.rand(20, 1) * 10
y = 2 * x + (5 + torch.randn(20, 1))
# 构建线性回归函数的参数
w = torch.randn((1), requires_grad=True)
b = torch.zeros((1), requires_grad=True) # 这俩都需要求梯度
# 设置学习率lr为0.1
lr = 0.1
for iteration in range(100):
# 前向传播
wx = torch.mul(w, x)
y_pred = torch.add(wx, b)
# 计算loss
loss = (0.5 * (y-y_pred)**2).mean()
# 反向传播
loss.backward()
# 更新参数
b.data.sub_(lr * b.grad) # 这种_的加法操作时从自身减,相当于-=
w.data.sub_(lr * w.grad)
# 梯度清零
w.grad.data.zero_()
b.grad.data.zero_()
print(w.data, b.data)
'''
tensor([-1.0229e+36]) tensor([-1.6542e+35])
'''