第二次能 “出点结果” 了。仍然是一个 Demo。
这次的目的是使用 TfRecord 这个文件格式来存储数据集(上次是用 txt,用到图片就现读取)。
所以,第一步,我们要写一个将数据集转换成 TfRecord 的脚本。
将数据集转换成 TfRecord 格式
我们依然使用 flower 这个数据集。5 个文件夹是图片的类别,每个文件夹下一大堆图片。
在这里,由于 TensorFlow 还用不好,所以使用比较熟悉的 ScikitImage 来读入和转换图片。读入图片后,将其序列化为 Example 这个 “名字很奇怪” 的类型,然后保存到磁盘上。代码见这里:
使用数据集
使用 tf.contrib.data.TFRecordDataset
创建数据集。然后对每一条记录进行反解析,得到图片、标签,最后将数据送入网络。
想使用一些比较高级的 API,例如 tf.estimator
等。虽然手动控制 Session 很方便,但是这些高级 API 还是能用就用吧,毕竟可以自动加入 TensorBoard、自动 Load 之前的状态等等。
这里没用 Slim 来定义网络。Slim 定义网络确实方便,但是感觉 tf.layers
定义网络也不怎么复杂。所以呢,各有所爱吧。
自己写网络
下一步就是把网络给换掉了。这里使用 Tiny Yolo 试试:
这是一个我一直垂涎的小网络。只需要把上面的相应函数替换掉,类别改成 5,然后重新制作数据集,图片大小改为 224×224×3 即可。
运行看看效果吧~
后记
数据集转换代码几乎都是自己写的。
网络代码大部分参考了官方 Models 的代码。
我是这样进行调试的: 现在已知官方 mnist 分类代码是可以正常工作的,那么如果我做出来的数据集也能正常工作,那么就说明我的代码没问题。所以,县写一个数据集转换的代码,一点一点进行调试,直到生成的数据集能让官方 mnist 分类代码可以正常工作为止。然后再根据需要,同步修改两边的代码。
本来数据集转换那里想使用 TensorFlow 的 image 包里面的东西,但是实在控制不好。例如,读入图片之后,直接 decode_image
出来的图片没有 channel 信息,用 decode_jpeg
出来的图不能 resize,提示「没有 size」。各种乱了一整天之后,最终决定使用 Scikit-Image 来进行读入和图片简单预处理。但我发现,使用 TensorFlow 处理图片速度可达 400 张 / s,但使用 Scikit-Image 处理图片就只有 160 张 / s。大概是 TensorFlow 使用了多线程的缘故?
这次 GPU 使用率可以达到 50% 左右了。不知道为什么还是赶不上官方 Mnist 分类代码的 GPU 使用率(80~90%)。
而且,也不知道为什么,训练精度可以达到 99.99%,但是测试精度爬升到 50% 左右就开始下降了。下降是因为过拟合了,这个在 TensorBoard 上可以看出来(大概是在 5k 次迭代左右过拟合的),但是为什么测试精度最高只有 50% ?这是我想不通的地方。希望能看到这篇文章的大佬不惜赐教。
另外吐槽:TensorFlow 各种例子看着很乱。比如,Mnist 例子在下面几个位置都可以找到:
tensorflow/examples/tutorials/mnist
models/tutorials/image/mnist
models/offcial/mnist
models/offcial/research/slim/datasets/mnist
- …
发表回复