直接上程序
network.py
#神经网络
import torch
import torch.nn as nn
from torch.autograd import Variable
class convolutional_block(nn.Module):#convolutional_block层
def __init__(self,cn_input,cn_middle,cn_output,s=2):
super(convolutional_block,self).__init__()
self.step1=nn.Sequential(nn.Conv2d(cn_input,cn_middle,(1,1),(s,s),padding=0,bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True),
nn.Conv2d(cn_middle,cn_middle,(3,3),(1,1),padding=(1,1),bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True),
nn.Conv2d(cn_middle,cn_output,(1,1),(1,1),padding=0,bias=False),nn.BatchNorm2d(cn_output,affine=False))
self.step2=nn.Sequential(nn.Conv2d(cn_input,cn_output,(1,1),(s,s),padding=0,bias=False),nn.BatchNorm2d(cn_output,affine=False))
self.relu=nn.ReLU(inplace=True)
def forward(self,x):
x_tmp=x
x=self.step1(x)
x_tmp=self.step2(x_tmp)
x=x+x_tmp
x=self.relu(x)
return x
class identity_block(nn.Module):#identity_block层
def __init__(self,cn,cn_middle):
super(identity_block,self).__init__()
self.step=nn.Sequential(nn.Conv2d(cn,cn_middle,(1,1),(1,1),padding=0,bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True),
nn.Conv2d(cn_middle,cn_middle,(3,3),(1,1),padding=1,bias=False),nn.BatchNorm2d(cn_middle,affine=False),nn.ReLU(inplace=True),
nn.Conv2d(cn_middle,cn,(1,1),(1,1),padding=0,bias=False),nn.BatchNorm2d(cn,affine=False))
self.relu=nn.ReLU(inplace=True)
def forward(self,x):
x_tmp=x
x=self.step(x)
x=x+x_tmp
x=self.relu(x)
return x
class Resnet(nn.Module):#主层
def __init__(self,c_block,i_block):
super(Resnet,self).__init__()
self.conv=nn.Sequential(nn.Conv2d(3,64,(7,7),(2,2),padding=(3,3),bias=False),nn.BatchNorm2d(64,affine=False),nn.ReLU(inplace=True),nn.MaxPool2d((3,3),2,1))
self.layer1=c_block(64,64,256,1)
self.layer2=i_block(256,64)
self.layer3=c_block(256,128,512)
self.layer4=i_block(512,128)
self.layer5=c_block(512,256,1024)
self.layer6=i_block(1024,256)
self.layer7=c_block(1024,512,2048)
self.layer8=i_block(2048,512)
self.out=nn.Linear(2048,2,bias=False)
self.avgpool=nn.AvgPool2d(7,7)
def forward(self,input):
x=self.conv(input)
x=self.layer1(x)
for i in range(2):
x=self.layer2(x)
x=self.layer3(x)
for i in range(3):
x=self.layer4(x)
x=self.layer5(x)
for i in range(5):
x=self.layer6(x)
x=self.layer7(x)
for i in range(2):
x=self.layer8(x)
x=self.avgpool(x)
x=x.view(x.size(0),-1)
output=self.out(x)
return output
net=Resnet(convolutional_block,identity_block).cuda()
main.py
#主程序
import numpy as np
import random
import os
import torch
import torchvision
from torchvision import datasets,transforms
import network
from PIL import Image
from torch.autograd import Variable
import torch.nn as nn
import time
def data_load(dir,batch,a=0,b=0,c=0):#读取图片文件
normalize = transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
transform = transforms.Compose([
transforms.Resize(size=(224, 224)),
transforms.RandomRotation(a),#旋转,增加训练样本数量
transforms.RandomHorizontalFlip(b),#水平翻转,增加训练样本数量
transforms.RandomVerticalFlip(c),#垂直翻转,增加训练样本数量
transforms.ToTensor(),
normalize
])
train_dataset = torchvision.datasets.ImageFolder(root=dir,transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset,batch_size=batch,shuffle=True)
return train_loader
def train(optimizer):
loss_function=nn.CrossEntropyLoss().cuda()
time1=time.time()
epco=2
batch=16
miss=0
add=0
loss_all=0
loss_down=0
loss_add=0
train_pic=0
train_loader=data_load(dir="train",batch=16,a=90,b=0.5,c=0.5)
if train_pic>0:
print(train_pic)
else:
print(str(len(train_loader)*epco))
for e in range(epco):
z=[]
x=[]
for i,(images,labels) in enumerate(train_loader):
x=Variable(images.cuda())
z=Variable(labels.cuda())
out=network.net.forward(x)
loss=loss_function(out,z)
optimizer.zero_grad()
loss.backward()
optimizer.step()
out=network.net.forward(x)
loss1=loss_function(out,z)
loss_all+=loss.item()
loss_down+=(loss.item()-loss1.item())
if loss1>loss:
loss_add=(loss1.item()-loss.item())
add+=1
if loss>=0.5/batch:
print(loss1)
print("===="+str(loss))
miss+=1
print("----------------------------------------------------------")
if (i+1)%100==0:
if train_pic>0:
print(str((e*train_pic+i+1)/(epco*train_pic)*100)+"%")
else:
print(str((e*len(train_loader)+i+1)/(epco*len(train_loader))*100)+"%")
if i%3000==0 and i!=0:
state = {"net":network.net.state_dict(), "optimizer":optimizer.state_dict()}
torch.save(state,"net.pth")
if train_pic>0 and i>=train_pic:
break
#下面是一些监控输出,可以不用管
print("add="+str(add))
if train_pic>0:
print("acc="+str((epco*train_pic-miss)/(epco*train_pic)*100)+"%")
print("avgloss="+str(loss_all/(epco*train_pic)))
print("avgloss_down="+str(loss_down/(epco*train_pic)))
else:
print("acc="+str((epco*len(train_loader)-miss)/(epco*len(train_loader))*100)+"%")
print("avgloss="+str(loss_all/(epco*len(train_loader))))
print("avgloss_down="+str(loss_down/(epco*len(train_loader))))
if add>0:
print("avgloss_add="+str(loss_add/add))
print(str(time.time()-time1)+"秒")
#保存参数和模型
state = {"net":network.net.state_dict(), "optimizer":optimizer.state_dict()}
torch.save(state,"net.pth")
def test():#单张测试
train_loader=data_load(dir="test",batch=1)
for i,(images,labels) in enumerate(train_loader):
x=Variable(images.cuda())
z=Variable(labels.cuda())
out=network.net.forward(x)
print(z)
print(out)
break
if out.argmax()==z:
print("正确")
else:
print("错误")
def acc(s):#多张测试,分成训练集和验证集
if s==0:
dir="train"
type="训练集"
else:
dir="test"
type="验证集"
train_loader=data_load(dir,batch=1)
corret=0
all=300
if all>len(train_loader):
all=len(train_loader)
for i,(images,labels) in enumerate(train_loader):
x=Variable(images.cuda())
z=Variable(labels.cuda())
out=network.net.forward(x)
if out.argmax()==z:
corret+=1
if i>=all:
break
print(type+"正确率:==============================================================================="+str(corret/all*100)+"%")
while True:
rate=0.0001
optimizer=torch.optim.Adam(network.net.parameters())
if not os.path.exists("net.pth"):
state = {"net":network.net.state_dict(), "optimizer":optimizer.state_dict()}
torch.save(state,"net.pth")
else:
checkpoint = torch.load("net.pth")
network.net.load_state_dict(checkpoint["net"])
optimizer.load_state_dict(checkpoint["optimizer"])
optimizer=torch.optim.Adam(network.net.parameters(),rate)
s=input("1:训练 2:分析 3:正确率(300张) 0:退出:")
while s!="1" and s!="2" and s!="3" and s!="0":
s=input("输入错误,重新输入:1:训练 2:分析 3:正确率(300张) 0:退出:")
if s=="1":
train(optimizer)
elif s=="2":
test()
elif s=="3":
acc(0)
acc(1)
elif s=="0":
break
文件夹,包括train,test,里面分别包括cat,dog两个文件夹,train里cat,dog各11000张,test里cat,dog各1500张
实测不加
transforms.RandomRotation()
transforms.RandomHorizontalFlip()
transforms.RandomVerticalFlip()
5轮后(epco=5),训练集和验证集都能打到95%左右