如何学习和利用深度学习算法框架

浏览: 1384

序:本文作者是我们公司的AI工程师,本文在Gitchat原创首发,之后我们将会更多地跟大家探讨人工智能的话题。

不知不觉,人工智能已经悄然的走进我们的生活。在我们的潜意识里,还是将人工智能和智能人形机器人联系在一起,这是我们对人工智能的固有偏见。在2016年的云栖大会上,马云的演讲飞速的被翻译成文字,显示在现场的大屏幕上;自动驾驶是汽车产业与人工智能、物联网、高性能计算等新一代信息技术深度融合的产物,是当前全球汽车与交通出行领域智能化和网联化发展的主要方向,已成为各国争抢的战略制高点;手机中的语音助手Siri,总能和我们愉快的聊天;iPhone手机上的照片-相簿-人物中自动对照片中的人脸进行识别和归类,将包含一个人脸的照片放在同一个相簿里面;今日头条中推荐的新闻总是你感兴趣的东西,不同人打开淘宝App出来的界面总不一样。人工智能已经应用在我们生活的很多领域了。

image.png

图1 iPhone手机上照片人物相簿

到底什么是人工智能(AI),创新工场的李开复对AI在《人工智能》中列举了AI的五个常见定义:1)AI就是让人觉得不可思议的计算机程序;2)AI就是与人类思考方式相似的计算机程序;3) AI就是与人类行为相似的计算机程序;4)AI就是会学习的计算机程序;5)AI就是根据对环境的感知,做出合理的行动,并获得很大收益的计算机程序。从其五点定义中,我们可以很轻易的得到这个结论:AI就是计算机程序。当然并不仅仅是这样,详细点的概括为,AI是一种为了解决某些问题而人工设计出的计算机程序,这个程序的算法是模仿人类思考问题的方式,并且具有学习能力。

2016年,AlphaGo与李世石的围棋大战无疑成为人工智能的一道里程碑,也是人工智能的再一次复兴。反观AlphaGo低层算法原理,如下图2所示,需要收集大量棋手的棋谱,通说深度神经网络来训练模型。人工智能的这一次复兴的最大特点是,AI在语音识别、机器视觉、数据挖掘等多个领域走进了业界多个真实的应用场景,与商业模式紧密结合,开始在各个行业发挥出真正的价值。可以说新时期的人工智能模式为:深度学习+大数据。

image.png

图2 AlphaGo算法模式

现在我们走进深度学习,是机器学习的一个分支。深度学习算法可以从数据中学习更加复杂的特征表达,是最后一步的特征学习变得更加简单有效。就图像识别而言,深度学习可以一层一层地将简单的像素特征逐步转化成更加复杂的特征,从而使不同类别的图像更加可分。和传统机器学习相比,深度学习的特点主要体现在“深度”二字中,主要体现在网络结构的深度和提取的特征深度。本文主要针对的是深度学习在机器视觉上的应用,那么我们就绕不开一个重要的网络结构——卷积神经网路。

在早期的图像识别中,主要是从图像低层特征入手,对图像特征进行归纳分析,当然,组织特征也是图像识别技术最大的难点。卷积神经网络,英文全称为Convolutional Neural Network,简称CNN,在最开始就是专门用来解决图像中的物体识别等问题,现在,CNN的应用已经不仅仅局限于图像识别和视频处理,也被应用于时间序列信号的处理,比如识别音频信号、文本数据。

CNN起源于神经科学家对喵星人的大脑的研究,他们将电极插到猫的脑子里,去观察视觉皮层的活动,他们的经过研究推断出,生物视觉是从物体小的部分入手,经过层层的抽象,最后拼起来送入处理中心,减少物体判断物体的可疑性。显然,这个推断和我们普通的BP神经网络原理背道而驰,BP神经网络认为,大脑的每个神经元都要感知物体的全部像素点,即全像素全连接,并且知识简单的映射,并没有对物体进行抽象处理。然而CNN最先证明了BP神经网络理论的不合理性。

image.png

图3 LeNet网络结构

经典的CNN的网络结构如图3所示,卷积神经网络主要结构有:卷积层、池化层和全连接层。在LeNet的网络结构中,对于一个32×32的图像,首先用6个卷积核对图像进行卷积得到6×28×28的一对数据,然后对数据的每一维做一个池化,得到6×14×14的数据结构,后面再用有16个卷积核的卷积层对数据进行卷积得到16×10×10的数据结构,再用一个池化层对将数据简化成16×5×5,后面接一个全连接的神经网络。

图4所示为我们常用的卷积神经网络实例,变化比较多的可能是卷积层和池化层的层数,卷积层和池化层的之中可能会连接数次,还可以在所用卷积核的Size上面做文章,也能达到不同的效果。

image.png

图4 CNN运用实例

以Mnist数字集为例来构建自己的CNN网络,下文中分别用Keras和TensorFlow对CNN网络进行了实现,实现代码如下所示。

1)Keras实现代码:

        import numpy  
       from keras.datasets import mnist  
       from keras.models import Sequential  
       from keras.layers import Dense  
       from keras.layers import Dropout  
       from keras.layers import Flatten  
       from keras.layers.convolutional import Convolution2D  
       from keras.layers.convolutional import MaxPooling2D  
       from keras.utils import np_utils  
       from keras import backend as K  
       K.set_image_dim_ordering('th')  

       seed = 7  
       numpy.random.seed(seed)  

加载数据:

        (X_train,y_train),(X_test,y_test) = mnist.load_data()  

       X_train = X_train.reshape(X_train.shape[0],1,28,28).astype('float32')  
       X_test = X_test.reshape(X_test.shape[0],1,28,28).astype('float32')  
       X_train = X_train/255  
       X_test = X_test/255  
       y_train = np_utils.to_categorical(y_train)  
       y_test = np_utils.to_categorical(y_test)  
       num_classes = y_test.shape[1]  

       def baseline_model():  

构建模型:

            model = Sequential()  
    model.add(Convolution2D(30,5,5,border_mode='valid',input_shape=(1,28,28),activation='relu'))  
           model.add(MaxPooling2D(pool_size=(2,2)))  
           model.add(Convolution2D(15,3,3,activation='relu'))  
           model.add(MaxPooling2D(pool_size=(2,2)))  
           model.add(Dropout(0.2))  
           model.add(Flatten())  
           model.add(Dense(128,activation='relu'))  
           model.add(Dense(50,activation='relu'))  
           model.add(Dense(num_classes,activation='softmax'))        model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])  
           return model  

     model = baseline_model()  
     model.fit(X_train,y_train,validation_data=(X_test,y_test),nb_epoch=10,batch_size=200,verbose=2)  
     scores = model.evaluate(X_test,y_test,verbose=0)  
     print("Baseline Error: %.2f%%" % (100-scores[1]*100))  

2)TensorFlow实现

    from tensorflow.examples.tutorials.mnist import input_data  
   import tensorflow as tf  
   mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)# 读取图片数据集  
   sess = tf.InteractiveSession()# 创建session  

一、函数声明部分

        def weight_variable(shape):  
           # 正态分布,标准差为0.1,默认最大为1,最小为-1,均值为0  
               initial = tf.truncated_normal(shape, stddev=0.1)  
               return tf.Variable(initial)  
       def bias_variable(shape):  
           # 创建一个结构为shape矩阵也可以说是数组shape声明其行列,初始化所有值为0.1  
               initial = tf.constant(0.1, shape=shape)  
               return tf.Variable(initial)  
       def conv2d(x, W):    
           # 卷积遍历各方向步数为1,SAME:边缘外自动补0,遍历相乘  
           return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')    
       def max_pool_2x2(x):    
           # 池化卷积结果(conv2d)池化层采用kernel大小为2*2,步数也为2,周围补0,取最大值。数据量缩小了4倍  
           return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')    

二、定义输入输出结构

        # 声明一个占位符,None表示输入图片的数量不定,28*28图片分辨率  
       xs = tf.placeholder(tf.float32, [None, 28*28])  
       # 类别是0-9总共10个类别,对应输出分类结果  
       ys = tf.placeholder(tf.float32, [None, 10])  
       keep_prob = tf.placeholder(tf.float32)  
       # x_image又把xs reshape成了28*28*1的形状,因为是灰色图片,所以通道是1.作为训练时的input,-1代表图片数量不定  
       x_image = tf.reshape(xs, [-1, 28, 28, 1])  

三、搭建网络,定义算法公式,也就是forward时的计算

        ## 第一层卷积操作 ##  
       # 第一二参数值得卷积核尺寸大小,即patch,第三个参数是图像通道数,第四个参数是卷积核的数目,代表会出现多少个卷积特征图像;  
       W_conv1 = weight_variable([5, 5, 1, 32])  
       # 对于每一个卷积核都有一个对应的偏置量。  
       b_conv1 = bias_variable([32])    
       # 图片乘以卷积核,并加上偏执量,卷积结果28x28x32  
       h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)    
       # 池化结果14x14x32 卷积结果乘以池化卷积核  
       h_pool1 = max_pool_2x2(h_conv1)  

       ## 第二层卷积操作 ##    
       # 32通道卷积,卷积出64个特征    
       w_conv2 = weight_variable([5,5,32,64])  
       # 64个偏执数据  
       b_conv2  = bias_variable([64])  
       # 注意h_pool1是上一层的池化结果,#卷积结果14x14x64  
       h_conv2 = tf.nn.relu(conv2d(h_pool1,w_conv2)+b_conv2)    
       # 池化结果7x7x64  
       h_pool2 = max_pool_2x2(h_conv2)    
       # 原图像尺寸28*28,第一轮图像缩小为14*14,共有32张,第二轮后图像缩小为7*7,共有64张    

       ## 第三层全连接操作 ##  
       # 二维张量,第一个参数7*7*64的patch,也可以认为是只有一行7*7*64个数据的卷积,第二个参数代表卷积个数共1024个  
       W_fc1 = weight_variable([7*7*64, 1024])  
       # 1024个偏执数据  
       b_fc1 = bias_variable([1024])  
       # 将第二层卷积池化结果reshape成只有一行7*7*64个数据# [n_samples, 7, 7, 64] ->> [n_samples, 7*7*64]  
       h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])  
       # 卷积操作,结果是1*1*1024,单行乘以单列等于1*1矩阵,matmul实现最基本的矩阵相乘,不同于tf.nn.conv2d的遍历相乘,自动认为是前行向量后列向量  
       h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)  

       # dropout操作,减少过拟合,其实就是降低上一层某些输入的权重scale,甚至置为0,升高某些输入的权值,甚至置为2,防止评测曲线出现震荡,个人觉得样本较少时很必要  
       # 使用占位符,由dropout自动确定scale,也可以自定义,比如0.5,根据tensorflow文档可知,程序中真实使用的值为1/0.5=2,也就是某些输入乘以2,同时某些输入乘以0  
       keep_prob = tf.placeholder(tf.float32)  
       h_fc1_drop = tf.nn.dropout(f_fc1,keep_prob) #对卷积结果执行dropout操作  

       ## 第四层输出操作 ##  
       # 二维张量,1*1024矩阵卷积,共10个卷积,对应我们开始的ys长度为10  
       W_fc2 = weight_variable([1024, 10])    
       b_fc2 = bias_variable([10])    
       # 最后的分类,结果为1*1*10 softmax和sigmoid都是基于logistic分类算法,一个是多分类一个是二分类  
       y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  
  

四、定义loss(最小误差概率),选定优化优化loss

        cross_entropy = -tf.reduce_sum(ys * tf.log(y_conv)) # 定义交叉熵为loss函数    
       train_step = tf.train.DradientDescentOptimizer(0.5).minimize(cross_entropy) # 调用优化器优化,其实就是通过喂数据争取cross_entropy最小化    

五、开始数据训练以及评测

        correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(ys,1))  
       accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  
       tf.global_variables_initializer().run()  
       for i in range(20000):  
           batch = mnist.train.next_batch(50)  
           if i%100 == 0:  
                   train_accuracy = accuracy.eval(feed_dict={x:batch[0], ys: batch[1], keep_prob: 1.0})  
                   print("step %d, training accuracy %g"%(i, train_accuracy))  
           train_step.run(feed_dict={x: batch[0], ys: batch[1], keep_prob: 0.5})  
       print("test accuracy %g"%accuracy.eval(feed_dict={x: mnist.test.images, ys: mnist.test.labels, keep_prob: 1.0}))

两种方式实现CNN都是比较容易,但是在代码量上,Keras占据很大优势,但是就代码的灵活程度上,Keras远远不及TensorFlow。事实上,Keras是TensorFlow的简化接口。具体地,Keras简单易学,对于想把深度学习作为黑箱子使用的人,Keras非常容易上手,在扩展性上面,Keras将大部分的内部运算代码都隐藏了,我们就自然而然的认为它的功能比较狭窄,但是我们还是可以通过theano和Tensorflow的语句来扩展功能和Keras结合使用。但是对初学者而言,不建议直接上手Keras,因为这样会忽略很多细节和低层原理。

以简单的CNN为基础出现了很多先进的卷积网络结构,AlexNet、VGGNet、Google Inception Net以及ResNet,这四种经典网络对卷积神经网络和深度学习有非常大的推动作用。ILSVRC的top-5错误率在最近几年取得了重大突破,而主要的突破点就在卷积神经网络和深度学习,传统的机器学习算法也难以追上深度学习的步伐了。

以下是关于关于学习深度学习算法框架的答疑:

1目前有考虑将深度学习硬件化吗?如果硬件化,那调参数是否会有所限制?深度学习软件化和硬件化的优缺点是啥?

            深度学习对硬件的配置要求还是挺高的,这个在很大程度上决定了训练模型的效率。目前深度学习还处于一个上升期,还有许多先进算法提出。当这个领域趋于稳定的时候,应该是会硬件化的。

调参数的话应该不会有很大限制,这个主要取决于硬件里面所嵌入的系统,为可能调整的参数留个接口,这个可以作为评价这个产品的指标。

硬件化的话,可以方便训练,使更多的人能够用到深度学习技术。而软件化,网络调试方便,可以灵活的设计自己的网络结构,缺点就是需要有一定的基础才能运用自如。

 

2,做深度学习的话,python无疑是最好的选择,那么需要有那些python基础?

如果你用纯python去开发深度学习框架的话,这个难度还是很大的,但是很多大牛和科研机构都给你开发好了很多深度学习库,可以方便我们使用。具体说的话,科学计算:numpy, pandas, matplotlib;机器学习:scikit learn;神经网络:tensorflow,tensorflow中的slim已经做了很多深度学习算法可供我们直接调用。

 

3. 神经网络的训练技巧是什么?

就我个人的经验,训练层数比较高的神经网络主要优化点有两个,一个是学习率,适当的降低学习效率,另外一个是更新使用小批量的数据,及降低batch_size,这样可是使梯度更加稳定。

 

4, 学习机器学习有哪些好工具推荐?

做图像处理的话,我推荐使用Matlab,容易上手而且使用简单,代码的可读性很强, 也可以用python来做图像处理,opencv提提供了python版本的,里面很多用法和matlab相似。python 中还有很多包是做机器学习的,比如tensorflow,theano,sklean。另外numpy,pandas这些包可以用来整理你的数据。

 

5, 深度学习目前面临的挑战和主要有哪些研究方向?

            当前深度学习主要是依靠数据驱动,即对一个特定任务来说,只要增加训练数据的规模,深度学习模型的表现就可以得到提高。但是发展到今天,这种思路面临很多挑战。

            a)如医疗、教育等领域,获取大量的监督数据的难度很大,或者是标注成本过高。

            b)当数据量达到一定规模之后,还是有一些难以颠覆的情况。比如说聊天机器人,你不可能遍历所有可能的答案。

            c)通用深度学习模型,直接应用到具体问题,表现(效果,性能,占用资源等)可能不尽如人意。这就要求根据特定的问题和数据,来定制和优化深度学习网络结构。这个是当前研究最多最热的地方。

            d)训练的问题。包括网络层数增加带来的梯度衰减,如何更有效的进行大规模并行训练等等。

            语音和图像由于信号来源比较稳定,深度学习在这两个领域的研究已经比较成熟。现在研究热点已经转向自然语言处理(NLP)。

6, 如何学习 TensorFlow?

首先,需要理解tensorflow中的几个基本概念即张量、计算图和会话,概念熟悉了之后,你就可以试着用tensorflow实现简单BP神经网,然后就可以学习实现RNN CNN LSTM等高级一点的神经网络,学习使用tensorboard实现对训练过程的可视化,再去实现比较经典神经网络结构 比如Resnet inception-v3等等

作者简介:向军,机器学习算法工程师,JavaWeb开发工程师,研究生毕业于江南大学,14年开始进入互联网行业,主要从事Java开发和Web项目架构,研究生期间进入AI领域,研究方向为数字图像处理在纺织服装行业的应用,擅长图像特征提取,深度神经网络,发表相关学术论文6篇(其中3篇EI,3篇SCI)

推荐 1
本文由 零一老师 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册