Task6 神经网络基础
建议第一天基础,第二天FastText
- 前馈神经网络、网络层数、输入层、隐藏层、输出层、隐藏单元、激活函数的概念。
- 感知机相关;定义简单的几层网络(激活函数sigmoid),递归使用链式法则来实现反向传播。
- 激活函数的种类以及各自的提出背景、优缺点。(和线性模型对比,线性模型的局限性,去线性化)
- 深度学习中的正则化(参数范数惩罚:L1正则化、L2正则化;数据集增强;噪声添加;early stop;Dropout层)、正则化的介绍。
- 深度模型中的优化:参数初始化策略;自适应学习率算法(梯度下降、AdaGrad、RMSProp、Adam;优化算法的选择);batch norm层(提出背景、解决什么问题、层在训练和测试阶段的计算公式);layer norm层。
- FastText的原理。
- 利用FastText模型进行文本分类。
- fasttext1 fasttext2 fasttext3 其中的参考
一、神经网络相关概念
1.前馈网络包括一个输入层和一个输出层,若干隐单元。隐单元可以分层也可以不分层,若分层,则称为多层前馈网络。网络的输入、输出神经元其激活函数一般取为线性函数,而隐单元则为非线性函数。任意的前馈网络,不一定是分层网络或全连接的网络。
在前馈神经网络中,各神经元分别属于不同的层。每一层的神经元可以接收前一层神经元的信号,并产生信号输出到下一层。第0 层叫输入层,最后一层叫输出层,其它中间层叫做隐藏层。整个网络中无反馈,信号从输入层向输出层单向传播,可用一个有向无环图表示。
2. 网络层数是指神经网络中的层级。
3. 输入层是指神经网络中的输入参数这一层这是神经网络的第0层。
4. 隐藏层是指除输入层和输出层以外的其他各层叫做隐藏层。隐藏层不直接接受外界的信号,也不直接向外界发送信号。
5. 输出层是指最终结果的输入结果这一层,也是神经网络最后一层。
6. 隐藏单元是指在隐藏层中一个神经元。
二、感知机
1.基本原理在李航的《统计学习方法》里有,这里参考博客2的一段minist手写识别代码
# Import MNIST data,准备MNIST输入数据
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)
import tensorflow as tf
# Hyper Parameters,超参
learning_rate = 0.1
num_steps = 500
batch_size = 128
display_step = 100
# Network Parameters,网络参数
n_hidden_1 = 256 # 1st layer number of neurons
n_hidden_2 = 256 # 2nd layer number of neurons
num_input = 784 # MNIST data input (img shape: 28*28)
num_classes = 10 # MNIST total classes (0-9 digits)
# tf Graph input,TensorFlow图模型结构的输入定义
X = tf.placeholder("float", [None, num_input])
Y = tf.placeholder("float", [None, num_classes])
# Store layers weight & bias,定义需要学习的网络参数,即网络权值
weights = {
'h1': tf.Variable(tf.random_normal([num_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, num_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([num_classes]))
}
# Create model,定义神经网络基本结构
def neural_net(x):
# Hidden fully connected layer with 256 neurons
layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
# Hidden fully connected layer with 256 neurons
layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
# Output fully connected layer with a neuron for each class
out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
return out_layer
# Construct model,初始化所定义神经网络结构的实例
logits = neural_net(X)
# Define loss and optimizer,定义误差函数与优化方式
loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=Y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
train_op = optimizer.minimize(loss_op)
# Evaluate model (with test logits, for dropout to be disabled),定义检验模型效果的方式
correct_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
# Initialize the variables (i.e. assign their default value),初始化所有定义的网络变量
init = tf.global_variables_initializer()
# Start training,开启session,将所有定义编译成实际的TensorFlow图模型并运行
with tf.Session() as sess:
# Run the initializer
sess.run(init)
for step in range(1, num_steps+1):
batch_x, batch_y = mnist.train.next_batch(batch_size)
# Run optimization op (backprop),进行前向传播,后向传播,以及优化
sess.run(train_op, feed_dict={X: batch_x, Y: batch_y})
if step % display_step == 0 or step == 1:
# Calculate batch loss and accuracy,计算每一批数据的误差及准确度
loss, acc = sess.run([loss_op, accuracy], feed_dict={X: batch_x,
Y: batch_y})
print("Step " + str(step) + ", Minibatch Loss= " + "{:.4f}".format(loss) + ", Training Accuracy= " + "{:.3f}".format(acc))
print("Optimization Finished!")
# Calculate accuracy for MNIST test images,计算测试数据上的准确度
print("Testing Accuracy:", sess.run(accuracy, feed_dict={X: mnist.test.images,
Y: mnist.test.labels}))
代码2:
import tensorflow as tf
input_data = tf.Variable( [[0, 10, -10],[1,2,3]] , dtype = tf.float32 )
output = tf.nn.sigmoid(input_data)
with tf.Session() as sess:
init = tf.initialize_all_variables()
sess.run(init)
print(sess.run(output))
三、激活函数
激活函数是一个能让模型进行收敛的一个函数,有sigmoid,tanh,ReLu等。按照吴恩达的说法,除非二分类用sigmoid,其他一般情况都可以用ReLu.
static inline float linear_activate(float x){return x;}
static inline float logistic_activate(float x){return 1./(1. + exp(-x));}
static inline float relu_activate(float x){return x*(x>0);}
static inline float tanh_activate(float x){return (exp(2*x)-1)/(exp(2*x)+1);}
四、正则化
1.过拟合:经典图片,就是在已有的训练集训练的太好了,导致泛化性能很差。
2.正则化
正则化(Regularization)是通过限制模型复杂度,从而避免过拟合,提高泛化能力的方法。选择经验风险与模型复杂度同时较小的模型(防止过拟合),这样可以较少泛化误差而不是训练误差。
常用正则化方法:
(1)
(2)数据集增强
深层神经网络一般都需要大量的训练数据才能获得比较理想的效果。在数据量有限的情况下,可以通过数据增强(Data Augmentation)来增加数据量,提高模型鲁棒性,避免过拟合。目前,数据增强还主要应用在图像数据上,在文本等其它类型的数据还没有太好的方法。图像数据的增强主要是通过算法对图像进行转变,引入噪声等方法来增加数据的多样性。增强的方法主要有几种:
- 旋转(Rotation):将图像按顺时针或逆时针方向随机旋转一定角度;
- 翻转(Flip):将图像沿水平或垂直方法随机翻转一定角度;
- 缩放(Zoom In/Out):将图像放大或缩小一定比例;
- 平移(Shift):将图像沿水平或垂直方法平移一定步长;
- 加噪声(Noise):加入随机噪声。
(3)early stop
提前停止(early stop)对于深层神经网络来说是一种简单有效的正则化方法。由于深层神经网络的拟合能力非常强,因此比较容易在训练集上过拟合。在使用梯度下降法进行优化时,我们可以使用一个和训练集独立的样本集合,称为验证集(validation set),并用验证集上的错误来代替期望错误。当验证集上的错误率不再下降,就停止迭代。 然而在实际操作中,验证集上的错误率变化曲线并不一定是平衡曲线,很可能是先升高再降低。因此,提前停止的具体停止标准需要根据实际任务上进行优化。
(4)dropout
这个意思就是在神经网络中会随机删除一部分神经元,这样整个网络对于某一个节点的依赖就会变小,因为不知道哪个神经元会被删掉,达到正则化的效果。
五、深度模型的优化
1.参数初始化
神经网络的训练过程中的参数学习是基于梯度下降法进行优化的。梯度下降法需要在开始训练时给每一个参数赋一个初始值。这个初始值的选取十分关键。在感知器和logistic 回归的训练中,我们一般将参数全部初始化为0。但是这在神经网络的训练中会存在一些问题。因为如果参数都为0,在第一遍前向计算时,所有的隐层神经元的激活值都相同。这样会导致深层神经元没有区分性。这种现象也称为对称权重现象。为了打破这个平衡,比较好的方式是对每个参数都随机初始化,这样使得不同神经元之间的区分性更好。如果要高质量地训练一个网络,给参数选取一个合适的初始化区间是非常重要的。一般而言,参数初始化的区间应该根据神经元的性质进行差异化的设置。如果一个神经元的输入连接很多,它的每个输入连接上的权重就应该小一些,以避免神经元的输出过大(当激活函数为ReLU 时)或过饱和(当
激活函数为sigmoid 函数时)。经常使用的初始化方法有Gaussian 分布初始化 和 Xavier 初始化方法。
上面这段话的意思就是,如果全部初始化为0的话,就都一样了;所以还是随机初始化吧。
2.自适应学习率算法
这部分实在是太多了,可以参考黄海广博士的深度学习笔记。
2.batch norm
3.layer norm