先留一段图像分类代码,空闲时间再做分析:
创建神经网络:
import torch
from torch import nn
import torch.nn.functional as F
class MyAlexNet(nn.Module):def __init__(self):super(MyAlexNet, self).__init__()self.c1=nn.Conv2d(in_channels=3,out_channels=48,kernel_size=11,stride=4,padding=2)self.ReLU=nn.ReLU()self.c2=nn.Conv2d(in_channels=48,out_channels=128,kernel_size=5,stride=1,padding=2)self.s2=nn.MaxPool2d(2)self.c3=nn.Conv2d(in_channels=128,out_channels=192,kernel_size=3,stride=1,padding=1)self.s3=nn.MaxPool2d(2)self.c4=nn.Conv2d(in_channels=192,out_channels=192,kernel_size=3,stride=1,padding=1)self.c5=nn.Conv2d(in_channels=192,out_channels=128,kernel_size=3,stride=1,padding=1)self.s5=nn.MaxPool2d(kernel_size=3,stride=2)self.flatten=nn.Flatten()self.f6=nn.Linear(128*6*6,2048)self.f7=nn.Linear(2048,2048)self.f8=nn.Linear(2048,1000)self.f9=nn.Linear(1000,2)def forward(self,x):x=self.ReLU(self.c1(x))x=self.ReLU(self.c2(x))x=self.s2(x)x=self.ReLU(self.c3(x))x=self.s3(x)x=self.ReLU(self.c4(x))x=self.ReLU(self.c5(x))x=self.s5(x)x=self.flatten(x)x=self.f6(x)x=F.dropout(x,p=0.5)x=self.f7(x)x=F.dropout(x,p=0.5)x=self.f8(x)x=F.dropout(x,p=0.5)x=self.f9(x)return x
if __name__ == '__main__':x=torch.rand([1,3,224,224])model=MyAlexNet()y=model(x)
数据预处理:
import os
from shutil import copy
import random
def mkdir(file):if not os.path.exists(file):os.makedirs(file)
#获取data文件夹下所有文件夹名(即需要分类的类名)
file_path='E:/BaiduNetdiskDownload/Kaggle猫狗大战/train'
flower_class= [cla for cla in os.listdir(file_path)]
#创建训练集train文件夹,并由类名在其目录下创建子目录
mkdir('data/train')
mkdir('data/train/cat')
mkdir('data/train/dog')
mkdir('data/val')
mkdir('data/val/cat')
mkdir('data/val/dog')
split_rate=0.1
for cla in flower_class:cla_path=file_path+'/'+cla#"E:\BaiduNetdiskDownload\Kaggle猫狗大战\train\train\cat.0.jpg"images=os.listdir(cla_path)print(cla_path)num=len(images)eval_index=random.sample(images,k=int(num*split_rate))for index,image in enumerate(images):if image in eval_index:image_path = cla_path+'/'+imageif "cat" in image_path:new_path = 'data/val/cat/'else:new_path = 'data/val/dog/'copy(image_path,new_path)else:image_path=cla_path+'/'+imageif "cat" in image_path:new_path='data/train/cat/'else:new_path='data/train/dog/'copy(image_path,new_path)print("\r[{}]processing[{}/{}]".format(cla,index+1,num),end="")print()
print("processing done!")
训练集用于 训练权重:
import torch
from torch import nn
from net import MyAlexNet
import numpy as np
from torch.optim import lr_scheduler
import os
from torchvision import transforms
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False
ROOT_TRAIN = 'C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/train'
ROOT_TEST='C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/val'
normalize=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
train_transform=transforms.Compose([transforms.Resize((224,224)),transforms.RandomVerticalFlip(),transforms.ToTensor(),normalize
])
val_transform=transforms.Compose([transforms.Resize((224,224)),transforms.ToTensor(),normalize
])
train_dataset=ImageFolder(ROOT_TRAIN,transform=train_transform)
val_dataset=ImageFolder(ROOT_TEST,transform=val_transform)
train_dataloader=DataLoader(train_dataset,batch_size=32,shuffle=True)
val_dataloader=DataLoader(val_dataset,batch_size=32,shuffle=True)
model=MyAlexNet()
loss_fn=nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(model.parameters(),lr=0.01,momentum=0.9)
lr_scheduler=lr_scheduler.StepLR(optimizer,step_size=10,gamma=0.5)
def train(dataloader,model,loss_fn,optimizer):loss,current,n =0.0,0.0,0.0for batch,(x,y) in enumerate(dataloader):image,y =x,youtput=model(image)cur_loss=loss_fn(output,y)_,pred=torch.max(output,axis=1)cur_acc=torch.sum(y==pred)/output.shape[0]optimizer.zero_grad()cur_loss.backward()optimizer.step()loss+=cur_loss.item()current+=cur_acc.item()n+=1train_loss=loss/ntrain_acc=current/nprint('train_loss'+str(train_loss))print('train_acc'+str(train_acc))return train_loss,train_acc
def val(dataloader,model,loss_fn):model.eval()loss,current,n=0.0,0.0,0.0with torch.no_grad():for batch,(x,y) in enumerate(dataloader):image,y =x,youtput=model(image)cur_loss=loss_fn(output,y)_,pred=torch.max(output,axis=1)cur_acc=torch.sum(y==pred)/output.shape[0]loss+=cur_loss.item()current+=cur_acc.item()n+=1val_loss=loss/nval_acc=current/nprint('val_loss'+str(val_loss))print('val_acc'+str(val_acc))return val_loss,val_acc
def matplot_loss(train_loss,val_loss):plt.plot(train_loss,label='train_loss')plt.plot(val_loss,label='val_loss')plt.legend(loc='best')plt.ylabel('loss')plt.xlabel('epoch')plt.title("训练集和验证集loss值对比图")plt.show()
def matplot_acc(train_loss,val_loss):plt.plot(train_acc,label='train_acc')plt.plot(val_acc,label='val_acc')plt.legend(loc='best')plt.ylabel('acc')plt.xlabel('epoch')plt.title("训练集和验证集acc值对比图")plt.show()
loss_train=[]
acc_train=[]
loss_val=[]
acc_val=[]
epoch=20
min_acc=0
for t in range(epoch):lr_scheduler.step()print(f"epoch{t+1}\n----------------")train_loss,train_acc=train(train_dataloader,model,loss_fn,optimizer)val_loss,val_acc=val(val_dataloader,model,loss_fn)loss_train.append(train_loss)acc_train.append(train_acc)loss_val.append(val_loss)acc_val.append(val_acc)if val_acc>min_acc:folder='save_model'if not os.path.exists(folder):os.mkdir('save_model')min_acc=val_accprint(f"save best model,第{t+1}轮")torch.save(model.state_dict(),'save_model/best.model.pth')if t==epoch-1:torch.save(model.state_dict(),'save_model/last_model.pth')
print('Done')
测试集用于测试模型:
import torch
from net import MyAlexNet
from torch.autograd import variable
from torchvision import datasets,transforms
from torchvision.transforms import ToPILImage
from torchvision.datasets import ImageFolder
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader
ROOT_TRAIN = 'C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/train'
ROOT_TEST='C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/val'
normalize=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
train_transform=transforms.Compose([transforms.Resize((224,224)),transforms.RandomVerticalFlip(),transforms.ToTensor(),normalize
])
val_transform=transforms.Compose([transforms.Resize((224,224)),transforms.ToTensor(),normalize
])
train_dataset=ImageFolder(ROOT_TRAIN,transform=train_transform)
val_dataset=ImageFolder(ROOT_TEST,transform=val_transform)
train_dataloader=DataLoader(train_dataset,batch_size=32,shuffle=True)
val_dataloader=DataLoader(val_dataset,batch_size=32,shuffle=True)
model=MyAlexNet()
model.load_state_dict(torch.load("C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/save_model/best.model.pth"))
classes=["cat","dog",
]
show=ToPILImage()
model.eval()
for i in range(50):x,y = val_dataset[i][0],val_dataset[i][1]show(x).show()x=torch.tensor(torch.unsqueeze(x,dim=0).float(),requires_grad=True)x=torch.tensor(x)with torch.no_grad():pred=model(x)print(pred)predicted,actual=classes[torch.argmax(pred[0])],classes[y]print(f'predicted:"{predicted}",Actual:"{actual}"')
没有显卡慢的跟狗屎一样。