首先介绍CIFAR-10数据集
第一步,写数据库处理
import torch
from mne import label
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision import transforms
#新建一个main函数,加载CIFAR-10数据集
def main():
batchza=32
cifar_train=datasets.CIFAR10('cifar',True,transform=transforms.Compose([
transforms.Resize((32,32)), # 把照片改成我需要的大小
transforms.ToTensor() # 转换为tensor
]),download=True) # transform,代表要做的一些变化
cifar_train=DataLoader(cifar_train,batch_size=batchza,shuffle=True)
cifar_test=datasets.CIFAR10('cifar',False,transform=transforms.Compose([
transforms.Resize((32,32)), # 把照片改成我需要的大小
transforms.ToTensor() # 转换为tensor
]),download=True) # transform,代表要做的一些变化
cifar_test=DataLoader(cifar_test,batch_size=batchza,shuffle=True)
# iter()可以用来得到dataload的迭代器,然后用迭代器的next方法得到一个batch
x,label=iter(cifar_train).next()
print('x:', x.shape,'label:',label.shape)
if __name__ == '__main__':
main()
然后新建一个module,写LeNet-5
import torch
from torch import nn
from torch.nn import functional as F
class LeNet5(nn.Module):
'''
for CIFAR-10
'''
def __init__(self):
#调用类初始化方法,初始化父类
super(LeNet5,self).__init__()
#然后查询需要用的网络结构,进行写
# 把网络写在Sequential里面,可以非常方便组织结构
self.conv_unit=nn.Sequential(
# 3,代表彩色,卷积核一般1-7
# x:[b,3,32,32]=>[b,6, , ]
nn.Conv2d(3,6,kernel_size=5,stride=1,padding=0),
nn.MaxPool2d(kernel_size=2,stride=2,padding=0),
#
nn.Conv2d(6,16,kernel_size=5,stride=1,padding=0),
nn.MaxPool2d(kernel_size=2,stride=2,padding=0),)
# 现在输出是一个四维的图,没法和全连接层相连,所以先打平一下,但是pytorch没有打平的类,所以不能写在Sequentical里
# flatten
#fc unit
self.fc_unit=nn.Sequential(
nn.Linear(16*5*5,120), # 这个最初的维度是要计算的。可以先设一个假设的图片,然后放入卷积层,看他的输出,例下面第四行tmp,然后把打平的结果写进去
nn.ReLU(),
nn.Linear(120,84), # 120变成84
nn.Linear(84,10),
)
# [b,3,32,32]
# tmp=torch.randn(2,3,32,32)
# out=self.conv_unit(tmp)
# # 输出结果为[b,16,5,5] 也就是说,从[b,3,32,32]变成现在的输出
# print('conv out:',out.shape)
# 使用交叉熵(分类问题)
# 其他问题使用MSE可以写成 self.criteon=nn.MSELoss()
# self.criteon=nn.CrossEntropyLoss()
# 定义前向运算
def forward(self,x):
"""
:param self:
:param x:[b,3,32,32]
:return:
"""
batchza=x.size(0) #x.shape=0
# x[b,3,32,32]=>[b,16,5,5]
x=self.conv_unit(x)
# x[b,16,5,5]=>[b,16*5*5]
x=x.view(batchza,16*5*5)
# [b,16*5*5]=>[b,10]
logits=self.fc_unit(x)
# [b,10],在10做softmax,所以是dim=1
# pred=F.softmax(logits,dim=1)
# loss=self.criteon(logits,y)
return logits
# 以下用来单独运行这一个py文件
def main():
net=LeNet5()
tmp=torch.randn(2,3,32,32)
out=net(tmp)
# 输出结果为[b,16,5,5] 也就是说,从[b,3,32,32]变成现在的输出
print('lenet out:',out.shape)
if __name__ == '__main__':
main()
然后写运行函数,输出训练loss和acc
# iter()可以用来得到dataload的迭代器,然后用迭代器的next方法得到一个batch
x,label=iter(cifar_train).next()
print('x:', x.shape,'label:',label.shape)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model=LeNet5().to(device)
criteon=nn.CrossEntropyLoss().to(device)
# 引入优化器,从model传入参数
optimizer=optim.Adam(model.parameters(),lr=1e-3)
print(model)
for epoch in range(1000):
model.train() # 告诉系统这是train
for batchidx,(x,label) in enumerate(cifar_train):
# x:[b,3,32,32]
# label:[b]
x,label=x.to(device),label.to(device)
logits=model(x)
# logits:[b,10]
# label:[b]
#loss:tensor scalar长度为0的标量
loss=criteon(logits,label)
#backprop
optimizer.zero_grad() # 先把梯度清零,因为每次backprop的时候,把梯度累加
loss.backward() # 调用backward会把得到的梯度累加
optimizer.step()
# 完成了一次epoch,使用item把loss转换为numpy打印出来
print(epoch,loss.item())
# test
# 做一个比对,统计总的数量和正确的
model.eval() # 告诉系统这是test
total_correct=0
total_num=0
for x,label in cifar_test:
# x:[b,3,32,32]
# label:[b]
x,label=x.to(device),label.to(device)
# [b,10]
logits=model(x)
# 取logits最大的值所在的位置作为pred
# [b]
pred=logits.argmax(dim=1)
# [b] vs [b] =>预测对的数量
total_correct+=torch.eq(pred,label).float().sum().item()
total_num+=x.size(0)
acc=total_correct/total_num
print(epoch,acc)
完整函数如下:
主函数
import torch
from torch import nn,optim
from mne import label
from torchvision import datasets
from torch.utils.data import DataLoader
from torchvision import transforms
from lenet5 import LeNet5
#新建一个main函数,加载CIFAR-10数据集
def main():
batchza=32
cifar_train=datasets.CIFAR10('cifar',True,transform=transforms.Compose([
transforms.Resize((32,32)), # 把照片改成我需要的大小
transforms.ToTensor() # 转换为tensor
]),download=True) # transform,代表要做的一些变化
cifar_train=DataLoader(cifar_train,batch_size=batchza,shuffle=True)
cifar_test=datasets.CIFAR10('cifar',False,transform=transforms.Compose([
transforms.Resize((32,32)), # 把照片改成我需要的大小
transforms.ToTensor() # 转换为tensor
]),download=True) # transform,代表要做的一些变化
cifar_test=DataLoader(cifar_test,batch_size=batchza,shuffle=True)
# iter()可以用来得到dataload的迭代器,然后用迭代器的next方法得到一个batch
x,label=iter(cifar_train).next()
print('x:', x.shape,'label:',label.shape)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model=LeNet5().to(device)
criteon=nn.CrossEntropyLoss().to(device)
# 引入优化器,从model传入参数
optimizer=optim.Adam(model.parameters(),lr=1e-3)
print(model)
for epoch in range(1000):
model.train() # 告诉系统这是train
for batchidx,(x,label) in enumerate(cifar_train):
# x:[b,3,32,32]
# label:[b]
x,label=x.to(device),label.to(device)
logits=model(x)
# logits:[b,10]
# label:[b]
#loss:tensor scalar长度为0的标量
loss=criteon(logits,label)
#backprop
optimizer.zero_grad() # 先把梯度清零,因为每次backprop的时候,把梯度累加
loss.backward() # 调用backward会把得到的梯度累加
optimizer.step()
# 完成了一次epoch,使用item把loss转换为numpy打印出来
print(epoch,loss.item())
# test
# 做一个比对,统计总的数量和正确的
model.eval() # 告诉系统这是test
total_correct=0
total_num=0
for x,label in cifar_test:
# x:[b,3,32,32]
# label:[b]
x,label=x.to(device),label.to(device)
# [b,10]
logits=model(x)
# 取logits最大的值所在的位置作为pred
# [b]
pred=logits.argmax(dim=1)
# [b] vs [b] =>预测对的数量
total_correct+=torch.eq(pred,label).float().sum().item()
total_num+=x.size(0)
acc=total_correct/total_num
print(epoch,acc)
if __name__ == '__main__':
main()
LeNet-5
import torch
from torch import nn
from torch.nn import functional as F
class LeNet5(nn.Module):
'''
for CIFAR-10
'''
def __init__(self):
#调用类初始化方法,初始化父类
super(LeNet5,self).__init__()
#然后查询需要用的网络结构,进行写
# 把网络写在Sequential里面,可以非常方便组织结构
self.conv_unit=nn.Sequential(
# 3,代表彩色,卷积核一般1-7
# x:[b,3,32,32]=>[b,6, , ]
nn.Conv2d(3,6,kernel_size=5,stride=1,padding=0),
nn.MaxPool2d(kernel_size=2,stride=2,padding=0),
#
nn.Conv2d(6,16,kernel_size=5,stride=1,padding=0),
nn.MaxPool2d(kernel_size=2,stride=2,padding=0),)
# 现在输出是一个四维的图,没法和全连接层相连,所以先打平一下,但是pytorch没有打平的类,所以不能写在Sequentical里
# flatten
#fc unit
self.fc_unit=nn.Sequential(
nn.Linear(16*5*5,120), # 这个最初的维度是要计算的。可以先设一个假设的图片,然后放入卷积层,看他的输出,例下面第四行tmp,然后把打平的结果写进去
nn.ReLU(),
nn.Linear(120,84), # 120变成84
nn.Linear(84,10),
)
# [b,3,32,32]
# tmp=torch.randn(2,3,32,32)
# out=self.conv_unit(tmp)
# # 输出结果为[b,16,5,5] 也就是说,从[b,3,32,32]变成现在的输出
# print('conv out:',out.shape)
# 使用交叉熵(分类问题)
# 其他问题使用MSE可以写成 self.criteon=nn.MSELoss()
# self.criteon=nn.CrossEntropyLoss()
# 定义前向运算
def forward(self,x):
"""
:param self:
:param x:[b,3,32,32]
:return:
"""
batchza=x.size(0) #x.shape=0
# x[b,3,32,32]=>[b,16,5,5]
x=self.conv_unit(x)
# x[b,16,5,5]=>[b,16*5*5]
x=x.view(batchza,16*5*5)
# [b,16*5*5]=>[b,10]
logits=self.fc_unit(x)
# [b,10],在10做softmax,所以是dim=1
# pred=F.softmax(logits,dim=1)
# loss=self.criteon(logits,y)
return logits
# 以下用来单独运行这一个py文件
def main():
net=LeNet5()
tmp=torch.randn(2,3,32,32)
out=net(tmp)
# 输出结果为[b,16,5,5] 也就是说,从[b,3,32,32]变成现在的输出
print('lenet out:',out.shape)
if __name__ == '__main__':
main()
|