Kaggle-狗种类的识别(Pytorch框架)基本图像识别流程

server/2024/9/23 12:52:43/

请添加图片描述

狗类别实现过程

一. 将数据集按标签分类,将标签转换为数字表示,并制作数据集
二. 搭建网络框架,inception,或者ResNet
三. 选择优化函数,训练模型

数据集制作

首先分析数据集,题中已经很明确告诉有120 种狗,那么就有120种标签值,分别为0-119。
给了一个训练集,和一个csv文件,图像在训练集中,图像的标签在csv文件里,那么如何将图片和它的标签去捆绑,因为训练图像的流程就是拿图像训练得出预测值,和它标签进行损失计算。
首先观察csv文件:

在这里插入图片描述

训练集:
在这里插入图片描述

csv文件中给出了每张图片的标签值,那么要做的就是按照csv文件里的标签值,将图片复制到另一个文件夹中,进行分类,属于同一品中的狗放到同一文件夹中,然后用内置API ImageFolder 去自动设置标签。具体原理如下

在这里插入图片描述
左面是已经将训练集分类好的新训练集,将同一种类的图片归置到一起,那么ImageFolder会将每个文件夹中的照片赋值为相同的标签值,从0开始,例如第一个文件夹kuvasz 里的照片的标签全部赋值为0,下一个文件夹kerry_blue_terrier 标签赋值为1 ,它这种标签是自动生成的,不需要人为的加

那么要做的第一步,读取csv文件,创建一个字典,保证每张图片能够准确划分到属于它的类(文件夹)中,因为训练集中的图片要按照字典查找它的标签才能复制到它对应的文件夹中。

python">import pandas as pd 
def read_train_csv():df=pd.read_csv("/kaggle/input/dog-breed-identification/labels.csv")    id=df.iloc[0:,0].values         #读取每张图片的id,也就是训练集图片名称,从第一行开始到最后一行,第一列,想要从pandas数据转化为列表,必须后缀.valuesbreed=df.iloc[0:,1].values      #读取第二行标签值return dict(zip(id,breed))      #将图片id和其对应的标签值捆绑,这里并不是图片,而是图片名称,图片要通过这个字典查询它应该放哪个文件夹中

定义复制函数

python">import shutil
import os
def copy_dir(data_dir,target_dir):       #源地址和目标地址os.makedirs(target_dir,exist_ok=True)        #如果目标地址不存在,先创建shutil.copy(data_dir,target_dir)             #复制

定义分类函数,将训练集分类,将图片按照上面的字典进行分类

python">#这里源文件地址是 /kaggle/input/dog-breed-identification/train
#目的文件地址是output中 :/kaggle/working/traindef train_to_data(data_dir,target_dir):    #训练集的地址,目标地址dict=read_train_csv()                  #用上面的读取csv文件函数返回训练集的字典for data in os.listdir(data_dir):      #将放训练集图片的文件夹迭代一张一张拿出来读label=dict.get(data.split('.')[0])  #因为我们用os读取出来是照片名称,格式为000bec180eb18c7604dcecc8fe0dba07.jpg,我们要前半部分作为value,去字典中查找key,那么查出来该img的labelfname=os.path.join(data_dir,data)   #获取该图片的地址copy_dir(fname,os.path.join(target_dir,label))   #将图片复制到对应的文件夹中,文件名称就是label
train_to_data("/kaggle/input/dog-breed-identification/train","/kaggle/working/train")  #进行数据分类#转移测试集,因为我们最后要预测测试集,所以也要把测试集封装成数据集,才能放到神经网络里面训练,否则光秃秃的测试集没法放进网络框架,和上面的一样
#但是将测试集都放到unknow文件中,这样ImageFolder会将其直接封装为标签值为0的数据集,因为我们要预测它标签值,所以这里赋值为多少都无所谓
for test_data in os.listdir("/kaggle/input/dog-breed-identification/test/"):copy_dir(os.path.join("/kaggle/input/dog-breed-identification/test",test_data),"/kaggle/working/test/unknow")

训练集图片分类完成后,那么就开始制作训练数据集了

python">#首先进行图像处理,数据增强,所有图像识别必须要做的,因为该数据集每张的图片大小不同,所以要统一图片像素大小import torchvision
train_transform=torchvision.transforms.Compose([torchvision.transforms.RandomResizedCrop(224,scale=(0.08,1.0),ratio=(3.0/4.0,4.0/3.0)),       #设置裁剪出来的像素大小为224torchvision.transforms.RandomHorizontalFlip(),    #随机进行水平翻转torchvision.transforms.ColorJitter(brightness=0.4,contrast=0.4,saturation=0.4),                              #调图像的色彩度                                                torchvision.transforms.ToTensor(),               #必须有,将图像变为tensor向量,否则没法放进网络中运行,将维度[224,224,3] 变为 [3,224,224]torchvision.transforms.Normalize([0.485,0.456,0.406],  [0.229,0.224,0.225])     #将图像数据标准化,减小计算量
])#对测试集进行图像处理  ,只需要改变尺寸,标准化数据就够了,因为只需预测
test_transform=torchvision.transforms.Compose([     torchvision.transforms.Resize(256),torchvision.transforms.CenterCrop(224),torchvision.transforms.ToTensor(),torchvision.transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])])#制作数据集,ImageFolder的原理上面已经说过,但是切记ImageFolder的文件地址必须是你分类数据集的上一级!,例如分好类后在文件夹/train/下
#那么ImageFolder的文件地址就只能到train/为止,因为ImageFolder是按照文件夹的名称赋值标签值的,它要看文件夹的名称,不能直接定位到具体某一类的文件夹上
from torch.utils.data import DataLoader
train_mid_data=torchvision.datasets.ImageFolder('/kaggle/working/train/',transform=train_transform)       #ImageFolder可以自动将对应文件夹中的图片进行标签赋值  但是切记,文件地址必须为上一级,否则会出错!
train_data=DataLoader(train_mid_data,batch_size=32,drop_last=True,shuffle=True)               #数据集制作,32个为一组,打乱数据集顺序,不能让网络挨次训练某一类型数据#制作测试集数据,方便后面直接扔到网络模型中预测
test_mid_data=torchvision.datasets.ImageFolder('/kaggle/working/test/',transform=test_transform)
test_data=DataLoader(test_mid_data,batch_size=32)    

以上就是完整的数据集制作流程,具体的图像数据集制作可以看下面这篇文章

PyTorch数据集制作

网络模型搭建

这里做了三种网络的对比,第一种是 ResNet残差网络,第二种是LeNet网络
,第三种GoolgeNet网络,对比了性能,第三种最好
第三种使用的是inception模块 ,inception具体的原理是用不同的卷积维度,对同一张图片进行卷积,然后将不同卷积后的结果结合起来形成完整的一个结果。
在这里插入图片描述

完整的一个GoogleNet模型如下图:
在这里插入图片描述

实现很简单:

python">from torch import nn
from torch.nn import functional as F
class inception(nn.Module):def __init__(self,inchannels,c1,c2,c3,c4):super().__init__()self.p1_1=nn.Conv2d(inchannels,c1,kernel_size=1)self.p2_1=nn.Conv2d(inchannels,c2[0],kernel_size=1)self.p2_2=nn.Conv2d(c2[0],c2[1],kernel_size=3,padding=1)self.p3_1=nn.Conv2d(inchannels,c3[0],kernel_size=1)self.p3_2=nn.Conv2d(c3[0],c3[1],kernel_size=5,padding=2)self.p4_1=nn.MaxPool2d(kernel_size=3,padding=1,stride=1)self.p4_2=nn.Conv2d(inchannels,c4,kernel_size=1)def forward(self,x):x1=F.relu(self.p1_1(x))x2=F.relu(self.p2_2(F.relu(self.p2_1(x))))x3=F.relu(self.p3_2(F.relu(self.p3_1(x))))x4=F.relu(self.p4_2(F.relu(self.p4_1(x))))return torch.cat((x1,x2,x3,x4),dim=1)b1=nn.Sequential(nn.Conv2d(in_channels=3,out_channels=64,kernel_size=7,stride=2,padding=3),nn.ReLU(),nn.MaxPool2d(kernel_size=3,stride=2,padding=1))
b2=nn.Sequential(nn.Conv2d(64,64,kernel_size=1),nn.ReLU(),nn.Conv2d(64,192,kernel_size=3,padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3,stride=2,padding=1))
b3=nn.Sequential(inception(192,64,(96,128),(16,32),32),inception(256,128,(128,192),(32,96),64),nn.MaxPool2d(kernel_size=3,stride=2,padding=1))
b4=nn.Sequential(inception(480,192,(96,208),(16,48),64),inception(512,160,(112,224),(24,64),64),inception(512,128,(128,256),(24,64),64),inception(512,112,(144,288),(32,64),64),inception(528,256,(160,320),(32,128),128),nn.MaxPool2d(kernel_size=3,stride=2,padding=1))
b5=nn.Sequential(inception(832,256,(160,320),(32,128),128),inception(832,384,(192,384),(48,128),128),nn.AdaptiveAvgPool2d((1,1)),nn.Flatten())#得到神经网络模型,上面模型是可以直接复制用的
def get_net():net=nn.Sequential(b1,b2,b3,b4,b5,nn.Linear(1024,120))return net

下面是一个简单模型框架也可以选择:

python">from torch import nn
from torch.nn import functional as F
class net(nn.Module):def __init__(self):super().__init__()#224 224 3self.conv1=nn.Conv2d(in_channels=3,out_channels=64,kernel_size=3,padding=1)self.bn1=nn.BatchNorm2d(64)self.pool1=nn.MaxPool2d(kernel_size=2,stride=2)#112 112 64self.conv2=nn.Conv2d(in_channels=64,out_channels=128,kernel_size=3,padding=1)self.bn2=nn.BatchNorm2d(128)self.pool2=nn.MaxPool2d(kernel_size=2,stride=2)#56 56 128self.conv3=nn.Conv2d(in_channels=128,out_channels=256,kernel_size=3,padding=1)self.bn3=nn.BatchNorm2d(256)self.pool3=nn.MaxPool2d(kernel_size=2,stride=2)#28 28 256self.conv4=nn.Conv2d(in_channels=256,out_channels=512,kernel_size=3,padding=1)self.bn4=nn.BatchNorm2d(512)self.pool4=nn.MaxPool2d(kernel_size=2,stride=2)#14 14 512self.conv5=nn.Conv2d(in_channels=512,out_channels=512,kernel_size=3,padding=1)self.bn5=nn.BatchNorm2d(512)self.pool5=nn.MaxPool2d(kernel_size=2,stride=2)#7 7 512self.Linear1=nn.Linear(in_features=7*7*512,out_features=240)self.Linear2=nn.Linear(in_features=240,out_features=120)def forward(self,x):x=F.relu(self.pool1(self.bn1(self.conv1(x))))x=F.relu(self.pool2(self.bn2(self.conv2(x))))x=F.relu(self.pool3(self.bn3(self.conv3(x))))x=F.relu(self.pool4(self.bn4(self.conv4(x))))x=F.relu(self.pool5(self.bn5(self.conv5(x))))x=x.flatten(start_dim=1)x=F.relu(self.Linear1(x))x=self.Linear2(x)return xdef get_net():net=net()return net

做训练函数

python">import matplotlib.pyplot as plt
# 将程序放到GPU上跑,否则默认cpu会卡死
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')             net=get_net().to(device)     #将模型放到GPU上,必须把数据也放到相同GPU上才能运行def train(net,train_data,epoch_num,lr,wd):#这里只是用了一个简单的Adam梯度下降算法,这篇文章只是一个基础构建,可以在此基础上改进optimer=torch.optim.Adamax(net.parameters(),lr=lr,weight_decay=wd)     num_batches=len(train_data)     #用来后面的损失函数计算,得到单个图片的损失值loss_function=nn.CrossEntropyLoss()   #损失函数loss_value=[]                         #记录损失值,用来画图,将该列表直接放到plt中就能画for epoch in range(epoch_num):       #进行大循环epoch_loss=0                     #每一次大循环都要重置损失值for img,label in train_data:   img=img.to(device)           #将数据都放在GPU上label=label.to(device)optimer.zero_grad()          #一系列训练模板y=net(img)loss=loss_function(y,label)epoch_loss+=loss.item()loss.backward()optimer.step()loss_value.append(epoch_loss/(num_batches*32))#画损失函数的图plt.plot(np.squeeze(loss_value))plt.ylabel('cost')plt.xlabel('iterations (per tens)')plt.show()
python">train(net,train_data,50,6e-5,5e-4)    #开始训练,后面俩参数都可以自己调

在这里插入图片描述

其实训练的结果不是太好,损失值还是太大,可以通过调学习率去调节,这里只是用的一个最基本的参数值

进行预测测试集

前面已经将测试集数据已经做好了,直接放模型里预测,去观察题中给的需要提交的csv文件格式,可以知道需要提交的并不是你要预测这张图片属于哪种狗子,而是这张图片属于每一类狗子的概率,这里就必须要用softmax函数了,具体原理可以上网差,他会将所有情况的概率总和变为1,然后每一类的概率就是看其在这1中占比多少。

python">preds=[]
for i,_ in test_data:out_put=torch.nn.functional.softmax(net(i.to(device)),dim=1)    #将预测值进行softmax处理preds.extend(out_put.cpu().detach().numpy())    #将得到的预测值变为numpy数组,因为只有numpy才能存到pandas文件中 
ids=sorted(os.listdir("/kaggle/working/test/unknow"))    #将测试集的顺序按id排序,因为提交的格式id就是按大小排序的
with open("/kaggle/working/submission.csv",'w') as f:     #制作csv文件f.write('id,'+','.join(train_mid_data.classes)+'\n')     #先将标题标签做好for i,output in zip(ids,preds):   f.write(i.split('.')[0]+','+','.join([str(num) for num in output])+'\n')    #将每一个对应的id和预测的结果加入到文件中,其实这里逗号,csv文件都会识别,将其作为分割符号,所以在csv文件中也不会看见逗号

http://www.ppmy.cn/server/120808.html

相关文章

Python redis 安装和使用介绍

python redis安装和使用 一、Redis 安装1.1、Windows安装 二、安装 redis 模块二、使用redis 实例1.1、简单使用1.2、连接池1.3、redis 基本命令 String1.3.1、ex - 过期时间(秒)1.3.2、nx - 如果设置为True,则只有name不存在时,当…

CSS-Grid布局详解

前言 Grid 栅格布局 是 CSS 语言中非常强大的种布局,它提供了丰富的工具属性,可以轻松实现复杂且灵活的布局设计,因此想要完美使用CSS Grid 也有一定的难度和复杂性,我自己也是花了不少时间才真正掌握它的使用,在这篇…

uni-app 多环境配置

前后端分离模式下,不同的环境如开发环境(dev)、测试环境(test)、生产环境(prod)等,不同环境后端数据库、api地址等可能都不同 。 uni-app中只有development和production两个环境 以配…

NSSCTF刷题篇1

js类型 [SWPUCTF 2022 新生赛]js_sign 这是一道js信息泄露的题目直接查看源码,有一个main.js文件点击之后,有一串数字和一段base64编码,解开base64编码得到这个编码为敲击码 解码在线网站:Tap Code - 许愿星 (wishingstarmoye.…

PostgreSQL 的log_hostname 参数测试

PostgreSQL 的log_hostname 参数测试 log_hostname 是 PostgreSQL 配置文件 (postgresql.conf) 中的一个参数,用于控制是否在日志条目中记录客户端主机名。默认情况下,PostgreSQL 只记录客户端的IP地址,而 log_hostname 参数允许数据库管理员…

论文阅读 - SELF-REFINE: Iterative Refinement with Self-Feedback

https://arxiv.org/pdf/2303.17651 目录 Abstract Introduction 2 Iterative Refinement with SELF-REFINE Evaluation 3.1 Instantiating SELF-REFINE 3.2 Metrics 3.3 Results Abstract 与人类一样,大型语言模型(LLMs)并非总能在首次…

【Django5】django的helloworld

安装django pip install djangoDjango官方中文文档 https://docs.djangoproject.com/zh-hans/5.1/Github链接 https://github.com/django/django创建Django项目 cd到想要创建项目的文件夹下,输入以下命令创建项目 这行代码将会在当前目录下创建一个 mysite 目录 …

【深度学习】初识神经网络

神经网络的表示 一个简单的两层神经网络如下图所示,每个圆圈都代表一个神经元,又名预测器。 一个神经元的计算详情如下。在我们原本输入的变量x的基础上,还有权重w和偏置b;在计算z过后,再将其带入sigmoid激活函数&…