兼职做效果图的网站,九江城乡建设网站为什么打不开,服务器上做网站,六种常见网络营销方法Pytorch 猫狗分类
用Pytorch框架#xff0c;实现分类问题#xff0c;好像是学习了一些基础知识后的一个小项目阶段#xff0c;通过这个分类问题#xff0c;可以知道整个pytorch的工作流程是什么#xff0c;会了一个分类#xff0c;那就可以解决其他的分类问题#xff0…Pytorch 猫狗分类
用Pytorch框架实现分类问题好像是学习了一些基础知识后的一个小项目阶段通过这个分类问题可以知道整个pytorch的工作流程是什么会了一个分类那就可以解决其他的分类问题当然了其实最重要的还是了解她的核心是怎么工作的。
那首先我们的第一个项目就做猫狗的分类。
声明整个数据和代码来自于b站链接使用pytorch框架手把手教你利用VGG16网络编写猫狗分类程序_哔哩哔哩_bilibili
我做了复现并且记录了自己在做这个项目分类时候一些所思所得。
目前我需要掌握pytorch针对于分类问题解决整个分类问题的工作流程是怎么样的其他的进阶需要自己去不断的练习和体会。因为分类问题也是计算机视觉想要解决的一个重要问题而且对于yolo系列直接解决了分类问题所以现在理解好基础的以后就能更好的理解大佬们的框架才知道怎么去优化网络。
前面说到通过softmax函数把分类问题转换成了概率问题把给你一个图片神经网络回答我是什么的问题转变成了给你一个图片神经网络输出是什么类别的概率是什么的问题。而神经网络的整个训练过程也是w在不断被训练的一个动态过程最后我们会训练出一个较好的w,输入图片神经网络就能告诉我们是什么类别了。
那现在就从数据开始吧。
数据清洗
拿到数据首先要分析数据集是什么样子的包括数据集包含了什么图片每张图片的命名时怎么样的
现在我们有很多猫和狗的照片存放在train文件夹下面猫照片狗照片分别存在cat和长这样
再点开dog文件夹 首先要根据这两类照片去生成一个标签文件具体步骤是这样
先遍历这两个数据集遍历的意思是相当于你打开照片的文件夹把照片一张一张的拿出来然后把每个照片归好类比如第二个dog文件夹里面你拿出第一张标记是狗记录下来类别和这张狗照片的路径位置记录在一个txt文档里面这就是到时候训练的时候提供给trian的一个label文件这个label文件告诉网络我现在给你一张照片记住他是一只狗你来训练吧。就按照这个逻辑把很多张狗的照片猫的照片都喂给网络让他训练说到训练训练的其实是w就是权重把权重w训练好了我们希望到时候给他随便一个猫或者狗的照片网络能告诉我这是一只狗还是一只猫。
那现在就开始准备标签文件。
刚说到想象一下我们从某个文件夹拿出来一张一张的照片那就用getcwd函数获取当前的工作目录。
1、导入包
Import os
from os import getcwd
【拓展获取当前工作目录】
import os
current_directory os.getcwd()
print(当前工作目录是:, current_directory)
2、指定照片的类别
classes[cat,dog]#所有类别放进列表这个好处是可以修改往里面添加或者删除就好了
3、定义数据集划分的方式
sets [train] #这里是表示只有训练集
表示当前的这个脚本是我们用来处理训练集的模型通过学习训练集中的特征和标签去构建预测模型这样的写法是便于添加的列表形式如果项目还需要val和test集那就直接在sets里面添加这些划分比如sets [train,val,test]
4、写标签文件重点来了
4.1先做一个空的txt文本文件用来存放等下制作的标签文件。
取出这个训练集对于sets里面的每一个数据集这里是只有trainfor se in sets打开或创建标签文件list_file
list_file open(cls_se.txt)创建或清空一个名为cls_train.txt的文件如果se是train用于写入图像信息。w 是文件打开模式表示写入接下来的操作中会通过list_file.write()方法往这个文件里写入数据
4.2 空文件做好了接下来放标签信息内容是【某张图片类别这个图片的储存位置】
4.2.1获取图片数据集储存位置
获取数据集路径,用os.join拼接起来: wd getcwd() #当前工作路径 datasets_path os.path.join(wd,se) # 拼接路径train意思数据集在trian文件夹这里面
最后指向的是train文件夹 列出数据集根目录下的子目录类别 types_name os.listdir(datasets_path)# 返回是[cat,dog] 【拓展】os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。这里会返回cat和dog这两个。
4.2.2 遍历最开始定义的数据集类别clsaaes取出索引作为图片数据集的类别
遍历类别对于每个type_name检查它是否属于classes列表,classes是我们最开始定义的类别列表包括cat和dog如果不在,就跳过这个类别否则就继续意思是如果类别是猫或狗就继续执行下面的代码如果类别不是猫或者狗就跳过不管了
for type_name in types_name: if type_name not in classes: continue 记录类别ID如果type_name在classes列表中获取其索引即类别ID): cls_idclasses.index(type_name)#输出0-1
【拓展】.index() 函数用于从列表中找出指定元素的第一个出现位置并返回其索引。如果元素不存在于列表中该方法会抛出一个 ValueError 异常。
classes.index(type_name)的意思是从classes这个猫狗类别的列表中根据type_name在classes的索引位置返回索引位置。
classes[cat,dog]type_name会返回01
4.2.3 遍历不同类别图片文件夹下的每一张图片检查格式是不是满足jpg等
构建图片目录路径photos_pathos.path.join(datasets_path,type_name)这里直接定位到存猫和狗的照片位置就是工作路径下的train下的cat和dog文件夹列出类别目录下的图片文件photos_name os.listdir(photos_path
【拓展】os.listdir(path) 函数接收一个路径参数 path这个路径可以是目录的绝对路径或相对路径。它的作用是返回指定目录下的所有文件和目录名不包括子目录中的文件组成的列表。列表中的每个元素都是一个字符串代表了目录下的一个项文件或子目录的名称。
在这里photos_path是两个照片的文件夹这里是把所有照片的名字都取出来了返回的形式是一个列表。
对每张照片的名字进行检查遍历图片文件对于每个图片文件检查其扩展名是否为.jpg, .png, 或 .jpeg。就算不是也继续
for photo_name in photos_name: _,postfix os.path.splitext(photo_name) # os.path.splitext是用来分割文件名字和拓展名字的 if postfix not in [.jpg,.png,.jpeg]: continue
【拓展】os.path.splitextpath是一个内置函数它接受一个文件路径或文件名作为参数并返回一个包含两个元素的元组第一个元素是文件的基本名不包括扩展名第二个元素是文件的扩展名包括前面的点;比如 返回(image, .jpg)如果 photo_name 是 image.jpg。
使用解包赋值_, postfix ...时下划线 _ 是一个常用的占位符表示我们不关心元组的第一个元素基本文件名只想保留第二个元素扩展名。因此postfix 变量将存储文件的扩展名如 .jpg、.png 或 .jpeg.
注意这个逻辑有个混淆的地方
if postfix not in [.jpg,.png,.jpeg]: continue
这段条件语句的目的是排除那些非.jpg, .png, .jpeg格式的文件。具体解释如下
当postfix即文件扩展名不是.jpg, .png, 或 .jpeg之一时postfix not in [.jpg,.png,.jpeg]这个条件为True。当这个条件为真时执行continue语句这意味着当前循环的剩余部分将被跳过直接开始检查下一个文件。条件为真意思是我检查到的这一张照片的拓展名不在这三个里面所以针对于这一张照片我选择continue也就是说我不管了我继续执行下一张照片。如果下一张照片的拓展名是属于这三个格式那我就进行进一步的图片操作。因此只有当文件扩展名确实是.jpg, .png, 或 .jpeg时代码才会继续执行后续对这些图像文件的操作比如将其路径写入到输出文件中。
所以正确的理解是这段代码是用来确保仅处理.jpg, .png, .jpeg这三种图片格式的文件而忽略所有其他格式的文件。
4.2.4 把要的图片的类别和每张图片的路径写进label文本文件里
那么对于是刚刚说的符合三个格式的照片我们收集起来写入到最开始打开的那个list_file的文件里面去:
list_file.write(str(cls_id);%s/%s%(wd, os.path.join(photos_path,photo_name)))
list_file.write(\n) 构造字符串str(cls_id);%s/%s%(wd, os.path.join(photos_path,photo_name)) 这部分代码构造了一条记录内容包括 cls_id这是图像所属类别的ID转换为字符串形式。假设cls_id为0或1对应于cat或dog。;分隔符用于在类别ID与文件路径之间提供清晰的分隔。%s/%s%(wd, os.path.join(photos_path,photo_name))这部分构造了图像的完整路径。%s是字符串格式化占位符第一个%s会被wd当前工作目录替换第二个%s会被os.path.join(photos_path,photo_name)的结果替换。os.path.join(photos_path,photo_name)确保了路径拼接的跨平台兼容性生成从当前工作目录到目标图片的完整相对路径。 写入文件list_file.write(...) 将上述构造的字符串写入到list_file所指向的文件中。这样每张图片的信息类别ID和相对路径就会以文本形式存储在文件里每条记录之间通过分号分隔每条记录末尾通过list_file.write(\n)添加换行符以便于之后读取时能清晰地区分每一条记录。 最后list_file.close() 注意原来的博主用的是gbk编码这样生成的label文件在我这是乱码其实一般用utf-8会好所以需要写一个程序把编码格式改成utf-8: # 转换脚本
# 转换脚本
def convert_gbk_to_utf8(input_file, output_file):with open(input_file, r, encodinggbk) as f:content f.read()with open(output_file, w, encodingutf-8) as f:f.write(content)# 调用函数进行转换
input_file cls_train.txt # 这里填写你的GBK编码文件名
output_file cls_train_1.txt # 输出的UTF-8编码文件名
convert_gbk_to_utf8(input_file, output_file)
总结
到这里就针对于我们的猫狗数据集完成了数据的清洗以及标签文件的制作。所以对于其他的数据集步骤也是大差不差的。
现在来总结一下
1、拿到数据做什么
数据清洗标签文件制作两个步骤相辅相成
首先拿到数据集我们要做两件事数据清洗和制作标签文件在这个项目里面照片都是很干净的数据不存在格式乱七八糟或者其他的情况所以清洗就是简单的判断是不是jpg等格式还是很简单的。
另外就是标签文件夹的制作。这里学到的一点是我们可以先分析图片的存放形式然后通过索引的方式遍历train文件夹下的不同类别的子目录完成自动生成好几个类别的作用。
2、分类标签文件存什么
标签文件信息类别图片路径
映射文件当图片和标签不是通过文件结构直接关联时会使用一个映射文件来记录这种对应关系。这个映射文件如CSV通常包含至少两列一列是图片的路径或文件名另一列是对应的类别标签。例如
1image_path,label
2data/cats/cat_001.jpg,0
3data/dogs/dog_002.png,1
在这个映射文件中第一列是图片的完整路径或相对于某个根目录的路径第二列是类别标签0代表猫1代表狗。
在使用深度学习框架如PyTorch进行训练时可以通过自定义的数据加载器DataLoader读取这种映射文件根据映射关系动态地加载图像和对应的标签从而实现图片与其类别信息的正确配对。
3、拓展到其他的数据处理过程
图片名字是各有不同的有的很复杂各种标点符号什么的会涉及更复杂的处理。所以要学会观察图片名字然后做出分割。分类问题的标签还是很简单的就是把图片文件路径读取然后拆开根据循环一张一张图片的取出来解析是什么类型然后配上每张图片的路径。
完整代码
import os
from os import getcwdclasses[cat,dog]
sets[train]if __name____main__:wdgetcwd()for se in sets:list_fileopen(cls_ se .txt,w)datasets_pathsetypes_nameos.listdir(datasets_path)#os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表for type_name in types_name:if type_name not in classes:continuecls_idclasses.index(type_name)#输出0-1photos_pathos.path.join(datasets_path,type_name)photos_nameos.listdir(photos_path)for photo_name in photos_name:_,postfixos.path.splitext(photo_name)#该函数用于分离文件名与拓展名if postfix not in[.jpg,.png,.jpeg]:continuelist_file.write(str(cls_id);%s/%s%(wd, os.path.join(photos_path,photo_name)))list_file.write(\n)list_file.close()
【为什么每个图片能精准匹配到他的类别】实际上是因为用了两个循环第一个大循环for type_name in types_name让你进入到cat文件夹然后第二个小循环(for photo_name in types_name)遍历cat文件夹下面的每一张图片 直到cat里面每一张图片都遍历完在跳入dog文件夹的大循环然后遍历dog文件夹下面的每一个狗的图片。
所以数据集组织结构要清晰每个类别下的图片需放在对应类别名称的文件夹中。