深度学习与App的魔幻结合

This post have got access from the original author Avihay Assouline to translate into Chinese. If you are interest in this article and want to repost it, you should add the refer link to this article in your repost.

这篇文章已从英文原作者Avihay Assouline那里得到翻译授权,如果你对本文感兴趣而且想转发,你应该在转发文章里加上本文的链接。

英文原文链接

深度学习与App的魔幻结合

打造你自己的自动驾驶汽车的第一步,是教会你的App从18000张图片中识别交通灯

机器学习是发展最快和最令人兴奋的领域之一,而其中最有代表性的是深度学习。自从我回到大学,我一直专注于这个领域。然而,在2009年的时候,软硬件和数据并不能达到实现深度学习的要求。但是,自从那以后,这些都不再是问题。

在这个简短的入门指南中,我将会通过深度学习的一些基本步骤,示范一下如何自己入门深度学习。我们将开发一款使用现场相机数据来识别交通灯的app。

在我们开始学习之前,我想说明一下一些事情。这个入门教程会跳过一些概念和难点,以便于降低入门门槛和尽快实现真实测试。另外,我们将只使用深度学习中的图片分类,以使整个入门过程变得更加直接和简单。

Youtube视频1

简介

在这里我假设你对深度学习有一定了解。你可能见过一些使用了深度学习的产品,比如Facebook的脸部识别,Apple的Siri,Mobileye的车辆碰撞识别等等。然而,随着最近深度学习框架的开源,不仅仅巨头们可以开发这些产品,创业公司现在也可以参与其中。例如, Clarifai 为你的应用提供了视觉能力, AIDoc 对医学放射工业发起了挑战。这些可以看出使用场景正在改变。

深度学习

什么是深度学习?什么是神经网络?我可以在这里讨论一下这些。但是,我更希望你看看这个由吴恩达讲解的深度学习的视频。虽然这段视频有点长,但是吴恩达提供了一些很好的例子和讲解。

如果你没有时间去看完这段视频,这里有一些里面说的的重点:在过去,为了让我们的电脑能够执行不同的任务,我们不得不为每个小问题单独编写算法。机器学习的强大之处在于,它能够使用同一种算法进行学习。它能够自己发现问题的关键和尝试自己去解决问题。在这个教程中你可以看到,除了提供数据给算法,我们几乎没有改变任何东西,然而它却能自己学习一个新的概念:交通灯。

吴恩达深度学习视频

训练过程

训练我们自己的深度学习神经网络,是实践学习算法的一步。我们提供一个图片分类的数据集给算法,希望它学习如何分类不属于训练数据集的新图片。

假设我们能够获得所需要的数据(这里称为“训练集”),用于训练我们的算法。然而,像人类一样,算法在训练期间是需要对其行为进行反馈的。为了实现对算法的行为反馈进行验证,我们需要为算法提供一个叫“验证集”的独立数据集。

在完成训练以后,我们将使用“训练集”中没有的数据作为输入数据,并看看它的表现如何。你猜对了,我们将需要第三个被称为“测试集”的数据集,这个数据集将会帮我们测试出算法的识别精确度。

我们总共需要3个不同的数据集:训练,验证,测试。

迁移学习

在实践中,我们不会经常从零开始训练我们的深度学习网络。因为现实中,很难找到足够大的数据集来做一些复杂任务,例如图片分类。

一般来说,我们会直接使用经过大量数据训练的网络作为初始的深度学习网络。在我们这个例子中,我们使用了一个经过一百万张图片训练的预训练神经网络,并用它来从20000张图片中学习新的分类。

这个小技巧确实有效,作为分类问题的一部分是共通的,例如识别边缘,颜色,甚至形状。

移动设备的机遇

如果你对现今的世界足够关注,你就能理解数据才是深度学习中最重要的东西。没有足够数量的数据,我们的算法将不能根据问题去学习并产生令人满意的结果。

这里有一个对于移动开发者来说非常巨大的机遇。全世界超过20亿设备不断提供各种不同类型的数据,这是非常有可能去开发一款应用去收集高质量数据,用于训练和学习。很多成功的创业公司都是围绕这个想法而建立的。

使用Caffe进行深度学习

Caffe

Caffe 是一个由Berkeley Visio和学习中心(BVLC)以及社区贡献者一同开发的深度学习框架。这个框架被世界范围内的计算机视觉研究者使用。尽管这是一个主要为计算机视觉开发的框架,然而他可以做其他很多深度学习的工作。

DIGITS

英伟达的 DIGITS 使用了web交互界面简化了深度学习的一般步骤,例如:

  • 数据集管理
  • 在多GPU系统中设计和训练神经网络
  • 通过先进的虚拟化进行实时性能管理

DIGITS 交互非常简单,开发者只需要专注于神经网络的设计和训练,不需要投入太多精力到编程和调试。

硬件要求

训练深度神经网络是一项计算密集型的工作。虽然你可以只通过只有CPU的机器来运行,但是事实上你更需要一个拥有GPU(例如英伟达的GTX系列,$500 - $700)的性能强大的机器来运行神经网络。

如果你没有这样一个性能强大的机器,你可以从亚马逊那里租一个。例如你可以从spotinst这里获取相关的服务,而且只需要 0.2 美元/小时。如果你需要更多的帮助,可以联系我。

开发一个识别交通灯的App

这里我们开始开发一个你之前在视频中看到的能识别交通灯的app。没什么需要担心的,所有的代码都在Github上开源。

为了继续这个教程,你应该先安装Caffe和DIGITS。在这个教程中,我们将直接使用DIGITS的web交互界面,因此不需要在学习其他任何语言或框架。

通过使用Caffe & DIGITS,我们在一个预训练的网络中实施迁移学习,并教会它红绿交通灯的新概念。然后,我们将把经过训练的网络应用到我们一个简单的移动应用中。

交通灯数据

很多创业公司和有开创精神的组织开源了一些非常有用的训练集。其中有一些设立了一些能赢取奖金的比赛,例如Udacity,Kaggle等。

为了让这个简单应用运行起来,我将会使用Nexar的 Challenge #1 数据集。这个数据集包括 18,659 个标有交通灯的图片。针对每张图片,有人手动标记了包含的是红灯还是绿灯或者没灯。在这个简单应用中,我们只关注图片是否存在交通灯,不关心交通灯的位置或其他。

训练

为了这个应用能正常使用,我们将从GoogLeNet做一次迁移学习。幸运的是,DIGITS的标准网络中已经包含了这个。我们只需下载预训练caffmodel文件并用DIGITS打开即可。

非常幸运,我有权限使用一个强大的机器,这个机器专门用来做VR体验,而且拥有一个运行在Ubuntu 14.04 平台上的GTX 1070 GPU。对于一些人来说,看着训练过程一定是非常无聊的,特别当你看到精度不断提高时。

第一步,建立训练/验证/测试 数据集。DIGITS 提供一个便捷的方法。DIGITS根据它们的标签和你将要检验和测试的数据划分百分比,将所有样本,划分到不同的目录。在我们的例子中,我们直接将DIGITS 一个目录划分为三个子目录:红,绿和背景。

第二步,建立模型。DIGITS 已经包含了我们想要的GoogLeNet神经网络。GoogLeNet已经通过训练能够将图片分成1000个不同的类别。在我们的例子中,为了让它能识别3种新的类型,我们需要对它进行一些改进。不要担心,这些只是一些简单的文本改动。

我们要做的改动是非常简单的: 查找/替换 所有出现loss1/classifier, loss2/classifier 和 loss3/classifier,并加上后缀‘/retrain’。例如 loss{x}/classifier 变成
loss{x}/classifier/retrain— 。 我们做这一步是为了让我们的神经网络重新学习,因为这新的部分与之前1000种分类都不同。

为了能运行迁移学习,我们将使用预学习网络信息(又称权重),而这只需让DIGITS 下载 bvlc_googlenet.caffemodel 这个预训练 caffe 模型即可。

值得庆贺,你现在已经做好了训练网络的准备了。

根据默认的训练设置, DIGITS 迁移学习能生成一个在验证集中精度达到 93.1% 的神经网络。难道这不令人兴奋吗?我们很难做到这一点:)

训练完成之后,我们可以通过DIGITS下载我们的模型,然后获取我们使用该模型开发移动应用的必要数据。

开发应用

幸运地,由于Aleph7noradaiko做了一些基础集成 ,我很容易的就可以将 Caffe 运行在iOS上。除了使用这些基础集成来作为我们的项目的开始,我们还要改进一下,以便它在相机的现场视频流中能正常运行。

这段代码非常简单,让我们来看一下 ViewController.mm 文件中最重要的部分:

    NSString *netDefinition = [NSBundle.mainBundle pathForResource:@"deploy"
                                                         ofType:@"prototxt"
                                                    inDirectory:@"model"];

    NSString *netWeights = [NSBundle.mainBundle pathForResource:@"model"
                                                           ofType:@"caffemodel"
                                                      inDirectory:@"model"];
    
    NSString *datasetMean = [NSBundle.mainBundle pathForResource:@"mean"
                                                          ofType:@"binaryproto"
                                                     inDirectory:@"model"];
    
    NSString *netLabels = [NSBundle.mainBundle pathForResource:@"labels"
                                                        ofType:@"txt"
                                                   inDirectory:@"model"];
    
    string net_definition = string([netDefinition UTF8String]);
    string net_weights = string([netWeights UTF8String]);
    string dataset_mean = string([datasetMean UTF8String]);
    string net_labels = string([netLabels UTF8String]);
    
    classifier = new Classifier(net_definition,
                                net_weights,
                                dataset_mean,
                                net_labels);

我们通过DIGITS下载的文件model.caffemodel, mean.binaryproto, labels.txt 和 deploy.prototxt ,创建一个新的分类器。

  cv::Mat src_img, bgra_img;
  UIImageToMat(image, src_img);
  
  cv::resize(src_img, src_img, cv::Size(224, 224));
  cv::cvtColor(src_img, bgra_img, CV_RGBA2BGR);
 
  vector<Prediction> result = classifier->Classify(bgra_img, 3);

我们需要输入各种尺寸的数据进行分类。为了做到这一点,我们需要把我们的UIImage对象转换为OpenCV的矩阵(第2行),改变其大小以适应我们的网络,然后把颜色序列从 RGBA 转换成 BGR。因为Caffe需要这样的输入格式,所以我们需要先做这个转换。另外,你可能注意到,当进行分类时,这里有一个魔术数字‘3’。这表示的是你数据集分类的数量 - 在我们这个例子中,表示:绿,红,背景。

    for (vector<Prediction>::iterator it = result.begin(); it != result.end(); ++it) {
        NSString* mylabel = [NSString stringWithUTF8String:it->first.c_str()];
        NSNumber* probability = [NSNumber numberWithFloat:it->second];
        
        if (it == result.begin() && probability.floatValue > 0.6) {
            _lightImage.image = [UIImage imageNamed:[labelToImage valueForKey:mylabel]];
        }
    }

接下来,我们只需重复识别和捕获最高确定性的识别。如果它通过了一些阀值(当前设定为 60% 确定性)我们将用正确的交通灯图片更新我们的UI。

准备去让你的数据跑起来吗?非常好!

你必须做的的所有事情,只是改变了一开始训练的样本和改变分类的数目。其他所有的东西都是不变的。

这是关于这个app的另外一段短视频:

Youtube视频2

我能在我的线上App上用它吗?

当然,最好不。至少我现在不推荐。这个有点例子太过于笨拙以至于不适合直接使用。

你应该在你桌面之外使用这个项目,去体验和测试你的算法,这是一种不需要编码就能测试你的POC项目的好方法。你也可以用它来开发快速应用,去收集你在训练过程中输入的新数据。

一旦你掌握了这个训练过程,你接下来将很容易的过渡到学习TensorFlow,或其他需要对深度学习有更深入理解的框架,例如 BrainCore

如果你喜欢这篇文章,并且想继续关注,请点击 ♥ (喜欢) - 这将是我继续下一篇的动力!

你也可以在Twitter中关注英文原文作者。

如果你喜欢这篇译文,记得在简书中给我点赞并关注我哦

本文Github地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容