神经网络
神经网络 (Neural Network) 是机器学习的一个分支,全称人工神经网络(Artificial Neural Network,缩写 ANN),是一种模仿生物神经网络的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。
Perceptron (感知器)
一个典型的神经网络由输入层、一个或多个隐藏层以及输出层组成,其中箭头代表着数据流动的方向,而圆圈代表激活函数(最常用的激活函数为 Sigmoid
函数),最简单的神经网络为感知器,它只有输入层和输出层:
$$z = g(a_{0} + w_1*a_1 + w_2*a_2 + w_3*a_3)$$
一般地,
$$Ln = \sum\limits{i=0}^{N{pixels}}{W{ni}.X_i} + b_n = X.W+b$$
Tensorflow 中可用 tf.nn.softmax
:
Y = tf.nn.softmax(tf.malmul(X, W) + b)
感知器只能解决简单的线性可分问题,而无法解决非线性可分问题,比如连 XOR(异或)这种最简单的分类问题都无法解决。
交叉熵
对于 sigmoid 激活函数,交叉熵比二次代价函数有两个显著的优势:
- 对于所有的训练输入,神经网络的实际输出值很接近期待输出的时候,交叉熵将会非常接近 0
- 受误差影响,当误差大的时候,权重更新就快,当误差小的时候,权重的更新就慢
mini-batch
当然可以每次只用一个训练图像来计算梯度并且立即更新权重和偏置,但在 100 个样本上都这样做可以得到一个更好地表示由不同样本图像施加约束的梯度并且可能更快地朝着解决方案收敛。mini-batch 的大小是可调整的参数。另外一个显著的好处是使用批处理也意味着使用较大的矩阵,而这些通常更容易在 GPU 上优化。
示例
import tensorflow as tf
X = tf.placeholder(tf.float32, [None, 28, 28, 1])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
init = tf.initialize_all_variables()
# model
Y=tf.nn.softmax(tf.matmul(tf.reshape(X,[-1, 784]), W) + b)
# placeholder for correct answers
Y_ = tf.placeholder(tf.float32, [None, 10])
# loss function
cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y))
# % of correct answers found in batch
is_correct = tf.equal(tf.argmax(Y,1), tf.argmax(Y_,1))
accuracy = tf.reduce_mean(tf.cast(is_correct,tf.float32))
optimizer = tf.train.GradientDescentOptimizer(0.003)
train_step = optimizer.minimize(cross_entropy)
sess = tf.Session()
sess.run(init)
for i in range(10000):
# load batch of images and correct answers
batch_X, batch_Y = mnist.train.next_batch(100)
train_data={X: batch_X, Y_: batch_Y}
# train
sess.run(train_step, feed_dict=train_data)
# success ? add code to print it
a,c = sess.run([accuracy, cross_entropy], feed=train_data)
# success on test data ?
test_data={X:mnist.test.images, Y_:mnist.test.labels}
a,c = sess.run([accuracy, cross_entropy], feed=test_data)
FNN (前馈神经网络)
前馈神经网络一般指拥有一个或多个隐含层的神经网络(如典型神经网络图示):各神经元从输入层开始,接收前一级输入,并输入到下一级,直至输出层。整个网络中无反馈,可用一个有向无环图表示。
只要拥有足够多的隐含层,前馈神经网络能以任意精读逼近任意复杂的连续函数。然而,如何设计隐含层的个数依然是一个未决问题,业界一般是根据经验来设置。较好的方法就是预先设定几个可选值,通过切换这几个值来看整个模型的预测效果,选择效果最好的值作为最终选择。这种方法又叫做 Grid Search(网格搜索)。
典型的前馈神经网络包括:
- BP 网络:指连接权调整采用了反向传播(Back Propagation)学习算法的前馈网络,激活函数为 Sigmoid 函数。
- RBF 网络:指隐含层神经元由 RBF 神经元组成的前馈网络。RBF 神经元是指神经元的变换函数为 RBF(Radial Basis Function,径向基函数)的神经元。典型的 RBF 网络由三层组成:一个输入层,一个或多个由 RBF 神经元组成的 RBF 层(隐含层),一个由线性神经元组成的输出层。
- 卷积神经网络(Convolutional Neural Network, CNN):由一个或多个卷积层和顶端的全连通层(对应经典的神经网络)组成,同时也包括关联权重和池化层(pooling layer)。这一结构使得卷积神经网络能够利用输入数据的二维结构。卷积神经网络在图像和语音识别方面能够给出更优的结果,并且需要估计的参数更少,使之成为一种颇具吸引力的深度学习结构。
RELU
在深度网络里,sigmoid 激活函数确实能带来很多问题。它把所有的值都挤到了 0 到 1 之间,而且当你重复做的时候,神经元的输出和它们的梯度都归零了。值得一提的是,出于历史原因,一些现代神经网络使用了 ReLU(修正线性单元),它大致是如下这个样子:
对于偏置值,如果用 ReLU 的话,最好的办法就是把它们都初始化成小的正值,这样神经元一开始就会工作在 ReLU 的非零区域内。
示例
K = 200
L = 100
M = 60
N = 30
W1 = tf.Variable(tf.truncated_normal([28*28, K] ,stddev=0.1))
B1 = tf.Variable(tf.zeros([K]))
W2 = tf.Variable(tf.truncated_normal([K, L], stddev=0.1))
B2 = tf.Variable(tf.zeros([L]))
W3 = tf.Variable(tf.truncated_normal([L, M], stddev=0.1))
B3 = tf.Variable(tf.zeros([M]))
W4 = tf.Variable(tf.truncated_normal([M, N], stddev=0.1))
B4 = tf.Variable(tf.zeros([N]))
W5 = tf.Variable(tf.truncated_normal([N, 10], stddev=0.1))
B5 = tf.Variable(tf.zeros([10]))
X = tf.reshape(X, [-1, 28*28])
Y1 = tf.nn.sigmoid(tf.matmul(X, W1) + B1)
Y2 = tf.nn.sigmoid(tf.matmul(Y1, W2) + B2)
Y3 = tf.nn.sigmoid(tf.matmul(Y2, W3) + B3)
Y4 = tf.nn.sigmoid(tf.matmul(Y3, W4) + B4)
Y = tf.nn.relu(tf.matmul(Y4, W5) + B5)
TensorFlow 有一个非常方便的函数可以在单步内计算 softmax 和交叉熵,它是以一种数值上较为稳定的方式实现的。如果要使用它,你需要在应用 softmax 之前将原始的权重和加上你最后一层的偏置隔离开来(在神经网络的术语里叫「logits」)。比如,可以把 Y = tf.nn.softmax(tf.matmul(Y4, W5) + B5)
替换为
Ylogits = tf.matmul(Y4, W5) + B5
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(Ylogits, Y_)
RNN(Recurrent Neural Networks,递归神经网络)
递归神经网络(RNN)是两种人工神经网络的总称:时间递归神经网络(recurrent neural network)和结构递归神经网络(recursive neural network)。时间递归神经网络的神经元间连接构成有向图,而结构递归神经网络利用相似的神经网络结构递归构造更为复杂的深度网络。
RNN 一般指代时间递归神经网络。单纯递归神经网络因为无法处理随着递归,权重指数级爆炸或消失的问题(Vanishing gradient problem),难以捕捉长期时间关联;而结合不同的 LSTM 可以很好解决这个问题。时间递归神经网络可以描述动态时间行为,因为和前馈神经网络(feedforward neural network)接受较特定结构的输入不同,RNN 将状态在自身网络中循环传递,因此可以接受更广泛的时间序列结构输入。
深度神经网络
隐含层较多的神经网络一般称为深度神经网络,比如
- LeNet5
- AlexNet
- GooLeNet 以及 Inception v3/v4
- Residual Networks (ResNet)
- SqueezeNet
- Efficient Neural Network (Enet)
- Fractalnet