pytorch(完结)
·
PyTorch语法
1.张量的创建
import torch
a=[1,2,3.]
print(type(a))
b=torch.tensor(a)
print(b)
print(type(b))
print(b.dtype)
import numpy as np
c=np.random.normal((2,3))
d=torch.tensor(c)
print(d)
e=torch.ones_like(d)
print(e)
f=torch.zeros_like(d)
print(f)
g=torch.rand_like(d)
print(g)
print(torch.rand((2,2)))
print(torch.randn([2,2]))
print(torch.rand([2,2,]).dtype)
h=torch.rand([2,2,])
print(h.dtype)
print(h.shape)
print(h.device)
print(torch.is_tensor(h))
i=torch.tensor(0)
print(torch.is_nonzero(i))
print('-'*34)
print(torch.numel(h))
print(torch.zeros([5,5]))
a=torch.zeros([5,5],dtype=torch.int32)
print(a)
print(torch.zeros([5,5]).dtype)
print(torch.ones_like(a))
print('-'*34)
print(torch.arange(5))
print(torch.arange(0,5,2))
print(torch.range(0,5))
print(torch.range(0,2).dtype)
print(torch.arange(0,5).dtype)
for i in torch.arange(5):
print('epoch:',i)
print(torch.eye(3))
print(torch.ones_like(a)*5)
print(torch.full([2,2],2))
print(torch.full_like(a,2))
a=torch.rand([3,2,])
print(a)
b=torch.rand([3,2,])
print(b)
print(torch.cat([a,b],dim=0))
2.张量的运算API(1)
import torch
b=torch.rand([3,2])
print(b)
c,d=torch.chunk(b,chunks=2,dim=1)
print(c)
print(d)
print(torch.reshape(torch.reshape(b,[2,3]),[-1]))
print('-'*34)
src = torch.tensor([[1,2],
[3,4],
[5,6]])
index = torch.tensor([[0,2],
[1,0],
[2,1]])
'''out = torch.zeros_like(src)
out.scatter_(dim=0, index=index, src=src)
#src [i][j] 这个数,要搬到 out 的 第 index [i][j] 行、第 j 列
print(out)
'''
a=torch.arange(10).reshape(5,2)
#print(a)
#print(torch.split(a,[1,4]))
'''
print(a.shape)
print(torch.squeeze(torch.reshape(a,[1,1,5,2]),dim=0).shape)
'''
b=torch.rand(5,2)
print(torch.stack([a,b],dim=0).shape) #torch.Size([2, 5, 2])
print(torch.stack([a,b],dim=1).shape) #torch.Size([5, 2, 2])
print(torch.cat([a,b],dim=0).shape) #torch.Size([10, 2])
print(torch.cat([a,b],dim=1).shape) #torch.Size([5, 4])
3.张量的运算API(2)
import torch
a=torch.rand([3,2])
print(a)
#print(torch.take(a,torch.tensor([0,2,4])))
'''
print(torch.tile(a,dims=[1,2]))
print(torch.tile(a,dims=[2,1]))
'''
'''
print(torch.transpose(a,0,1))
print('-'*34)
print(torch.unbind(a,dim=0))
print(torch.unbind(a,dim=1))
print('-'*34)
print(torch.unsqueeze(a,dim=0).shape)
print(torch.unsqueeze(a,dim=1).shape)
print(torch.unsqueeze(a,dim=-1).shape)
'''
b=torch.zeros_like(a)
print(torch.where(a>0.5,a,b))
4.dataset的基本代码实现
from torch.utils.data import Dataset
from PIL import Image
import os
class MyDataset(Dataset):
def __init__(self,root_dir,label_dir):
self.root_dir=root_dir
self.label_dir=label_dir
self.path=os.path.join(self.root_dir,self.label_dir)
self.img_path=os.listdir(self.path)
def __getitem__(self,index):
img_name=self.img_path[index]
img_item_path=os.path.join(self.root_dir,self.label_dir,img_name)
img=Image.open(img_item_path)
label=self.label_dir
return img,label
def __len__(self):
return len(self.img_path)
root_dir='dataset'
ants_label_dir='ants'
bees_label_dir='bees'
ants_dataset=MyDataset(root_dir,ants_label_dir)
bees_dataset=MyDataset(root_dir,bees_label_dir)
dataset=ants_dataset+bees_dataset
5.如何用 SummaryWriter 记录图像和标量
import numpy
numpy.bool8 = bool
from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image
writer=SummaryWriter('logs')
image_path='dataset/ants/0013035.jpg'
img_PIL=Image.open(image_path)
img_array=np.array(img_PIL)
print(type(img_array))
print(img_array.shape)
writer.add_image("test",img_array,1,dataformats='HWC')
#y=2x
for i in range(100):
writer.add_scalar('y=2x', 2*i, i)
writer.close()
6.使用transforms.ToTensor()将PIL图像转换为Tensor
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
img_path="dataset/ants/0013035.jpg"
img_PIL=Image.open(img_path)
writer=SummaryWriter('logs')
#1.使用transforms.ToTensor()将PIL图像转换为Tensor
transform=transforms.ToTensor()
img_tensor=transform(img_PIL)
writer.add_image('Tensor_img',img_tensor)
writer.close()
7.transform的常见图像预处理操作
from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
img=Image.open("dataset/1E6B8C5DB9722D99D028F39265867A60.png")
print(img)
writer=SummaryWriter('logs')
# ToTensor
trans_totensor=transforms.ToTensor()
img_tensor=trans_totensor(img)
writer.add_image('ToTensor',img_tensor)
# Normalize
'''
将输入张量 img_tensor 的每个通道减去均值 mean,再除以标准差 std。
公式:output = (input - mean) / std'''
print(img_tensor[0][0][0])
transform_norm=transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])
img_norm=transform_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image('Normalize',img_norm,2)
#Resize
print(img.size)
#将输入图像 img(PIL 格式)缩放到 512×512 像素,得到 img_resize(依然是 PIL 图像)
transform_resize=transforms.Resize((512,512))
#img.PIL->resize->img_resize PIL
img_resize=transform_resize(img)
#img_resize PIL->to_tensor->img_resize_tensor Tensor
img_resize=trans_totensor(img_resize)
writer.add_image('Resize',img_resize,0)
print(img_resize)
#Compose
#Resize(512) 表示将图像的短边缩放到 512 像素,长边等比例缩放(保持宽高比)。
transforms_resize_2=transforms.Resize(512)
#PIL->PIL->Tensor
transform_compose=transforms.Compose([transform_resize,trans_totensor])
#先执行 transform_resize(对输入图像做尺寸调整),再执行 trans_totensor(将 PIL 图像转为 PyTorch 张量)
img_resize_2=transform_compose(img)
writer.add_image('Compose',img_resize_2,1)
#RandomCrop
#从同一张原始图像中随机裁剪出 10 个不同的 256×256 子图,并将它们全部转换为 PyTorch 张量。
transform_randomcrop=transforms.RandomCrop(256)
trans_compose_2=transforms.Compose([transform_randomcrop,trans_totensor])
#组合两个操作:先随机裁剪,再将裁剪后的 PIL 图像转换为张量(形状 (C, 256, 256),值域 [0,1])
for i in range(10):
img_crop=trans_compose_2(img)
writer.add_image('RandomCrop',img_crop,i)
writer.close()
8.transform与dataset的结合
import torchvision
from torch.utils.tensorboard import SummaryWriter
dataset_transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor()
])
train_set=torchvision.datasets.CIFAR10(root='./data', train=True, transform=dataset_transform, download=True)
test_set=torchvision.datasets.CIFAR10(root='./data', train=False, transform=dataset_transform, download=True)
'''
print(train_set[0])
print(train_set.classes)
img,target=train_set[0]
print(img)
print(target)
print(train_set.classes[target])
img.show()
'''
#print(test_set[0])
writer=SummaryWriter('p10')
for i in range(10):
img,target=test_set[i]
writer.add_image('test_set',img,i)
writer.close()
9.dataloader
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
test_data=torchvision.datasets.CIFAR10(root="./data", train=False, transform=torchvision.transforms.ToTensor())
test_dataloader=DataLoader(test_data, batch_size=64, shuffle=False, num_workers=0, drop_last=True)
img,target=test_data[0]
print(img.shape)
print(target)
writer=SummaryWriter(log_dir="./dataloader")
for epoch in range(2):
step=0
for data in test_dataloader:
imgs, targets=data
#print(imgs.shape)
#print(targets)
writer.add_images("Epoch: {}".format(epoch), imgs, step)
step+=1
writer.close()
10.神经网络的基本骨架
import torch
from torch import nn
class MyModule(nn.Module):
def __init__(self):
super().__init__()
def forward(self,input):
output=input+1
return output
mynodule=MyModule()
x=torch.tensor(1.0)
y=mynodule(x)
print(y)
11.卷积操作
import torch
import torch.nn.functional as F
input=torch.tensor([
[1,2,0,3,1],
[0,1,2,3,1],
[1,2,1,0,0],
[5,2,3,1,1],
[2,1,0,1,1],])
kernel=torch.tensor([
[1,2,1],
[0,1,0],
[2,1,0],])
input=torch.reshape(input,(1,1,5,5))
kernel=torch.reshape(kernel,(1,1,3,3))
print(input.shape)
print(kernel.shape)
output=F.conv2d(input,kernel,stride=1)
print(output)
output2=F.conv2d(input,kernel,stride=2)
print(output2)
output3=F.conv2d(input,kernel,stride=1,padding=1)
print(output3)
12.神经网络——卷积层
conv1: Conv2d(3, 32, kernel_size=(5,5), stride=(1,1), padding=(2,2))
Conv2d:二维卷积层,用于提取图像空间特征
3:输入通道数,对应 RGB 图像由红、绿、蓝3 个单通道灰度图叠加而成,所以输入通道固定为 3。卷积层会同时对这 3 个通道做卷积运算,融合色彩与纹理信息。32:输出通道数,该层输出 32 组卷积特征图,该层使用了 32 个不同的 5×5 卷积核kernel_size=(5,5):卷积核大小,5×5 的方形卷积窗口stride=(1,1):步长,卷积核每次在宽、高方向各移动 1 个像素padding=(2,2):填充,在图像四周补 2 圈 0 像素,作用:保证卷积后特征图宽高不变
计算:卷积核(小权重矩阵)和图像对应位置逐元素相乘,再全部求和,得到一个输出点。
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from urllib3.filepost import writer
dataset=torchvision.datasets.CIFAR10("./data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=64)
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1=torch.nn.Conv2d(3,6,kernel_size=3,stride=1,padding=0)
def forward(self,x):
x=self.conv1(x)
return x
net=Net()
writer=SummaryWriter("logs")
step=0
for data in dataloader:
imgs,targets=data
output=net(imgs)
print(imgs.shape)
print(output.shape)
#torch.Size([64, 3, 32, 32])
writer.add_images("input",imgs,step)
#torch.Size([64, 6, 30, 30])->torch.Size([xx, 3, 30, 30])
output=torch.reshape(output,(-1,3,30,30))
writer.add_images("output",output,step)
step+=1
13.神经网络——最大池化
pool1: MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
MaxPool2d:最大池化层,下采样、降维、简化特征、减少计算量
kernel_size=2:池化窗口大小 2×2stride=2:步长 2,窗口不重叠padding=0:不补零dilation=1:空洞卷积系数,普通池化固定为 1,池化核元素紧挨着,无空隙ceil_mode=False:向下取整计算输出尺寸
import torch
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from urllib3.filepost import writer
input=torch.tensor([
[1,2,0,3,1],
[0,1,2,3,1],
[1,2,1,0,0],
[5,2,3,1,1],
[2,1,0,1,1]
])
dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=64)
class MaxPool(torch.nn.Module):
def __init__(self):
super(MaxPool, self).__init__()
self.pool=torch.nn.MaxPool2d(kernel_size=3,ceil_mode=False)
def forward(self,x):
x=self.pool(x)
return x
model=MaxPool()
writer=SummaryWriter('logs')
step=0
for data in dataloader:
imgs,targets=data
writer.add_image("input",imgs,step)
output=model(imgs)
writer.add_image("output",output,step)
step+=1
writer.close()
14.神经网络——非线性激活
import torch
import torchvision
from torch import nn
from torch.nn import Sigmoid, ReLU
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
input=torch.tensor([
[1,-0.5],
[-1,3]])
output=torch.reshape(input,(-1,1,2,2))
dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=64)
class Relu(torch.nn.Module):
def __init__(self):
super(Relu, self).__init__()
self.relu=ReLU()
self.sigmoid1=Sigmoid()
def forward(self,input):
output=self.sigmoid1(input)
return output
model=Relu()
writer=SummaryWriter('logs')
step=0
for data in dataloader:
imgs,targets=data
writer.add_images("input",imgs,global_step= step)
output=model(imgs)
writer.add_images("output",output,global_step=step)
step+=1
writer.close()
15.神经网络——线性层
linear1: Linear(in_features=1024, out_features=64, bias=True)
Linear:全连接层,把二维特征图展平为一维向量做特征融合
in_features=1024:输入神经元总数 说明:经过 3 次池化后,特征图展平一共 1024 个数值out_features=64:输出 64 个神经元bias=True:启用偏置项(网络默认开启,提升拟合能力)让网络学习能力更强,能适配更多样本、提升拟合效果。
import torch
import torchvision
from torch.utils.data import DataLoader
dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=64) #
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.linear=torch.nn.Linear(196608,10)
def forward(self,input):
output=self.linear(input)
return output
net=Net()
for data in dataloader:
imgs,targets=data
print(imgs.shape)
output=torch.flatten(imgs)
print(output.shape)
output=net(output)
print(output.shape)
线性层负责对输入进行可学习的加权组合与维度变换,是网络表达能力的“骨架”;而非线性层负责引入弯曲能力,二者相辅相成,缺一不可。
16.Sequential的使用
按顺序把网络层串成一整条流水线,数据从上到下依次经过每一层,不用手动逐层调用。代码简洁、结构清晰,适合一层接一层线性串联的网络。
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.tensorboard import SummaryWriter
from urllib3.filepost import writer
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.model1=nn.Sequential(
Conv2d(3, 32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 64, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Flatten(),
Linear(1024,64),
Linear(64, 10)
)
def forward(self,x):
x=self.model1(x)
return x
net=Net()
print(net)
input=torch.ones(64,3,32,32)
output=net(input)
print(output.shape)
writer=SummaryWriter('logs_seq')
writer.add_graph(net,input)
writer.close()
17.损失函数
import torch
from torch.nn import L1Loss
from torch import nn
inputs=torch.tensor([1,2,3],dtype=torch.float32)
targets=torch.tensor([1,2,5],dtype=torch.float32)
inputs=torch.reshape(inputs,[1,1,1,3])
targets=torch.reshape(targets,[1,1,1,3])
loss=L1Loss()#L1Loss:平均绝对误差,算差值绝对值
output=loss(inputs,targets)
loss_mse=nn.MSELoss ()#均方误差(MSE),算差值平方
output_mse=loss_mse(inputs,targets)
print(output)
print(output_mse)
x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x=torch.reshape(x,[1,3])
loss_cross=nn.CrossEntropyLoss()
output_cross=loss_cross(x,y)
print(output_cross)
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=1)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.model1=nn.Sequential(
Conv2d(3, 32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 64, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Flatten(),
Linear(1024,64),
Linear(64, 10)
)
def forward(self,x):
x=self.model1(x)
return x
loss=nn.CrossEntropyLoss()#交叉熵,专用于分类任务
Net=Net()
for data in dataloader:
imgs,targets=data
outputs=Net(imgs)
result_loss=loss(outputs,targets)
print(result_loss)
18.优化器
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
dataset=torchvision.datasets.CIFAR10("../data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=1)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.model1=nn.Sequential(
Conv2d(3, 32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 32, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 64, kernel_size=5, padding=2),
MaxPool2d(kernel_size=2),
Flatten(),
Linear(1024,64),
Linear(64, 10)
)
def forward(self,x):
x=self.model1(x)
return x
loss=nn.CrossEntropyLoss()
Net=Net()
optim=torch.optim.SGD(Net.parameters(),lr=0.01)
for epoch in range(20):
running_loss=0.0
for data in dataloader:
imgs,targets=data
outputs=Net(imgs)
result_loss=loss(outputs,targets)
optim.zero_grad()#每次循环清零梯度
result_loss.backward()#反向传播计算梯度
optim.step()#根据梯度优化相关参数
running_loss+=result_loss
print(f"第{epoch}轮训练损失为:{running_loss}")
19.完整的模型训练套路
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from model import *
train_data=torchvision.datasets.CIFAR10(root="./data", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data=torchvision.datasets.CIFAR10(root="./data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
train_data_size=len(train_data)
test_data_size=len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))
#利用dataloader加载数据集
train_dataloader=DataLoader(train_data,batch_size=64)
test_dataloader=DataLoader(test_data,batch_size=64)
#创建网络模型
net=Net()
#损失函数
loss_fn=nn.CrossEntropyLoss()
#优化器
learning_rate=1e-2
optimizer=torch.optim.SGD(net.parameters(),lr=learning_rate)
#记录训练次数
total_train_step=0
#测试次数
total_test_step=0
#训练的轮数
epoch=10
writer=SummaryWriter("logs_train")
for i in range(epoch):
print("第{}轮训练开始".format(i+1))
net.train()
for data in train_dataloader:
images,targets=data
output=net(images)
loss=loss_fn(output,targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step+=1
if total_train_step%100==0:
print("训练次数:{},loss:{}".format(total_train_step,loss.item()))
writer.add_scalar("train_loss",loss.item(),total_train_step)#add_scalar 就是专门用来向 TensorBoard 记录单个数值曲线的方法。
#测试步骤
net.eval()
total_test_loss=0
total_accuracy=0
with torch.no_grad():
for data in test_dataloader:
images,targets=data
output=net(images)
loss=loss_fn(output,targets)
total_test_loss+=loss.item()
accuracy=(output.argmax(1)==targets).sum()
total_accuracy+=accuracy.item()
print("整体测试集上的loss:{}".format(total_test_loss))
print("整体测试集上的accuracy:{}".format(total_accuracy/test_data_size))
writer.add_scalar("test_loss",total_test_loss,total_test_step)
writer.add_scalar("test_accuracy",total_accuracy/test_data_size,total_test_step)
total_test_step+=1
torch.save(net,"net_{}.pth".format(i+1))#第 1 个参数:要保存的对象(模型 / 参数 / 字典)第 2 个参数:保存路径 / 文件名
#第二种保存模型的方式 torch.save(net.state_dict(),"net_params_{}.pth".format(i+1))
print("模型已保存")
writer.close()
20.现有网络模型的使用,修改,保存
import torchvision
from torch import nn
'''
split="train"
加载训练集,用来给模型训练、更新权重。
split="val"
加载验证集,训练中途用来评估模型效果、调参数。
split="test"
加载测试集,训练全部结束后,做最终效果评测。
'''
#train_data=torchvision.datasets.ImageNet("./data_image",split="train",transform=torchvision.transforms.ToTensor(),download=True)
vgg16_false=torchvision.models.vgg16(pretrained=False)
# 不加载预训练权重,随机初始化参数
vgg16_true=torchvision.models.vgg16(pretrained=True)
# 加载ImageNet预训练权重(官方训练好的参数)
vgg16_true.classifier.add_module('add_linear',nn.Linear(1000,10))
print(vgg16_true)
vgg16_false.classifier[6]=nn.Linear(4096,10)
print(vgg16_false)
import torch
import torchvision
vgg16=torchvision.models.vgg16(pretrained=False)
#保存方式1,模型结构+模型参数
torch.save(vgg16,"vgg16_method1.pth")
#保存方式2,模型参数
torch.save(vgg16.state_dict(),"vgg16_method2.pth")
利用GPU训练
21.模型验证套路
import torch
import torchvision
from PIL import Image
from torch import nn
from model import Net
imag_path="dataset/1E6B8C5DB9722D99D028F39265867A60.png"
image=Image.open(imag_path)
print(image)
transform=torchvision.transforms.Compose(
[torchvision.transforms.Resize((32,32)),
torchvision.transforms.ToTensor()
])
image=transform(image)
print(image.shape)
model=Net()
state_dict = torch.load("net_params_1.pth")
model.load_state_dict(state_dict)
image=torch.reshape(image,[1,3,32,32])
model.eval()
with torch.no_grad():
output=model(image)#关闭后能大幅减少显存占用。
print(output)
print(output.argmax(1))

所有评论(0)