人工智能(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很高,所以识别率很差。有待进一步验证。

另外一个原因很可能是最致命的

上一篇讲到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 方法是我新增的,主要是为了把文件所在目录的路劲切出来

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 的分类名在所有分类里面的位置。用这个位置作为label。

这里 读者估计有一个疑问

“为啥不直接用分类名‘n01330764’作为label标签去训练呢?”

这里也是迫于无奈,因为后续的代码有2个限制,1,label必须是int型,2label最大值不能大于分类总数。所以不能简单把“n”删除然后转成数字 1330764 。

虽然不太优雅,各位看官轻拍。

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

好了,到止为止,train的代码就改完了,先训练一段时间。

cifar10_eval.py 这边需要改个地方。
if len(sys.argv)==1:
  SinglePicPath = "/tmp/8.jpg"
else:
  SinglePicPath =sys.argv[1]

通过参数传入 单图片的地址,用来执行识别程序。

先跑一下8.jpg

得出来结果是0 之所以有这么多,是因为batchsize=128 不过都是一样的。

然后我用C# MVC写了一个页面。用来上传图片,然后输出中文结果。

主要核心代码是:

 Thumbnails.Of(file).ZoomMethod(Thumbnails.ThumbnailZoomMethod.CUT).Resize(32, 32).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 的数量级太大,正正经经训练一次,估计要很久很久很久。

另外还要切换成GPU模式,估计不太难。有教程。

期待踩坑日志之三吧,烧年们。

另外说一点关于tensorboard的,这东西真是厉害。安装方便。直接命令行 pip tensorboard

然后

logdir 指向

 wt = tf.summary.FileWriter("/tmp/broaddata3")

代码中设置的 summary的地址。

然后打开浏览器查看。

这里有个坑需要注意, tensorboard的运行盘符必须跟log所在盘符一致,否则一直提示拿不到文件。

这里可以看到我新增了一个label_sum 的曲线图,可以看到确实拿到不同的label了,而且最小是从0开始的。

此致敬礼。

				
时间: 2024-08-10 15:09:24

人工智能(AI)库TensorFlow 踩坑日记之二的相关文章

quick cocos2dx 3.3rc1 踩坑日记(二)------ 声音引擎

昨天在群里有人说setSoundsVolume和setMusicVolume设置声音大小无效...我记得cocos2dx是没实现内容的,就贸贸然回答说,是这你的没用,但群里有人说是有用的,我就去虚心请教,大神人很好,回答了我很多问题,告诉我说实现了,而且是针对不同的平台.实现的文件位置,如下图: 我先测试setMusicVolume,在win32下setMusicVolume是无效的,在Android上是可以的. 但在测试setSoundsVolume时,就遇见问题了,当调用audio.play

cocos2dx 3.3rc0 踩坑日记(二)------ HttpClient 的使用

昨天写了Curl的简单使用,遇见了几个坑,今天用HttpClient写样例还是遇见了坑~ 按照网上的资料写总是遇见问题...应该是版本不一样!!!下面我来说说HttpClient的使用方法. 首先要引入头文件和命名空间 #include "network/HttpClient.h" using namespace cocos2d::network; 但是这样还不行,编译的话会报错,无法解析的外部符号....... 出现这个需要添加network库,添加库的方式和以前有点不同.3.x有些

SpringBoot踩坑日记-定时任务不定时了?

问题描述br/>springboot定时任务用起来大家应该都会用,加两注解,加点配置就可以运行.但是如果仅仅处在应用层面的话,有很多内在的问题开发中可能难以察觉.话不多说,我先用一种极度夸张的手法,描述一下遇到的一个问题.@Componentpublic class ScheduleTest {@Scheduled(initialDelay = 1000,fixedRate = 2*1000)public void test_a(){System.out.println("123"

米忽悠踩坑日记-1

米忽悠踩坑日记-1            --知不足,而后进 进入米哈游差不多一个半月了,就以刚刚上线的某个任务作为节点写一篇踩坑日记吧. 1.安全意识,尽量考虑到玩家各种奇奇怪怪的操作以及有可能想刷道具的行为. 2.日志方面,记录玩家的每一步操作,成功或者失败,需要记录清楚,uid,region以及其他的信息,如奖励的ID,更新一次游戏玩家数据也记录 3.在写代码时候不要总想着先实现逻辑再来优化结构,因为一个小任务的代码量不一定少,而且任务排的很紧,如果不从一开始就保持良好的结构自己看起来简直

vue 组件传值踩坑日记 1

今天在用平时很少用到的传值方式,是V2.4以后新加入属性$attrs $listener 以及inheritAttrs. 总结:这样形式的代码适合套娃模式的组件传递,却不适合兄弟组件的传值,那样的传值方式,需要创建一个事件总线,说白了就是新new一个空的vue,详见,我的第二篇日志<vue 组件传值踩坑日记 2> 废话不多说,直接上代码,大家可以边看注释边测试一下效果吧 <!DOCTYPE html> <html lang="en"> <hea

AI相关 TensorFlow -卷积神经网络 踩坑日记之一

上次写完粗浅的BP算法 介绍 本来应该继续把 卷积神经网络算法写一下的 但是最近一直在踩 TensorFlow的坑.所以就先跳过算法介绍直接来应用场景,原谅我吧. TensorFlow 介绍 TF是google开源出来的人工智能库,由python语言写的 官网地址:http://www.tensorflow.org/   请用科学上网访问 中文地址:http://www.tensorfly.cn/ 当然还有其他AI库,不过大多数都是由python 写的 .net 的AI库叫 Accord.net

cocos2dx 3.3rc0 踩坑日记(一)------ 弱联网 Curl

这两天看了视频学习了下弱联网技术,用的是Curl,具体使用方法我就多说了,可以参考官方样例和下面的文章,解释的很清楚. [Curl (libcurl) 开发 之一]Cocos2dx之libcurl(curl_easy)的编程教程(帮助手册)! CURL使用2 我要说的我又踩到一个坑...为什么是又呢...天生就是来踩坑的... 先说下使用之前需要加入curl.h的路径$(EngineRoot)external\curl\include\win32和链接库libcurl_imp.lib 如图所示:

quick-cocos2d-x 踩坑日记(一)------ NodeEx 与 shortcodes

今天在模仿一个demo,想自己去完善一些功能,自己写的时候就遇见了一个坑...先看代码: local label = cc.ui.UILabel.new({     UILabelType = 1,     text = "Max Score 10",     font = "fonts/font-issue1343.fnt",     x = boardSize.width / 2,     y = boardSize.height * 0.4,     }):a

cocos creator踩坑日记(持续更新中...)

踩坑一 问题:项目在构建成Web Mobile后运行在浏览器和微信中,点击页面任何地方都会导致自动全屏 解决:在构建之后的main.js中,去掉 cc.view.enableAutoFullScreen(true) 踩坑二 问题:精灵使用move to后路径上会留下一些线条 原因:脏矩形出问题了 解决: Canvas模式下才有脏矩形,使用这个方法之前要判断 if (cc._renderType === cc.game.RENDER_TYPE_CANVAS) { cc.renderer.enabl