iOS 10 和macOS中的神经网络

原文:Neural Networks in iOS 10 and macOS 作者:Bolot Kerimbaev 编译:刘崇鑫 责编:周建丁(zhoujd@csdn.net)

长期以来,苹果公司一直在其产品中使用了机器学习:Siri回答我们的问题,并供我们娱乐;iPhoto能在我们的照片中进行人脸识别;Mail app能检测垃圾邮件。作为应用开发者,我们已经利用了苹果的API提供的一些功能,如人脸检测,并且从iOS10开始,我们将获得能用于语音识别和SiriKit的高级API。

有时候,我们可能想超越平台内置API的限制,创造独一无二的东西。但更多的时候,我们是使用了一些现成的库或直接建于Accelerate或Metal的快速计算功能之上,推出自己的机器学习功能。

例如,我的同事专为办公室建立了一个录入系统,只使用一台可检测人脸的iPad,然后在Slack投递一个gif,并允许用户通过自定义命令开门。

但是现在,我们有了用于神经网络的第一方支持:在2016年的WWDC上,苹果公司推出了两个神经网络的API,分别称为基础神经网络子程序(BNNS)和卷积神经网络(CNN)。

机器学习和神经网络

AI先驱Arthur Samuel将机器学习定义为“没有明确编程的情况下,给予计算机学习能力的研究领域”。人们用机器学习系统理解一些数据的意义,而这些数据不能很容易地使用传统模型来描述。

例如,编写一段计算房子建筑面积的程序很容易,我们可以考虑到所有房间和其他空间的规模和形状,但是却不能在公式中计算房子的价值;而另一方面,机器学习系统却非常适合解决这样的问题。通过给系统提供已知的具体数据,如市场价值、房屋尺寸、卧室数量等,从而可以利用它预测价格。

神经网络是构建机器学习系统最常用的模型之一。早在半个多世纪前的1940年,已经发展了神经网络的数学基础,而上世纪80年代,并行计算才使其更为可行;并且到了2000年,人们对于深度学习的兴趣又引发了神经网络的回潮。

神经网络由多个层构造,其中每个层由一个或多个节点组成。最简单的神经网络具有三层:输入、隐藏和输出。输入层节点可以代表图像中的各个像素或一些其他参数;如果我们试着自动检测照片的内容,输出层节点则经常作为分类的结果,例如“狗”或“猫”;隐藏层节点配置为对输入执行操作,或配置为应用激活函数。

层类型

三种常见的层的类型为:池化(pooling)层、卷积层和全连接层。

池化层通常通过使用输入的最大值或平均值来汇集数据,降低其大小。一系列的卷积和池化层可以结合起来,用于将照片逐步提炼成越来越高层次的特征集合。

卷积层将卷积矩阵用于图像的每个像素,实现图像变换。如果你已经用过Pixelmator或Photoshop滤镜,那你很可能也用过了卷积矩阵。卷积矩阵通常是一个3×3或5×5的矩阵,被施加到输入图像的像素中,以计算输出图像中新的像素值。为获得输出像素值,我们就乘以原图像中的像素值,并计算平均值。

例如,该卷积矩阵用于图像模糊:

1 1 1
1 1 1
1 1 1

而下面的矩阵能够锐化图像:

 0 -1  0
-1  5 -1 0 -1  0

神经网络的卷积层使用卷积矩阵处理输入,并产生下一层的数据。例如,提取图像中的诸如边缘特征的新特性。

全连接层可以被认为是滤波器尺寸和原始图像相同的卷积层。换句话说,你可以这么认为,全连接层是一个函数,能够为每个像素分配权重,平均其结果,然后给出单个的输出值。

训练和推理

每一层都需要配置适当的参数。例如,卷积层需要输入和输出图像的信息(规模、通道数目等),也需要卷积层参数(内核大小、矩阵等)。全连接层通过输入和输出向量、激活函数和权重来定义。

要获得这些参数,必须训练神经网络。需要以下几步才能完成:通过神经网络传递输入,确定输出,测量误差(即实际结果与预测结果相差多远),并通过反向传播调整权重。训练神经网络可能需要数百、数千甚至成千上万的样本。

目前,苹果公司新的机器学习API,可用于构建只做推理的神经网络,而不是训练。这都是Big Nerd Ranch的功劳。

Accelerate: BNNS

第一个新的API是Accelerate框架的一部分,被称为基础神经网络子程序(BNNS,Basic Neural Network Subroutines)。BNNS补充了BLAS(基础线性代数子程序),并用于一些第三方的机器学习应用。

BNNS在BNNSFilter类中定义层。Accelerate支持三种类型的层:

  • 卷积层(由BNNSFilterCreateConvolutionLayer函数创建)
  • 全连接层(BNNSFilterCreateFullyConnectedLayer)
  • 池化层(BNNSFilterCreatePoolingLayer)

MNIST 数据库是一个众所周知的数据集,包含数以万计的手写数字,用于扫描和调整,以适应20乘20像素的图像。

一种处理图像数据的方法是将图像转换成向量,并使之通过一个全连接层。对于MNIST数据,一个20×20的图像将成为400个值的向量。下面展示了如何将手写的数字“1”转换为向量:

下面是配置全连接层的实例代码,该层将大小为400的向量作为输入,采用S形的激活函数,输出向量大小为25:

// input layer descriptor
    BNNSVectorDescriptor i_desc = {        .size = 400,        .data_type = BNNSDataTypeFloat32,        .data_scale = 0,        .data_bias = 0,
    };

    // hidden layer descriptor
    BNNSVectorDescriptor h_desc = {        .size = 25,        .data_type = BNNSDataTypeFloat32,        .data_scale = 0,        .data_bias = 0,
    };

    // activation function
    BNNSActivation activation = {        .function = BNNSActivationFunctionSigmoid,        .alpha = 0,        .beta = 0,
    };

    BNNSFullyConnectedLayerParameters in_layer_params = {        .in_size = i_desc.size,        .out_size = h_desc.size,        .activation = activation,        .weights.data = theta1,        .weights.data_type = BNNSDataTypeFloat32,        .bias.data_type = BNNSDataTypeFloat32,
    };

    // Common filter parameters
    BNNSFilterParameters filter_params = {        .version = BNNSAPIVersion_1_0;   // API version is mandatory
    };

    // Create a new fully connected layer filter (ih = input-to-hidden)
    BNNSFilter ih_filter = BNNSFilterCreateFullyConnectedLayer(&i_desc, &h_desc, &in_layer_params, &filter_params);

    float * i_stack = bir; // (float *)calloc(i_desc.size, sizeof(float));
    float * h_stack = (float *)calloc(h_desc.size, sizeof(float));
    float * o_stack = (float *)calloc(o_desc.size, sizeof(float));int ih_status = BNNSFilterApply(ih_filter, i_stack, h_stack);

Metal!

该部分会得到更多的Metal吗?确实是的,因为第二个神经网络API是Metal Performance Shaders(MPS)框架的一部分。Accelerate是在CPU上进行快速计算的框架,而Metal将GPU发挥了极致。Metal的特点是卷积神经网络(CNN,Convolution Neural Network)。

MPS自带了一个类似的API集。

  • 创建卷积层需要使用MPSCNNConvolutionDescriptor和MPSCNNConvolution函数。
  • MPSCNNPoolingMax将为池化层提供参数。
  • 全连接层由MPSCNNFullyConnected函数创建。
  • 激活函数由MPSCNNNeuron的子类定义:
    • MPSCNNNeuronLinear
    • MPSCNNNeuronReLU
    • MPSCNNNeuronSigmoid
    • MPSCNNNeuronTanH
    • MPSCNNNeuronAbsolute

BNNS和CNN的比较

下表为Accelerate和Metal激活函数列表:

Accelerate/BNNS

Metal Performance Shaders/CNN

BNNSActivationFunctionIdentity

BNNSActivationFunctionRectifiedLinear

MPSCNNNeuronReLU

MPSCNNNeuronLinear

BNNSActivationFunctionLeakyRectifiedLinear

BNNSActivationFunctionSigmoid

MPSCNNNeuronSigmoid

BNNSActivationFunctionTanh

MPSCNNNeuronTanH

BNNSActivationFunctionScaledTanh

BNNSActivationFunctionAbs

MPSCNNNeuronAbsolute

池化函数:

Accelerate/BNNS

Metal Performance Shaders/CNN

BNNSPoolingFunctionMax

MPSCNNPoolingMax

BNNSPoolingFunctionAverage

MPSCNNPoolingAverage

Accelerate和Metal为神经网络提供的一组函数功能非常相似,所以二者选择取决于每个应用程序。GPU通常首选各种机器学习所需的计算,而数据局部性可能会导致Metal CNN的运行性能比Accelerate BNNS版本要差。如果神经网络对已存入GPU的图像进行操作,例如,使用MPSImage和新MPSTemporaryImage时,很明显,这时更适合用Metal。

原文发布于微信公众号 - 人工智能头条(AI_Thinker)

原文发表时间:2016-07-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨熹的专栏

用 TensorFlow 创建自己的 Speech Recognizer

参考资料 源码请点:https://github.com/llSourcell/tensorf... ---- 语音识别无处不在,siri,google,讯飞...

3245
来自专栏PaddlePaddle

技术|深度学习技术黑话合辑

1262
来自专栏小鹏的专栏

tensorflow_cookbook--preface

Preface         TensorFlow在2015年11月由Google开放,从此,它已经成为GitHub上最受欢迎的机器学习库。 TensorFl...

18610
来自专栏人工智能

使用TensorFlow自动识别验证码(三)

先知安全技术社区独家发表本文,如需要转载,请先联系先知案件技术社区授权;未经授权请勿转载。 0X000 前言 这是该 系列的第三篇文章, 本系列最后一篇。前面几...

2747
来自专栏机器之心

ACL 2018 | 神经语言模型如何利用上下文信息:长距离上下文的词序并不重要

2465
来自专栏机器学习之旅

应用:多算法识别撞库刷券等异常用户

在运营业务中,绝大多数公司会面临恶意注册,恶意刷接口,恶意刷券等流量问题,此类问题的常规解决方案都是拍定单位时间内的ip访问上限次数、qps上限次数等等,会存在...

1412
来自专栏人工智能

MLlib中的随机森林和提升方法

本帖是与来自于Origami Logic 的Manish Amd共同撰写的。

30110
来自专栏小鹏的专栏

用 TensorFlow 创建自己的 Speech Recognizer

参考资料 源码请点:https://github.com/llSourcell/tensorf... 语音识别无处不在,siri,google,讯飞输入法...

3166
来自专栏深度学习自然语言处理

这些神经网络调参细节,你都了解了吗

今天在写本科毕业论文的时候又回顾了一下神经网络调参的一些细节问题,特来总结下。主要从weight_decay,clip_norm,lr_decay说起。

1882
来自专栏专知

【前沿】Geoffery Hinton 的 NIPS2017 Capsule论文简读

10月26日,深度学习元老Hinton的NIPS2017 Capsule论文《Dynamic Routing Between Capsules》终于在arxiv...

2613

扫码关注云+社区

领取腾讯云代金券