传统神经网络
1. 线性回归
梯度下降法
- 总结:
随机初始化参数;
开启循环:t = 0, 1, 2 …
带入数据求出结果: y^t
与真值作比较得到: loss=y−y^t
对各个变量求导得到 Δm
Δm=[x1,t,x2,t,x3,t,1]
更新变量 m :m:=m−ηΔm
如果 loss足够小或 t$循环结束,则停止
2. 线性到非线性
评价非线性激励的两个标准
- 正向对输入的调整
- 反向梯度损失
常用的非线性激励函数
sigmoid函数
y(x)=sigmoid(x)=11+e−xy(x)′=y(x)(1−y(x))
由图可以知道,当导数最大时, x=0 ,此时 y(x)=0.5 , y(x)′=y(x)(1−y(x))=0.5×(1−0.5)=0.25 。
反向梯度下降非常明显,至少会减少75%.tanh函数
f(x)=tanh(x)=21+e−2x−1f′(x)=1−f2(x)
反向梯度较sigmoid函数损失要少,但其导数最大时, f(x)=0 ,正向传播为0,表示正向传播已经不进行工作了,此时的反向梯度已经没有意义了。ReLU(Rectified linear unit)修正线性单元
f(x)={0forx<0xforx⩾0f′(x)={0forx<01forx⩾0
正向截断负值,会损失大量特征;由于,其导数在 x>0 的情况下会一直为1,反向传播不会产生梯度损失的情况。
虽然其正向传播截断负值,会损失大量的特征,但是因为在一般的算法使用中我们抽取问题的特征会足够多,剩下的部分依然足够描述深度学习的模型。Leaky ReLU(Rectified linear unit)
f(x)={0.01xforx<0xforx⩾0f′(x)={0.01forx<01forx⩾0
<\center>
消除ReLU在正向传播中的缺点,保留更多的特征;但是会带来少量的反向传播的梯度损失。
神经元-神经网络
神经网络的每一个神经元均是一个上诉的非线性单元,多个非线性单元组成一层,多层组成一个神经网络。
问题:是否存在线性回归网络?
answer: 线性回归网络并不存在。
由上面的公式可以看出,如果用线性函数,则多层的神经网络最后就等效于一个单层的网络,所以在神经网络中,需要使用非线性激励函数。
3. 神经网络的“配件”
损失函数-Loss
- 合适的损失函数能够确保深度学习模型收敛的更好;
- 设计合适的损失函数是研究工作的主要内容之一.
1.Softmax
选择该损失函数对
loss
的影响:
由上面的结果可以知道,使用Softmax函数的好处是这样可以使得分类问题的预测结果更加明显,不同类别之间的差距更大。
2.Cross entropy
目标为0-1的分类:分类误差越小,则损失越小,对0、1的分类计算各自的损失。
但是会产生exploding gradient (梯度爆炸)问题,例如,实际的 yn=1 ,但是预测中 y^n 接近于0,则 logy^n 便趋向于负无穷,最终的损失趋向于无穷大,产生梯度爆炸问题。
解决梯度爆炸问题的方法之一:
将损失函数变换为以上形式,则即时 p 接近于0,但是最终
Cross entropy的用途:可以用于目标为[0,1]区间的回归问题,以及生成问题。
3.自定义损失函数
- 看中某一个属性:单独将某一些预测值取出或者赋予不同大小的参数;
- 合并多个loss:多目标训练任务,设置合理的loss结合方式。例如图片中,识别位置的loss和识别种类的loss作相应的结合,最终结合到一起共同指导模型的训练;
- 神经网络融合:不同神经网络loss结合,共同loss对网络进行训练指导,emsemble.
学习速率-Learning rate
设置的数值大,收敛的速度比较快;设置的数值小,则产生的精度比较高。
1.如何选择合适的学习率?
- Fixed 直接固定学习率
- Step 通过设置步长逐步调整学习速率
- Adagrad 在训练参数的过程中动态调整学习率
# Assume the gradient dx and parameter vector x
cache += dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)
- RMSprop
cache = decay_rate * cache + (1-decay_rate) *dx**2
x += - learning_rate * dx / (np.sqrt(cache) + eps)
动量
x += - learning_rate * dx
在模型梯度下降的过程中,会让模型沿着已经得到优化的方向前进,不用重新找方向,只是需要微调。
相当于:
# Momentum update
v = mu * v - learning_rate * dx # integrate velocity
x += v # integrate position
- 问题:用动量和直接调大学习率有什么区别?
- Answer:方向不同找的更加准确。
前一种是在原点上考虑梯度,然后结合动量投射相加做更新;
后一种是在动量投射的基础之上进行梯度更新,动量相加做更新。
x_ahead = x + mu*v
# evaluate dx_ahead (the gradient at x)
v = mu*v - learning_rate * dx_ahead
x += v
过拟合-Overfitting
如果有更多的参数能够参与到决策中,会对输入有更高的适应性,则训练出的参数w
会更好。
如何应对过拟合?
1.Regularization
在loss函数中,加入正则化项。
问题:什么叫做
weight decay
与Regularization有什么联系?
Answer:红框中的一项也叫做weight decay,两者是等价的。
2.Dropout
随机的选择一部分神经元将他们的输出置为零,一般选择的Dropout的比例为50%。随机选择神经元节点会使得表现更加均衡。
一般最后的一个或者两个hidden layer 选择做Dropout。
问题:Dropout、Pooling的区别
Answer:Pooling的本质是降维的过程;而Dropout的本质是Regularization,因为其最终的目的是使得某一层的参数更加均衡。
3.Fine-tuning /Data Augmentation
本质上就是用一些已经训练好的模型,再去进行训练,这个过程中,大部分的参数已经不用再更新,实际的参数大量减少。
如图,前一部分的前一部分的结构和部分直接固定,仅对后面一部分进行更新。
4. Mnist数据集
以下利用官方的数据集合,以TensorFlow为框架,搭建神经网络模型,实现mnsit手写字体的识别。
下载下来的数据集被分成两部分:60000行的训练数据集mnist.train
和10000行的测试数据集mnist.test
。
mnist.train.images
是一个形状为 [60000, 784] 的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点,即每张图片大小为
28×28
。
mnist.train.labels
是一个 [60000, 10] 的数字矩阵,数字n将表示成一个只有在第n维度(从0开始)数字为1的10维向量。比如,标签0将表示成([1,0,0,0,0,0,0,0,0,0,0])。
- 代码
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("mnist/", one_hot=True)
import tensorflow as tf
# Parameters
learning_rate = 0.001
training_epochs = 30
batch_size = 100
display_step = 1
# Network Parameters
n_hidden_1 = 256 # 1st layer number of features
n_hidden_2 = 512 # 2nd layer number of features
n_input = 784 # MNIST data input (img shape: 28*28)
n_classes = 10 # MNIST total classes (0-9 digits)
# tf Graph input
# 这里的None表示此张量的第一个维度可以是任何长度的。
x = tf.placeholder("float", [None, n_input])
y = tf.placeholder("float", [None, n_classes])
# Create model
def multilayer_perceptron(x, weights, biases):
# Hidden layer with RELU activation
layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
layer_1 = tf.nn.relu(layer_1)
# Hidden layer with RELU activation
layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
layer_2 = tf.nn.relu(layer_2)
#we can add dropout layer
# drop_out = tf.nn.dropout(layer_2, 0.75)
# Output layer with linear activation
out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
return out_layer
# Store layers weight & biases
weights = {
'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes]))
}
biases = {
'b1': tf.Variable(tf.random_normal([n_hidden_1])),
'b2': tf.Variable(tf.random_normal([n_hidden_2])),
'out': tf.Variable(tf.random_normal([n_classes]))
}
# Construct model
pred = multilayer_perceptron(x, weights, biases)
# Define loss and optimizer
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
# Initializing the variables
init = tf.global_variables_initializer()
# Launch the graph
with tf.Session() as sess:
sess.run(init)
# Training cycle
for epoch in range(training_epochs):
avg_cost = 0.
total_batch = int(mnist.train.num_examples/batch_size)
# Loop over all batches
for i in range(total_batch):
batch_x, batch_y = mnist.train.next_batch(batch_size)
# Run optimization op (backprop) and cost op (to get loss value)
_, c = sess.run([optimizer, cost], feed_dict={x: batch_x,
y: batch_y})
# Compute average loss
avg_cost += c / total_batch
# Display logs per epoch step
if epoch % display_step == 0:
print("Epoch:", '%04d' % (epoch+1), "cost=", \
"{:.9f}".format(avg_cost))
print("Optimization Finished!")
# Test model
# tf.argmax 是一个非常有用的函数,它能给出某个tensor对象在某一维上的其数据最大值所在的索引值。由于标签向量是由0,1组成,因此最大值1所在的索引位置就是类别标签。
correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
# Calculate accuracy
# correct_prediction 给我们一组布尔值。为了确定正确预测项的比例,我们可以把布尔值转换成浮点数,然后取平均值。
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print("Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}))
版权声明:本博客为博主学习xiaoxiang学院《深度学习》课程总结,博文图片均为课程PPT图片。
同时,本文为博主原创文章,博客地址:http://blog.csdn.net/koala_tree,未经博主允许不得转载。