神经网络
1 神经网络基础
1.1 感知器
为了理解神经网络,我们应该先理解神经网络的组成单元——神经元,神经元也叫做感知器。
在线性回归模型中每一个输入值与对应权重的乘积之和得到的数据或通过激活函数来进行判别,下面我们看一下感知器
一个感知器有如下组成部分:
输入权值,一个感知器可以有多个输入a1,a2,a3...an,每个输入上有一个权值wi
激活函数,感知器的激活函数有许多选择,以前用的是阶跃函数),其中z为权重数据积之和
输出,y=f(w∗x+b)
1.2 神经网络
定义:在机器学习和认知科学领域,人工神经网络(artificial neural network, 缩写ANN),简称神经网络(:neural network,缩写NN)或类神经网络,是一 种模仿生物神经网络的结构和功能的计算模型,用于对函数进行估计或近似。
神经网络的种类:
基础神经网络:单层感知器,线性神经网络,BP神经网络,Hopfield神经网络等
进阶神经网络:玻尔兹曼机,受限玻尔兹曼机,递归神经网络等
深度神经网络:深度置信网络,卷积神经网络,循环神经网络,LSTM网络等
神经网络其实就是按照一定规则连接起来的多个神经元。
神经网络的特点:
输入向量的维度和输入神经元的个数相同
每个连接都有个权值
同一层神经元之间没有连接
由输入层,隐层,输出层组成
第N层与第N-1层的所有神经元连接,也叫全连接
神经网络的组成:
结构(Architecture)例如,神经网络中的变量可以是神经元连接的权重
激励函数(Activity Rule)大部分神经网络模型具有一个短时间尺度的动力学规则,来定义神经元如何根据其他神经元的活动来改变自己的激励值。
学习规则(Learning Rule)学习规则指定了网络中的权重如何随着时间推进而调整。(反向传播算法)
下面的例子来看一看,图上已经标注了各种输入、权重信息
对于每一个样本来说,输入值x1,x2,x3,也就是节点1,2,3的输入值,那么对于隐层每一个神经元来说都对应有一个偏置项b,它和权重一起才是一个完整的线性组合。
上图得出隐层的输出,也就是输出层的输入值,矩阵表示如下:
同理,对于输出层来说我们已经得到了隐层的值,可以通过同样的操作得到输出层的值。
其实,分类问题的类别个数决定了你的输出层的神经元个数
2 浅层人工神经网络模型
2.1 one-hot编码
2.1.1 定义
独热编码将分类特征转换为使用分类和回归算法更好的格式,我们看下面这个例子。有七个分类数据的样本输入属于四类。现在,我可以将这些编码到我所做的这些名义值,但是从机器学习的角度来看这是不合适的。那么他们只是单纯的序数值,而不是名义值。
我们做的是为每个类别生成一个布尔列。这些列中只有一列可以为每个样本取值1。因此,术语一个热编码。
神经网络中样本的目标值一定要经过one-hot编码
2.2.2 API
tf.one_hot
tf.one_hot(indices, depth, on_value=None, off_value=None, axis=None, dtype=None, name=None)
indices 在独热编码中位置,即数据集标签
depth 张量的深度,即类别数
2.2 SoftMax回归
softmax回归是一种自然简单的模型。如果要将概率分配给几个不同的东西之一的对象,softmax是要做的事情,因为softmax给出了一个[0,1]之间的概率值加起来为1的列表。
那么我们通常说的激活函数有很多,我们这个使用softmax函数.softmax模型可以用来给不同的对象分配概率。即使在之后,我们训练更加精细的模型时,最后一步也需要用softmax来分配概率。这里的softmax可以看成是一个激励(activation)函数,把我们定义的线性函数的输出转换成我们想要的格式。因此,给定一张图片,它对于每一个数字的吻合度可以被softmax函数转换成为一个概率值。
softmax回归有两个步骤:首先我们将我们的输入的数据加在某些类中,然后将该证据转换成概率。每个输出的概率,对应着独热编码中具体的类别。
公式:
SoftMax使得每一个输出值得到一个概率值。
特点:计算概率值;所有类别的概率值相加都等于1(解释性强,哪个类别概率大就属于哪个类别)
softmax模型,用数学式子表示:y=softmax(Wx+b)
2.3 损失计算-交叉熵损失
2.3.1 定义
在线性回归中,计算误差损失的策略为均方误差,预测值与标准值差的平方和。因为的输出值是概率并且还有标签,所以不能用这种方式。那么就需要一种更好的方法形容这个分类过程的好坏。这里就要用到交叉熵损失。
损失计算-交叉熵损失公式
公式:
它表示的是目标标签值与经过权值求和过后的对应类别输出值
2.3.2 API
tf.nn.softmax_cross_entropy_with_logits
tf.nn.softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, dim=-1, name=None)
计算logits与labels之间的softmax交叉熵损失,该函数已经包含了softmax功能,logits和labels必须有相同的形状[batch_size, num_classes]和相同的类型(float16, float32, or float64)。
labels 独热编码过的标签值
logits 没有log调用过的输入值
返回 交叉熵损失列表
2.4 正向传播与反向传播
2.4.1 正向传播
正向传播:输出经过一层层的计算得出输出
神经网络的训练类似于线性回归中的训练优化过程,步骤为:
①计算结果误差
②通过梯度下降找到误差最
③更新权重以及偏置项
这样我们可以得出每一个参数在进行一次计算结果之后,通过特定的数学理论优化误差后会得出一个变化率α
2.4.2 反向传播
反向传播:从损失计算开始,梯度下降更新权重
就是通过误差最小得到新的权重等信息,然后更新整个网络参数。通常我们会指定学习的速率λ(超参数),通过 变化率和学习速率 率乘积,得出各个权重以及偏置项在一次训练之后变化多少,以提供给第二次训练使用
2.3 其他方法API介绍
(1)获取数据
tensorflow.examples.tutorials.mnist.input_data
(2)损失值列表平均值计算
tf.reduce_mean(input_tensor) 计算张量的尺寸的元素平均值
(3)损失下降API
tf.train.GradientDescentOptimizer(learning_rate) 梯度下降优化
learning_rate:学习率
minimize(loss):最小化损失
return:梯度下降op
(4)准确性计算
equal_list = tf.equal(tf.argmax(y, 1), tf.argmax(y_label, 1))
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
3 Mnist数据集神经网络实现流程
3.1 流程
(1)准备数据
(2)全连接结果计算
(3)损失优化
(4)模型评估(计算准确性)
3.2 API实现
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_integer("flag", 1, "测试或训练")
def mnistNN():
# 获取真实值
mnist = input_data.read_data_sets("./data",one_hot=True)
# 命名空间作用域关了规范管理
with tf.variable_scope("data"):
# 建立占位符为了在实时运行的时候提供参数 x[None,784] y_true[None,10]
x = tf.placeholder(tf.float32,[None,784])
y_true = tf.placeholder(tf.int32,[None,10])
# 建立一个全连接层的神经网络 a[784,10] b[10]
with tf.variable_scope("full_model"):
# 随机初始化权重和偏置,参数要有话必须使用变量定义,因为要训练
weight = tf.Variable(tf.random_normal([784,10],mean=0.0,stddev=1.0),name="W")
# constant创建一个常数张量
bias = tf.Variable(tf.constant(0.0,shape=[10]))
# 预测None个样本的输出结果
y_predict = tf.matmul(x,weight) + bias
# 求出所有样本的损失,求平均值
with tf.variable_scope("softmax_coss"):
# 求平均交叉熵损失
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true,logits=y_predict))
# 梯度下降求出损失
with tf.variable_scope("optimizer"):
train = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
# 计算准确率
with tf.variable_scope("accuracy"):
equal_list = tf.equal(tf.argmax(y_true,1),tf.argmax(y_predict,1))
# equal_list有None个值,对其求平均值
accuracy = tf.reduce_mean(tf.cast(equal_list,tf.float32))
# 收集变量
# 单个数字收集,损失和准确率
tf.summary.scalar("losses",loss)
tf.summary.scalar("accuracy",accuracy)
# 高纬度变量收集
tf.summary.histogram("weights",weight)
tf.summary.histogram("bias",bias)
# 因为有变量一定要初始化变量,
init = tf.global_variables_initializer()
# 定义合并变量的操作
merged = tf.summary.merge_all()
# 创建一个saver,用来保存模型
saver = tf.train.Saver()
with tf.Session() as sess:
# 初始化变量
sess.run(init)
# 建立events文件,然后写入,不用指定文件名
filterWriter = tf.summary.FileWriter("./test",graph=sess.graph)
# 训练
if FLAGS.flag == 1:
# 迭代步数训练,更新参数预测
for i in range(2000):
# 取出真实存在的特征值和目标值 train.next_batch批量读取数据
mnist_x, mnist_y = mnist.train.next_batch(50)
# 运行train训练 用feed_dict进行赋值,格式为字典型
sess.run(train, feed_dict={x: mnist_x, y_true: mnist_y})
# 写入每步训练的值
summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})
# 第一个参数每次的值,第二个参数第几次的值
filterWriter.add_summary(summary, i)
print("训练次数为:%d,准确率为:%f" %(i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))
# 保存模型
saver.save(sess, "./tmp/fc_model")
else:
# 测试
# 加载模型
saver.restore(sess,"./tmp/fc_model")
for i in range(50):
# 每次测试一张图片
x_test,y_test = mnist.test.next_batch(1)
print("第%d张图片,数字目标为%d,预测结果为:%d"%(
i,
tf.argmax(y_test,1).eval(),
tf.argmax(sess.run(y_predict,feed_dict={x: x_test, y_true: y_test}),1).eval()
))
return None
if __name__ == '__main__':
mnistNN()