(本文独家发布在金蝶云社区上)
前一篇文章https://vip.kingdee.com/article/11521主要介绍了基本的深度学习概念,TensorFlow简介,以及用TensorFlow搭建了简单的全连接网络,下篇我们将介绍一些改进技术,特别是用在图像上的卷积神经网络。
4. 继续改进模型
书接上回,为了让我们的模型的精确度继续有所提升,我们决定在输入层与输出层之间再增加更多的计算层。也可以叫做隐藏层。首先我们再加一层Fully Connected layer(全连接层)。
除此之外,我们对于之前的模型还要做一点小小的改动。首先,还有一个另外的参数来控制隐藏层的单元的数量。这个数量主要通过输入和输出的size决定:
hidden = tf.layers.dense(inputs=input, units=1024, activation=tf.nn.relu) output = tf.layers.dense(inputs=hidden, units=labels_size)
注意到这次,我们是通过输入参数的方式来使用激活函数。它的意思是从神经计算单元出来就进行激活函数运算,上面的代码例子是relu函数。RELU已经过多次证明,在深度学习里非常好用。RELU函数全称是Rectified Linear Units,它其实是一个简单的max(0, x)函数,即小于0的用0来代替,大于0的,直接就是一个线性函数。当然Relu还有很多变种,来应对更复杂的情况,这里就不是他们的讨论范围了。
然后,运行代码后你应该能看到性能上有一点点提升。随着我们的网络变得越来越深,这也意味着需要被训练的参数也越来越多,相应的训练时间就变得更长。另一方面,这个改进也极大得提高了我们模型的精确度,达到了94%的高度。
接下来需要添加的是两层是卷积网络。他们和刚才Dense有很大得不同,而且尤其对2维度和2维以上的数据非常有效果(比如图像数据)。卷积计算层的参数有:卷积窗口的大小,以及过滤器(filter)的数量。将padding设置成same表明当前卷积输出和输入数据的大小是一样的。这个步骤的计算完成后,我们进行max pooling运算。
卷积的使用允许我们能够充分得利用输入数据的二维表达。当我们之前将图像数据扁平化处理后直接交给Dense layer,我们就损失了这种多维数据的拓扑信息。要回到原来的结构时,我们可以使用tf.reshape函数。
input2d = tf.reshape(input, [-1,image_size,image_size,1])
下面是卷积计算和max池化计算(max pooling layerr)的代码。注意,下一个网络是Dense网络,所以输出需要再Flatten回去。
conv1 = tf.layers.conv2d(inputs=input2d, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2) pool_flat = tf.reshape(pool1, [-1, 14 * 14 * 32]) hidden = tf.layers.dense(inputs= pool_flat, units=1024, activation=tf.nn.relu) output = tf.layers.dense(inputs=hidden, units=labels_size)
增加了卷积网络后,精确度又增加了不少,达到了97%,但是同时训练时间也显著变长。为了充分利用该模型,我们应该继续加上另一层计算层。我们再次使用2维度输入,但仅展平(Flatten)第二层的输出。第一层现在不需要展平,因为卷积计算适合运行在更高的维度上。
此时,你要非常小心地运行这些代码,因为网络的复杂度增长了好多,但是我们同时也得到了更高得准确度。
5. Dropout 层
接下来我将介绍另外一个既能够提升网络性又能避免过拟合的技术,叫做Dropout,这个我也找不到准确的翻译了,就直接说英文好了。我们将其放在从隐藏的Dense layer出来之后。Dropout的工作机制是这样的,每个计算节点根据一定的概率来关掉或者保持原样。它一般用在训练阶段,因此请注意当评估网络的时候要将dropout层的功能要关掉。
要使用Dropout的话,我们需要改一点代码。首先,我们需要一个placeholder变量在训练和测试的时候存储dropout的概率。
should_drop = tf.placeholder(tf.bool)
第二,我们需要定义dropout层,然后和output layer连接上。架构的其他地方都是一样:
hidden = tf.layers.dense(inputs=pool_flat, units=1024, activation=tf.nn.relu) dropout = tf.layers.dropout(inputs=hidden, rate=0.5, training=should_drop) output = tf.layers.dense(inputs=dropout, units=labels_size)
6. 总结
综上,这个教程主要介绍了深度学习的基本概念,TensorFlow基本介绍,以及如何用TensorFlow搭建多层卷积神经网络。代码也可以被重用其他图像识别任务上,以及用不同的数据集。越是复杂的图像,越需要更深,更复杂的网络,比如Inception或者ResNet。
学习这个代码练习关键的一点就是你可以不需要掌握复杂的统计技术或者编写复杂的矩阵乘积代码来创建AI模型。TensorFlow已经为你做了大量的底层工作。然后,你仍然需要什么算法适用于你的数据和应用,以及确定最佳的超参数,比如网络的结构,层的深度,batch的大小,学习率。
最后,要小心TensorFlow这种函数库给你提供得诸多方便给你带来得陷阱,因为它越是灵活,你可能越是要小心其灵活背后带来的灾难。
推荐阅读