TensorFlow2.0(10):加载自定义图片数据集到Dataset
生死路,彭云轩,格雅手表6152g
前面的博客中我们说过,在加载数据和预处理数据时使用tf.data.dataset对象将极大将我们从建模前的数据清理工作中释放出来,那么,怎么将自定义的数据集加载为dataset对象呢?这对很多新手来说都是一个难题,因为绝大多数案例教学都是以mnist数据集作为例子讲述如何将数据加载到dataset中,而英文资料对这方面的介绍隐藏得有点深。本文就来捋一捋如何加载自定义的图片数据集实现图片分类,后续将继续介绍如何加载自定义的text、mongodb等数据。
如果你已有数据集,那么,请将所有数据存放在同一目录下,然后将不同类别的图片分门别类地存放在不同的子目录下,目录树如下所示:
$ tree flower_photos -l 1
flower_photos
├── daisy
├── dandelion
├── license.txt
├── roses
├── sunflowers
└── tulips
所有的数据都存放在flower_photos目录下,每一个子目录(daisy、dandelion等等)存放的都是一个类别的图片。如果你已有自己的数据集,那就按上面的结构来存放,如果没有,想操作学习一下,你可以通过下面代码下载上述图片数据集:
下载好后,建议将整个flower_photos目录移动到项目根目录下。
out[2]:
['data/flower_photos/sunflowers/9448615838_04078d09bf_n.jpg',
'data/flower_photos/roses/15222804561_0fde5eb4ae_n.jpg',
'data/flower_photos/daisy/18622672908_eab6dc9140_n.jpg',
'data/flower_photos/roses/459042023_6273adc312_n.jpg',
'data/flower_photos/roses/16149016979_23ef42b642_m.jpg']
读取图片的同时,我们也不能忘记图片与标签的对应,要创建一个对应的列表来存放图片标签,不过,这里所说的标签不是daisy、dandelion这些具体分类名,而是整型的索引,毕竟在建模的时候y值一般都是整型数据,所以要创建一个字典来建立分类名与标签的对应关系:
out[3]:
['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
out[4]:
{'daisy': 0, 'dandelion': 1, 'roses': 2, 'sunflowers': 3, 'tulips': 4}
data/flower_photos/sunflowers/9448615838_04078d09bf_n.jpg ---> 3
data/flower_photos/roses/15222804561_0fde5eb4ae_n.jpg ---> 2
data/flower_photos/daisy/18622672908_eab6dc9140_n.jpg ---> 0
data/flower_photos/roses/459042023_6273adc312_n.jpg ---> 2
data/flower_photos/roses/16149016979_23ef42b642_m.jpg ---> 2
不过,这个ds可不是我们想要的,毕竟,里面的元素只是图片路径,所以我们要进一步处理。这个处理包含读取图片、重新设置图片大小、归一化、转换类型等操作,我们将这些操作统统定义到一个方法里:
out[10]:
<mapdataset shapes: ((192, 192, 3), ()), types: (tf.float32, tf.int32)>
这时候,其实就已经将自定义的图片数据集加载到了dataset对象中,不过,我们还能秀,可以继续shuffle随机打散、分割成batch、数据repeat操作。这些操作有几点需要注意:
(1)先shuffle、repeat、batch三种操作顺序有讲究:
- 在repeat之后shuffle,会在epoch之间数据随机(当有些数据出现两次的时候,其他数据还没有出现过)
- 在batch之后shuffle,会打乱batch的顺序,但是不会在batch之间打乱数据。
(2)shuffle操作时,buffer_size越大,打乱效果越好,但消耗内存越大,可能造成延迟。
推荐通过使用 tf.data.dataset.apply 方法和融合过的 tf.data.experimental.shuffle_and_repeat 函数来执行这些操作:
好了,至此,本文内容其实就结束了,因为已经将自定义的图片数据集加载到了dataset中。
下面的内容作为扩展阅读。
上面的方法是简单的在每次epoch迭代中单独读取每个文件,在本地使用 cpu 训练时这个方法是可行的,但是可能不足以进行gpu训练并且完全不适合任何形式的分布式训练。
可以使用tf.data.dataset.cache在epoch迭代过程间缓存计算结果。这能极大提升程序效率,特别是当内存能容纳全部数据时。
在被预处理之后(解码和调整大小),图片就被缓存了:
使用内存缓存的一个缺点是必须在每次运行时重建缓存,这使得每次启动数据集时有相同的启动延迟。如果内存不够容纳数据,使用一个缓存文件:
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!!
点击进行留言回复
相关文章:
-
-
-
-
-
python中def是做什么的
python使用def开始函数定义,紧接着是函数名,括号内部为函数的参数,内部为函数的 具体功能实现代码,如果想要函数有返回值, 在expressions中的逻...
[阅读全文]
-
-
-
-
-
-
网友评论