前言
有段时间没更新博客了,主要是很久没有学习新的知识,所以也没什么可写的了,所以借着17年的尾巴,更新一篇,希望2018年,大家能开心,没有遗憾。
其实在学完了这么多算法后,我有个感触,在如何把这些算法应用到现实生活中是我们所需要学习的一大难点。什么算法适合你的模型?一般情况下,算法都不会直接能拟合你的数据的很好,那么又怎么让你的数据适合你的算法呢?书上举的例子能拟合的那么好,一般都是经过很多年的实践,所得出的经典例子。所以一个模型的建立不仅仅只有算法,还有一些数据的处理等工作,所以学习的东西到应用不是那么简单。
深度学习(deep learning)听起来很神秘莫测,其实它就是多层的神经网络。随着AlphaGo在围棋上的惊艳表现,深度学习就已经火了起来,在人脸识别、无人驾驶汽车、语音识别等方面都有深度学习的支撑。那么与传统的机器学习算法有哪些区别呢?最大的区别我想应该如下:
由于传统的特征提取基本上都是人工提取,费时费力,而在这点上深度学习可以自动将简单特征提取更加复杂的特征,并使用组合特征解决问题。举个栗子,人脸识别中,如何识别哪里是眼睛?如果传统机器算法中,我们还要定义一些像素中是眼睛的特征,然后特征提取,费时费力,效果还不一定好。而深度学习能先提取一些简单特征,比如线条,然后组合成形状,再一步组合成复杂图案特征。可以看到深度学习很好地拟合了这些复杂机器学习问题。
TensorFlow环境搭建
我的是在windows下安装的TensorFlow-gpu-1.4.0版本,gpu版本提供了并行计算,加快了训练计算速度。提供一篇博客,可以参考安装。
TensorFlow初探
TensorFlow作为Google开源的深度学习框架,也是方便了我们学习深度学习。首先我们需要了解几个概念:
计算图
TensorFlow中每一个计算都是存储在计算图的节点中,而计算图间的箭头描述了计算之间的依赖关系。其实提供了Tensorboard进行计算的可视化,也就更好理解计算图了。向量
这个概念在前面博客也提过,可以理解为多维数组,是TensorFlow的特有数据结构,大大提高了代码的可读性。会话(session)
有了运算和数据结构,会话则是执行这些定义好的运算和数据。
在了解几个基本概念后,那么深度学习又称深层神经网络,有哪些特点呢?
首先,非线性是关键词,前面博客中我们提到如Tenh、Sigmoid、Relu等激活函数都是非线性函数,如果我们采用线性函数作为激活函数,那么深层和浅层也就变化不大了,解决的问题也就有限了,例如:
拟合非线性的分类问题,线性激活函数无论多少层神经网络都拟合的不好。
其次,深层神经网络的多层,为什么要多层呢?使用单层或出现无法解决异或问题(符号相同输出为0)
可以看到单层神经网络无法分类异或问题。
损失函数
与传统机器学习分类问题和回归问题不同,神经网络使用的损失函数使用的是概率分布距离定义的交叉熵来表示。什么是交叉熵可以参考这里
H(p,q)=−∑xp(x)logq(x)
公式中的输入是概率分布,但是神经网络的输出不一定是概率分布,这时我们使用Softmax回归来输出概率分布。神经网络优化算法
深层神经网络通过反向传播算法和梯度下降算法调整神经网络中参数值。梯度下降前面博客中有关Logistic算法中有使用到,是一种求解极值的算法。还有一种正则化的方法能有效防止过拟合的问题,通过惩罚参数值,防止模型对于噪音拟合。通过交叉验证来评估模型对于未知值的预测结果,另外我们通过滑动平均模型来使模型对于测试数据更健壮。
MNIST数字识别问题
这个例子是手写体数字识别数据集,作为深度学习入门样例。我们可以在Yann LeCun教授的个人网站下载数据集
TensorFlow提供了一个类来处理MNIST数据,这个类会将从数据包中解析和测试神经网络使用的格式。
from tensorflow.examples.tutorials.mnist import input_data#这个类能解析成神经网络的格式
mnist=input_data.read_data_sets("C:\\Users\\user\\Desktop\\",one_hot=True)
print("Training data size:",mnist.train.num_examples)
print("Validating data size:",mnist.validation.num_examples)
print("Testing data size:",mnist.test.num_examples)
print("Example training data:",mnist.train.images[0])
print("Example training data label:",mnist.train.labels[0])
input_data.read_data_sets可以自动将数据集分为train、validation和test三个数据集,train有55000张图片,validation有5000张图片,这两个来自于MNIST提供的训练数据集,test集有10000张图片。后两句打印第一张图片的像素矩阵和标签。像素的范围都是[0,1],代表颜色深浅。
batch_size=100
xs,ys=mnist.train.next_batch(batch_size)
print(xs.shape)
print(ys.shape)
mnist.train.next_batch选取一小部分作为作为训练batch,方便使用随机梯度下降。
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
INPUT_NODE = 784 # 输入节点
OUTPUT_NODE = 10 # 输出节点
LAYER1_NODE = 500 # 隐藏层数
BATCH_SIZE = 100 # 每次batch打包的样本个数
# 模型相关的参数
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99
REGULARAZTION_RATE = 0.0001
TRAINING_STEPS = 5000
MOVING_AVERAGE_DECAY = 0.99
def inference(input_tensor, avg_class, weights1, biases1, weights2, biases2):
# 使用滑动平均类
if avg_class == None:
layer1 = tf.nn.relu(tf.matmul(input_tensor, weights1) + biases1)
return tf.matmul(layer1, weights2) + biases2
else:
# 不使用滑动平均类
layer1 = tf.nn.relu(tf.matmul(input_tensor, avg_class.average(weights1)) + avg_class.average(biases1))
return tf.matmul(layer1, avg_class.average(weights2)) + avg_class.average(biases2)
def train(mnist):
x = tf.placeholder(tf.float32, [None, INPUT_NODE], name='x-input')
y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name='y-input')
# 生成隐藏层的参数。
weights1 = tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE], stddev=0.1))
biases1 = tf.Variable(tf.constant(0.1, shape=[LAYER1_NODE]))
# 生成输出层的参数。
weights2 = tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE], stddev=0.1))
biases2 = tf.Variable(tf.constant(0.1, shape=[OUTPUT_NODE]))
# 计算不含滑动平均类的前向传播结果
y = inference(x, None, weights1, biases1, weights2, biases2)
# 定义训练轮数及相关的滑动平均类
global_step = tf.Variable(0, trainable=False)
variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
variables_averages_op = variable_averages.apply(tf.trainable_variables())
average_y = inference(x, variable_averages, weights1, biases1, weights2, biases2)
# 计算交叉熵及其平均值
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
cross_entropy_mean = tf.reduce_mean(cross_entropy)
# 损失函数的计算
regularizer = tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)
regularaztion = regularizer(weights1) + regularizer(weights2)
loss = cross_entropy_mean + regularaztion
# 设置指数衰减的学习率。
learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
mnist.train.num_examples / BATCH_SIZE,
LEARNING_RATE_DECAY,
staircase=True)
# 优化损失函数
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
# 反向传播更新参数和更新每一个参数的滑动平均值
with tf.control_dependencies([train_step, variables_averages_op]):
train_op = tf.no_op(name='train')
# 计算正确率
correct_prediction = tf.equal(tf.argmax(average_y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 初始化回话并开始训练过程。
with tf.Session() as sess:
tf.global_variables_initializer().run()
validate_feed = {x: mnist.validation.images, y_: mnist.validation.labels}
test_feed = {x: mnist.test.images, y_: mnist.test.labels}
# 循环的训练神经网络。
for i in range(TRAINING_STEPS):
if i % 1000 == 0:
validate_acc = sess.run(accuracy, feed_dict=validate_feed)
print("After %d training step(s), validation accuracy using average model is %g " % (i, validate_acc))
xs,ys=mnist.train.next_batch(BATCH_SIZE)
sess.run(train_op,feed_dict={x:xs,y_:ys})
test_acc=sess.run(accuracy,feed_dict=test_feed)
print(("After %d training step(s), test accuracy using average model is %g" %(TRAINING_STEPS, test_acc)))
def main(argv=None):
mnist=input_data.read_data_sets("C:\\Users\\user\\Desktop\\",one_hot=True)
train(mnist)
if __name__=='__main__':
tf.app.run()
经过5000次迭代,可以看到结果还是不错的,附上ipynb实现