1、张量的操作:拼接、切分、索引和变换
一、张量拼接与切分
1.1 torch.cat() (cat()不会拓展张量的维度)
功能:将张量按维度dim进行拼接
torch.cat(tensors,
dim=0,
out=None)
代码实际操作如下:
import numpy as np
import torch
flag = True
if flag:
t = torch.ones((2, 3))
t_0 = torch.cat([t, t], dim=0) #在第一维度上进行拼接,拼接后的维度是(4,3)
t_1 = torch.cat([t, t], dim=1) #在第二维度上进行拼接,拼接后的维度是(2,6)
t_2 = torch.cat([t, t, t], dim=1) #在第二维度上进行拼接,拼接后的维度是(2,9)
print("t_0:{} shape:{}\nt_1:{} shape:{}\nt_2:{} shape:{}".format(t_0, t_0.shape, t_1, t_1.shape, t_2, t_2.shape))
1.2 torch.stack() (stack() 会拓展张量的维度)
功能:在新创建的维度dim上进行拼接。
举个例子,如果要求将[2,3]矩阵的内容在dim=1上进行拼接,则需要将[2,3]矩阵的内容转换为[2,1,3]的形式之后再使用和torch.cat()一样的拼接方式进行拼接,看到的一些比较好的对于torch.stack()的拼接的解释的文章可以参考一下这一篇(点击)。
torch.stack(tensors,
dim=0,
out=None)
具体的代码实现如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.ones((2, 3))
s = torch.zeros((2, 3))
t_stack = torch.stack([t, s], dim=0) #对两个矩阵的第0维进行拓展
print("\nt_stack:{} shape:{}".format(t_stack, t_stack.shape)) #拓展后的矩阵为(2,2,3)
tensor([[[1., 1., 1.],
[1., 1., 1.]],
[[0., 0., 0.],
[0., 0., 0.]]])
t_stack = torch.stack([t, s], dim=1) #对两个矩阵的第1维进行拓展
print("\nt_stack:{} shape:{}".format(t_stack, t_stack.shape)) #拓展后的矩阵为(2,2,3)
tensor([[[1., 1., 1.],
[0., 0., 0.]],
[[1., 1., 1.],
[0., 0., 0.]]])
t_stack = torch.stack([t, s], dim=2) #对两个矩阵的第2维进行拓展
print("\nt_stack:{} shape:{}".format(t_stack, t_stack.shape)) #拓展后的矩阵为(2,3,2)
tensor([[[1., 0.],
[1., 0.],
[1., 0.]],
[[1., 0.],
[1., 0.],
[1., 0.]]])
1.3 torch.chunk()
功能:将张量按维度dim进行平均切分
返回值:张量列表
注意事项:若不能整除,最后一份张量小于其他张量
torch.chunk(input,
chunks,
dim=0)
具体的代码示例如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
a = torch.ones((2, 5)) #创建一个矩阵
list_of_tensors = torch.chunk(a, dim=1, chunks=2) #从第一维度将矩阵划分为两部分,因为5不能被2整除,所以得到的两个矩阵中,一个矩阵为(2,3),一个矩阵为(2,2)
for idx, t in enumerate(list_of_tensors):
print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))
1.4 torch.split()
功能:将张量按维度dim进行切分
返回值:张量列表
torch.split(tensor,
split_size_or_sections,
dim=0)
具体的代码示例如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.ones((2, 5))
list_of_tensors = torch.split(t, 2, dim=1) #2表示每一份的长度,最后得到划分后的三份矩阵,分别为(2,2),(2,2),(2,1)
for idx, t in enumerate(list_of_tensors):
print("第{}个张量:{}, shape is {}".format(idx+1, t, t.shape))
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.ones((2, 5))
list_of_tensors = torch.split(t, [2, 1, 2], dim=1) #根据列表进行划分,划分后的三个矩阵的形状分别为(2,2),(2,1),(2,2)
for idx, t in enumerate(list_of_tensors):
print("第{}个张量:{}, shape is {}".format(idx + 1, t, t.shape))
二、张量索引
2.1 torch.index_select()
功能:在维度dim上,按index索引数据
返回值:依index索引数据拼接的张量
torch.index_select(input,
dim,
index,
out=None)
具体的代码示例如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.randint(0, 9, size=(3, 3)) #随机生成(3,3)的二维矩阵
idx = torch.tensor([0, 2], dtype=torch.long) #要索引的序列,注意dtype必须是torch.long不能是torch.float
t_select = torch.index_select(t, dim=0, index=idx) #以第0维为索引的维度,最后得到的矩阵为(2,3)
print("t:\n{}\nt_select:\n{}".format(t, t_select))
2.2 torch.masked_select()
功能:按mask中的True进行索引
返回值:一维张量
torch.masked_select(input,
mask,
out=None)
具体的代码示例如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.randint(0, 9, size=(3, 3))
mask = t.ge(5) #ge的意思是大于等于,greater than or equal,同样的有gt:greater than 和le、lt,ge的作用是找t中大于等于5的数赋值为True,小于5的数赋值为False
t_select = torch.masked_select(t, mask) #按mask中的True进行索引返回一个一维矩阵
print("t:\n{}\nmask:\n{}\nt_select:\n{}".format(t, mask, t_select))
三、张量变换
3.1 torch.reshape()
功能:变换张量形状
注意事项:当张量在内存中是连续时,新张量与input共享数据内存
torch.reshape(input,
shape)
具体的代码示例如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.randperm(8) #0-8之间随机排列的8个数
t_reshape = torch.reshape(t, (-1, 2, 2)) #一维矩阵被重新reshape为(2,2,2)形式
print("t:{}\nt_reshape:\n{}".format(t, t_reshape))
t[0] = 1024 #将t[0]的值进行修改
print("t:{}\nt_reshape:\n{}".format(t, t_reshape))
print("t.data 内存地址:{}".format(id(t.data))) #t.data的内存地址和t_reshape的内存地址是一样的
print("t_reshape.data 内存地址:{}".format(id(t_reshape.data )))
3.2 torch.transpose()
功能:交换张量的两个维度
torch.transpose(input,
dim0,
dim1)
具体的代码示例如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.rand((2, 3, 4))
t_transpose = torch.transpose(t, dim0=0, dim1=1) #经过交换后张量的维度变为(3,2,4)
print("t shape:{}\nt_transpose shape:{}".format(t.shape, t_transpose.shape))
3.3 torch.t()
功能:2维张量转置,对矩阵而言,等价于torch.transpose(input,0,1)
torch.t(input)
3.4 torch.squeeze()
功能:压缩长度为1的维度(轴)
torch.squeeze(input,
dim=None,
out=None)
具体示例代码如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t = torch.rand((1, 2, 3, 1))
t_sq = torch.squeeze(t) #将所有轴长为1的都去掉,t_sq变为(2,3)
t_0 = torch.squeeze(t, dim=0) #第0维如果是1,则将第0维去掉,t_0变为(2,3,1)
t_1 = torch.squeeze(t, dim=1) #第1维是2,不是1,所以不能删除,t_1仍然为(1,2,3,1)
print(t.shape)
print(t_sq.shape)
print(t_0.shape)
print(t_1.shape)
3.5 torch.unsqueeze()
功能:依据dim扩展维度
torch.usqueeze(input,
dim,
out=None)
2、张量的数学运算
一、加减乘除
torch.add()
功能:逐元素计算 input + alpha x other (这里面add不仅仅有加法的功能还有乘法的功能,因为在深度学习中经常需要用到这样的情况)。类似的用法还有:
torch.addcdiv() : out = input + value x tensor1 / tensor2
torch.addcmul() : out = input + value x tensor1 x tensor2
torch.add(input,
alpha=1,
other,
out=None)
具体的代码示例如下:
import numpy as np
import torch
flag = True
# flag = False
if flag:
t_0 = torch.randn((3, 3)) #创建一个(3,3)正态分布的矩阵
t_1 = torch.ones_like(t_0) #创建一个(3,3)的全1矩阵
t_add = torch.add(t_0, 10, t_1)
print("t_0:\n{}\nt_1:\n{}\nt_add_10:\n{}".format(t_0, t_1, t_add))
torch.addcdiv()
torch.addcmul()
torch.addcuml(input,
value=1,
tensor1,
tensor2,
out=None)
torch.sub()
torch.div()
torch.mul()
二、对数,指数,幂函数
torch.log(input,out=None)
torch.log10(input,out=None)
torch.log2(input,out=None)
torch.exp(input,out=None)
torch.pow()
三、三角函数
torch.abs(input,out=None)
torch.acos(input,out=None)
torch.cosh(input,out=None)
torch.cos(input,out=None)
torch.asin(input,out=None)
torch.atan(input,out=None)
torch.atan2(input,other,out=None)
3、线性回归
线性回归是分析一个变量与另外一(多)个变量之间关系的方法
因变量:Y 自变量:x 关系:线性 y = wx + b 分析:求解w,b
求解步骤
1、确定模型 model: y = wx + b
2、选择损失函数 MSE,均方误差
3、求解梯度并更新w,b
使用pytorch的一个具体线性回归公式推导代码:
import torch
import matplotlib.pyplot as plt
torch.manual_seed(10)
lr = 0.05 # 学习率
# 创建训练数据
x = torch.rand(20, 1) * 10 # x data (tensor), shape=(20, 1) rand是生成均匀分布的20个点,再乘于10,范围就是0-10之间
y = 1*x + (5 + torch.randn(20, 1)) # y data (tensor), shape=(20, 1),torch.randn(20, 1)是噪声,符合正态分布
# 构建线性回归参数
w = torch.randn((1), requires_grad=True) #线性函数中只有一个w,先随机初始化一个w
b = torch.zeros((1), requires_grad=True) #线性回归中只有一个b,先随机初始化b的值为0
for iteration in range(1000):
# 前向传播
wx = torch.mul(w, x) #将w和x的值相乘
y_pred = torch.add(wx, b) #计算wx + b的值
# 计算 MSE loss
loss = (0.5 * (y - y_pred) ** 2).mean() #计算损失函数
# 反向传播
loss.backward() #使用自带的梯度求导模块
# 更新参数
b.data.sub_(lr * b.grad)
w.data.sub_(lr * w.grad)
b.grad.zero_() #将张量梯度清零
w.grad.zero_() #将张量梯度清零
# 绘图
if iteration % 20 == 0: #每迭代20次进行一次输出
plt.scatter(x.data.numpy(), y.data.numpy())
plt.plot(x.data.numpy(), y_pred.data.numpy(), 'r-', lw=5)
plt.text(2, 20, 'Loss=%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': 'red'})
plt.xlim(1.5, 10)
plt.ylim(8, 28)
plt.title("Iteration: {}\nw: {} b: {}".format(iteration, w.data.numpy(), b.data.numpy()))
plt.pause(0.5)
if loss.data.numpy() < 1: #如果损失函数的值小于0.8则停止循环
break
最后得到的线性回归拟合公式如下图所示:
————————————————
本篇幅的所有内容是基于深度之眼的pytorch课程的视频进行摘录的,所有代码均来自视频中余老师的讲解,如有侵权,请联系我进行删除。