人工智能(AI)库TensorFlow 踩坑日记之二
上次 踩坑日志之一 遗留的问题终于解决了,所以作者(也就是我)终于有脸出来写第二篇了。
首先还是贴上 卷积算法的示例代码地址 :https://github.com/tensorflow/models
这个库里面主要是一些常用的模型用tensorflow实现之后的代码。其中我用的是
models/tree/master/tutorials/image/cifar10 这个示例,上一篇也大致讲过了。
关于上次遇到问题是:
虽然训练了很多次,但是每次实际去用时都是相同的结果。这个问题主要原因是
在核心代码文件cifar10.py里
tf.app.flags.DEFINE_integer('batch_size', 128,
"""Number of images to process in a batch.""")
被我改成 batch_size =1
一开始我误以为这个batch要跟训练文件的.bin 文件里面的图片数量对应,其实不然。这个batch_size 是为了用
cifar10_input.py
images, label_batch = tf.train.batch(
[image, label],
batch_size=batch_size,
num_threads=num_preprocess_threads,
capacity=min_queue_examples + 3 * batch_size)
创建一个图片跟标签的队列,每个队列128个元素,便于分布式处理。
由于改成1之后可能是影响是训练效果。导致整体的loss很高,所以识别率很差。有待进一步验证。
2018-03-11 修正
batch_size 作用就是一次性训练这么多次之后才开始做梯度下降,这样loss 的波动不会太大。
2018-06-19 补充
https://blog.csdn.net/ycheng_sjtu/article/details/49804041
看完这篇文章之后终于对batch_size 有了一个更深刻的理解。就是越小的batch会导致局部的梯度波动大,难以收敛。
另外一个原因很可能是最致命的
上一篇讲到label的对应方式是
# Create a queue that produces the filenames to read.
filename_queue = tf.train.string_input_producer(filenames)
label 也是用string_input_producer 做了另外一条字符串队列
因为label 是分类名称,也是图片所在文件夹的名称,所以我在外面把图片文件夹名称都丢到一个label的string队列里,然后里面做出队 depuqeue。
这其实是错误的,因为两条队列要完美保持一致,而且还不能加shuffle 参数 这个参数可以随机获取图片文件,以便训练模型效果更具备泛化能力。
# Create a queue that produces the filenames to read.
filename_queue = tf.train.string_input_producer(filenames,name="filename_queue_hcq",shuffle=True)
shuffle=true 还是要加的。
label的获取方式就得另外想办法。
把 cifar10_input.py 方法 read_cifar10 改造如下:
def read_cifar10(filename_queue):
class CIFAR10Record(object):
pass
reader = tf.WholeFileReader()
key, value = reader.read(filename_queue) image0 = tf.image.decode_jpeg(value,3) esized_image = tf.image.resize_images(image0, [32, 32],
method=tf.image.ResizeMethod.AREA)
result = ImageNetRecord()
re2=splitfilenames(tf.constant( filenames),len(filenames))
key=splitfilenames(tf.reshape(key,[1],name="key_debug"),1)
label=diff(re2,key)
其中 splitilenames ,diff 方法是我新增的,主要是为了把文件所在目录的路劲切出来
def splitfilenames(inputs,allstringlen):
a = tf.string_split(inputs, "/\\")
bigin = tf.cast(tf.size(a.values) / allstringlen -2, tf.int32)
slitsinglelen = tf.cast(tf.size(a.values) / allstringlen, tf.int32)
val = tf.reshape(a.values, [allstringlen, slitsinglelen])
re2 = tf.cast(tf.slice(val, [0, bigin], [allstringlen, 1]),tf.string)
re2 =tf.reshape(re2,[allstringlen])
re2 =tf.unique(re2).y
return re2
比如”H:\imagenet\fortest\n01440764“ 切出来 “n01330764”。 这个方法是支持批量处理的。
之所以写的这么麻烦。是因为输入量是tensor,所以所有操作都必须按照tensorflow的api写。
diff方法(代码在下面) 是为了判定key 的分类名在所有分类里面的文件排序位置(数字0-1000以内)。用这个位置作为label。
这里 读者估计有一个疑问
“为啥不直接用分类名‘n01330764’作为label标签去训练呢?”
这里也是迫于无奈,因为原始代码cifar10的后续功能有2个限制,1,label必须是int型,2label最大值不能大于分类总数。所以不能简单把“n”删除然后转成数字 1330764 。
否则会出各种错。修正这2个问题明显比我新增一个diff方法改动更大。
虽然不太优雅,各位看官轻拍。
def diff(re2,key): keys = tf.fill([tf.size(re2)],key[0]) numpoi= tf.cast(tf.equal(re2, keys),tf.int32)
numpoi=tf.argmax(numpoi)
return numpoi
2018-06-19 修正
后来这里取label的方法还是换成文件夹按字母排序后的位置作为label了。这样保险很多,而且性能也好一些。
好了,到止为止,train(训练过程)的代码就改完了,可以开始训练了。
cifar10_eval.py 这边需要改个地方。
if len(sys.argv)==1:
SinglePicPath = "/tmp/8.jpg"
else:
SinglePicPath =sys.argv[1]
通过参数传入 单图片的地址,用来放到生产环境执行识别程序。
先跑一下8.jpg 测试一下
得出来结果是0 之所以有这么多,是因为
cifar10_eval 原来的代码用了一部分跟训练代码一致的过程,其中训练代码中batchsize=128,导致虽然输入只有1张图,输出的结果还是有128个。有点多余,不过取其中一个作为结果就可以了。
(这里可以在把batchsize改为1,只在运行时用1)
然后我用C# MVC写了一个页面。用来上传图片,然后输出中文结果。
主要核心代码是(C#):
Thumbnails.Of(file).ZoomMethod(Thumbnails.ThumbnailZoomMethod.CUT).Resize(, ).ToFiles(imagepath);
var p = new Process();
//C:\Users\Administrator\AppData\Local\Programs\Python\Python35\python.exe
p.StartInfo.FileName = @"C:\Users\Administrator\AppData\Local\Programs\Python\Python35\python.exe";
p.StartInfo.Arguments = @"H:\tensorflow_cnn\tensorflow_cnn\tutorials\image\cifar10\cifar10_runsingle.py " + imagepath;
p.StartInfo.WorkingDirectory = @"H:\";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.Start();
string output = p.StandardOutput.ReadToEnd();
string errmsg = p.StandardError.ReadToEnd();
p.WaitForExit();
p.Close();
var num = Regex.Replace(output, @".*\[array\(\[(\d+),.*\].*", "$1", RegexOptions.Singleline);
string result;
主要是把图片改为 32*32 然后用Process 拉起python 去执行 cifar10_runsingle.py (这个是cifar10_eval.py 改造后的)。
然后用正则把 结果的数字切出来。
剩下就是把位置比如 0替换成“n01330764”
“n01330764” 再替换成中文,上一篇有下载中文的链接。
测试一下
------------------------------------------
--------------------------------------
-------------------
因为把eval(评估代码)改成执行代码了,所以eval 测试集(在imagenet下载自带的)反而没应用上了。暂时不能判断识别率高低。这是下一步要改造的地方。
不过imagenet 的数量级太大,正正经经训练一次,估计要很久很久很久。
另外还要切换成GPU模式,估计不太难。有教程。
期待踩坑日志之三吧,烧年们。
另外说一点关于tensorboard的,这东西真是厉害。安装方便。直接命令行
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorflow-tensorboard
-i 地址是用了清华的pip镜像 这样安装比较快不容易出错。
然后
logdir 指向
wt = tf.summary.FileWriter("/tmp/broaddata3")
代码中设置的 summary的地址。
然后打开浏览器查看。
这里有个坑需要注意, tensorboard的运行盘符必须跟log所在盘符一致,否则一直提示拿不到文件。
这里可以看到我新增了一个label_sum 的曲线图,可以看到确实拿到不同的label了,而且最小是从0开始的。
此致敬礼。
更新:
2019-03-22
由于之前的例子都是一张一张读取图片,最后我还是修改为打包进Bin文件,然后训练时再一次性读取
源码路径如下 使用方法查看项目 ReadME
https://github.com/g7rhythm/MYcifar255
人工智能(AI)库TensorFlow 踩坑日记之二的更多相关文章
- 人工智能(AI)库TensorFlow 踩坑日记之一
上次写完粗浅的BP算法 介绍 本来应该继续把 卷积神经网络算法写一下的 但是最近一直在踩 TensorFlow的坑.所以就先跳过算法介绍直接来应用场景,原谅我吧. TensorFlow 介绍 TF是g ...
- java连数据库和数据库连接池踩坑日记(二)-------数据库连接池c3p0
关于数据库连接池,我觉得有些沮丧,因为最后被毙掉了说不用考虑多线程的问题…… 数据库连接池的推荐:https://www.cnblogs.com/nuccch/p/8120349.html 我最终选择 ...
- 小程序框架MpVue踩坑日记(二)
数据嵌套超过三层或者等于三层的时候 父组件传值给子组件后,如果子组件内的值需要改变 通过this.emit()传值后,父组件的值虽然会改变,但是视图并不会重新渲染 原因就是数据嵌套太多,没有触发ren ...
- AI相关 TensorFlow -卷积神经网络 踩坑日记之一
上次写完粗浅的BP算法 介绍 本来应该继续把 卷积神经网络算法写一下的 但是最近一直在踩 TensorFlow的坑.所以就先跳过算法介绍直接来应用场景,原谅我吧. TensorFlow 介绍 TF是g ...
- hexo博客谷歌百度收录踩坑日记
title: hexo博客谷歌百度收录踩坑日记 toc: false date: 2018-04-17 00:09:38 百度收录文件验证 无论怎么把渲染关掉或者render_skip都说我的格式错误 ...
- Hexo搭建静态博客踩坑日记(二)
前言 Hexo搭建静态博客踩坑日记(一), 我们说到利用Hexo快速搭建静态博客. 这节我们就来说一下主题的问题与主题的基本修改操作. 起步 chrome github hexo git node.j ...
- Hexo搭建静态博客踩坑日记(一)
前言 博客折腾一次就好, 找一个适合自己的博客平台, 专注于内容进行提升. 方式一: 自己买服务器, 域名, 写前端, 后端(前后分离最折腾, 不分离还好一点)... 方式二: 利用Hexo, Hug ...
- linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二)
linux centos7环境下安装apache2.4+php5.6+mysql5.6 安装及踩坑集锦(二) 安装apache web容器 . yum方式安装apache 注意apache在linux ...
- JavaScript 新手的踩坑日记
引语 在1995年5月,Eich 大神在10天内就写出了第一个脚本语言的版本,JavaScript 的第一个代号是 Mocha,Marc Andreesen 起的这个名字.由于商标问题以及很多产品已经 ...
随机推荐
- 【FFmpeg】FFmpeg常用基本命令
1.分离视频音频流 ffmpeg -i input_file -vcodec copy -an output_file_video //分离视频流 ffmpeg -i input_file -acod ...
- 动态分配数组(new)和用随机数赋值(rand)
#include <iostream>#include <ctime>#include <cstdlib>using namespace std; int main ...
- 两本最近阅读的工具书的记录 关于Python和Linux命令行的 不喜勿喷 只是写给自己用
<Linux命令行完全技术宝典>读书心得 张栋作者 在学习Linux系统中,我们需要掌握各种管理的方法和技巧,而管理Linux系统最有效的方法就是命令行的控制.而我在图书馆中读到的< ...
- 基于FPGA的IIR滤波器
基于FPGA的IIR滤波器 by方阳 版权声明:本文为博主原创文章,转载请指明转载地址 ...
- linux上搭建zookeeper
1.zookeeper介绍 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提 ...
- 搭建带热更新功能的本地开发node server
引言 使用webpack有一段时间了,对其中的热更新的大概理解是:对某个模块做了修改,页面只做局部更新而不需要刷新整个页面来进行更新.这样就能节省因为整个页面刷新所产生开销的时间,模块热加载加快了开发 ...
- 持续集成篇-- SonarQube代码质量管理平台的安装
视频教程:http://www.roncoo.com/course/view/85d6008fe77c4199b0cdd2885eaeee53 IP:192.168.4.221 环境:CentOS 6 ...
- Yii 中出现“<?= ... ?>”是什么意思?
这是php的标签,和<?php ?>一样的.用<?= ?> 就不用echo,否则你要输出的话,需要加上echo词汇输出.这个就是用在模板里面方便点.
- css之选择器总结
首先我们来看下有哪些选择器??? 一.基础选择器: html标签选择器:通过html标签来选择元素. ①所有的html标签都可以当做选择器. ②无论标签藏多深都会被选中. ③选择的是所有的标签而不是某 ...
- 8.javaweb之session
session是客户端和服务端的一次会话 web的session是指用户在浏览某个网站时,从进入网站到关闭浏览器的这段时间,uyejiushi用户浏览这个网站所花费的时间. session是一个时间的 ...