经过了高强度的几轮学习之后,我们可以稍微放松一下,来看看近几年来掀起了机器学习的一些经典卷积神经网络们。我们将依次介绍AlexNet,VGGNet,Google InceptionNet和ResNet.这几个神经网络是近年来ILSVRC比赛的杰出表现者,而且主要突破点都是在深度学习和神经网络。成绩的大幅度提升几乎都是伴随着卷积神经网络的层数加深,15年的冠军ResNet甚至用了152个隐层。因而,传统的学习算法已经难以追上神经网络的步伐了。
当然这并不是说,传统的学习算法,如线性模型,决策树,支持向量机,贝叶斯分类器,聚类什么的已经要退出历史舞台了,虽然神经网络拥有强大的拟合能力,但是在自然语音处理,语音识别,文本分类,机器翻译等领域,依然需要将神经网络与一些传统算法结合起来,才能发挥更好的效果。无论如何,技术的迭代更新实在太快了,我只是没事废话一下。废话不多说,先介绍一下AlexNet吧。
由于我们使用的依然是TF的CPU版,已经再也带不动如此大规模的复杂的计算了,因此接下来我们只展示如何用TF实现AlexNet,之后会有专门的章节介绍如何使用GPU加速计算的。AlexNet是首次在CNN中成功运用ReLU,Dropout和LRN等Trick,并使用了GPU加速,数据增强(随机从256*256的图像中截取224*224大小的区域,以及水平翻转的镜像,相当于增加了2048倍的数据量,避免陷入过拟合)。它包含了6亿3000万个连接,6000万个参数和65万个神经元,拥有5个卷积层,其中有3个卷积层后面连接了最大池化层,最后还有3个全连接层。如果仔细地阅读了我前面几篇的同学,应该不会觉得理解下面代码有太多困难。我们直接将AlexNet整合成一个函数,方便调用。
import tensorflow as tf def weight_variable(shape): initial=tf.truncated_normal(shape,stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initial=tf.constant(0.1,shape=shape) return tf.Variable(initial) def print_activations(t):#用来输出参数的结构 print(t.op.name,' ',t.get_shape().as_list()) def inference(images): parameters=[] with tf.name_scope('conv1') as scope:#使用scope函数能够将scope内生成的Variable自动命名为conv1/xxx,便于区分不同卷积层之间的组件 kernel=tf.Variable(tf.truncated_normal([11,11,3,64],dtype=tf.float32,stddev=1e-1),name='weights') conv=tf.nn.conv2d(images,kernel,[1,4,4,1],padding='SAME') biases=tf.Variable(tf.constant(0.0,shape=[64],dtype=tf.float32),trainable=True,name='biases') bias=tf.nn.bias_add(conv,biases) conv1=tf.nn.relu(bias,name=scope) print_activations(conv1) parameters+=[kernel,biases]#再添加一个卷积层之后我们再添加一个池化层和LRN层 lrn1=tf.nn.lrn(conv1,4,bias=1.0,alpha=0.001/9,beta=0.75,name='lrn1') pool1=tf.nn.max_pool(lrn1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='VALID',name='pool1') print_activations(pool1) with tf.name_scope('conv2') as scope: kernel=tf.Variable(tf.truncated_normal([5,5,64,192],dtype=tf.float32,stddev=1e-1),name='weights') conv=tf.nn.conv2d(pool1,kernel,[1,1,1,1],padding='SAME') biases=tf.Variable(tf.constant(0.0,shape=[192],dtype=tf.float32),trainable=True,name='biases') bias=tf.nn.bias_add(conv,biases) conv2=tf.nn.relu(bias,name=scope) print_activations(conv2) parameters+=[kernel,biases]#再添加一个卷积层之后我们再添加一个池化层和LRN层 lrn2=tf.nn.lrn(conv2,4,bias=1.0,alpha=0.001/9,beta=0.75,name='lrn2') pool2=tf.nn.max_pool(lrn2,ksize=[1,3,3,1],strides=[1,2,2,1],padding='VALID',name='pool2') print_activations(pool2) with tf.name_scope('conv3') as scope: kernel=tf.Variable(tf.truncated_normal([3,3,192,384],dtype=tf.float32,stddev=1e-1),name='weights') conv=tf.nn.conv2d(pool2,kernel,[1,1,1,1],padding='SAME') biases=tf.Variable(tf.constant(0.0,shape=[384],dtype=tf.float32),trainable=True,name='biases') bias=tf.nn.bias_add(conv,biases) conv3=tf.nn.relu(bias,name=scope) parameters+=[kernel,biases] print_activations(conv3) with tf.name_scope('conv4') as scope: kernel=tf.Variable(tf.truncated_normal([3,3,384,256],dtype=tf.float32,stddev=1e-1),name='weights') conv=tf.nn.conv2d(conv3,kernel,[1,1,1,1],padding='SAME') biases=tf.Variable(tf.constant(0.0,shape=[256],dtype=tf.float32),trainable=True,name='biases') bias=tf.nn.bias_add(conv,biases) conv4=tf.nn.relu(bias,name=scope) print_activations(conv4) parameters+=[kernel,biases] with tf.name_scope('conv5') as scope: kernel=tf.Variable(tf.truncated_normal([3,3,256,256],dtype=tf.float32,stddev=1e-1),name='weights') conv=tf.nn.conv2d(conv4,kernel,[1,1,1,1],padding='SAME') biases=tf.Variable(tf.constant(0.0,shape=[256],dtype=tf.float32),trainable=True,name='biases') bias=tf.nn.bias_add(conv,biases) conv5=tf.nn.relu(bias,name=scope) print_activations(conv5) parameters+=[kernel,biases] pool5=tf.nn.max_pool(conv5,ksize=[1,3,3,1],strides=[1,2,2,1],padding='VALID',name='pool5') print_activations(pool5)#接下来做3个全连接层 w_fc1=weight_variable([192*192*256,4096]) b_fc1=bias_variable([4096]) h_pool5_flat=tf.reshape(pool5,[-1,192*192*256]) h_fc1=tf.nn.relu(tf.matmul(h_pool5_flat,w_fc1)+b_fc1) keep_prob1=tf.placeholder(tf.float32) h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob1) w_fc2=weight_variable([4096,4096]) b_fc2=bias_variable([4096]) h_fc2=tf.nn.relu(tf.matmul(h_fc1_drop,w_fc2)+b_fc2) keep_prob2=tf.placeholder(tf.float32) h_fc2_drop=tf.nn.dropout(h_fc2,keep_prob2) w_fc3=weight_variable([4096,1000]) b_fc3=bias_variable([1000]) h_fc3=tf.nn.relu(tf.matmul(h_fc2_drop,w_fc3)+b_fc3) keep_prob3=tf.placeholder(tf.float32) h_fc3_drop=tf.nn.dropout(h_fc3,keep_prob3) w_fc4=weight_variable([1000,22000])#拥有22000类……也是变态
b_fc4=bias_variable([22000])
A=tf.nn.softmax(tf.matmul(h_fc3_drop,w_fc4)+b_fc4)
return AlexNet_out,parameters
由于数据集也大,因此这一篇博客中我只写出AlexNet的八层隐层的代码,就不涉及输入和输出,以及loss函数和优化器。关键是,这还只是5年前的一个经典的卷积神经网络。无论如何,现在的我只能抱着我这台5年前的计算机望洋兴叹。有兴趣的同学……可以看看Alex开源的程序。……世界好大……学习完之后觉得好渺小……难过。另外,在使用TF进行深度学习这一系列完结后,我会把所有的相关代码统一全部上传。