今年来人工智能的概念越来越火,AlphaGo以4:1击败李世石更是起到推波助澜的作用。作为一个开挖掘机的菜鸟,深深感到不学习一下deep learning早晚要被淘汰。
既然要开始学,当然是搭一个深度神经网络跑几个数据集感受一下作为入门最直观了。自己写代码实现的话debug的过程和运行效率都会很忧伤,我也不知道怎么调用GPU… 所以还是站在巨人的肩膀上,用现成的框架吧。粗略了解一下,现在比较知名的有caffe、mxnet、tensorflow等等。选哪个呢?对我来说选择的标准就两个,第一要容易安装(想尽快入门的迫切心情实在难以忍受一大堆的配置安装…);第二文档要齐全(这应该是废话 - -)。这几个大名鼎鼎的框架文档都是比较齐全的,那就看最容易安装的。看了几个文档,tensorflow算是最容易安装的了。基本就是pip intall 给定的URL
就可以了。安装方式的文档可以在tensorflow安装教程上查看。
tensorflow基本概念与用法
tensorflow直译过来就是张量流。去年google刚推出tensorflow的时候我就纳闷,为什么深度学习会牵扯到张量,以前学弹塑性力学的时候就是一大堆张量看的很烦…不过还好要理解tensorflow里的tensor完全不用理会那些。先来看一下官方文档的说明:
class tf.Tensor
Represents a value produced by an Operation.
A Tensor is a symbolic handle to one of the outputs of an Operation. It does not hold the values of that operation’s output, but instead provides a means of computing those values in a TensorFlow Session.
首先,Tensor代表了执行一个操作(运算)所产生的值。其次,一个Tensor实例并不会保存具体的值,而只是代表了产生这些值的运算方式。好像有些拗口,也就是说假如有一个加法操作add
,令c = add(1,1)
。那么c
就是一个tensor实例了,代表了1+1
的结果,但是它并没有存储2
这个具体的值,它只知道它代表1+1
这个运算。从这里也可以看出,tensorflow里的api都是惰性求值,等真正需要知道具体的值的时候,才会执行计算,其他时候都是在定义计算的过程。
Tensor可以代表从常数一直到N维数组的值。
Flow指的是,指的是tensorflow这套框架里的数据传递全部都是tensor,也就是运算的输入,输出都是tensor。
常用操作
这里只是简单介绍一下在后面定义卷积神经网络的时候会用到的东西。想要了解更详细的内容还得参考官网上的文档。
首先import tensorflow as tf
,后面的tf
就代表tensorflow啦。
常数
tf.constant
是一个Operation,用来产生常数,可以产生scalar与N-D array. a是一个tensor,代表了由constant这个Operation所产生的标量常数值的过程。 b就是代表了产生一个2*2的array的过程。
a = tf.constant(3)
b = tf.constant(3,shape=[2,2])
变量
变量代表了神经网络中的参数,在优化计算的过程中需要被改变。tf.Variable
当然也是一个Operation,用来产生一个变量,构造函数需要传入一个Tensor对象,传入的这个Tensor对象就决定了这个变量的值的类型(float 或 int)与shape。
变量虽然与Tensor有不同的类型,但是在计算过程中是与Tensor一样可以作为输入输出的。(可以理解为Tensor的派生类,但是实际上可能并不是这样,我还没有看源码)
变量在使用前都必须初始化。
w = tf.Variable(b)
Operation
其实Operation不应该单独拿出来说,因为之前的tf.constant和tf.Variable都是Op,不过还是说一下常规的操作,比如tf.matmul
执行矩阵计算,tf.conv2d
用于卷积计算,Op的详细用法以及其他的Op可以参考api文档。
tf.matmul(m,n)
tf.conv2d(...)
TensorFlow的计算由不同的Operation组成,比如下图
定义了6*(3+5)这个计算过程。6、3、5其实也是Op,这在前面介绍过了。
卷积神经网络用于人脸关键点识别
写到这里终于要开始进入正题了,先从CNN做起吧。Tensorflow的tutorial里面有介绍用CNN(卷积神经网络)来识别手写数字,直接把那里的代码copy下来跑一遍也是可以的。但是那比较没有意思,kaggle上有一个人脸关键点识别的比赛,有数据集也比较有意思,就拿这个来练手了。
定义卷积神经网络
首先是定义网络结构,在这个例子里我用了3个卷积层,第一个卷积层用 3∗3 的卷积核,后面两个用 2∗2 的卷积核。每个卷积层后面都跟max_pool池化层,之后再跟3个全连接层(两个隐层一个输出层)。每个卷积层的feature_map分别用32、64、128。
产生权值的函数代码如下
#根据给定的shape定义并初始化卷积核的权值变量
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
#根据shape初始化bias变量
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
定义卷积运算的代码如下。对tf.nn.con2d()
的参数还是要说明一下
1. x
是输入的样本,在这里就是图像。x
的shape=[batch, height, width, channels]。
- batch是输入样本的数量
- height, width是每张图像的高和宽
- channels是输入的通道,比如初始输入的图像是灰度图,那么channels=1,如果是rgb,那么channels=3。对于第二层卷积层,channels=32。
2. W
表示卷积核的参数,shape的含义是[height,width,in_channels,out_channels]。
3. strides
参数表示的是卷积核在输入x
的各个维度下移动的步长。了解CNN的都知道,在宽和高方向stride的大小决定了卷积后图像的size。这里为什么有4个维度呢