深度学习入门(一)pytorch基础
1、torch.tensor()根据指定数据创建张量
import torch
import numpy as np
# 创建张量标量
data = torch.tensor(10)
# 通过numpy创建
data = torch.tensor(np.random.randn(2,3))
# 通过列表创建
data = torch.tensor([[10.,20.,30.],[40.,50.,60]])
执行结果
tensor(10)
tensor([[ 0.1345, 0.1149, 0.2435],
[ 0.8026, -0.6744, -1.0918]], dtype=torch.float64)
tensor([[10., 20., 30.],
[40., 50., 60.]])
2、torch.Tensor()根据指定形状创建张量,也可以用来创建指定数据的张量
# 1. 创建2行3列的张量, 默认dtype为float32
data = torch.Tensor(2, 3)
# 2. 注意: 如果传递列表, 则创建包含指定元素的张量
data = torch.Tensor([10])
data = torch.Tensor([10, 20])
执行结果
tensor([[0.0000e+00, 3.6893e+19, 2.2018e+05],
[4.6577e-10, 2.4158e-12, 1.1625e+33]])
tensor([10.])
tensor([10., 20.])
3、torch.IntTensor()、torch.FloatTensor()、torch.DoubleTensor() 创建指定类型的张量
# 1. 创建2行3列, dtype为int32 的张量
data = torch.IntTensor(2, 3)
# 2. 注意: 如果传递的元素类型不正确, 则会进行类型转换
data = torch.IntTensor([2.5, 3.3])
# 3. 其他的类型初始化
data = torch.ShortTensor() # int16
data = torch.LongTensor() # int64
data = torch.FloatTensor() # float32
data = torch.DoubleTensor() # float64
自行结果
tensor([[1606422944, 880, 0],
[ 0, 0, 0]], dtype=torch.int32)
tensor([2, 3], dtype=torch.int32)
tensor([], dtype=torch.int16)
tensor([], dtype=torch.int64)
tensor([])
tensor([], dtype=torch.float64)
4、torch.arange()、torch.linspace()创建线性张量
# 1. 在指定区间按照步长生成元素[start, end, step)
data = torch.arange(0, 10, 2)
# 2. 在指定区间按照元素个数生成[start, end, steps]
data = torch.linspace(0, 9, 10)
自行结果
tensor([0, 2, 4, 6, 8])
tensor([ 0.0000, 1.2222, 2.4444, 3.6667, 4.8889, 6.1111, 7.3333, 8.5556,
9.7778, 11.0000])
5、设置随机种子保证每次的执行结果一样
import torch # 需要安装torch模块,虚拟环境中已经安装好了
import numpy as np
import random
SEED = 42
# 1. Python 内置 random 模块
random.seed(SEED)
# 2. NumPy
np.random.seed(SEED)
# 3. PyTorch CPU
torch.manual_seed(SEED)
# 4. PyTorch GPU(如果用 CUDA)
if torch.cuda.is_available():
torch.cuda.manual_seed(SEED)
torch.cuda.manual_seed_all(SEED) # 多 GPU 时用
# 5. 让 cuDNN 行为确定性(可选,但强烈推荐)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False # 关闭 benchmark,防止 cuDNN 自动优化导致不一致
# 查看随机数种子
print('随机数种子:', torch.random.initial_seed()) # 42
6、torch.zeros()、torch.zeros_like()创建全0张量
# 1. 创建指定形状全0张量
data = torch.zeros(2, 3)
# 2. 根据张量形状创建全0张量
data = torch.zeros_like(data)
执行结果
tensor([[0., 0., 0.],
[0., 0., 0.]])
tensor([[0., 0., 0.],
[0., 0., 0.]])
7、torch.ones()、torch.ones_like()创建全0张量
# 1. 创建指定形状全1张量
data = torch.ones(2, 3)
# 2. 根据张量形状创建全1张量
data = torch.ones_like(data)
执行结果
tensor([[1., 1., 1.],
[1., 1., 1.]])
tensor([[1., 1., 1.],
[1., 1., 1.]])
8、torch.full()、torch.full_like()创建全为指定值张量
# 1. 创建指定形状指定值的张量
data = torch.full([2, 3], 10)
# 2. 根据张量形状创建指定值的张量
data = torch.full_like(data, 20)
执行结果
tensor([[10, 10, 10],
[10, 10, 10]])
tensor([[20, 20, 20],
[20, 20, 20]])
9、张量元素类型转换
data = torch.full([2, 3], 10)
data = data.type(torch.float)
data = data.type(torch.float64)
data = data.type(torch.DoubleTensor)
data = data.type(torch.int32)
data = data.type(torch.int64)
data = data.type(torch.IntTensor)
data = data.double()
data = data.short()
data = data.int()
data = data.long()
data = data.float()
执行结果
torch.int64
torch.float32
torch.float64
torch.float64
torch.int32
torch.int64
torch.int32
torch.float64
torch.int16
torch.int32
torch.int64
torch.float32
10、NumPy数组和张量互相转换
data_tensor = torch.tensor([2, 3, 4])
# numpy转tensor
# 不copy会共享内存,数据修改时会互相影响
data_tensor = torch.from_numpy(np.array([2, 3, 4]).copy())
data_tensor = torch.tensor(np.array([2, 3, 4]).copy())
# tensor转numpy
data_numpy = data_tensor.numpy().copy()
执行结果
tensor([2, 3, 4])
tensor([2, 3, 4], dtype=torch.int32)
tensor([2, 3, 4], dtype=torch.int32)
[2 3 4]
11、标量张量和数字转换
# 当张量只包含一个元素时, 可以通过 item() 函数提取出该值
data = torch.tensor([30,])
data = torch.tensor(30)
执行结果
30
30
12、张量基本运算add、sub、mul、div、neg、matmul
import torch # 需要安装torch模块,虚拟环境中已经安装好了
import numpy as np
import random
data = torch.randint(0, 10, [2, 3])
print('data =', data)
# 1. 不修改原数据
new_data = data.add(10) # 等价new_data = data + 10
print("data + 10 =", new_data)
# 2. 直接修改原数据注意: 带下划线的函数为修改原数据本身
data.add_(10) # 等价data += 10
print("data + 10 =", data)
# 3. 其他函数
print("data - 100 =", data.sub(100))
print("data1 * 100 =", data.mul(100))
print("data1 / 100 =", data.div(100))
print("data1 * (-1) =", data.neg())
data1 = torch.tensor([[1, 2], [3, 4]])
data2 = torch.tensor([[5, 6], [7, 8]])
# 矩阵点乘
# 第一种方式
data = torch.mul(data1, data2)
print("data1 * data2 =", data)
# 第二种方式
data = data1 * data2
print("data1 * data2 =", data)
# 矩阵乘法运算
# 第一种方式
data = data1 @ data2
print("data1 @ data2 =", data)
# 第二种方式
data = torch.matmul(data1, data2)
print("data1 @ data2 =", data)
data = data.type(torch.float64)
print('data =', data)
print('data.mean() =', data.mean())
print('data.mean(dim=0) =', data.mean(dim=0)) # 按列计算均值
print('data.mean(dim=1) =', data.mean(dim=1)) # 按行计算均值
print('data.sum() =', data.sum())
print('data.sum(dim=0) =', data.sum(dim=0))
print('data.sum(dim=1) =', data.sum(dim=1))
print('torch.pow(data, 2) =', torch.pow(data, 2))
# 计算平方根
print('data.sqrt() =', data.sqrt())
# 指数计算, e^n次方
print('data.exp() =', data.exp())
# 对数计算
print('data.log() =', data.log()) # 以e 为底
print('data.log2() =', data.log2())
print('data.log10() =', data.log10())
执行结果
data = tensor([[6, 3, 2],
[2, 0, 8]])
data + 10 = tensor([[16, 13, 12],
[12, 10, 18]])
data + 10 = tensor([[16, 13, 12],
[12, 10, 18]])
data - 100 = tensor([[-84, -87, -88],
[-88, -90, -82]])
data1 * 100 = tensor([[1600, 1300, 1200],
[1200, 1000, 1800]])
data1 / 100 = tensor([[0.1600, 0.1300, 0.1200],
[0.1200, 0.1000, 0.1800]])
data1 * (-1) = tensor([[-16, -13, -12],
[-12, -10, -18]])
data1 * data2 = tensor([[ 5, 12],
[21, 32]])
data1 * data2 = tensor([[ 5, 12],
[21, 32]])
data1 @ data2 = tensor([[19, 22],
[43, 50]])
data1 @ data2 = tensor([[19, 22],
[43, 50]])
data = tensor([[19., 22.],
[43., 50.]], dtype=torch.float64)
data.mean() = tensor(33.5000, dtype=torch.float64)
data.mean(dim=0) = tensor([31., 36.], dtype=torch.float64)
data.mean(dim=1) = tensor([20.5000, 46.5000], dtype=torch.float64)
data.sum() = tensor(134., dtype=torch.float64)
data.sum(dim=0) = tensor([62., 72.], dtype=torch.float64)
data.sum(dim=1) = tensor([41., 93.], dtype=torch.float64)
torch.pow(data, 2) = tensor([[ 361., 484.],
[1849., 2500.]], dtype=torch.float64)
data.sqrt() = tensor([[4.3589, 4.6904],
[6.5574, 7.0711]], dtype=torch.float64)
data.exp() = tensor([[1.7848e+08, 3.5849e+09],
[4.7278e+18, 5.1847e+21]], dtype=torch.float64)
data.log() = tensor([[2.9444, 3.0910],
[3.7612, 3.9120]], dtype=torch.float64)
data.log2() = tensor([[4.2479, 4.4594],
[5.4263, 5.6439]], dtype=torch.float64)
data.log10() = tensor([[1.2788, 1.3424],
[1.6335, 1.6990]], dtype=torch.float64)
13、索引操作
import torch # 需要安装torch模块,虚拟环境中已经安装好了
import numpy as np
import random
data = torch.randint(0, 10, [4, 5])
print('data =', data)
# 列表索引
# 第1行所有列
print('data[0] =', data[0])
# 所有行第0列
print('data[:, 0] =', data[:, 0])
# [0,2], [1,3]
print('data[[0, 1], [2, 3]] =', data[[0, 1], [2, 3]])
# [0,1], [0,2], [1,1], [1,2]
print('data[[[0], [1]], [1, 2]] =', data[[[0], [1]], [1, 2]])
# 范围索引
# 前3行的前2列数据
print('data[:3, :2] =', data[:3, :2])
# 第2行到最后的前2列数据
print('data[2:, :2] =', data[2:, :2])
# 布尔索引
# 所有列数据,筛选行的条件:第三列大于5的行数据
print('data[data[:, 2] > 5] =', data[data[:, 2] > 5])
# 所有行数据,筛选列的条件:第二行大于5的列数据
print('data[:, data[1] > 5] =', data[:, data[1] > 5])
# 多维索引
data = torch.randint(0, 10, [3, 4, 5])
print('data =', data)
# 获取0轴上的第一个数据
print('data[0, :, :] =', data[0, :, :])
# 获取1轴上的第一个数据
print('data[:, 0, :] =', data[:, 0, :])
# 获取2轴上的第一个数据
print('data[:, :, 0] =', data[:, :, 0])
执行结果
data = tensor([[7, 3, 4, 5, 2],
[7, 9, 8, 6, 2],
[2, 9, 6, 6, 8],
[1, 3, 7, 5, 7]])
data[0] = tensor([7, 3, 4, 5, 2])
data[:, 0] = tensor([7, 7, 2, 1])
data[[0, 1], [2, 3]] = tensor([4, 6])
data[[[0], [1]], [1, 2]] = tensor([[3, 4],
[9, 8]])
data[:3, :2] = tensor([[7, 3],
[7, 9],
[2, 9]])
data[2:, :2] = tensor([[2, 9],
[1, 3]])
data[data[:, 2] > 5] = tensor([[7, 9, 8, 6, 2],
[2, 9, 6, 6, 8],
[1, 3, 7, 5, 7]])
data[:, data[1] > 5] = tensor([[7, 3, 4, 5],
[7, 9, 8, 6],
[2, 9, 6, 6],
[1, 3, 7, 5]])
data = tensor([[[2, 1, 1, 4, 8],
[7, 6, 5, 1, 0],
[1, 2, 6, 0, 9],
[8, 4, 3, 6, 5]],
[[7, 8, 5, 7, 6],
[9, 9, 9, 2, 9],
[6, 7, 4, 7, 9],
[1, 7, 9, 3, 0]],
[[6, 8, 4, 3, 1],
[0, 0, 8, 8, 7],
[0, 5, 0, 1, 4],
[2, 2, 6, 5, 3]]])
data[0, :, :] = tensor([[2, 1, 1, 4, 8],
[7, 6, 5, 1, 0],
[1, 2, 6, 0, 9],
[8, 4, 3, 6, 5]])
data[:, 0, :] = tensor([[2, 1, 1, 4, 8],
[7, 8, 5, 7, 6],
[6, 8, 4, 3, 1]])
data[:, :, 0] = tensor([[2, 7, 1, 8],
[7, 9, 6, 1],
[6, 0, 0, 2]])
14、reshape函数
reshape 函数可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状。
data = torch.tensor([[10, 20, 30], [40, 50, 60]])
# 1. 使用shape 属性或者size 方法都可以获得张量的形状
print(data.shape, data.shape[0], data.shape[1])
print(data.size(), data.size(0), data.size(1))
# 2. 使用reshape 函数修改张量形状
new_data = data.reshape(1, 6)
print(new_data.shape)
new_data = data.reshape(3, 2)
print(new_data.shape)
new_data = data.reshape(1, 6)
print(new_data.shape)
new_data = data.reshape(-1)
print(new_data.shape)
执行结果
torch.Size([2, 3]) 2 3
torch.Size([2, 3]) 2 3
torch.Size([1, 6])
torch.Size([3, 2])
torch.Size([1, 6])
torch.Size([6])
15、squeeze()和unsqueeze()函数
squeeze 函数删除形状为1 的维度(降维),unsqueeze 函数添加形状为1的维度(升维)。
mydata1 = torch.tensor([1, 2, 3, 4, 5])
print('mydata1--->', mydata1.shape, mydata1) # 一个普通的数
# 组1维数据
mydata2 = mydata1.unsqueeze(dim=0)
print('在0维度上拓展维度:', mydata2, mydata2.shape) # 1*5
mydata3 = mydata1.unsqueeze(dim=1)
print('在1维度上拓展维度:', mydata3, mydata3.shape) # 5*1
mydata4 = mydata1.unsqueeze(dim=-1)
print('在最后1个维度上拓展维度:', mydata4, mydata4.shape) # 5*1
mydata5 = mydata4.squeeze()
print('压缩维度:', mydata5, mydata5.shape) # 1*5
执行结果
mydata1---> torch.Size([5]) tensor([1, 2, 3, 4, 5])
在0维度上拓展维度: tensor([[1, 2, 3, 4, 5]]) torch.Size([1, 5])
在1维度上拓展维度: tensor([[1],
[2],
[3],
[4],
[5]]) torch.Size([5, 1])
在最后1个维度上拓展维度: tensor([[1],
[2],
[3],
[4],
[5]]) torch.Size([5, 1])
压缩维度: tensor([1, 2, 3, 4, 5]) torch.Size([5])
16、transpose()和permute()函数
transpose 函数可以实现交换张量形状的指定维度, 例如: 一个张量的形状为(2, 3, 4) 可以通过transpose 函数把3 和4 进行交换, 将张量的形状变为(2, 4, 3) 。permute 函数可以一次交换更多的维度。
data = torch.tensor(np.random.randint(0, 10, [3, 4, 5]))
print('data shape:', data.size())
# 1 交换1和2维度
mydata2 = torch.transpose(data, 1, 2)
print('mydata2.shape--->', mydata2.shape)
# 2 将data 的形状修改为(4, 5, 3), 需要变换多次
mydata3 = torch.transpose(data, 0, 1)
mydata4 = torch.transpose(mydata3, 1, 2)
print('mydata4.shape--->', mydata4.shape)
# 3 使用permute 函数将形状修改为(4, 5, 3)
# 3-1 方法1
mydata5 = torch.permute(data, [1, 2, 0])
print('mydata5.shape--->', mydata5.shape)
# 3-2 方法2
mydata6 = data.permute([1, 2, 0])
print('mydata6.shape--->', mydata6.shape)
执行结果
data shape: torch.Size([3, 4, 5])
mydata2.shape---> torch.Size([3, 5, 4])
mydata4.shape---> torch.Size([4, 5, 3])
mydata5.shape---> torch.Size([4, 5, 3])
mydata6.shape---> torch.Size([4, 5, 3])
17、view()和contiguous()函数
view 函数也可以用于修改张量的形状,只能用于存储在整块内存中的张量。在PyTorch 中,有些张量是由不同的数据 块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理,例如: 一个张量经过了 transpose 或者permute 函数的处理之后,就无法使用view 函数进行形状操作。
data = torch.tensor([[10, 20, 30], [40, 50, 60]])
print('data--->', data, data.shape)
# 1 判断是否使用整块内存
print(data.is_contiguous()) # True
# 2 view
mydata2 = data.view(3, 2)
print('mydata2--->', mydata2, mydata2.shape)
# 3 判断是否使用整块
print('mydata2.is_contiguous()--->', mydata2.is_contiguous())
# 4 使用transpose 函数修改形状
mydata3 = torch.transpose(data, 0, 1)
print('mydata3--->', mydata3, mydata3.shape)
print('mydata3.is_contiguous()--->', mydata3.is_contiguous())
# 5 需要先使用contiguous 函数转换为整块内存的张量,再使用view 函数
print(mydata3.contiguous().is_contiguous())
mydata4 = mydata3.contiguous().view(2, 3)
print('mydata4--->', mydata4.shape, mydata4)
执行结果
data---> tensor([[10, 20, 30],
[40, 50, 60]]) torch.Size([2, 3])
True
mydata2---> tensor([[10, 20],
[30, 40],
[50, 60]]) torch.Size([3, 2])
mydata2.is_contiguous()---> True
mydata3---> tensor([[10, 40],
[20, 50],
[30, 60]]) torch.Size([3, 2])
mydata3.is_contiguous()---> False
True
mydata4---> torch.Size([2, 3]) tensor([[10, 40, 20],
[50, 30, 60]])
18、torch.cat()
torch.cat()函数可以将两个张量根据指定的维度拼接起来,不改变维度数。
data1 = torch.randint(0, 10, [1, 2, 3])
data2 = torch.randint(0, 10, [1, 2, 3])
print(data1)
print(data2)
# 1. 按0维度拼接
new_data = torch.cat([data1, data2], dim=0)
print(new_data)
print(new_data.shape)
# 2. 按1维度拼接
new_data = torch.cat([data1, data2], dim=1)
print(new_data)
print(new_data.shape)
# 3. 按2维度拼接
new_data = torch.cat([data1, data2], dim=2)
print(new_data)
print(new_data.shape)
执行结果
tensor([[[4, 9, 0],
[4, 1, 1]]])
tensor([[[4, 4, 8],
[4, 5, 1]]])
tensor([[[4, 9, 0],
[4, 1, 1]],
[[4, 4, 8],
[4, 5, 1]]])
torch.Size([2, 2, 3])
tensor([[[4, 9, 0],
[4, 1, 1],
[4, 4, 8],
[4, 5, 1]]])
torch.Size([1, 4, 3])
tensor([[[4, 9, 0, 4, 4, 8],
[4, 1, 1, 4, 5, 1]]])
torch.Size([1, 2, 6])
19、自动微分模块
训练神经网络时,最常用的算法就是反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应 参数的梯度进行调整。为了计算这些梯度,PyTorch内置了名为torch.autograd的微分引擎。它支持任意 计算图的自动梯度计算:

接下来我们使用这个结构进行自动微分模块的介绍。我们使用backward 方法、grad 属性来实 现梯度的计算和访问
import torch
def test01():
x = torch.tensor(5)
y = torch.tensor(0.)
w = torch.tensor(1., requires_grad=True, dtype=torch.float32)
b = torch.tensor(3., requires_grad=True, dtype=torch.float32)
z = w * x + b
loss = torch.nn.MSELoss()
loss = loss(z, y)
loss.backward()
print("W梯度:", w.grad)
print("b梯度:", b.grad)
test01()
def test02():
x = torch.ones(2, 5)
y = torch.zeros(2, 3)
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
z = x @ w + b
# print('x = ', x, 'w = ', w)
# print('z = ', z, ' x @ w = ', x @ w, 'b = ', b)
loss = torch.nn.MSELoss()
loss = loss(z, y)
loss.backward()
print(w.grad)
print(b.grad)
test02()
20、PyTorch构建线性回归模型相关API
import torch
from torch.utils.data import TensorDataset, DataLoader
from torch import nn, optim
from sklearn.datasets import make_regression
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def create_dataset():
x, y, coef = make_regression(
n_samples=100,
n_features=1,
noise=10,
coef=True,
bias=1.5,
random_state=40,
)
x = torch.tensor(x)
y = torch.tensor(y)
return x, y, coef
def dm01():
# 构造数据集
x, y, coef = create_dataset()
# 构造数据集对象
dataset = TensorDataset(x, y)
# 构造数据加载器
# dataset=:数据集对象
# batch_size=:批量训练样本数据
# shuffle=:样本数据是否进行乱序
dataloader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)
# 构造模型
# in_features指的是输入张量的大小size
# out_features指的是输出张量的大小size
model = nn.Linear(in_features=1, out_features=1)
# 构造平方损失函数
criterion = nn.MSELoss()
# 构造优化函数
optimizer = optim.SGD(params=model.parameters(), lr=1e-2)
epochs = 100
# 损失的变化
loss_epoch = []
total_loss = 0.0
train_sample = 0.0
for _ in range(epochs):
for train_x, train_y in dataloader:
# 将一个batch的训练数据送入模型
y_pred = model(train_x.type(torch.float32))
# 计算损失值
loss = criterion(y_pred, train_y.reshape(-1, 1).type(torch.float32))
total_loss += loss.item()
train_sample += len(train_y)
# 梯度清零
optimizer.zero_grad()
# 自动微分(反向传播)
loss.backward()
# 更新参数
optimizer.step()
# 获取每个batch的损失
loss_epoch.append(total_loss / train_sample)
# 绘制损失变化曲线
plt.plot(range(epochs), loss_epoch)
plt.title('损失变化曲线')
plt.grid()
plt.show()
# 绘制拟合直线
plt.scatter(x, y)
x = torch.linspace(x.min(), x.max(), 100)
y1 = torch.tensor([v * model.weight + model.bias for v in x])
y2 = torch.tensor([v * coef + 1.5 for v in x])
plt.plot(x, y1, label='训练')
plt.plot(x, y2, label='真实')
plt.grid()
plt.legend()
plt.show()
dm01()
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)