大家好啊,我是董董灿。
本项目代码地址:gitee.com/iwaihou/res…
前天,我完全手写的算法,并手搭的神经网络,终于成功的识别出一张图片。
点击链接查看出猫现场:我出猫了,第一阶段完成!
成功地识别出来猫,意味着我搭建的整个流程跑通了。
这个流程主要包括了以下几个步骤:
虽然流程通了,但是识别一张图片要耗时 40 分钟!这推理速度,简直就是龟速。
忍不了,于是我优化了一波,识别一张图片的耗时直接从40分钟降到1分多钟。
接着我从百度图片中下载了 12 张动物图片 — 组成十二生肖。
输入给了我手写的神经网络,希望它能正确的识别出来,顺便也测试一下网络的鲁棒性。
下面是十二生肖图片的识别结果,至于怎么优化的,在文章最后会有介绍。
子鼠,识别结果为 mink — 水貂,识别错误,扣一分。
不过这个老鼠是不是有那么点像水貂?
丑牛,识别为 ox - 公牛,识别正确!加一分。 而且还是公牛,是根据上翘的尾巴做的区分吗?
寅虎,识别为 tiger - 老虎,识别正确!加一分。
这萌萌的老虎特征这么明显,要是识别错,那可以下班了。
卯兔,识别为 hare - 野兔,识别正确!加一分。
这站立的姿势,警觉地竖起的耳朵,野兔无疑了。
辰龙,识别成 harp - 竖琴,识别错误,不减分。
神经网络识别不出来龙,真的不怪神经网络,因为它的类比分类里就没有中国龙这一类。
不过识别成竖琴的话,看这弯曲的身形,还确实是有点神似。
巳蛇,识别为 garter snake - 袜带蛇,识别正确!加一分。 虽然我不知道什么事袜带蛇,但它说是,就是了。
午马,识别成 Mexican hairless - 墨西哥无毛犬,识别错误,减一分。 这个不应该的。
是不是因为这匹马身上太光滑,没有马儿们标志性的鬃毛么? 但是那飘逸的尾巴,也能说明问题啊。
未羊,识别成 ram - 公羊,算是识别正确吧。
我感觉识别出是绵羊更好一些。
申猴,识别出 macaque - 猕猴,识别正确,加一分。
看这身形和毛发,这么像猕猴桃,是猕猴了!
酉鸡,识别出 cock - 公鸡,识别正确,加一分。这个是送分题。
戌狗,识别出 Samoyed - 萨摩耶,识别正确,加一分。
这一身雪白的气质,小萨独有。
亥猪,识别出 hog - 猪,识别正确,加一分。
二师兄小时候,还是很可爱的。
优化完神经网络之后,识别这 12 张图片,总共花了十来分钟。
十二生肖,共 12 种动物类别,剔除“龙”这一项,因为模型分类中没有,其他11个分类,有两个识别错误,分别是老鼠识别成了水貂,骏马识别成了墨西哥无毛犬。
整体识别成功率 81%,还算不错。
下面说一下我是如何将这个网络推理一张图片的耗时,从 40 分钟一张,优化到 1 分钟一张的。
在最开始的版本中,整个推理过程,消耗的 90% 的时间集中在卷积运算中。
尤其是卷积运算中的乘累加部分。
在第一版手写卷积算法时,我为了完全展示卷积的运算逻辑,采用了最原始的多层循环,也就造成了现在的龟速卷积从零手写Resnet50实战—手写龟速卷积。
这种多重循环的写法,时间复杂度O(N^6),简直是没法忍受的。
于是,我针对卷积的乘累加运算,做了一个简单优化。
优化方法也很简单:将最内层的循环乘累加替换成向量内积。
卷积的这种优化方法,在编译器或者指令优化场合很常见:尽可能用向量指令代替循环标量运算。
基本原理就是:原来一个时钟周期只可以计算一次循环的一个标量,而现在一个时钟周期可以计算一个向量。
在 python 的应用代码中,也可以这么做,利用 numpy 提供的 vdot 函数,直接对两个数组做向量内积。 然后加到一个数值上完成累加。
基本就下面一条语句搞定。
acc += np.vdot(img[hi_index][wi_index], weight[co_][kh_][kw_])
就这一点改动,整个网络的推理性能,便从原来的 40 分钟,直接降到了 1 分钟。
阅读量:483
点赞量:0
收藏量:0