“大数据智能-Lucida使用”版本间的差异
(→LSTM) |
|||
(3位用户的11个中间修订版本未显示) | |||
第10行: | 第10行: | ||
所有这些智能个人助理,包括十几年前十分火热的掌上电脑(PDA),都包含一个共同的功能:对日历的操作,即:能够查看并安排日程。与曾经的 PDA 不同的是,智能个人助理能够利用机器学习,智能地理解人类以自然语言给出的操作日历的指令,如“把下午3点的会议改到4:30”、“下一个会议在哪里开?”、“我这个周五的日历上有什么安排?”等。这一功能极大地方便了用户,尤其是商业用户的使用。 | 所有这些智能个人助理,包括十几年前十分火热的掌上电脑(PDA),都包含一个共同的功能:对日历的操作,即:能够查看并安排日程。与曾经的 PDA 不同的是,智能个人助理能够利用机器学习,智能地理解人类以自然语言给出的操作日历的指令,如“把下午3点的会议改到4:30”、“下一个会议在哪里开?”、“我这个周五的日历上有什么安排?”等。这一功能极大地方便了用户,尤其是商业用户的使用。 | ||
− | [[文件:Siri calendar.PNG|无框|Siri 的 Calendar Events Retrieval 功能截图]] | + | [[文件:Siri calendar.PNG|256px|无框|Siri 的 Calendar Events Retrieval 功能截图]] |
=== Framework === | === Framework === | ||
第20行: | 第20行: | ||
==图像匹配IMM== | ==图像匹配IMM== | ||
+ | |||
===概述=== | ===概述=== | ||
所谓图像匹配,就是给定一张图片,并在一个图片集中寻找与这张图片最相似的图片。 | 所谓图像匹配,就是给定一张图片,并在一个图片集中寻找与这张图片最相似的图片。 | ||
第28行: | 第29行: | ||
进入Learn页面,加入一张吉娃娃的图片。 | 进入Learn页面,加入一张吉娃娃的图片。 | ||
− | [[文件:Add chihuahua1.png| | + | [[文件:Add chihuahua1.png|500px]] |
加入成功。 | 加入成功。 | ||
− | [[文件:Add chihuahua2.png| | + | [[文件:Add chihuahua2.png|500px]] |
再加入一张蓝莓松饼的图片。 | 再加入一张蓝莓松饼的图片。 | ||
− | [[文件:Add muffin1.png| | + | [[文件:Add muffin1.png|500px]] |
加入成功。 | 加入成功。 | ||
− | [[文件:Add muffin2.png| | + | [[文件:Add muffin2.png|500px]] |
接下来尝试匹配一张吉娃娃的图片。 | 接下来尝试匹配一张吉娃娃的图片。 | ||
− | [[文件:Chihuahua2.png| | + | [[文件:Chihuahua2.png|150px]] |
进入Infer页面,上传这张图片,再单击ask按钮。 | 进入Infer页面,上传这张图片,再单击ask按钮。 | ||
− | [[文件:Ask1.png| | + | [[文件:Ask1.png|500px]] |
遗憾的是由于训练数据过少,Lucida认为这张吉娃娃与蓝莓松饼的图片更加接近。 | 遗憾的是由于训练数据过少,Lucida认为这张吉娃娃与蓝莓松饼的图片更加接近。 | ||
第82行: | 第83行: | ||
==图像分类IMC== | ==图像分类IMC== | ||
− | === | + | ===概览及使用方式=== |
− | IMC | + | '''IMC'''(image classification)是Lucida智能助手中的一项功能,用于对用户上传的图片内容进行分类。 |
+ | |||
+ | 使用前,需确保后台数据库中至少已有一张图片知识。用户可以在“'''Learn'''”页面上传图片,并对图片注上标签(Label)信息,即图片的类别。 | ||
+ | |||
+ | 在“'''Infer'''”页面中,用户可以上传照片,并通过语音或者文字输入的方式询问(例如:“这是什么东西”或“这是什么动物”),系统将在后台数据库中进行匹配,返回可能性最大的图片类别答案。 | ||
===代码解读与实现=== | ===代码解读与实现=== | ||
− | + | IMC功能主要通过 '''IMCHandler''' 和 '''IMCServer''' 两部分组成。 | |
− | + | ====IMCHandler==== | |
− | + | IMCHandler负责异步处理客户端发来的请求信息和数据,并对输入图片进行预处理以及将其放入神经网络模型中进行识别。 | |
− | Caffe | + | IMCHandler的实现主要运用了 '''Folly Futures''' 和 '''Caffe''' 两大框架。 |
− | + | Folly Futures,是一种由Facebook为C++11带来的用于同步并发操作的构件。它能够被视为对异步操作结果的只读代理对象。这个对象的初始值为未知。如果Future的客户端试图在操作完成前读取它的值,可能会被阻塞。所以Future通常和一个Promise关联,Promise提供对Future的值进行写访问。异步操作能够立即返回只读的Future,而不堵塞。当异步操作完成时,用户可通过setValue()方法设置它的结果。 | |
+ | |||
+ | 在IMCHandler中,Folly Futures主要用于判断create、learn或infer三项Lucida基本操作指令是否已经执行完成:若执行尚未完成,系统日志将自动报错。 | ||
+ | |||
+ | Caffe,是一个清晰,可读性高,快速的深度学习框架。它具有上手快,速度快,模块化,开放性,社区好等优点。Caffe是纯粹的C++/CUDA架构,支持命令行、Python和MATLAB接口,可以在CPU和GPU之间直接无缝切换。 | ||
+ | |||
+ | 在IMCHandler中,首先将输入图片进行预处理,将图形大小重新设置为 227 x 227 的标准大小,随后输入到一个24层的神经网络模型中进行识别计算,最终返回与可能性最大的图片类别。 | ||
+ | |||
+ | ====IMCServer==== | ||
+ | |||
+ | IMCServer默认在端口8085上开启IMC服务器,并使用4个线程进行后续操作处理。 | ||
+ | |||
+ | 通过Facebook Thrift框架进行网络间的数据异步交换:从网页客户端获得用户输入的图片及问题,交给IMCHandler进行识别处理;待IMCHandler返回答案后,再将答案从服务器发送至网页端,完成本次提问操作。 | ||
===小结=== | ===小结=== | ||
− | + | '''IMC''' 主要运用了Caffe深度学习框架以及健壮且强大的Folly Futures库,对图像进行处理、识别,最终有效地实现了图像分类。 | |
+ | |||
+ | 与直接调用OpenCV库中的算法实现的IMM图像匹配功能相比,IMC的主要区别在于利用了神经网络模型进行学习和预测,后期更加易于扩展,可以不断改进后台所使用的神经网络模型。 | ||
==问答QA== | ==问答QA== | ||
− | + | ===Lucida demo QA使用介绍=== | |
(1)用户自定义信息类 | (1)用户自定义信息类 | ||
*在“学习”栏增加至少一段信息。例如“约翰25岁” | *在“学习”栏增加至少一段信息。例如“约翰25岁” | ||
*转到“推断“栏,询问一个与你所添加信息相关的的问题。例如“约翰多少岁?” | *转到“推断“栏,询问一个与你所添加信息相关的的问题。例如“约翰多少岁?” | ||
− | + | ||
− | 文件:Infer.png | + | [[文件:Infer.png]] |
− | + | ||
(2)网页信息类 | (2)网页信息类 | ||
*在“学习“栏加入一条wiki百科的网址。例如“https://en.wikipedia.org/wiki/University_of_Michigan” | *在“学习“栏加入一条wiki百科的网址。例如“https://en.wikipedia.org/wiki/University_of_Michigan” | ||
*转到“推断“栏,询问与添加百科信息有关的问题。例如“密歇根大学位于哪里?” | *转到“推断“栏,询问与添加百科信息有关的问题。例如“密歇根大学位于哪里?” | ||
− | + | ||
− | 文件:Infer2.png | + | [[文件:Infer2.png]] |
− | + | ||
(3)数据库信息类 | (3)数据库信息类 | ||
例: | 例: | ||
− | 谁是中国的最后一位皇帝? | + | *谁是中国的最后一位皇帝? |
− | 谁发现了南极点? | + | *谁发现了南极点? |
− | 谁发明了电话? | + | *谁发明了电话? |
− | 哪位希腊数学发发展了几何学? | + | *哪位希腊数学发发展了几何学? |
− | 慕尼黑协定在何时签订? | + | *慕尼黑协定在何时签订? |
− | 泰森在何时夺冠 | + | *泰森在何时夺冠 |
− | 尼罗河位于什么地方? | + | *尼罗河位于什么地方? |
− | + | ===依赖项介绍=== | |
(1)OpenEphyra:OpenEphyra 是一个使用 Java 开发的模块化、可扩展的开源问答系统。它从网络和其他资源检索自然语言问题的答案。开发者能基于这项项目开发新的问答系统,而不用关心端到端系统。 | (1)OpenEphyra:OpenEphyra 是一个使用 Java 开发的模块化、可扩展的开源问答系统。它从网络和其他资源检索自然语言问题的答案。开发者能基于这项项目开发新的问答系统,而不用关心端到端系统。 | ||
− | + | ||
− | 文件:Oe.png | + | [[文件:Oe.png]] |
− | + | ||
(2)Indri:提供目前最先进的文本搜索,支持多种结构的询问语言。可在一台机器上实现对五千万个文档的文本收集;分配搜索后,量级能再增加一倍。支持linux,solaris,windows和mac os等多个系统。 | (2)Indri:提供目前最先进的文本搜索,支持多种结构的询问语言。可在一台机器上实现对五千万个文档的文本收集;分配搜索后,量级能再增加一倍。支持linux,solaris,windows和mac os等多个系统。 | ||
第142行: | 第160行: | ||
(4)Apache Thrift:提供标量化跨语言开发服务。由一个软件栈和代码生成引擎组成,提供在C++, Java, Python, PHP, Ruby等多种语言间无缝高效转换的服务。 | (4)Apache Thrift:提供标量化跨语言开发服务。由一个软件栈和代码生成引擎组成,提供在C++, Java, Python, PHP, Ruby等多种语言间无缝高效转换的服务。 | ||
− | + | ===代码结构=== | |
(1)文件结构 | (1)文件结构 | ||
*main:主函数目录 | *main:主函数目录 | ||
**QADaemon.java:主函数,启动QA服务,监听客户端请求 | **QADaemon.java:主函数,启动QA服务,监听客户端请求 | ||
− | *handler:处理Lucida服务的代码目录 | + | *handler:处理Lucida服务的代码目录 |
**KnowledgeBase.java:知识库类(KnowledgeBase) | **KnowledgeBase.java:知识库类(KnowledgeBase) | ||
**QAServiceHandler.java:远程调用框架Thrift文件中的QA服务接口(QAServiceHandler) | **QAServiceHandler.java:远程调用框架Thrift文件中的QA服务接口(QAServiceHandler) | ||
第192行: | 第210行: | ||
以上就是该项目程序的主要部分。 | 以上就是该项目程序的主要部分。 | ||
− | + | ||
===原理分析=== | ===原理分析=== | ||
第241行: | 第259行: | ||
===功能实现示例=== | ===功能实现示例=== | ||
+ | |||
*训练集(From Bing Picture) | *训练集(From Bing Picture) | ||
− | |||
− | |||
[[文件:Face-training.jpg|1000px]] | [[文件:Face-training.jpg|1000px]] | ||
+ | |||
*测试集(From Bing Picture) | *测试集(From Bing Picture) | ||
+ | |||
[[文件:9-Hillary.jpg|300px]] | [[文件:9-Hillary.jpg|300px]] | ||
− | |||
*效果 | *效果 | ||
+ | |||
[[文件:FACE-input.PNG|500px]] | [[文件:FACE-input.PNG|500px]] | ||
→ | → | ||
第375行: | 第394行: | ||
} | } | ||
[[File:FACE-struct.png]] | [[File:FACE-struct.png]] | ||
+ | |||
====FACE服务器搭建==== | ====FACE服务器搭建==== | ||
FACEServer.cpp | FACEServer.cpp | ||
第402行: | 第422行: | ||
*人脸特征点检测 | *人脸特征点检测 | ||
*人脸的对齐 | *人脸的对齐 | ||
− | + | 采用卷积神经网络(CNN)方法,通过深度卷积网络来学习高级的过完全特征(有监督), | |
− | + | CNN的最后一层激活值作为输出,并且采用CNN最后一层的激活值输出作为features, | |
+ | 不同的人脸区域放入CNN中提取特征,形成了互补、过完全的特征表示(form complementary and over-complete representations)。 | ||
*具体细节 | *具体细节 | ||
采用多尺度,多人脸区域,训练多个CNN网络,最后得出一张人脸图像的多维度特征。 | 采用多尺度,多人脸区域,训练多个CNN网络,最后得出一张人脸图像的多维度特征。 | ||
CNN的结构如下: | CNN的结构如下: | ||
− | [[ | + | [[文件:FACE-CNN.png|700px]] |
*说明: | *说明: | ||
Face patches 是进过对齐过后的的人脸块,也就是说已左(右)眼为中心的人脸区域块,嘴角为中心的人脸区域块等等,这样就有多个不同的输入块输入到CNN中。 | Face patches 是进过对齐过后的的人脸块,也就是说已左(右)眼为中心的人脸区域块,嘴角为中心的人脸区域块等等,这样就有多个不同的输入块输入到CNN中。 | ||
第416行: | 第437行: | ||
*特点: | *特点: | ||
在训练CNN中,训练数据的类别越多,其性能越好,但是会在训练模型中出现问题,也就是太慢。CNN的输出是特征,而不是输出类别。 | 在训练CNN中,训练数据的类别越多,其性能越好,但是会在训练模型中出现问题,也就是太慢。CNN的输出是特征,而不是输出类别。 | ||
− | 分类采用Joint Bayesian | + | 分类采用Joint Bayesian 来进行人脸的verification;也采用了神经网络来比较,但是联合贝叶斯的效果比较好。 |
===小结=== | ===小结=== | ||
第422行: | 第443行: | ||
==语音识别ASR== | ==语音识别ASR== | ||
+ | |||
+ | 语音识别Automatic Speech Recognition (ASR)功能研究: | ||
+ | |||
+ | Lucida语音识别使用的是一个开源的C++语音识别工具集"Kaldi"来完成的。Kaldi的模型是使用LSTM的循环卷积网络(RNN)来完成深度学习开发的。下面我们来介绍LSTM和Kaldi的相关内容。 | ||
+ | |||
+ | ===LSTM=== | ||
+ | Kaldi是一个基于C++的语音识别工具包,实现了各种经典的语音信号特征提取及分析算法及最新的循环神经网络结构(以LSTM为主)。 | ||
+ | |||
+ | 语音识别引擎的基本系统框架如下图所示,深度学习模型中包含多层LSTM网络。 | ||
+ | |||
+ | [[文件:LSTM12.png|600px]] | ||
+ | |||
+ | LSTM通过巧妙的结构设计有效解决了RNN的上述问题,其核心在于细胞状态(Cell)的引入(如下图):细胞状态对应A中最上方的链式结构,负责保存长期信息。 | ||
+ | |||
+ | [[文件:LSTM13.png|600px]] | ||
+ | |||
+ | 三个σ表示sigmoid函数;由于sigmoid函数的输出范围为[0,1],其输出向量u和其它向量v点乘的结果等效于v中的每个元素受到u中对应元素的门限作用,所以这三个sigmoid的输出向量在LSTM中被定义为门限,从左至右依次为:忘记门,输入门,输出门。 | ||
+ | |||
+ | 首先,忘记门作用于Cell,决定哪些长期信息继续保留、哪些被舍弃;前一时刻的隐含层状态h_(t-1)及当前时刻输入x_t共同决定当前时刻的写入信息(图中tanh矩形框部分),该信息经过输入门的作用后加入到Cell中,从而实现细胞状态的更新;更新后的细胞状态经过输出门的作用后输出当前时刻的隐含层状态h_t,从而完成当前时刻的前向传播流程。 | ||
+ | |||
+ | 三个门限的输入值可以取决于前一时刻的隐含层状态h_(t-1)、当前时刻的输入x_t、偏置、细胞状态(peephole)等多种因素,上述因素的不同组合可以产生LSTM的各种变体。每一个依赖项的线性变换矩阵均可以通过反向传播算法进行训练。 | ||
+ | |||
+ | ===Kaldi语音识别架构及其LSTM实现=== | ||
+ | |||
+ | Kaldi是一个基于C++的语音识别工具包,实现了各种经典的语音信号特征提取及分析算法及最新的循环神经网络结构(以LSTM为主)。 | ||
+ | 语音识别引擎的基本系统框架如下图所示,深度学习模型中包含多层LSTM网络。 | ||
+ | |||
+ | [[文件:14.png|600px]] | ||
+ | |||
+ | Kaldi中的LSTM模型结构及各个节点的计算公式如下图所示;整体结构和前文介绍的LSTM基本网络结构类似,主要区别在于两点:一是门限取决于当前时刻输入、前一时刻的输出及元胞状态这三项;二是为了降低LSTM输出数据维度、减少运算量,在输出门的输出状态后增加了一个projection线性变换层,用于实现输出数据降维。 | ||
+ | |||
+ | [[文件:LSTM15.png|600px]] | ||
+ | |||
+ | 对于n帧的语音特征输入,单层LSTM的处理流程伪代码如下图所示: | ||
+ | |||
+ | [[文件:LSTM16.png|600px]] | ||
+ | |||
+ | ===Lucida中的实现方式=== | ||
+ | 我们发现,在Lucida中,ASR的任务完全交给了Kaldi GStreamer server来实现。 | ||
+ | |||
+ | ====GStreamer==== | ||
+ | GStreamer 是一个开源的多媒体框架库。利用它,可以构建一系列的媒体处理模块,包括从简单的 ogg 播放功能到复杂的音频(混音)和视频(非线性编辑)的处理。 | ||
+ | |||
+ | 应用程序可以透明的利用解码和过滤技术。开发者可以使用简洁通用的接口来编写一个简单的插件来添加新的解码器或滤镜。 | ||
+ | |||
+ | 在这里,Kaldi的语音识别模型被视为GStreamer的一个插件。 | ||
+ | |||
+ | ====Master Server==== | ||
+ | 主服务器负责接收客户端的识别请求,为每一个请求分配一个Worker,Worker负责学习和识别的过程。 | ||
+ | |||
+ | ====Client==== | ||
+ | 用户可以调用给定的client程序,以指定的速率发送音频文件到服务器的监听端口,正常情况下会返回识别结果。 | ||
+ | |||
+ | 也可以使用提供的简单的HTTP API来发送和接收音频文件和识别结果。 |
2019年3月15日 (五) 15:07的最后版本
日历服务CA
Introduction
随着 2012 年 iPhone 4s 和它附带的个人助理 Siri 的发布,智能个人助理成为各大互联网公司研发的热点。
近年来,紧随 Siri,Google 发布了个人助理 Google Now,Amazon 发布了具有个人助理功能的智能硬件 Echo,Microsoft 也将它出品的游戏 Halo 中士官长的助理 Cortana 开发成了可以用在 Windows 10 和 Windows 10 Mobile 操作系统上的真正的个人助理。
伴随着最近的大数据、人工智能和创新创业热潮,国内许多厂家开发的产品也以个人助理为主要卖点,如创新工场投资的创业公司出门问问的主打产品就是具有自主知识产权的中文语音交互智能手表系统 Ticwear 和搭载这一操作系统的智能手表。Clarity 实验室开发的 Lucida AI 就是一个开源的智能个人助理(Intelligent Personal Assistants, IPA)框架。
所有这些智能个人助理,包括十几年前十分火热的掌上电脑(PDA),都包含一个共同的功能:对日历的操作,即:能够查看并安排日程。与曾经的 PDA 不同的是,智能个人助理能够利用机器学习,智能地理解人类以自然语言给出的操作日历的指令,如“把下午3点的会议改到4:30”、“下一个会议在哪里开?”、“我这个周五的日历上有什么安排?”等。这一功能极大地方便了用户,尤其是商业用户的使用。
Framework
从总体原理来看,Calendar Events Retrieval 这一功能的实现主要由两部分组成:负责对人类友好型的输入的理解和处理的后端和负责对日历进行操作的前端。
具体来说,后端负责利用神经网络等手段,将输入的语音、文字或图片转换成计算机可理解的数据,如转换为时间区间。例如,后端可能会将文本输入“What was on my Google calendar last year?”转换成"2015-10-22T00:00:00 2015-10-22T23:59:59"(基于当天日期)。而前端接收后端发来的机器可理解的数据,与日历服务(如 Google Calendar, Microsoft Exchange 或 CalDav)交互。
当然,还需要考虑的一个问题是后端与前端的交互。当然,同前后端的实现相比,这一问题较为无关紧要。前后端通信可以通过REST API, Apache Thrift 等协议完成。
图像匹配IMM
概述
所谓图像匹配,就是给定一张图片,并在一个图片集中寻找与这张图片最相似的图片。
在目前主要用于图片检索服务,在Baidu和Google上都有这样的功能,可以找同一张图片的多种不同分辨率的版本,或者找一张图片的相关图片,效果很好。
使用方法演示
进入Learn页面,加入一张吉娃娃的图片。
加入成功。
再加入一张蓝莓松饼的图片。
加入成功。
接下来尝试匹配一张吉娃娃的图片。
进入Infer页面,上传这张图片,再单击ask按钮。
遗憾的是由于训练数据过少,Lucida认为这张吉娃娃与蓝莓松饼的图片更加接近。
依赖项介绍
OpenCV
OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
Facebook Thrift
Thrift最初由Facebook研发,主要用于各个服务之间的RPC通信,支持跨语言,常用的语言比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#,Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。Thrift是一个典型的CS(客户端/服务端)结构,客户端和服务端可以使用不同的语言开发。
MangoDB
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
代码实现简介
Lucida中的Image Matching主要是采用下面的实现方式:
(1)对于一张图片,调用OpenCV中的SurfFeatureDetector提取这张图片的特征点,得到一个描述矩阵。
(2)将这个矩阵利用GridFS存储在MangoDB数据库中。
(3)利用深度学习模型进行训练。
(4)得到最为匹配的一张图片。
中间的数据通信过程均基于Facebook Thrift。
图像分类IMC
概览及使用方式
IMC(image classification)是Lucida智能助手中的一项功能,用于对用户上传的图片内容进行分类。
使用前,需确保后台数据库中至少已有一张图片知识。用户可以在“Learn”页面上传图片,并对图片注上标签(Label)信息,即图片的类别。
在“Infer”页面中,用户可以上传照片,并通过语音或者文字输入的方式询问(例如:“这是什么东西”或“这是什么动物”),系统将在后台数据库中进行匹配,返回可能性最大的图片类别答案。
代码解读与实现
IMC功能主要通过 IMCHandler 和 IMCServer 两部分组成。
IMCHandler
IMCHandler负责异步处理客户端发来的请求信息和数据,并对输入图片进行预处理以及将其放入神经网络模型中进行识别。
IMCHandler的实现主要运用了 Folly Futures 和 Caffe 两大框架。
Folly Futures,是一种由Facebook为C++11带来的用于同步并发操作的构件。它能够被视为对异步操作结果的只读代理对象。这个对象的初始值为未知。如果Future的客户端试图在操作完成前读取它的值,可能会被阻塞。所以Future通常和一个Promise关联,Promise提供对Future的值进行写访问。异步操作能够立即返回只读的Future,而不堵塞。当异步操作完成时,用户可通过setValue()方法设置它的结果。
在IMCHandler中,Folly Futures主要用于判断create、learn或infer三项Lucida基本操作指令是否已经执行完成:若执行尚未完成,系统日志将自动报错。
Caffe,是一个清晰,可读性高,快速的深度学习框架。它具有上手快,速度快,模块化,开放性,社区好等优点。Caffe是纯粹的C++/CUDA架构,支持命令行、Python和MATLAB接口,可以在CPU和GPU之间直接无缝切换。
在IMCHandler中,首先将输入图片进行预处理,将图形大小重新设置为 227 x 227 的标准大小,随后输入到一个24层的神经网络模型中进行识别计算,最终返回与可能性最大的图片类别。
IMCServer
IMCServer默认在端口8085上开启IMC服务器,并使用4个线程进行后续操作处理。
通过Facebook Thrift框架进行网络间的数据异步交换:从网页客户端获得用户输入的图片及问题,交给IMCHandler进行识别处理;待IMCHandler返回答案后,再将答案从服务器发送至网页端,完成本次提问操作。
小结
IMC 主要运用了Caffe深度学习框架以及健壮且强大的Folly Futures库,对图像进行处理、识别,最终有效地实现了图像分类。
与直接调用OpenCV库中的算法实现的IMM图像匹配功能相比,IMC的主要区别在于利用了神经网络模型进行学习和预测,后期更加易于扩展,可以不断改进后台所使用的神经网络模型。
问答QA
Lucida demo QA使用介绍
(1)用户自定义信息类
- 在“学习”栏增加至少一段信息。例如“约翰25岁”
- 转到“推断“栏,询问一个与你所添加信息相关的的问题。例如“约翰多少岁?”
(2)网页信息类
- 在“学习“栏加入一条wiki百科的网址。例如“https://en.wikipedia.org/wiki/University_of_Michigan”
- 转到“推断“栏,询问与添加百科信息有关的问题。例如“密歇根大学位于哪里?”
(3)数据库信息类
例:
- 谁是中国的最后一位皇帝?
- 谁发现了南极点?
- 谁发明了电话?
- 哪位希腊数学发发展了几何学?
- 慕尼黑协定在何时签订?
- 泰森在何时夺冠
- 尼罗河位于什么地方?
依赖项介绍
(1)OpenEphyra:OpenEphyra 是一个使用 Java 开发的模块化、可扩展的开源问答系统。它从网络和其他资源检索自然语言问题的答案。开发者能基于这项项目开发新的问答系统,而不用关心端到端系统。
(2)Indri:提供目前最先进的文本搜索,支持多种结构的询问语言。可在一台机器上实现对五千万个文档的文本收集;分配搜索后,量级能再增加一倍。支持linux,solaris,windows和mac os等多个系统。
(3)MongoDB:可以应用于各种规模的企业、各个行业以及各类应用程序的开源数据库。它为开发人员 提供了传统数据库的功能:二级索引,完整的查询系统以及严格一致性等等。
(4)Apache Thrift:提供标量化跨语言开发服务。由一个软件栈和代码生成引擎组成,提供在C++, Java, Python, PHP, Ruby等多种语言间无缝高效转换的服务。
代码结构
(1)文件结构
- main:主函数目录
- QADaemon.java:主函数,启动QA服务,监听客户端请求
- handler:处理Lucida服务的代码目录
- KnowledgeBase.java:知识库类(KnowledgeBase)
- QAServiceHandler.java:远程调用框架Thrift文件中的QA服务接口(QAServiceHandler)
(2)代码执行流程
- 初始化thrift对象
- 远程服务调用框架,响应客户请求
TTransport transport = new TSocket("localhost", port); TProtocol protocol = new TBinaryProtocol(new TFramedTransport(transport)); LucidaService.Client client = new LucidaService.Client(protocol);
- 与服务器通讯
transport.open();
- 创建新的QA服务并学习提问内容(依次执行"create","learn","answer")
- Indri用于知识检索
- OpenEphyra用于后台的问答模型处理
client.create(LUCID, create_spec); client.learn(LUCID, knowledge); String answer = client.infer(LUCID, query);
手写数字识别DIG
简介
手写数字识别DIG这个单元由我们第三组负责。
由于技术上对Lucida API调用规则以及thrift语法了解不深,我们组在工业云安装完成Lucida后对于这个项目并没能成功做出自己的前端,因此,我们主要是对Lucida 3000端口的页面和实现DIG的程序代码以及Lucida tutorial里面的内容的一些分析,并查阅了相关资料。
流程分析
首先,手写数字识别这个项目,可以通过给定一个只包含一个手写数字的jpeg格式照片,这一个项目可以识别出这个数字是0到9当中的哪一个。
然后,这一个项目的代码结构主要分为以下的几个部分:
0.压缩并存储。在这一步当中,程序通过对给定jpeg文件的输入进行分析,并通过将这个文件压缩到一个固定大小然后存储起来。
1.黑白二值化。就是通过对原有图片进行一定的修改,因为初始的神经网络只接受0和1的输入,使得数字部分和背景部分能更好的区分开来。在这一步当中,应该可以通过采取较优的黑白二值化的方法(比如说可以与周围一定数量的像素点进行比对)从而同时消除噪点,提高识别的精度。
2.对正图片中心,因为图片偏移会对神经网络得到正确结果产生较大影响,所以对正图片中心是必不可少的预处理过程。
3.把修改后的图片作为神经网络的输入。这一步,就是把经过上两步操作后得到的像素矩阵输入到神经网络当中,然后通过调用caffe(卷积神经网络框架)返回权值从而得到与各个数字的一个相关权值;
4.根据得到的相关权值,返回结果。
以上就是该项目程序的主要部分。
原理分析
我们可以注意到里面运用到了一个卷积神经网络框架模型。我们通过查阅资料得知,该模型,是通过前期的一些训练准备从而具有对相关图片的识别能力。
训练准备的步骤大概分为两步:
首先,是初始化网络及学习参数,如设置网络初始权矩阵、学习因子等。
然后,就是提供大量的手写的0~9的图片的并且采取监督模式学习,训练神经网络,不断修正,直到满足要求为止。
而训练神经网络这一步,分为前向传播过程和后向传播过程。
前向传播过程就是通过给定的训练模式的输入,计算网络的输出模型,并与期望模式进行比较,如果达到要求,则进行下一个训练模式;如果未达要求,则进行后向传播的过程。
(与我们的识别图像一步比较相似,只不过我们识别图像的时候是直接返回网络计算出来的输出模型)
后向传播过程则是可分为三个步骤:
1. 计算同一层单元的误差;
2. 修正权值和阈值;
3. 进行下一个训练模式。
上面的具体操作则是通过将原本的特征maps与一个可学习的卷积核进行卷积,并通过一个激活函数得到输出特征map。然后再利用计算出来的灵敏度map进行梯度下降方法对原本的特征maps进行修正。 那么,通过对足够多的训练模式去训练网络,我们就可以得到一个足够优的神经网络去解决手写数字识别问题。
应用方法
在一定量的数据集训练之后,该网络具有识别数字的能力之后,在真正应用时不必再次学习,只需要载入神经网络每个节点对应的权值即可。所以Lucida没有公开它训练的过程,而是直接提供的具有识别能力的训练好的网络的参数。
与传统方式对比
与传统数字模式识别算法的对比:传统数字模式识别算法基于对每个数字连通块、形状、线的弯曲情况的分析制造出一条条规则来判断图片归属,而神经网络不用再去分析每个数字的特点,而是预先准备一定量的数据集,就可以自己寻找特征。传统数字模式识别算法可能会因手写字体、连笔等差异对识别结果产生很大影响,而神经网络在大量数据训练后,能较好提取出区分这些数字的特征,对于字体等条件依赖不大、更接近人脑识别数字。
参考资料
1.《Notes on Convolutional Neural Networks》,Jake Bouvrie
2.《基于神经网络的图像识别方法》,彭淑敏,王军宁
3.《Deep Learning论文笔记之(四)CNN卷积神经网络推导和实现》,zouxy09
4. Caffee 神经网络框架 http://caffe.berkeleyvision.org
人脸识别FACE
功能实现示例
- 训练集(From Bing Picture)
- 测试集(From Bing Picture)
- 效果
代码解读与实现
FACE 主要有 FACEHandler 和 FACEServer 两部分代码组成,由CONGFIG进行配置。
CONFIG的结构
两个卷积层的卷积神经网络(CNN),C++实现
- 第一层:输入层
name: "face" input: "data" input_dim: 1 input_dim: 3 input_dim: 152 input_dim: 152
- 第二层:卷积层
layers { name: "conv1" type: CONVOLUTION bottom: "data" top: "conv1" convolution_param { num_output: 32 kernel_size: 11 stride: 1 } }
- 第三层:池层
layers { name: "pool2" type: POOLING bottom: "conv1" top: "pool2" pooling_param { pool: MAX kernel_size: 3 stride: 2 } }
- 第四层:卷积层
layers { name: "conv3" type: CONVOLUTION bottom: "pool2" top: "conv3" convolution_param { num_output: 16 kernel_size: 9 stride: 1 } }
- 第五层:LOCAL
layers { name: "local4" type: LOCAL bottom: "conv3" top: "local4" local_param { num_output: 16 kernel_size: 9 stride: 1 } }
- 第六层:LOCAL
layers { name: "local5" type: LOCAL bottom: "local4" top: "local5" local_param { num_output: 16 kernel_size: 7 stride: 2 } }
- 第七层:LOCAL
layers { name: "local6" type: LOCAL bottom: "local5" top: "local6" local_param { num_output: 16 kernel_size: 5 stride: 1 } }
- 第八层:内积
layers { name: "fc7" type: INNER_PRODUCT bottom: "local6" top: "fc7" inner_product_param { num_output: 4096 } }
- 第九层:内积
layers { name: "fc8" type: INNER_PRODUCT bottom: "fc7" top: "fc8" inner_product_param { num_output: 83 } }
- 第十层:SOFTMAX
layers { name: "prob" type: SOFTMAX bottom: "fc8" top: "prob" }
- 第十一层:ARGMAX
layers { name: "argmax" type: ARGMAX bottom: "prob" top: "argmax" }
FACE服务器搭建
FACEServer.cpp 定义了端口和线程:Port 8086 / Threads 4 定义了服务器指向:
auto handler = std::make_shared<FACEHandler>(); auto server = folly::make_unique<ThriftServer>(); server->setPort(FLAGS_port); server->setNWorkerThreads(FLAGS_num_of_threads); server->setInterface(std::move(handler)); server->setIdleTimeout(std::chrono::milliseconds(0)); server->setTaskExpireTime(std::chrono::milliseconds(0));
人脸识别解决方案
FACEHandler.cpp编写了FACE的解决方案,应用Caffe深度学习框架。
- 重要概念
network、weights FACEHandler::FACEHandler()为最重要的函数
- 原理
*对原始数据分离训练集和测试集 *转换为caffe可以处理的lmdb格式 *根据设定的Net网络和Solver配置文件进行训练 *得到训练的模型
- 步骤
在我们组选择好训练数据和测试数据之后,就需要进行数据处理了,处理方法主要分为3个步骤。 *人脸检测 *人脸特征点检测 *人脸的对齐 采用卷积神经网络(CNN)方法,通过深度卷积网络来学习高级的过完全特征(有监督), CNN的最后一层激活值作为输出,并且采用CNN最后一层的激活值输出作为features, 不同的人脸区域放入CNN中提取特征,形成了互补、过完全的特征表示(form complementary and over-complete representations)。
- 具体细节
采用多尺度,多人脸区域,训练多个CNN网络,最后得出一张人脸图像的多维度特征。 CNN的结构如下:![]()
- 说明:
Face patches 是进过对齐过后的的人脸块,也就是说已左(右)眼为中心的人脸区域块,嘴角为中心的人脸区域块等等,这样就有多个不同的输入块输入到CNN中。 最后再把不同的块所输出的特征连接起来,就形成了一个最终一张人脸的特征。然后再用各种分类器对其特征进行分类。采用argmax,softmax。
- 输入图像:
多个人脸正方形块(因为后面要考虑到是全局图像还是局部图像,且需要考虑到尺度问题),其中局部图像是关键点(每个图像一个关键点)居中, 不同的区域大小和不同的尺度图像输入到CNN中,其CNN的结构可能会不相同,最后将所有的特征级联起来。
- 特点:
在训练CNN中,训练数据的类别越多,其性能越好,但是会在训练模型中出现问题,也就是太慢。CNN的输出是特征,而不是输出类别。 分类采用Joint Bayesian 来进行人脸的verification;也采用了神经网络来比较,但是联合贝叶斯的效果比较好。
小结
FACE主要运用了Folly Futures库和Caffe开源深度学习框架,对图像进行预先处理,可以识别人脸,并以Trump-Hillary这一最简单的两类问题做了验证。
语音识别ASR
语音识别Automatic Speech Recognition (ASR)功能研究:
Lucida语音识别使用的是一个开源的C++语音识别工具集"Kaldi"来完成的。Kaldi的模型是使用LSTM的循环卷积网络(RNN)来完成深度学习开发的。下面我们来介绍LSTM和Kaldi的相关内容。
LSTM
Kaldi是一个基于C++的语音识别工具包,实现了各种经典的语音信号特征提取及分析算法及最新的循环神经网络结构(以LSTM为主)。
语音识别引擎的基本系统框架如下图所示,深度学习模型中包含多层LSTM网络。
LSTM通过巧妙的结构设计有效解决了RNN的上述问题,其核心在于细胞状态(Cell)的引入(如下图):细胞状态对应A中最上方的链式结构,负责保存长期信息。
三个σ表示sigmoid函数;由于sigmoid函数的输出范围为[0,1],其输出向量u和其它向量v点乘的结果等效于v中的每个元素受到u中对应元素的门限作用,所以这三个sigmoid的输出向量在LSTM中被定义为门限,从左至右依次为:忘记门,输入门,输出门。
首先,忘记门作用于Cell,决定哪些长期信息继续保留、哪些被舍弃;前一时刻的隐含层状态h_(t-1)及当前时刻输入x_t共同决定当前时刻的写入信息(图中tanh矩形框部分),该信息经过输入门的作用后加入到Cell中,从而实现细胞状态的更新;更新后的细胞状态经过输出门的作用后输出当前时刻的隐含层状态h_t,从而完成当前时刻的前向传播流程。
三个门限的输入值可以取决于前一时刻的隐含层状态h_(t-1)、当前时刻的输入x_t、偏置、细胞状态(peephole)等多种因素,上述因素的不同组合可以产生LSTM的各种变体。每一个依赖项的线性变换矩阵均可以通过反向传播算法进行训练。
Kaldi语音识别架构及其LSTM实现
Kaldi是一个基于C++的语音识别工具包,实现了各种经典的语音信号特征提取及分析算法及最新的循环神经网络结构(以LSTM为主)。 语音识别引擎的基本系统框架如下图所示,深度学习模型中包含多层LSTM网络。
Kaldi中的LSTM模型结构及各个节点的计算公式如下图所示;整体结构和前文介绍的LSTM基本网络结构类似,主要区别在于两点:一是门限取决于当前时刻输入、前一时刻的输出及元胞状态这三项;二是为了降低LSTM输出数据维度、减少运算量,在输出门的输出状态后增加了一个projection线性变换层,用于实现输出数据降维。
对于n帧的语音特征输入,单层LSTM的处理流程伪代码如下图所示:
Lucida中的实现方式
我们发现,在Lucida中,ASR的任务完全交给了Kaldi GStreamer server来实现。
GStreamer
GStreamer 是一个开源的多媒体框架库。利用它,可以构建一系列的媒体处理模块,包括从简单的 ogg 播放功能到复杂的音频(混音)和视频(非线性编辑)的处理。
应用程序可以透明的利用解码和过滤技术。开发者可以使用简洁通用的接口来编写一个简单的插件来添加新的解码器或滤镜。
在这里,Kaldi的语音识别模型被视为GStreamer的一个插件。
Master Server
主服务器负责接收客户端的识别请求,为每一个请求分配一个Worker,Worker负责学习和识别的过程。
Client
用户可以调用给定的client程序,以指定的速率发送音频文件到服务器的监听端口,正常情况下会返回识别结果。
也可以使用提供的简单的HTTP API来发送和接收音频文件和识别结果。