程序:
我们在训练卷积神经网络之前,要搭建好数据集,分成训练集和测试集两部分。
本程序以花分类数据集为例,将数据集分成训练集和测试集。
先把完整的程序贴出来。
#split_data.py
import os
from shutil import copy, rmtree
import random
def mk_file(file_path: str):
if os.path.exists(file_path):
# 如果文件夹存在,则先删除原文件夹在重新创建
rmtree(file_path)
os.makedirs(file_path)
def main():
# 保证随机可复现
random.seed(0)
# 将数据集中10%的数据划分到验证集中
split_rate = 0.1
# 指向你解压后的flower_photos文件夹
cwd = os.getcwd()
data_root = os.path.join(cwd, "flower_data")
origin_flower_path = os.path.join(data_root, "flower_photos")
assert os.path.exists(origin_flower_path)
flower_class = [cla for cla in os.listdir(origin_flower_path)
if os.path.isdir(os.path.join(origin_flower_path, cla))]
# 建立保存训练集的文件夹
train_root = os.path.join(data_root, "train")
mk_file(train_root)
for cla in flower_class:
# 建立每个类别对应的文件夹
mk_file(os.path.join(train_root, cla))
# 建立保存验证集的文件夹
val_root = os.path.join(data_root, "val")
mk_file(val_root)
for cla in flower_class:
# 建立每个类别对应的文件夹
mk_file(os.path.join(val_root, cla))
for cla in flower_class:
cla_path = os.path.join(origin_flower_path, cla)
images = os.listdir(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 = os.path.join(cla_path, image)
new_path = os.path.join(val_root, cla)
copy(image_path, new_path)
else:
# 将分配至训练集中的文件复制到相应目录
image_path = os.path.join(cla_path, image)
new_path = os.path.join(train_root, cla)
copy(image_path, new_path)
print("\r[{}] processing [{}/{}]".format(cla, index+1, num), end="") # processing bar
print()
print("processing done!")
if __name__ == '__main__':
main()
下面简单介绍一下程序流程
1、引入库
import os
from shutil import copy, rmtree
import random
os库
os 库提供通用的、基本的操作系统交互功能。
os 库是Python标准库,包含几百个函数,常用的有路径操作、进程管理、环境参数等。
os可以实现简单的文件夹和文件操作。
可参考Python os库使用
shutil
shutil可以实现复杂的文件操作,比如对文件的拷贝和复制。
random
很常用的关于随机生成的库。
2、mk_file函数
def mk_file(file_path: str):
if os.path.exists(file_path):
# 如果文件夹存在,则先删除原文件夹在重新创建
rmtree(file_path)
os.makedirs(file_path)
os.path.exists(path) :判断path对应文件或目录是否存在,返回True或False
rmtree() :递归地删除文件夹下的所有子文件夹和子文件。
os.makedirs():可以创建多级目录,如果路径的目录都不存在,都可以创建出来。
所以这个mk_file函数的作用是,当目标文件已经存在,删除后再创建。即覆盖更新过程。
3、主函数
- 1
def main():
# 保证随机可复现
random.seed(0)
# 将数据集中30%的数据划分到验证集中
split_rate = 0.3
random.seed():创建随机种子,括号里添加具体数值方便让后续的随机生成操作可复现。
- 2
# 指向你解压后的flower_photos文件夹
cwd = os.getcwd()
data_root = os.path.join(cwd, "flower_data")
origin_flower_path = os.path.join(data_root, "flower_photos")
assert os.path.exists(origin_flower_path) #确定这个路径是存在的
flower_class = [cla for cla in os.listdir(origin_flower_path)
if os.path.isdir(os.path.join(origin_flower_path, cla))] #建立一个花的类别的列表
os.getcwd():返回程序的当前路径。
这里我放置这个split_data.py程序的路径为 E:\1test\date_test
os.path.join(path1,path2): 路径拼接
所以data_root 得到路径E:\1test\date_test\flower_data
origin_flower_path得到路径E:\1test\date_test\flower_data\flower_photos
说明一下,我们存放有花数据的文件夹flower_data,与这个程序在同一级文件夹下。
flower_data文件夹里有我们下载好(或自己爬好)的未划分的数据
data_root = os.path.join(cwd, “flower_data”)定位了flower_data文件夹的路径。
origin_flower_path = os.path.join(data_root, “flower_photos”)定位了下一级文件夹里flower_photos的路径。
os.listdir():用于返回一个由文件名和目录名组成的列表,需要注意的是它接收的参数需要是一个绝对的路径。
如:
已知路径path = /home/python/Desktop/
请输出该路径下的所有文件和目录名称
import os
path = '/home/python/Desktop/'
for i in os.listdir(path):
print(i)
os.path.isdir():用于判断对象是否为一个目录
如:
已知路径path = /home/python/Desktop/
请输出该目录下包含的目录名称
import os
for i in os.listdir(path):
if os.path.isdir(i):
print(i)
则
flower_class = [cla for cla in os.listdir(origin_flower_path)
if os.path.isdir(os.path.join(origin_flower_path, cla))]
这句代码,把origin_flower_path 下的花的类别文件夹名,生成了一个花类列表[“daisy”,“dandelion”,“roses”,“sunflowers”,“tulips”]
- 3
# 建立保存训练集的文件夹
train_root = os.path.join(data_root, "train")
mk_file(train_root)
for cla in flower_class:
# 建立每个类别对应的文件夹
mk_file(os.path.join(train_root, cla))
# 建立保存验证集的文件夹
val_root = os.path.join(data_root, "val")
mk_file(val_root)
for cla in flower_class:
# 建立每个类别对应的文件夹
mk_file(os.path.join(val_root, cla))
解释:
train_root = os.path.join(data_root, "train")
mk_file(train_root)
#在data_root路径下(flower_data文件夹)创建train文件夹
for cla in flower_class:
mk_file(os.path.join(train_root, cla))
# 在建立好的train文件夹下,建立每个类别对应的文件夹
验证集同理。
注意这一步形成了空的、分别用来保存训练集和测试集的文件夹,需要下一步填入图片。
- 4
for cla in flower_class:
cla_path = os.path.join(origin_flower_path, cla)
images = os.listdir(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 = os.path.join(cla_path, image)
new_path = os.path.join(val_root, cla)
copy(image_path, new_path)
else:
# 将分配至训练集中的文件复制到相应目录
image_path = os.path.join(cla_path, image)
new_path = os.path.join(train_root, cla)
copy(image_path, new_path)
print("\r[{}] processing [{}/{}]".format(cla, index+1, num), end="") # processing bar
print()
解释:
cla_path = os.path.join(origin_flower_path, cla)
#定位到原始数据集的各类花的文件夹(含有一类花的所有图片)
images = os.listdir(cla_path)
#将这类花文件夹下的所有图片形成一个列表。
num = len(images)
# 随机采样验证集的索引
eval_index = random.sample(images, k=int(num*split_rate))
k=int(num*split_rate)即要挑选出的验证集图片数。
这一步用随机方法形成了要放进验证集里的图片的索引的一个列表。
for index, image in enumerate(images):
if image in eval_index:
# 将分配至验证集中的文件复制到相应目录
image_path = os.path.join(cla_path, image)
new_path = os.path.join(val_root, cla)
copy(image_path, new_path)
enumerate函数可以同时获得索引和值。
所以这句代码的意思 ,我从原来一个花类(如daisy)的所有图片中判断,如果这个图片的索引是上一步要取出作为验证集的,那就把它copy到之前建好的放验证集的空的同名文件夹下(如val\daisy).
else:
# 将分配至训练集中的文件复制到相应目录
image_path = os.path.join(cla_path, image)
new_path = os.path.join(train_root, cla)
copy(image_path, new_path)
紧接着,如果不是要作为验证集的图片,把他copy到之前建好的放训练集的空的同名文件夹下(如train\daisy).
print("\r[{}] processing [{}/{}]".format(cla, index+1, num), end="") # processing bar
实时显示进度。
以上就是这个将数据集分割为训练集和验证集的思路。
以后自己通过爬取图片建立数据集,按照这个程序思路,就不用自己一点一点算数量,进行复制粘贴的麻烦工作了。直接使用这个程序,更改一下文件夹名称,直接用就可以了。不过要注意层级结构,这个脚本和放数据的文件是同级的,可以参考上面的截图。
希望能对你有所帮助!o( =•ω•= )m