PyTorch
PyTorch
详情请看Pytorch 最全入门介绍,Pytorch入门看这一篇就够了-腾讯云开发者社区-腾讯云 (tencent.com)
1.PyTorch
1.1简介
Pytorch是torch的python版本,是由Facebook开源的神经网络框架,专门针对 GPU 加速的深度神经网络(DNN)编程。Torch 是一个经典的对多维矩阵数据进行操作的张量(tensor )库,在机器学习和其他数学密集型应用有广泛应用。与Tensorflow的静态计算图不同,pytorch的计算图是动态
的,可以根据计算需要实时改变计算图。但由于Torch语言采用 Lua,导致在国内一直很小众,并逐渐被支持 Python 的 Tensorflow 抢走用户。作为经典机器学习库 Torch 的端口,PyTorch 为 Python 语言使用者提供了舒适的写代码选择。
至于为什么推荐使用Pytorch,我想最主要的原因就是它非常的简洁
,非常符合Python的风格。
Pytorch中一共有5个不同的层次结构,分别为硬件层、内核层、低阶API、中阶API和高阶API。
1.2安装
- 如果安装速度慢,可选择换源
测试安装是否成功
import torch
print(torch.__version__) # pytorch版本
print(torch.version.cuda) # cuda版本
print(torch.cuda.is_available()) # 查看cuda是否可用
2.Pytorch基础
2.1Tensor操作
Tensor是PyTorch中最基本的数据结构,你可以将其视为多维数组或者矩阵。PyTorch tensor和NumPy array非常相似,但是tensor还可以在GPU上运算,而NumPy array则只能在CPU上运算。
import torch
# 创建一个未初始化的5x3矩阵
x = torch.empty(5, 3)
print(x)
# 创建一个随机初始化的5x3矩阵
x = torch.rand(5, 3)
print(x)
# 创建一个5x3的零矩阵,类型为long
x = torch.zeros(5, 3, dtype=torch.long)
print(x)
# 直接从数据创建tensor
x = torch.tensor([5.5, 3])
print(x)
# 创建一个tensor,并设置requires_grad=True以跟踪计算历史
x = torch.ones(2, 2, requires_grad=True)
print(x)
# 对tensor进行操作
y = x + 2
print(y)
# y是操作的结果,所以它有grad_fn属性
print(y.grad_fn)
# 对y进行更多操作
z = y * y * 3
out = z.mean()
print(z, out)
在PyTorch中,可以使用.backward()
来计算梯度
# 因为out包含一个标量,out.backward()等价于out.backward(torch.tensor(1.))
out.backward()
# 打印梯度 d(out)/dx
print(x.grad)
2.2GPU加速
检查是否存在可用的GPU
import torch
print(torch.cuda.is_available())
如果返回True,则存在可用GPU,使用.to()
将tensor移动到GPU上:
# 创建一个tensor
x = torch.tensor([1.0, 2.0])
# 移动tensor到GPU上
if torch.cuda.is_available():
x = x.to('cuda')
#也可以直接在创建tensor的时候就指定其设备:
if torch.cuda.is_available():
x = torch.tensor([1.0, 2.0], device='cuda')
将模型和数据移动到GPU上:
# 创建一个简单的模型
model = torch.nn.Linear(10, 1)
# 创建一些数据
data = torch.randn(100, 10)
# 移动模型和数据到GPU
if torch.cuda.is_available():
model = model.to('cuda')
data = data.to('cuda')
#Tensor在CPU和GPU之间转移
# 判断是否支持CUDA
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 创建一个Tensor
x = torch.rand(3, 3)
# 将Tensor转移到GPU上
x_gpu = x.to(device)
# 或者
x_gpu = x.cuda()
# 将Tensor转移到CPU上
x_cpu = x_gpu.cpu()
#将模型转移到GPU上
model = Model()
model.to(device)
2.3自动求导
在深度学习中,我们经常需要进行梯度下降优化。这就需要我们计算梯度,也就是函数的导数。在PyTorch中,我们可以使用自动求导机制(autograd)来自动计算梯度。
在PyTorch中,我们可以设置tensor.requires_grad=True
来追踪其上的所有操作。完成计算后,我们可以调用.backward()
方法,PyTorch会自动计算和存储梯度。这个梯度可以通过.grad
属性进行访问。
import torch
# 创建一个tensor并设置requires_grad=True来追踪其计算历史
x = torch.ones(2, 2, requires_grad=True)
# 对这个tensor做一次运算:
y = x + 2
# y是计算的结果,所以它有grad_fn属性
print(y.grad_fn)
# 对y进行更多的操作
z = y * y * 3
out = z.mean()
print(z, out)
# 使用.backward()来进行反向传播,计算梯度
out.backward()
# 输出梯度d(out)/dx
print(x.grad)
#输出结果
<AddBackward0 object at 0x000001444CBCBFA0>
tensor([[27., 27.],
[27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
以上示例中,out.backward()
等同于out.backward(torch.tensor(1.))
。如果out
不是一个标量,因为tensor是矩阵,那么在调用.backward()
时需要传入一个与out
同形的权重向量进行相乘。
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:
y = y * 2
print(y)
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
2.4求最小值
使用自动微分机制配套使用SGD随机梯度下降来求最小值
import numpy as np
import torch
# f(x) = a*x**2 + b*x + c的最小值
x = torch.tensor(0.0, requires_grad=True) # x需要被求导
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
optimizer = torch.optim.SGD(params=[x], lr=0.01) #SGD为随机梯度下降
print(optimizer)
def f(x):
result = a * torch.pow(x, 2) + b * x + c
return (result)
for i in range(500):
optimizer.zero_grad() #将模型的参数初始化为0
y = f(x)
y.backward() #反向传播计算梯度
optimizer.step() #更新所有的参数
print("y=", y.data, ";", "x=", x.data)
2.5数据
Pytorch主要通过Dataset和DataLoader进行构建数据管道。
- Dataset:一个数据集抽象类,所有自定义的Dataset都需要继承它,并且重写_getitem_()或_ get_sample_()这个类方法.
- DataLoader:一个可迭代的数据装载器。在训练的时候,每一个for循环迭代,就从DataLoader中获取一个batch_sieze大小的数据。
DataLoader(
dataset,
batch_size=1,
shuffle=False,
sampler=None,
batch_sampler=None,
num_workers=0,
collate_fn=None,
pin_memory=False,
drop_last=False,
timeout=0,
worker_init_fn=None,
multiprocessing_context=None,
)
Epoch | 所有的样本数据都输入到模型中,称为一个epoch |
---|---|
Iteration | 一个Batch的样本输入到模型中,称为一个Iteration |
Batchsize | 一个批次的大小,一个Epoch=Batchsize*Iteration |
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# 数据转换
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
# 下载并加载训练集
trainset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
# 下载并加载测试集
testset = datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)
自定义数据集
from torch.utils.data import Dataset, DataLoader
class MyDataset(Dataset):
def __init__(self, x_tensor, y_tensor):
self.x = x_tensor
self.y = y_tensor
def __getitem__(self, index):
return (self.x[index], self.y[index])
def __len__(self):
return len(self.x)
x = torch.arange(10)
y = torch.arange(10) + 1
my_dataset = MyDataset(x, y)
loader = DataLoader(my_dataset, batch_size=4, shuffle=True, num_workers=0)
for x, y in loader:
print("x:", x, "y:", y)
3.神经网络框架
3.1构建神经网络
PyTorch提供了torch.nn
库,它是用于构建神经网络的工具库。torch.nn
库依赖于autograd
库来定义和计算梯度。nn.Module
包含了神经网络的层以及返回输出的forward(input)
方法。
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module): #定义一个Net类,继承自nn.Module
def __init__(self):
super(Net, self).__init__()
# 输入图像channel:1,输出channel:6,5x5卷积核
self.conv1 = nn.Conv2d(1, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
# 全连接层
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
#定义数据的流向
def forward(self, x):
# 使用2x2窗口进行最大池化
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# 如果窗口是方的,只需要指定一个维度
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flat_features(self, x):
size = x.size()[1:] # 获取除了batch维度之外的其他维度
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
3.2模型的加载和保存
# 保存
torch.save(model, PATH)
# 加载
model = torch.load(PATH)
model.eval()
3.3训练网络
for epoch in range(2): # 在数据集上训练两遍
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# 获取输入数据
inputs, labels = data
# 梯度清零
optimizer.zero_grad()
# 前向传播
outputs = net(inputs)
# 计算损失
loss = criterion(outputs, labels)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
# 打印统计信息
running_loss += loss.item()
if i % 2000 == 1999: # 每2000个批次打印一次
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了