使用场景
训练神经网络时常常用到自己的数据,那么如何读取这大量的图片数据以及打上label使我们开始训练前要处理好的事情。这时候,当你有一个分好类别的文件夹,你可以导入
from torchvision.datasets import ImageFolder
它会很大程度上的方便你的数据预处理工作。(鉴于新手小白对读取自己的文件(夹)完全不了解)
官方定义
def __init__(
self,
root: str,
transform: Optional[Callable] = None,
target_transform: Optional[Callable] = None,
loader: Callable[[str], Any] = default_loader,
is_valid_file: Optional[Callable[[str], bool]] = None,
)
使用起来最重要的一个参数即"Root":即存有分类图像文件夹的更上一层文件夹(比如:1.jpg->保存这一类分类的文件夹“dogs”->需要填入作Root的文件夹“Data”)
transform表示对图像的处理变换,如transforms.Resize()、Transforms.ToTensor()等等。
其它的参数一般不会用到,不用太深究。
方便之处
在实现的过程中,为什么一定要读取带有子文件夹的更高一层文件夹呢(子文件夹需要时装有不同分类图片的文件夹)?
原因就在于:ImageFolder会自动根据文件夹中的图片文件及其对应的分类(通过子文件夹结构来确定)构建数据集。
大白话来说就是:给定这个根文件夹,ImageFolder会获得两类元素:1.文件夹中所有的图片文件(PIL类型)。2.文件对应的分类标签。而这个分类标签的设置依据,就是根据图片所属的子文件夹,设置不同label(设置为从0开始的int型,即第n个文件夹,label = n-1)。来自相同子文件夹的label相同,不同子文件夹的label不同,从而轻松得到了所有数据的类别。
实际例子
比如说现在有这样一个数据集,cats和dogs里分别存有200张该类别图片。使用ImageFolder时选取的Root文件夹为“testing_data”。
test_dataset = ImageFolder("data/testing_data")
此时查看test_dataset的基本信息type、length可以看到:说明已经成功读取了总共400张的图片。
再看其每一项的组成(print(test_dataset[0]))得到:
(<PIL.Image.Image image mode=RGB size=150x149 at 0x1B63A0DE790>, 0)
前一项是PIL类型图片,后一项是该图片label。
如果你还是不敢确定究竟有没有分好类(还是说我前面是骗你的其实它在乱分类?),可以遍历一下整个dataset查看label的分布和各项个数:
X_test = []
y_test = []
for file in test_dataset:
img, label = file
X_test.append(img)
y_test.append(label)
print(y_test)
print(sum(y_test)) #二分类中只有0和1,所以sum()得到的是1的个数(dogs的num)
得到:
一半0,一半1。
400项,和为200。
包不骗你的,包好用的!