首先说明,本文采用二分类自制数据集(数据集形式在下附图)
一、Model
二、dataseet
三、train
四、遇到的问题
一、Model
框架搭建根据Alexnet网络构建
# @Author : Cai Yu
# @Site :
# @File : train.py
# @Software: PyCharm
import torch
import torch.nn as nn
from dataset import Mydataset
from torch.optim import lr_scheduler
import torch.utils
from torch.utils.data import DataLoader
class Alexnet(nn.Module):
def __init__(self):
super(Alexnet,self).__init__()
self.backbone = nn.Sequential(
nn.Conv2d(3,96,11,4),
nn.ReLU(),
nn.MaxPool2d(3,2),
nn.Conv2d(96,256,5,1,2),
nn.MaxPool2d(3,2),
nn.ReLU(),
nn.Conv2d(256,384,3,1,1),
nn.ReLU(),
nn.Conv2d(384,384,3,1,1),
nn.ReLU(),
nn.Conv2d(384, 128, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(3,2),
)
self.fc = nn.Sequential(
nn.Linear(128*6*6,4096),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(4096,2000),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(2000,1),
)
def forward(self,x):
f = self.backbone(x)
output = torch.flatten(f,1)
output = self.fc(output)
return output
需要注意的是:经过backbone之后,得到特征f是[batch_size,3,6,6],因此将特征输入fc层应该变成 [batch_sizt,3*6*6],将四维拉平成二维
fc第一个linear输入维度应该是6*6*182
二、dataseet
本数据集全部放在一个文件夹datasets里,文件名以标签_编号.jpg命名
import os
import numpy as np
import cv2
from torch.utils.data import Dataset
class Mydataset(Dataset):
def __init__(self,root):
self.dataset = []
img_list = os.listdir(root)#传入路径返回文件里面的名字集合
for img in img_list:
img_dir = os.path.join(root,img)
self.dataset.append(img_dir)
def __len__(self):
return len(self.dataset)
def __getitem__(self, index):
data = self.dataset[index]
img = cv2.imread(data)/255
img = cv2.resize(img,(256,256))
img = np.transpose(img,(2,0,1))
label = data.split('\\')[-1]
label = int(label.split('_')[0])
return np.float32(img),np.float32(label)
三、train
def train(net,root):
empoches = 20;
batch_size = 2;
net = net.to(device)
print("training on",device)
#定义一个优化器
optimizer = torch.optim.Adam(net.parameters(),lr=0.0001)
#学习率调整
scheduler = lr_scheduler.StepLR(optimizer,step_size=10,gamma=0.5)
#定义一个损失函数
loss = nn.BCELoss()
for epoch in range(empoches):
loss_sum,acc_sum = 0.0,0.0
dataset = Mydataset(root)
dataloader = DataLoader(dataset,batch_size = batch_size,shuffle = True)
n = dataset.__len__()
scheduler.step()
for img,label in dataloader:
# label = torch.as_tensor(label)
label = label.unsqueeze(1).to(device)
p = net(img.to(device).cuda())
p = torch.sigmoid(p)
loss_c = loss(p,label)##注意一定要将loss()函数赋值给一个新的变量
#反向传播
optimizer.zero_grad()
loss_c.backward()
optimizer.step()
loss_sum += loss_c.cpu().item()
p = torch.where(p>0.5,1,0)
acc_sum += (p == label).sum().cpu().item()
print('epoch %d,lr%8f,loss%8f,acc%.3f'%(epoch,scheduler.get_lr()[0],loss_sum/n,acc_sum/n))#acc=蒙对的数量/总数//
torch.save(net.state_dict(),'train_two.pth')
return net
打印一个epoch的acc和loss:acc_sum/n (才对的个数/总个数)这里的总个数就是所有样本个数
loss_sum/n (这里也除总数个人认为loss值大小无所谓主要看趋势)