将数据集分为训练集和测试集(python脚本)

程序:

我们在训练卷积神经网络之前,要搭建好数据集,分成训练集和测试集两部分。
本程序以花分类数据集为例,将数据集分成训练集和测试集。

先把完整的程序贴出来。

#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

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值