赞
踩
相信喜欢机器学习、深度学习的小伙伴对神经网络这个词肯定不陌生,那么什么是神经网络呢?它可以用来做什么呢?怎么做呢?今天好好总结一下。
是一种模仿生物神经网络的结构和功能的数学模型或计算模型。神经网络由大量的人工神经元联结进行计算。大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自适应系统。现代神经网络是一种非线性统计性数据建模工具,常用来对输入和输出间复杂的关系进行建模,或用来探索数据的模式。
典型的网络结构为:
至于输入层是什么,隐藏层是什么,输出层是什么,怎么输入,怎么输出,下面会写。先了解了神经网络的基本结构。
举2个栗子
猫狗分类:有一大堆猫、狗照片,把每一张照片送进一个机器里,机器需要判断这幅照片里的东西是猫还是狗。
手写数字识别:将手写的图片读入到机器中,机器自动判定这个数字是什么。
简单地说,就是对图片的一个识别和一个简单的分类。
为了更方便理解神经网络,在介绍神经网络之前先来介绍一下感知机。
感知机:计算机模拟大脑经行信息处理的过程。有n个输入数据,通过权重与各数据之间的计算和,比较激活函数结果,得出输出。解决分类问题。
其结构如下图,是不是和线性回归比较像,线性回归是y=w1x1+w2x2+……+wnxn+b。而感知机和它及其类似,感知机通过输出来判定是哪一类。
为了简单理解,我们先来看一个例子。
假设给定两个特征x1,x2,设置权重w1=1,w2=1,设置阈值为1.5,那么计算后可知(0,1)、(1,0)的结果为1,小于1.5,(0,0)的结果为0,小于1.5,(1,1)的结果为2,大于1.5,所以就把四个样本点分为了2类,其中的黑线就为分类线,但是很显然这个线是不唯一的,那如何来确定呢,继续看。
好了,上面我们已经用感知机解决了一个简单的二分类问题,那么肯定大家有疑问,如果我要解决三类、四类、更多类的问题怎么办呢?
当然是要画两条线了,但是两条线是怎么画出来的呢?用两个感知机!
有两个感知机也就意味着有了两个权重,有了两个输出,即有了两条线
多分类,需要多个感知机即可。如果想要更形象的了解是如何进行分类的,可以来玩一下这个网站
好了,到现在感知机的内容算是结束了。明白了吧。
但是感知机和我们的神经网络有什么关系呢?我们要讲的是神经网络啊,别急!
感知机是神经网络的基础,简单地说,神经网络就是由多个感知机运算组成的。其实感知机就是神经元。
神经网络的结构:输入层、隐藏层、输出层。
神经网络的特点:
大家都知道神经网络进行图片分类很厉害,但是图片怎么输入呢,我们之前不都是直接输入的特征吗?
图片的特征就是像素。打开图片属性可以查看像素。
来看张图片,这是minist手写数据集中的一张。MINIST数据集中的每一张图片有28*28像素点组成,即有28 * 28=724个像素点,每个像素点的值区间在0~255之间。也就是说对这样一张图片进行识别需要784个特征,x1,x2,x3……x784。也就是说输入层有784个元素。下面确定全连接层(输出层),因为数字有10类,所以最后要分成10类(0,1,2……9),所以全连接层有10个元素。至此,已经确定了输入层和输出层。
那么中间层怎么确定呢?不急,下面说。我们先掠过中间层。建立好一个简单的模型。那么通过计算可以知道,需要有784*10个权重。也就是说需要7840个神经元。最后还有10个偏置。
那么输出的10个结果是什么样的呢?机器是不能直接输出判断的结果1,2,3的,而是输出的概率。在哪一个位置输出的概率大,则认为这张图片是什么数字。这就需要用到softmax。
加上softmax后的结构如下图。
假设我们有一个数组,V,Vi表示V中的第i个元素,那么这个元素的softmax值为:
也就是说,是该元素的指数,与所有元素指数和的比值。这就是softmax的公式。
举个例子:假设一些x1,x2,x3经过中间层、输出层,输出的3个数字分别为20,120,40,那么我们可以带入到softmax公式中计算(ps:此处算出来的数都是我编的,主要是为了方便理解)
S1=e20/( e20+e120+e40)=0.2
S2=e120/( e20+e120+e40)=0.3
S3=e40/( e20+e120+e40)=0.5
计算出来的概率值和应该为1。
至此,我们已经得到了概率值。
那么有了概率之后,怎么来反映到标签呢?用one-hot编码。
One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。
One-Hot编码是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值。然后,每个整数值被表示为二进制向量,除了整数的索引之外,它都是零值,它被标记为1。
内部很繁琐,如果想详细了解,请百度。
下面举个栗子帮助理解:
比如我们要手写识别的数字1,我们需要将真实值转化为one-hot编码。则将1转化为了[0,1,0,0,0,0,0,0,0,0]。同理2可以转化为[0,0,1,0,0,0,0,0,0,0]
那么现在总结一下,我们完成了哪些工作:我们有了输入,有了输出(概率),有了真实值。下面的问题是,如何将输出和真实值联系在一起。
这就需要用到交叉熵损失
交叉熵是什么:交叉熵刻画的是实际输出(概率)与期望输出(概率)的距离,也就是交叉熵的值越小,两个概率分布就越接近。
比如说我们softmax后的结果为[0.11,0.22,0.13,0.14……0.12],对应的真实值one-hot编码是[0,1,0,0,0,0,0,0,0,0]。那么代入公式为H(y)=-(0log(0.11)+1log(0.22)+……)
实质就是衡量两者的的差的大小。我们希望得到的是如果softmax后的结果为[0,1,0,0,0,0,0,0,0,0],那怎么最后得到的结果就是-1log1=0(因为其余项都是0),也就是如果交叉熵为0,那么预测百分之百正确。
所以我们需要做的就是提高1类别对应的softmax后的那个数中的概率。我们希望把[0.11,0.22,0.13,0.14……0.12]中0.22那个位置的概率提高到1,从而把该标签判定为1。
下面就是让将交叉熵损失尽可能的小,需要通过不断更新权重,下面就要介绍到反向传播算法了。
反向传播的作用:前向传递输入信号直至输出产生误差,反向传播误差信息更新权重矩阵,使得交叉熵最小。
反向传播算法的内部是复杂的,先了解这么多,一会在代码中介绍。
我们还要知道,神经网络是以矩阵的方式计算的。
如下图,输入层中的手写图片张数由实际确定,所以为None,但是像素是785,所以输入层的矩阵为[None,784],又知道最后输出的是10个结果,所以权重的个数为784*10,最后一层的矩阵为[None,10],还要记得有偏置,有10个。这便是神经网络的计算流程。
代码
from tensorflow.examples.tutorials.mnist import input_data#tensorflow自带数据集 import tensorflow as tf #实现一个简单的神经网络识别手写数字(无中间层) def full_connected(): mnist=input_data.read_data_sets("Mnist",one_hot=True)#下载数据集并保存在Mnist文件中 #1、建立占位符,x[None,784],y_true[None,10] with tf.variable_scope("data"): x=tf.placeholder(tf.float32,[None,784]) y_true=tf.placeholder(tf.float32,[None,10]) #2、建立一个全连接层的神经网络 w[784,10],b[10] with tf.variable_scope("fc_model"): #随机初始化权重和样本 weight=tf.Variable(tf.random_normal([784,10],mean=0.0,stddev=1.0),name="w")#随机初始化w bias=tf.Variable(tf.constant(0.0,shape=[10]))#注意,bias为一维数组,就是10个数,所以定义shape=[10] y_predict=tf.matmul(x,weight)+bias#预测的结果 [None,784]*[784,10]+[10]=[None,10] #3、求出样本的损失值,然后求平均值 with tf.variable_scope("soft_cross"): loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true,logits=y_predict))#tf.nn.softmax_cross_entropy_with_logits可计算交叉熵损失 #4、反向传播(梯度下降) with tf.variable_scope("optimizer"): train_op=tf.train.GradientDescentOptimizer(0.1).minimize(loss) #5、计算准确率 with tf.variable_scope("acc"): equal_list=tf.equal(tf.argmax(y_true,1),tf.argmax(y_predict,1))#equal_list为一个列表,即y_true与y_predict同则为1,否则为0,最后的equal_list是一个类似[0,0,0,0,1,1……]的列表 accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))#把equal_list转化为float类型,并求平均值,即为准确率 #定义初始化变量op init_op=tf.global_variables_initializer() with tf.Session() as sess: sess.run(init_op) for i in range(200): mnist_x,mnist_y=mnist.train.next_batch(50)#每次取出50个值进行训练 sess.run(train_op,feed_dict={x:mnist_x,y_true:mnist_y})#注意,一定要用feed_dict,因为前面使用了占位符 print("训练第%d步,准确率为:%f" %(i,sess.run(accuracy,feed_dict={x:mnist_x,y_true:mnist_y}))) return None if __name__=="__main__": full_connected()
在tensoboard中进行可视化完整代码
from tensorflow.examples.tutorials.mnist import input_data#tensorflow自带数据集 import tensorflow as tf def full_connected(): mnist=input_data.read_data_sets("Mnist",one_hot=True)#下载数据集并保存在Mnist文件中 #1、建立占位符,x[None,784],y_true[None,10] with tf.variable_scope("data"): x=tf.placeholder(tf.float32,[None,784]) y_true=tf.placeholder(tf.float32,[None,10]) #2、建立一个全连接层的神经网络 w[784,10],b[10] with tf.variable_scope("fc_model"): #随机初始化权重和样本 weight=tf.Variable(tf.random_normal([784,10],mean=0.0,stddev=1.0),name="w")#随机初始化w bias=tf.Variable(tf.constant(0.0,shape=[10]))#注意,bias为一维数组,就是10个数,所以定义shape=[10] y_predict=tf.matmul(x,weight)+bias#预测的结果 [None,784]*[784,10]+[10]=[None,10] #3、求出样本的损失值,然后求平均值 with tf.variable_scope("soft_cross"): loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true,logits=y_predict))#tf.nn.softmax_cross_entropy_with_logits可计算交叉熵损失 #4、反向传播(梯度下降) with tf.variable_scope("optimizer"): train_op=tf.train.GradientDescentOptimizer(0.2).minimize(loss) #5、计算准确率 with tf.variable_scope("acc"): equal_list=tf.equal(tf.argmax(y_true,1),tf.argmax(y_predict,1))#equal_list为一个列表,即y_true与y_predict同则为1,否则为0,最后的equal_list是一个类似[0,0,0,0,1,1……]的列表 accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))#把equal_list转化为float类型,并求平均值,即为准确率 #定义初始化变量op init_op=tf.global_variables_initializer() #在tensorboard中可视化-------------------------------------------- #收集变量(单个数字) tf.summary.scalar("losses",loss) tf.summary.scalar("acc",accuracy) #收集变量(多维度变量) tf.summary.histogram("weights",weight) tf.summary.histogram("bias",bias) #合并变量 merged=tf.summary.merge_all() #tensorboard进行可视化-------------------------------------------- with tf.Session() as sess: sess.run(init_op) filewriter=tf.summary.FileWriter("路径",graph=sess.graph)#建立event文件并写入 for i in range(200):#200为迭代步数 mnist_x,mnist_y=mnist.train.next_batch(50) sess.run(train_op,feed_dict={x:mnist_x,y_true:mnist_y}) #写入每步训练值 summary=sess.run(merged,feed_dict={x:mnist_x,y_true:mnist_y}) filewriter.add_summary(summary,i) print("训练第%d步,准确率为:%f" %(i,sess.run(accuracy,feed_dict={x:mnist_x,y_true:mnist_y}))) return None if __name__=="__main__": full_connected()
可视化结果
测试代码
FLAGS=tf.app.flags.FLAGS tf.app.flags.DEFINE_string('f', '', 'kernel') tf.app.flags.DEFINE_integer("is_train",1, "指定程序是预测还是训练") def full_connected(): mnist=input_data.read_data_sets("Mnist",one_hot=True)#下载数据集并保存在Mnist文件中 #1、建立占位符,x[None,784],y_true[None,10] with tf.variable_scope("data"): x=tf.placeholder(tf.float32,[None,784]) y_true=tf.placeholder(tf.float32,[None,10]) #2、建立一个全连接层的神经网络 w[784,10],b[10] with tf.variable_scope("fc_model"): #随机初始化权重和样本 weight=tf.Variable(tf.random_normal([784,10],mean=0.0,stddev=1.0),name="w")#随机初始化w bias=tf.Variable(tf.constant(0.0,shape=[10]))#注意,bias为一维数组,就是10个数,所以定义shape=[10] y_predict=tf.matmul(x,weight)+bias#预测的结果 [None,784]*[784,10]+[10]=[None,10] #3、求出样本的损失值,然后求平均值 with tf.variable_scope("soft_cross"): loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true,logits=y_predict))#tf.nn.softmax_cross_entropy_with_logits可计算交叉熵损失 #4、反向传播(梯度下降) with tf.variable_scope("optimizer"): train_op=tf.train.GradientDescentOptimizer(0.2).minimize(loss) #5、计算准确率 with tf.variable_scope("acc"): equal_list=tf.equal(tf.argmax(y_true,1),tf.argmax(y_predict,1))#equal_list为一个列表,即y_true与y_predict同则为1,否则为0,最后的equal_list是一个类似[0,0,0,0,1,1……]的列表 accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))#把equal_list转化为float类型,并求平均值,即为准确率 #定义初始化变量op init_op=tf.global_variables_initializer() #创建一个saver saver=tf.train.Saver() with tf.Session() as sess: sess.run(init_op) if FLAGS.is_train==1: for i in range(200): mnist_x,mnist_y=mnist.train.next_batch(50)#每次取出50个值进行训练 sess.run(train_op,feed_dict={x:mnist_x,y_true:mnist_y})#注意,一定要用feed_dict,因为前面使用了占位符 print("训练第%d步,准确率为:%f" %(i,sess.run(accuracy,feed_dict={x:mnist_x,y_true:mnist_y}))) #保存模型 saver.save(sess,"路径/model") else: saver.restore(sess,"路径/model") for i in range(20): x_test,y_test=mnist.test.next_batch(1) print("第%d张图片,手写数字的目标是%d,预测结果是%d" %(i,sess.run(tf.argmax(y_test,1)),sess.run(tf.argmax(sess.run(y_predict,feed_dict={x:x_test,y_true:y_test}),1)))) return None if __name__=="__main__": full_connected()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。