Torch
1. 张量的创建
1.1 直接创建
1.1.1 torch.tensor
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.2, 0.2], [1.2, 2.3], [3.2, 1.3]])
'''
tensor([[0.2, 0.2],
[1.2, 2.3],
[3.2, 1.3]])
'''
1.1.2 torch.from_numpy(ndarray)
torch.from_numpy(ndarray)
- 功能:从numpy创建tensor
- 注意事项:从torch.from_numpy创建的tensor于原ndarray共享内存,当修改其中一个数据,另一个也将会被改动。
样例:
array = numpy.array([1, 2, 3, 4]) t = torch.from_numpy(array)
1.2 依据数值创建
1.2.1
torch.zeros
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) # 2行3列
'''
tensor([[0, 0, 0],
[0, 0, 0]])
'''
1.2.2 torch.zeros_like
torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False)
- 功能:依input形状创建全0张量
- input: 创建与input同形状的全0张量
- dtype: 数据类型
- layout: 内存中布局形式
- device: 所在设备,gpu/cpu
- requires_grad: 是否需要梯度
样例:
input = torch.empty(3, 2)
torch.zeros_like(input)
'''
tensor([[0, 0],
[0, 0],
[0, 0]])
'''
1.2.3 torch.ones
torch.ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:依size创建全1张量
- size: 张量的形状,如(3, 3)、(3, 224, 224)
- out: 输出的张量
- layout: 内存中布局形式,有strided, sparse_coo等
- device: 所在设备,gpu/cpu
- requires_grad: 是否需要梯度
样例:
torch.ones(2, 3) # 2行3列
'''
tensor([[1, 1, 1],
[1, 1, 1]])
'''
1.2.4 torch.ones_like
torch.ones_like(input, dtype=None, layout=None, device=None, requires_grad=False)
- 功能:依input形状创建全1张量
- input: 创建与input同形状的全0张量
- dtype: 数据类型
- layout: 内存中局形式
- device: 所在设备,gpu/cpu
- requires_grad: 是否需要梯度
样例:
input = torch.empty(2, 3)
torch.ones_like(input)
'''
tensor([[1, 1, 1],
[1, 1, 1]])
'''
1.2.5 torch.full
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:依size创建值全为fill_value的张量
- size: 张量的形状,如(3, 3)、(3, 224, 224)
- fill_value: 张量的值
- out: 输出的张量
- dtype: 数据类型
- layout: 内存中布局形式,有strided, sparse_coo等
- device: 所在设备,gpu/cpu
- requires_grad: 是否需要梯度
样例:
torch.full((3, 2), 1.23)
'''
tensor([[1.23, 1.23],
[1.23, 1.23],
[1.23, 1.23]])
'''
1.2.6 torch.full_like
torch.full_like(input, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:依input形状创建指定数据的张量
- dtype: 数据类型
- layout: 内存中布局形式,有strided, sparse_coo等
- device: 所在设备,gpu/cpu
- requires_grad: 是否需要梯度
1.2.7 torch.arange
torch.arange(start=0, end. step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:创建
等差
的1维张量- start: 数列起始值
- end: 数列“结束值”
- step: 数列公差,默认为1
- 注意事项:数值区间为
[𝑠𝑡𝑎𝑟𝑡,𝑒𝑛𝑑)
!!!!!
样例;
torch.arange(0, 3, 1)
'''
tensor([0, 1, 2])
'''
1.2.8 torch.linspace
torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:创建
均分
的1维张量- start: 数列起始值
- end: 数列“结束值”
- step: 数列长度
样例:
torch.linspace(start=-5, end=5, steps=3)
'''
tensor([-5., 0., 5.])
'''
1.2.9 torch.logspace
torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:创建
对数均分
的1维张量- start: 数列起始值
- end: 数列“结束值”
- step: 数列长度
- base: 对数函数的底,默认为10
- 注意事项:长度为
steps
,底为base
样例:
torch.logspace(start=0.1, end=1, steps=4)
'''
tensor([ 1.2589, 2.5119, 5.0119, 10.0000])
'''
1.2.10 torch.eye
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.]])
'''
1.3 依概率分布创建张量
1.3.1 torch.normal
torch.normal(mean, std, out=None)
- 功能:生成
正态分布(高斯分布)
- mean: 均值
- std: 标准差
- 四种模式::
- mean为
标量
,std为标量
- mean为
标量
,std为张量
- mean为
张量
,std为标量
- mean为
张量
,std为张量
样例:
# 1. mean为标量,std为标量
mean1 = torch.tensor([1.0])
std1 = torch.tensor([2.0])
normal1 = torch.normal(mean=mean1, std=std1)
print(f'mean为标量,std为标量: {normal1}')
# 2. mean为标量,std为张量
mean2 = torch.tensor([1.0])
std2 = torch.arange(1, 0, -0.1)
normal2 = torch.normal(mean=mean2, std=std2)
print(f'mean为标量,std为张量: {normal2}')
# 3. mean为张量,std为标量
mean3 = torch.arange(1, 0, -0.1)
std3 = torch.tensor([1.0])
normal3 = torch.normal(mean=mean3, std=std3)
print(f'mean为张量,std为标量: {normal3}')
# 4. mean为张量,std为张量
mean4 = torch.arange(1., 11.)
std4 = torch.arange(1, 0, -0.1)
normal4 = torch.normal(mean=mean4, std=std4)
print(f'mean为张量,std为张量: {normal4}')
'''
mean为标量,std为标量:
tensor([0.8404])
mean为标量,std为张量:
tensor([ 1.9674, 0.3015, 1.4441, 1.1592, -0.3160, 0.8436, 1.1548, 1.1149, 0.8569, 0.8924])
mean为张量,std为标量:
tensor([-1.1098, 0.0993, 0.7905, 1.5703, -0.2797, -0.5459, -0.7058, -1.1746, 0.1725, 1.2089])
mean为张量,std为张量:
tensor([-0.1302, 1.2099, 1.6807, 2.5063, 5.4447, 6.4120, 6.9074, 8.2245, 8.9090, 10.0049])
'''
1.3.2 torch.normal
torch.normal(mean, std, size, out=None)
- 功能:生成一定大小的生成
正态分布(高斯分布)
- size: 张量的形状,如(3, 3)、(3, 224, 224)
样例:
torch.normal(3, 2, size=(1, 3))
'''
tensor([[3.6354, 3.2656, 3.2746]])
'''
1.3.3 torch.randn
torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:生成
标准正态分布
- size: 张量的形状,如(3, 3)、(3, 224, 224)
样例:
torch.randn(3, 2)
'''
tensor([[0.2405, 1.3955],
[1.3470, 2.4382],
[0.2028, 2.4505]])
'''
1.3.4 torch.rand
torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:在区间
[0,1)
上,生成均匀分布
- size: 张量的形状,如(3, 3)、(3, 224, 224)
样例:
torch.normal(3, 2, size=(1, 3))
'''
tensor([[3.6354, 3.2656, 3.2746]])
'''
1.3.5 torch.randint
torch.randint(low=0, high, size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
- 功能:区间
[𝑙𝑜𝑤,ℎ𝑖𝑔ℎ)
生成整数均匀分布
- size: 张量的形状,如(3, 3)、(3, 224, 224)
样例:
torch.randint(1, 10, (2, 2))
'''
tensor([[8, 6],
[1, 3]])
'''
1.3.6 torch.randperm
torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False)
- 功能:生成从
0到n-1的随机排列
- n: 张量的长度
样例:
torch.randperm(6)
'''
tensor([2, 0, 4, 5, 1, 3])
'''
1.3.7 torch.bernoulli
torch.bernoulli(input, *, generator=None, out=None)
- 功能:以
input
为概率,生成伯努利分布(0-1分布,两点分布)
- input: 概率值
样例:
a = torch.empty(2, 2).uniform_(0, 1) # 生成2×2的概率矩阵
torch.bernoulli(a)
'''
tensor([[0., 1.],
[1., 0.]])
'''
2. 张量的操作
2.1 张量拼接与切分
2.1.1 torch.cat
torch.cat(tensors, dim=0, out=None)
- 功能:将张量
按维度dim
进行拼接- tensors: 张量序列seq
- dim: 要拼接的维度
dim=0按行拼接 dim=1按列拼接 dim=n按维度拼接
x = torch.randn(2, 3)
print(x.shape)
a = torch.cat((x, x, x), 1)
a.shape
'''
torch.Size([2, 3])
torch.Size([2, 9])
'''
2.1.2 torch.stack
torch.stack(tensors, dim=0, out=None)
- 功能:对序列数据内部的张量进行
扩维拼接
,指定维度由程序员选择、大小是生成后数据的维度区间。- tensors: 张量序列seq
- dim: 指定扩张的维度
dim=0按行扩张 dim=1按列扩张 dim=n按维度扩张
拼接后的tensor形状,会根据不同的dim发生变化。 参考:pytorch拼接函数:torch.stack()和torch.cat()详解
T1:
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
T2:
tensor([[10, 20, 30],
[40, 50, 60],
[70, 80, 90]])
----------------------------------------------
R0 = torch.stack((T1, T2), dim=0)
'''
tensor([[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]],
[[10, 20, 30],
[40, 50, 60],
[70, 80, 90]]])
torch.Size([2, 3, 3])
----------------------------------------------
'''
R1 = torch.stack((T1, T2), dim=1)
'''
tensor([[[1, 2, 3],[10, 20, 30]],
[[4, 5, 6],[40, 50, 60]],
[[7, 8, 9],[70, 80, 90]]])
torch.Size([3, 2, 3])
'''
----------------------------------------------
R2 = torch.stack((T1, T2), dim=2)
'''
tensor([[[1, 10],[2, 20],[3, 30]],
[[4, 40],[5, 50],[6, 60]],
[[7, 70],[8, 80],[9, 90]]])
torch.Size([3, 3, 2])
'''
R3 = torch.stack((T1, T2), dim=3)
'''
IndexError: Dimension out of range (expected to be in range of [-3, 2], but got 3)
'''
2.1.3 torch.chunk
torch.chunk(input, chunks, dim=0)
- 功能:将张量按维度
dim
进行平均切分- 返回值: 张量列表
- 注意事项:若不能整除,最后一份张量小于其他张量
- input: 要切分的
张量
- chunks: 要切分的
份数
- dim: 要切分的
维度
0按照列切分 1按照行切分
a = torch.arange(10).reshape(5,2)
torch.chunk(a, 2)
'''
tensor([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
(tensor([[0, 1],
[2, 3],
[4, 5]]),
tensor([[6, 7],
[8, 9]]))
'''
---------------------------------------
torch.chunk(a, 2, 1)
'''
(tensor([[0],
[2],
[4],
[6],
[8]]),
tensor([[1],
[3],
[5],
[7],
[9]]))
'''
2.1.4 torch.split
torch.split(tensor, split_size_or_sections, dim=0)
- 功能:将张量按维度
dim
进行切分- 返回值: 张量列表
- tensor: 要切分的
张量
- split_size_or_sections: 为
int
时,表示每一份的长度;为list
时,按list元素切分- dim: 要切分的
维度
0按照列切分 1按照行切分
a = torch.arange(10).reshape(5,2)
torch.split(a, 2)
'''
tensor([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
(tensor([[0, 1],
[2, 3]]),
tensor([[4, 5],
[6, 7]]),
tensor([[8, 9]]))
'''
torch.split(a, [3, 1, 1])
'''
(tensor([[0, 1],
[2, 3],
[4, 5]]),
tensor([[6, 7]]),
tensor([[8, 9]]))
'''
2.2 张量索引
2.2.1 torch.index_select
torch.index_select(input, dim, index, out=None)
- 功能:在维度
dim
上,按index索引数据- 返回值: 依index索引数据拼接的张量
- input: 要索引的张量
- dim: 要索引的
维度
0按照列切分 1按照行切分- index: 要索引数据的序号
x = torch.randn(3, 4)
indices = torch.tensor([0, 2])
torch.index_select(x, 0, indices)
'''
x: tensor([[-0.1468, 0.7861, 0.9468, -1.1143],
[ 1.6908, -0.8948, -0.3556, 1.2324],
[ 0.1382, -1.6822, 0.3177, 0.1328]])
indices: tensor([0, 2])
tensor([[-0.1468, 0.7861, 0.9468, -1.1143],
[ 0.1382, -1.6822, 0.3177, 0.1328]])
'''
2.2.2 torch.masked_select
torch.masked_select(input, mask, out=None)
- 功能:按mask中的True进行索引
- 返回值: 一维张量
- input: 要索引的张量
- mask: 与input同形状的布尔类型张量
x = torch.randn(3, 4)
print('x:',x)
mask = x.ge(0.5)
print('mask:',mask)
torch.masked_select(x, mask)
'''
x: tensor([[ 0.1373, 0.2405, 1.3955, 1.3470],
[ 2.4382, 0.2028, 2.4505, 2.0256],
[ 1.7792, -0.9179, -0.4578, -0.7245]])
mask: tensor([[False, False, True, True],
[ True, False, True, True],
[ True, False, False, False]])
tensor([1.3955, 1.3470, 2.4382, 2.4505, 2.0256, 1.7792])
'''
2.3 张量变换
2.3.1 torch.reshape
torch.reshape(input, shape)
- 功能:
变换张量形状
- 注意事项: 当张量在内存中是连续时,新张量与input共享数据内存
- input: 要变换的张量
- shape: 新张量的形状
a = torch.arange(4.)
torch.reshape(a, (2, 2))
'''
tensor([0., 1., 2., 3.])
tensor([[0., 1.],
[2., 3.]])
'''
2.3.2 torch.transpose
torch.transpose(input, dim0, dim1)
- 功能:
交换张量
的两个维度
- input: 要交换的张量
- dim0: 要交换的维度
- dim1: 要交换的维度
x = torch.randn(2, 3)
torch.transpose(x, 0, 1)
'''
x:
tensor([[ 1.2799, -0.9941, 1.8150],
[-0.6028, 1.6148, 1.9302]])
torch.Size([2, 3])
tensor([[ 1.2799, -0.6028],
[-0.9941, 1.6148],
[ 1.8150, 1.9302]])
torch.Size([3, 2])
'''
x = torch.randn(2, 3, 4)
print(x)
print(x.shape)
a = torch.transpose(x, 0, 2)
print(a)
print(a.shape)
'''
tensor([[[ 0.8885, -1.4867, -0.8898, 0.9005],
[ 0.2615, -0.1494, 1.1523, -1.1309],
[ 1.4025, -0.4167, 0.1655, -0.7157]],
[[ 1.2425, -1.3332, 0.2961, -0.0937],
[-0.7556, -0.1198, 0.9545, 0.1492],
[ 1.6222, 0.1947, -1.5953, 0.5859]]])
torch.Size([2, 3, 4])
tensor([[[ 0.8885, 1.2425],
[ 0.2615, -0.7556],
[ 1.4025, 1.6222]],
[[-1.4867, -1.3332],
[-0.1494, -0.1198],
[-0.4167, 0.1947]],
[[-0.8898, 0.2961],
[ 1.1523, 0.9545],
[ 0.1655, -1.5953]],
[[ 0.9005, -0.0937],
[-1.1309, 0.1492],
[-0.7157, 0.5859]]])
torch.Size([4, 3, 2])
'''
2.3.3 torch.t
torch.t(input)
- 功能:2维张量转置,对矩阵而言,等价于torch.transpose(input, 0, 1)
x = torch.randn((2, 2))
print(x)
torch.t(x)
'''
tensor([[ 0.5740, -0.0798],
[ 0.9674, -0.7761]])
tensor([[ 0.5740, 0.9674],
[-0.0798, -0.7761]])
'''
2.3.4 torch.squeeze
torch.squeeze(input, dim=None, out=None)
- 功能:压缩长度为1的维度(轴)
维度压缩
- dim: 若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除
x = torch.zeros(2, 1, 2, 1, 2)
print(x)
print(x.shape)
y = torch.squeeze(x)
print(y)
print(y.shape)
'''
tensor([[[[[0., 0.]],
[[0., 0.]]]],
[[[[0., 0.]],
[[0., 0.]]]]])
torch.Size([2, 1, 2, 1, 2])
tensor([[[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.]]])
torch.Size([2, 2, 2])
'''
2.3.5 torch.unsqueeze
torch.unsqueeze(input, dim, out=None)
- 功能:依据dim
扩展维度
- dim: 扩展的维度 0行扩展 1列扩展 -1最后一个维度扩展
x = torch.tensor([1, 2, 3])
print(x.shape)
t0 = torch.unsqueeze(x, 0)
print(t0.shape)
t1 = torch.unsqueeze(x, 1)
print(t1.shape)
t2 = torch.unsqueeze(x, -1)
print(t2.shape)
t0, t1, t2
'''
x:
torch.Size([3])
t0:
tensor([[1, 2, 3]])
torch.Size([1, 3])
t1:
tensor([[1],
[2],
[3]])
torch.Size([3, 1])
t2:
tensor([[1],
[2],
[3]]))
torch.Size([3, 1])
'''
线性回归模型
- 线性回归是分析一个变量与另外一(多)个变量之间关系的方法。
- 因变量是$y$,自变量是$x$,关系线性:$y=w\times x + b$,任务是求解 $w$,$b$。
- 我们的求解步骤是:
- 确定模型:$Model \to y = w \times x + b$
- 选择损失函数:这里用$MSE:\frac{1}{m}\sum_{i=1}^m(y_i-\hat y_i)^2$
- 求解梯度并更新$w$,$b$: \(\begin{array}{lcl} w &=& w - lr \times w.grad \\ b &=& b - lr \times w.grad \end{array}\)
- 下面我们开始写一个线性回归模型:
# 首先我们得有训练样本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)
部分学习内容来自: 天池实验室