目录
- 基础
- 数据可视化
- 切换设备device
- 定义神经网络类
- 打印每层的参数大小
- 自动微分
- 计算梯度
- 禁用梯度追踪
- 优化模型参数
- 模型保存
- 模型加载
- 进阶
- padding更准确的补法
- ReLU增加计算量但是减少内存消耗的办法
- 输出合并
- 自适应平均池化(将输入shape变成指定的输出shape)
- python方法
- 读取图片
- 获取绝对路径方法
- 数据加载
- 获取数据的分类索引,并进行翻转
- 将类别写入json文件
- 读取json文件
- 打印训练时间
基础
数据可视化
import torch
from torch.utils.data import Dataset
from torchvision import datasets
from torchvision.transforms import ToTensor
import matplotlib.pyplot as plttraining_data = datasets.FashionMNIST(root="data1",train=True,download=True,transform=ToTensor()
)test_data = datasets.FashionMNIST(root="data1",train=False,download=True,transform=ToTensor()
)
labels_map = {0: "T-Shirt",1: "Trouser",2: "Pullover",3: "Dress",4: "Coat",5: "Sandal",6: "Shirt",7: "Sneaker",8: "Bag",9: "Ankle Boot",
}
cols, rows = 3, 3
for i in range(1, cols * rows + 1):sample_idx = torch.randint(len(training_data), size=(1,)).item() #用于随机取出一个training_dataimg, label = training_data[sample_idx]plt.subplot(3,3,i) #此处i必须是1开始plt.title(labels_map[label])plt.axis("off")plt.imshow(img.squeeze(), cmap="gray")
plt.show()
切换设备device
device = ("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),nn.ReLU(),nn.Linear(512, 512),nn.ReLU(),nn.Linear(512, 10),)def forward(self, x):x = self.flatten(x)logits = self.linear_relu_stack(x)return logits
打印每层的参数大小
print(f"Model structure: {model}\n\n")for name, param in model.named_parameters():print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
自动微分
详见文章Variable
需要优化的参数需要加requires_grad=True
,会计算这些参数对于loss的梯度
import torchx = torch.ones(5) # input tensor
y = torch.zeros(3) # expected output
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
z = torch.matmul(x, w)+b
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y)
计算梯度
计算导数
loss.backward()
print(w.grad)
print(b.grad)
禁用梯度追踪
训练好后进行测试,也就是不要更新参数时使用
z = torch.matmul(x, w)+b
print(z.requires_grad)with torch.no_grad():z = torch.matmul(x, w)+b
print(z.requires_grad)
优化模型参数
- 调用optimizer.zero_grad()来重置模型参数的梯度。梯度会默认累加,为了防止重复计算(梯度),我们在每次遍历中显式的清空(梯度累加值)。
- 调用loss.backward()来反向传播预测误差。PyTorch对每个参数分别存储损失梯度。
- 我们获取到梯度后,调用optimizer.step()来根据反向传播中收集的梯度来调整参数。
optmizer.zero_grad()
loss.backward()
optmizer.step()
模型保存
import torch
import torchvision.models as modelsmodel = models.vgg16(weights='IMAGENET1K_V1')
torch.save(model.state_dict(), 'model_weights.pth')
模型加载
model = models.vgg16() # we do not specify ``weights``, i.e. create untrained model
model.load_state_dict(torch.load('model_weights.pth'))
model.eval()
进阶
padding更准确的补法
input=torch.randn(1,1,3,3)
m=torch.nn.ZeroPad2d((1,1,2,0)) #左,右,上,下
m(input)
ReLU增加计算量但是减少内存消耗的办法
torch.nn.ReLU(inplace=True)
输出合并
output=[branch1,branch2,branch3,branch4]
torch.cat(output,1) #在1维度上合并
自适应平均池化(将输入shape变成指定的输出shape)
avgpool=torch.nn.AdaptiveAvgPool2d((1,1)) #输出shape为(1,1)
python方法
读取图片
from PIL import Image
im=Image.open('1.jpg')
获取绝对路径方法
import os
data_root=os.path.abspath(os.getcwd())
data_root
数据加载
data_transform={'train':transforms.Compose([transforms.RandomResizedCrop(224),transforms.ToTensor(),transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))]),'val':transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
}from torchvision import transforms,datasets,utils
train_dataset=datasets.ImageFolder(root=data_root+'train',transform=data_transform['train'])
获取数据的分类索引,并进行翻转
train_dataset.class_to_idx
cla_dict=dict((val,key) for key,val in flower_list.items())
将类别写入json文件
import json
json_str=json.dumps(cla_dict,indent=4) #转成json文件
with open('class_indices.json','w') as json_file: #写入json文件json_file.write(json_str)
读取json文件
try:json_file=open('./class_indices.json','r')class_indict=json.load(json_file)
except Exception as e:print(e)exit(-1)
打印训练时间
import time
t1=time.perf_counter()
'.....'
time.perf_counter-t1