pytorch使用
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" #原始环境为了避免混乱的包冲突
1. 张量(tensor)
import torch
import numpy as np
1.1 初始化
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data) #从列表初始化
np_array = np.array(data)
x_data = torch.from_numpy(np_array) #从numpy初始化
x_ones = torch.ones_like(x_data) #保持相同规模,全部置1
x_rand = torch.rand_like(x_data, dtype=torch.float) #保持相同规模,生成随机数
根据维度进行初始化
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)
1.2 张量运算
像numpy一样进行索引和切片
tensor[0] #第一行
tensor[:,0] #第一列
tensor[...,-1] #最后一列
t1 = torch.cat([tensor, tensor, tensor], dim=1) #进行拼接
算数运算
#内积
tensor*tensor tensor.mul(tensor)
#矩阵乘法
X@X X.matmul(X)
tensor.sum() #所有元素求和
#增加_ , 进行原地操作
tensor.add_(5) #所有元素增加5
内存共享(可以轻松使用numpy的所有运算)
#从tensor生成numpy , 与从numpy生成tensor,二者内存共享
np_ = tensor.numpy()
tensor = torch.from_numpy(np_)
2. 数据集和数据读取
2.1 可视化(随机展示9张图片)
import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plt
#training_data每个索引包含一个元组,第一个数据为图像tensor,第二个数据为预测类别int
figure = plt.figure(figsize=(8, 8)) #创建一个图像对象,尺寸为8X8
cols, rows = 3, 3
for i in range(1, cols * rows + 1):
sample_idx = torch.randint(len(training_data), size=(1,)).item() #生成随机索引
img, label = training_data[sample_idx] #根据索引读取图片和预测标签
figure.add_subplot(rows, cols, i) #在3X3的子图网格中添加子图
plt.title(label) #可以让预测标签映射到实际名字作为显示
plt.axis("off")
plt.imshow(img.squeeze(), cmap="gray") #显示压缩的灰度图
plt.show()
2.2 自定义数据集类进行读取
import os
import pandas as pd
from torchvision.io import read_image
class CustomImageDataset(Dataset): #继承自Dataset的类
自定义数据集类必须包含三部分:__init__, __len__, and __getitem__
def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
self.img_labels = pd.read_csv(annotations_file) #图片名字和对应标签
self.img_dir = img_dir #图片路径
self.transform = transform
self.target_transform = target_transform
def __len__(self):
return len(self.img_labels) #数据的个数
def __getitem__(self, idx):
img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0]) #拼接图像路径,和图像名称
image = read_image(img_path) #读取图片成张量格式
label = self.img_labels.iloc[idx, 1] #对应图片的标签
if self.transform:
image = self.transform(image)
if self.target_transform:
label = self.target_transform(label)
return image, label #返回图像和对应标签
2.3 数据洗牌和迭代
from torch.utils.data import DataLoader
train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=True)
train_features, train_labels = next(iter(train_dataloader)) #每次可以得到64个随机数据
2.4 Transforms
简单处理
transform=ToTensor(), #对数据进行处理,这里是变成张量格式,同时归一化处理
#对标签数据进行处理,这里是根据类别进行one-hot编码
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
Script the transformation
transforms = torch.nn.Sequential(
transforms.CenterCrop(10),
transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
)
scripted_transforms = torch.jit.script(transforms)
3. 建立一个神经网络
import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
device = ( #检验cuda能否使用
"cuda"
if torch.cuda.is_available()
else "mps"
if torch.backends.mps.is_available()
else "cpu"
)
print(f"Using {device} device")
class NeuralNetwork(nn.Module): #注意这里的模型是有参数的(权重和偏差)
def __init__(self):
super().__init__() #父类初始化
self.flatten = nn.Flatten() #将二维图像展平成一维向量
self.linear_relu_stack = nn.Sequential( #按序组合多个层
nn.Linear(28*28, 512), #全连接层,将28×28图像展平后,连接到512神经元的隐藏层
nn.ReLU(), #ReLU激活函数
nn.Linear(512, 512), #全连接层,将512隐藏层输出连接到另一个512隐藏层
nn.ReLU(), #ReLU激活函数
nn.Linear(512, 10), #全连接层,将512隐藏层输出连接到10维的输出层
)
def forward(self, x): #前向传播
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
model = NeuralNetwork().to(device) #j将这个类放到gpu上
4. 完整的前向传播和反向传播
一次训练迭代过程过程
def train_loop(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset) #总训练数据集大小
model.train()
for batch, (X, y) in enumerate(dataloader):
# Compute prediction and loss
pred = model(X)
loss = loss_fn(pred, y)
# Backpropagation
loss.backward()
optimizer.step()
optimizer.zero_grad()
if batch % 100 == 0: #每一百轮输出一次
loss, current = loss.item(), (batch + 1) * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
def test_loop(dataloader, model, loss_fn):
# Set the model to evaluation mode - important for batch normalization and dropout layers
# Unnecessary in this situation but added for best practices
model.eval()
size = len(dataloader.dataset)
num_batches = len(dataloader)
test_loss, correct = 0, 0
# Evaluating the model with torch.no_grad() ensures that no gradients are computed during test mode
# also serves to reduce unnecessary gradient computations and memory usage for tensors with requires_grad=True
with torch.no_grad():
for X, y in dataloader:
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= num_batches
correct /= size
print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
进行多次迭代更新参数
model = NeuralNetwork()
epochs = 10
for t in range(epochs):
print(f"Epoch {t+1}\n-------------------------------")
train_loop(train_dataloader, model, loss_fn, optimizer)
test_loop(test_dataloader, model, loss_fn)
print("Done!")
存储模型
torch.save(model, 'model.pth')
model = torch.load('model.pth')