卷积神经网络--猫狗系列【CNN】

文章讲述了如何使用PyTorch进行猫狗图像分类的预处理,包括处理损坏图片,按比例划分训练集和测试集,应用随机大小裁剪和归一化等预处理步骤。之后,构建了一个简单的CNN模型并进行训练,最后展示了训练过程中的精度结果。
摘要由CSDN通过智能技术生成

数据集,这次这个是分了类的【文末分享】

各12500张:

两点需要注意:

①猫狗分类是彩色图片,所以是3个channel;

②猫狗分类的图片大小不一,但是CNN的输入要求是固定大小,所以要resize。

划分训练集和测试集:

文件夹如下:

这里要注意,文件里面有三个图片是打不开的,这会导致后续运行时报错,打不开的三个图片分别是:猫猫666,猫猫10404,狗狗11702:【要么替换图片要么直接删掉(这个我选择的是替换)】

然后按照8:2来划分:(移动文件的过程,从train随机选取一些图片到test中)

import os,shutildef mymovefile(srcfile,dstfile):    if not os.path.isfile(srcfile):        print("src not exist!")    else:        fpath,fname=os.path.split(dstfile)    #分离文件名和路径        if not os.path.exists(fpath):            os.makedirs(fpath)                #创建路径        shutil.move(srcfile,dstfile)          #移动文件test_rate=0.2#训练集和测试集的比例为8:2。img_num=12500test_num=int(img_num*test_rate)import randomtest_index = random.sample(range(0, img_num), test_num)file_path=r"D:\Users\Twilight\PycharmProjects\CNN\PetImages"tr="train"te="test"cat="Cat"dog="Dog"#将上述index中的文件都移动到/test/Cat/和/test/Dog/下面去。for i in range(len(test_index)):    #移动猫    srcfile=os.path.join(file_path,tr,cat,str(test_index[i])+".jpg")    dstfile=os.path.join(file_path,te,cat,str(test_index[i])+".jpg")    mymovefile(srcfile,dstfile)    #移动狗    srcfile=os.path.join(file_path,tr,dog,str(test_index[i])+".jpg")    dstfile=os.path.join(file_path,te,dog,str(test_index[i])+".jpg")    mymovefile(srcfile,dstfile)

猫狗分类的数据集预处理:

import numpy as npfrom torchvision import transforms,datasets#定义transformstransforms = transforms.Compose([transforms.RandomResizedCrop(150),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406],                            std=[0.229, 0.224, 0.225])])
train_data = datasets.ImageFolder(os.path.join(file_path,tr), transforms)test_data=datasets.ImageFolder(os.path.join(file_path,te), transforms)

RandomResizedCrop(150)是用来把图片的每一个channel大小都变成(150,150);

mean=[0.485, 0.456, 0.406],有3个数的原因是猫狗分类是彩色图片,所以有3个channel,所以每一个channel上都有一个平均值,同理,std也是;

上面的data已经把猫狗的图片都囊括了,而且标签已经自动变成了0和1。这就是ImageFolder的威力。

做一下测试:

#测试print(train_data)print(len(train_data))print(len(test_data))

print(train_data[0][0])print(train_data[0][1])

第一张[0]训练图片的具体情况:前面是图片[0],后面是标签[1]。标签0代表猫猫,1代表狗狗:因为在/train的文件夹下Cat在Dog的前面,所以前者是0,后者是1。

​print(train_data[0][0].shape)print(train_data[1][0].shape)

每一张图片都是(3,150,150),3表示3个channel。

结果分析:(都是合理的)

网络架构以及训练结果

from torch.utils import databatch_size=32train_loader = data.DataLoader(train_data,batch_size=batch_size,shuffle=True,pin_memory=True)test_loader = data.DataLoader(test_data,batch_size=batch_size)import torchimport torch.nn as nnimport torch.nn.functional as Fimport torch.optim as optim#架构会有很大的不同,因为28*28-》150*150,变化挺大的,这个步长应该快一点。class CNN(nn.Module):    def __init__(self):        super(CNN,self).__init__()        self.conv1=nn.Conv2d(3,20,5,5)#和MNIST不一样的地方,channel要改成3,步长我这里加快了,不然层数太多。        self.conv2=nn.Conv2d(20,50,4,1)        self.fc1=nn.Linear(50*6*6,200)        self.fc2=nn.Linear(200,2)#这个也不一样,因为是2分类问题。    def forward(self,x):        #x是一个batch_size的数据        #x:3*150*150        x=F.relu(self.conv1(x))        #20*30*30        x=F.max_pool2d(x,2,2)        #20*15*15        x=F.relu(self.conv2(x))        #50*12*12        x=F.max_pool2d(x,2,2)        #50*6*6        x=x.view(-1,50*6*6)        #压扁成了行向量,(1,50*6*6)        x=F.relu(self.fc1(x))        #(1,200)        x=self.fc2(x)        #(1,2)        return F.log_softmax(x,dim=1)lr=1e-4device=torch.device("cuda" if torch.cuda.is_available() else "cpu" )model=CNN().to(device)optimizer=optim.Adam(model.parameters(),lr=lr)def train(model,device,train_loader,optimizer,epoch,losses):    model.train()    for idx,(t_data,t_target) in enumerate(train_loader):        t_data,t_target=t_data.to(device),t_target.to(device)        pred=model(t_data)#batch_size*2        loss=F.nll_loss(pred,t_target)
        #Adam        optimizer.zero_grad()        loss.backward()        optimizer.step()        if idx%10==0:            print("epoch:{},iteration:{},loss:{}".format(epoch,idx,loss.item()))            losses.append(loss.item())def test(model,device,test_loader):    model.eval()    correct=0#预测对了几个。    with torch.no_grad():        for idx,(t_data,t_target) in enumerate(test_loader):            t_data,t_target=t_data.to(device),t_target.to(device)            pred=model(t_data)#batch_size*2            pred_class=pred.argmax(dim=1)#batch_size*2->batch_size*1            correct+=pred_class.eq(t_target.view_as(pred_class)).sum().item()    acc=correct/len(test_data)    # print("accuracy:{},average_loss:{}".format(acc,average_loss))    print("accuracy:{}".format(acc))num_epochs=10losses=[]from time import *begin_time=time()for epoch in range(num_epochs):    train(model,device,train_loader,optimizer,epoch,losses)# test(model,device,test_loader)end_time=time()print(test(model,device,test_loader))

​每一轮的部分截图:

精确度:

【修改网络架构,因为是彩色的,有3个channel,而且训练资源有限,增大了卷积的步长 -->self.conv1=nn.Conv2d(3,20,5,5)的最后一个参数5,即卷一次,移动5个格子,不写默认是1格。这样做,可以快速把图片缩小,原来是150*150的图片,这样可以变成30*30。】

资料分享栏目

数据集之猫狗分类(kaggle+分了类的)

链接:https://pan.baidu.com/s/1NByVZwxUk4nmCCTCetqgCA 

提取码:rmmx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天都是被迫学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值