import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
# 搭建自己的网络结构,其中不包括输入层与输出层
self.covn1 = nn.Conv2d(1,10,5)
self.covn2 = nn.Conv2d(20,20,5)
def forward(self,input): #前向传播
x = F.relu(self.covn1(input)) # 将输入的数据先进行卷积操作,然后进行一个非线性变化
return F.relu(self.covn2(x))
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
#获得数据 train=False:创建的是一个训练集 download=True:自己会下载数据集到本地文件
# torchvision.transforms.ToTensor():将数据类型转化为tensor类型
dataset = torchvision.datasets.CIFAR10("./data", train=False,transform=torchvision.transforms.ToTensor(), download=True)
#加载器 shuffle:是否打乱顺序 drop_last:是否删除掉除最后不尽的样本
dataloader = DataLoader(dataset, batch_size=64, shuffle=False,drop_last=False)
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
# 输入通道3,因为图片为彩色的,输出通道为6,卷积核是6个,卷积核的大小为3*3的,步长为1 ,不进行卷积填充
self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)
def forward(self,input):
#将输入数据进行卷积操作
x = self.conv1(input)
return x
#初始化网络
tudui = Tudui()
#输出网络结构
# print(tudui)
for data in dataloader:
imgs, targets = data
output = tudui(imgs)
print(imgs.shape)
print(output.shape)
#./ 表示当前目录下的
#../ 表示当前文件的上一级目录所在的目录
import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
"""
writer = SummaryWriter("./logs")
for i in range(100):
#tag 图像的标题 scalar_value 表示y轴的数据 global_step 表示x轴的数据
writer.add_scalar("y=2x",2*i,i)
"""
#获得数据 train=False 创建的是一个训练集 download=True 自己会下载数据集到本地文件
dataset = torchvision.datasets.CIFAR10("./data",train=False,transform=torchvision.transforms.ToTensor(),download=True)
#加载器 shuffle 是否打乱顺序 drop_last 是否删除掉除最后不尽的样本
dataloader = DataLoader(dataset,batch_size=64,shuffle=False,drop_last=False)
writer = SummaryWriter("./logs") # 实例化一个类,文件存放在logs文件夹下
step = 0
for data in dataloader:
imgs, targets = data
print(imgs.shape)
# torch.Size([64,3,32,32]) imgs 为tensor类型
writer.add_images("input", imgs, step) # 将图片存入writer类中
step = step + 1
writer.close() # 最后关闭writer类
"""
tensorboard --logdir=logs 启动文件查看
每次运行之前如果图像有问题可删除logs文件夹下的文件再启动
指定查看的端口号 tensorboard --logdir=logs --port=6007
"""
定义一个有序的容器,神经网络将根据定义的层顺序执行,并且也有效简化代码
import torch
from torch import nn
from torch.nn import Sequential
"""
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5,padding=2)
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2)
self.maxpool2 = nn.MaxPool2d(kernel_size=2)
self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2)
self.maxpool3 = nn.MaxPool2d(kernel_size=2)
self.flatter = nn.Flatten()
self.linear1 = nn.Linear(in_features=1024, out_features=64)
self.linear2 = nn.Linear(in_features=64, out_features=10)
def forward(self,input):
x = self.conv1(input)
x = self.maxpool1(x)
x = self.conv2(x)
x = self.maxpool2(x)
x = self.conv3(x)
x = self.maxpool3(x)
x = self.flatter(x)
x = self.linear1(x)
x = self.linear2(x)
return x
"""
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.model = Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Flatten(),
nn.Linear(in_features=1024, out_features=64),
nn.Linear(in_features=64, out_features=10),
)
def forward(self,input):
x = self.model(input)
return x
tudui = Tudui()
input = torch.ones((64,3,32,32))
output = tudui(input)
print(output)
# 交叉熵损失函数
loss = nn.CrossEntropyLoss()
tudui = Tudui()
for data in dataloader:
imgs,target = data
output = tudui(imgs) #output.shape = [64,10] target.shape = [64]
result_loss = loss(output,target)
result_loss.backward() #反向传播 (只是进行反向传播 并没有进行梯度的优化)
#交叉熵损失函数
loss = nn.CrossEntropyLoss()
tudui = Tudui()
# 采用随机梯度下降算法
optim = torch.optim.SGD(tudui.parameters(), lr=0.01) # 第一个参数为优化的对象 第二个为学习率
for _ in range(20):
loss_sum = 0.0
for data in dataloader:
imgs, target = data
output = tudui(imgs)
result_loss = loss(output, target)
loss_sum = loss_sum + result_loss
optim.zero_grad() # 将优化器中的梯度全部重置为0
result_loss.backward() # 反向传播
optim.step() # 进行梯度更新
print(loss_sum)
import torch
import torchvision
# pretrained=False 表示不使用vgg16训练imgesNet数据集训练好的参数,只是一个vgg16的网络架构
vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1
torch.save(vgg16, "./model/vgg16_1.pth") # 不仅保存了网络模型的结构 也保存了内部的参数
# 加载方式1 加载模型
model1 = torch.load("./model/vgg16_1.pth")
print(model1)
# 保存方式2 (官方推荐的方式)
torch.save(vgg16.state_dict(),"./model/vgg16_2.pth") #只保存vgg16里面的参数 保存在一个字典的形式
# 加载方式2 加载模型(此方式需要先获得一个网路架构,然后再将参数加载进去)
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(torch.load("./model/vgg16_2.pth")) # 将参数加载入模型中
print(vgg16)
拿vgg16网络模型架构为例
import torchvision
from torch import nn
vgg16_false = torchvision.models.vgg16(pretrained=False)
#在原有的vgg16模型结构中添加一层网络结构 add_linear1:新加的网络层的名字
vgg16_false.add_module("add_linear1", nn.Linear(in_features=1000, out_features=10))
运行结果:
······
in_features 为上层输出 out_features 为输出 bias=True表示需要一个偏置变量
加入到名为classifier层的网络结构内部
vgg16_false.classifier.add_module("add_linear2", nn.Linear(in_features=1000, out_features=10))
# 修改的是classifier[name]的第六层网络的参数
vgg16_false.classifier[6] = nn.Linear(in_features=1000, out_features=9)
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from model import *
from torch import nn
import torch
import torchvision
# 加载数据集
train_data = torchvision.datasets.CIFAR10("../data", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
# 使用dataloader加载数据
train = DataLoader(train_data, batch_size=64)
test = DataLoader(test_data, batch_size=64)
# 初始化模型
tudui = Tudui()
loss_function = nn.CrossEntropyLoss() # 损失函数
learning_rate = 0.01
optim = torch.optim.SGD(tudui.parameters(), lr=learning_rate) # 优化器
# tensorboard
writer = SummaryWriter("./logs")
epochs = 10
train_step = 0
test_step = 0
for i in range(epochs):
print("第{}轮训练开始".format(i+1))
tudui.train() # 把网络设置为训练状态
for data in train:
imgs, targets = data
output = tudui(imgs)
loss = loss_function(output, targets)
# 优化器优化模型
optim.zero_grad()
loss.backward()
optim.step()
# 写入tensorboard
train_step = train_step + 1
if train_step %100 == 0:
print("训练{}次,loss为{}".format(train_step, loss.item()))
writer.add_scalar("train", loss.item(), train_step)
# 进行模型的测试
tudui.eval() # 把网络设置为测试状态
total_test_loss = 0
total_accuracy = 0
with torch.no_grad(): # 使梯度不再发生变化
for data in test:
imgs, targets = data
output = tudui(imgs)
loss = loss_function(output, targets)
total_test_loss = total_test_loss + loss.item()
# argmax(axis=1) 跨列找最大值 并返回下标
accuracy = (output.argmax(axis=1) == targets).sum() # 预测正确的个数和
total_accuracy = total_accuracy + accuracy
print("整体的正确率为{}".format(total_accuracy/len(test_data)))
print("整体测试集上的loss为{}".format(total_test_loss))
writer.add_scalar("test", total_test_loss, test_step)
test_step = test_step + 1
# 进行每epochs参数保存
torch.save(tudui.state_dict(), "./model/tudui_{}.pth".format(i))
print("tudui_{}.pth模型已保存".format(i))
writer.close()
import torch
from PIL import Image
from torch import nn
class Tudui(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Flatten(),
nn.Linear(in_features=1024, out_features=64),
nn.Linear(in_features=64, out_features=10)
)
def forward(self, input):
x = self.model(input)
return x
tudui = Tudui()
image_path = "imgs/bird.png"
img = Image.open(image_path)
# 将图片转换为32*32的,然后转化为tensor类型
Compose函数是依次执行列表中操作并返回
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
torchvision.transforms.ToTensor()])
image = transform(img)
# 将图片转化为Tensor型
image = torch.reshape(image, (1, 3 ,32, 32))
# print(image.shape)
# 加载训练好的模型 然后告诉程序用gpu训练好的数据在cpu上运行
tudui.load_state_dict(torch.load("./model/tudui_29.pth", map_location=torch.device("cpu")))
print(tudui)
tudui.eval()
with torch.no_grad():
output = tudui(image)
target = output.argmax(axis=1)
print(target)
"""
调用gpu要用电脑显卡对应的版本的cuda
1.网络模型 tudui.cuda()
2.数据(输入,标注) imgs.cuda() target.cuda()
3.损失函数 loss.cuda()
为提高代码的健壮性,可以加上判断
if torch.cuda.is_available(): //如果显卡可用
tudui.cuda()
imgs.cuda
target.cuda()
loss.cuda()
可以使用Google colab实验室环境进行跑实验
"""
# 加载数据集
# 使用dataloader加载数据
# 创建模型
# 初始化模型
loss_function = nn.CrossEntropyLoss()
loss.cuda() # 新加
# tensorboard
tudui.train()
for data in train:
imgs, targets = data
imgs = imgs.cuda() # 新加
targets = targets.cuda() # 新加
......
tudui.eval()
with torch.no_grad():
for data in test:
imgs, targets = data
imgs = imgs.cuda() # 新加
targets = targets.cuda() # 新加
"""
常用的方法: 开头加入
device = torch.device("cuda") # 表示使用gpu运行实验
调用gpu要用电脑显卡对应的版本的cuda
1.网络模型 tudui.to(device)
2.数据(输入,标注) imgs = imgs.to(device) targets = targets.to(device)
3.损失函数 loss.to(device)
可以使用Google colab实验室环境进行跑实验
"""
# device = torch.device("cpu") # 表示使用cpu运行实验
device = torch.device("cuda") # 表示使用gpu运行实验
# 加载数据集
# 使用dataloader加载数据
# 创建模型
# 初始化模型
......
tudui.to(device) # 新加
loss_function = nn.CrossEntropyLoss()
loss_function.to(device) # 新加
# tensorboard
......
tudui.train()
for data in train:
imgs, targets = data
imgs = imgs.to(device) # 新加
targets = targets.to(device) # 新加
.....
tudui.eval()
with torch.no_grad():
for data in test:
imgs, targets = data
imgs = imgs.to(device) # 新加
targets = targets.to(device) # 新加
......