深度学习之神经网络(第一节)

    技术2024-05-18  92

    感知机

    如上图所示,这里的神经网络是模拟人的神经网络的工作方式所提出的一种理念。 感知机简单来说就是在收集了数据进行处理后由感知机得出结果,就像人喝水,由温觉感受器去感觉水温,然后得出结论要不要喝?

    感知机与逻辑回归的关系

    由上图我们可以看到,当只有一个感知机时,这不就跟逻辑回归一样吗,只是逻辑回归里叫sigmod,以0.5为阈值。上图所示,与或问题好解决,只需要一个感知机就行,如与问题,当w1和w2等于1时,右上角的点的目标值是2,而我阈值假设是1.5,那么大于1.5的是一个类,小于1.5的是另一个类,那么一定能找到一条直线能将(1,1)这个点与其他三个点分开!!如果要解决异或问题,也就是相同为0,不同为1,很明显(0,0)和(1,1)为同类,(0,1)与(1,0)为同类,这时,光凭w1,w2所构成的一条直线是不能将其成功划分的,那么我们就考虑用两条线!!!这时就要增加一个感知机!!到这也许你还是很懵逼,那么我们就直观来感受一下,请点击下面链接!动态感受分类 这个网站就是感受一下如何将右图中的两种原点准确分类! 当只有一个感知机时,最后的分类情况如下: 我们再看看两个感知机的情况,很明显有两条白线,离最终分类结果又近了一步。 下面来看看三个感知机,这是中间是个三角形,也就是三条白线线将其分割成最终结果。

    神经网络

    神经网络的发展

    神经网络的特点

    神经网络的组成

    输出结果时,并不是直接得到该样本是属于啥类,而是会算出该样本属于所有类别的概率,取最大,这一点又和朴素贝叶斯相似。

    浅层人工神经网络模型

    由上图,我们回忆一下,逻辑回归针对二分类问题,也就是是与不是的问题,用的是sigmod(激活函数)。而神经网络是针对多分类问题,利用softmax来得出某样本属于各个类别的概率,关注最大概率的那个。然后策略与优化后面再说!

    Mnist数据集神经网络分析

    这个手写的1我们要怎么识别?简单来说就是把这张图数字化,变成以像素来看待的,空白地方计为零,其他地方非零。然后经过大量图片的训练后,将此图传进去,即可判断!! 再来复习一下one-hot编码:

    再三强调一定要记住神经网络最后的结果是所有分类都有,然后我们利用one-hot编码来进行标记,每一横行都是一个样本,在所属分类下记为1即可。 one-hotAPI介绍 获取数据

    SoftMax回归

    损失计算-交叉熵损失公式

    相关API

    全连接-从输入直接到输出

    SoftMax计算、交叉熵

    损失值列表平均值计算

    损失下降API

    准确性计算

    equal_list = tf.equal(tf.argmax(y, 1), tf.argmax(y_label, 1)) accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32)) 成功为1,失败为0

    Mnist数据集神经网络案例

    这里就拿识别手写数字举例! 这个数据集里的图片都是28个像素*28个像素的,也就是784个特征,None代指若干个样本,也就是若干行。然后数字是从0~9,一拱十个数字,也就是十个类别。如上图,我这就只举了一层,也就是输入之后经过一层感知机就输出了。特征值是[none,784], 目标值是[none,10],目标值为什么是10列?因为是[none,10]是用的one-hot编码,初始化w是[784,10],这样一来,[none,784]矩阵乘[784,10]=[none,10]。 示例代码:

    FLAGS = tf.app.flags.FLAGS tf.app.flags.DEFINE_integer("is_train", 1, "指定程序是预测还是训练") def full_connected(): # 获取真实的数据 mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True) # 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.int32, [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") bias = tf.Variable(tf.constant(0.0, shape=[10])) # 预测None个样本的输出结果matrix [None, 784]* [784, 10] + [10] = [None, 10] y_predict = tf.matmul(x, weight) + bias # 3、求出所有样本的损失,然后求平均值 with tf.variable_scope("soft_cross"): # 求平均交叉熵损失 loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict)) # 4、梯度下降求出损失 with tf.variable_scope("optimizer"): train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss) # 5、计算准确率 with tf.variable_scope("acc"): ##这里y_true里面依然有占位符,我们在后面的会话里给他赋值 equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1)) # equal_list None个样本 [1, 0, 1, 0, 1, 1,..........] accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32)) # 收集变量 单个数字值收集 tf.summary.scalar("losses", loss) tf.summary.scalar("acc", accuracy) # 高纬度变量收集 tf.summary.histogram("weightes", weight) tf.summary.histogram("biases", bias) # 定义一个初始化变量的op init_op = tf.global_variables_initializer() # 定义一个合并变量de op merged = tf.summary.merge_all() # 创建一个saver saver = tf.train.Saver() # 开启会话去训练 with tf.Session() as sess: # 初始化变量 sess.run(init_op) # 建立events文件,然后写入 filewriter = tf.summary.FileWriter("./tmp/summary/test/", graph=sess.graph) if FLAGS.is_train == 1: # 迭代步数去训练,更新参数预测 for i in range(2000): # 取出真实存在的特征值和目标值 mnist_x, mnist_y = mnist.train.next_batch(50) # 运行train_op训练 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}))) # 保存模型 saver.save(sess, "./tmp/ckpt/fc_model") else: # 加载模型 saver.restore(sess, "./tmp/ckpt/fc_model") # 如果是0,做出预测 for i in range(100): # 每次测试一张图片 [0,0,0,0,0,1,0,0,0,0] 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

    深层的神经网络

    卷积神经网络

    全连接神经网络的缺点 也就是说当中间层多了起来,就没法搞了,于是引入下面的卷积神经网络!!! 卷积神经网络的发展历史 卷积神经网络错误率

    卷积神经网络的结构分析

    卷积层

    conv是卷积层,relu是激活函数,pool是池化层。 数据变化 下面我们来举一个计算卷积层的例子: 初始要识别的图片是55的,通道数1,也就是黑白图片,然后我们设一个33的过滤器(也称之为权重),然后将过滤器放在image的左上角,然后我们知道图片的像素就是特征值,而过滤器是权重,那么当过滤器放在图片左上角时,该过滤器会压着image左上角的九个元素,也是1个33的矩阵,那么我们就可以用这个矩阵乘权重,就会得出来一个值,我们就把他填入feature map得左上角第一个位置,然后filter水平向右移动,又压着新的九个像素,我们再做乘法,把得出的结果填入feature map的第一行第二列。。。然后过滤器再向右移,到头之后又向下移,反正要把图片扫描完!!(这个例子步长为1) 下面举个例子步长为2: 道理跟步长为1的一样,最后我们要的是feature map!!也就是卷积之后的这个结果。 卷积层的零填充 我们在移动filter时,有时候不能刚好扫描完图片,那么会超出几个像素,这时有两个策略,第一个是为了不越界,我就少扫描一部分,但这样不够准确。第二个方案是零填充,就是在filter越过图片时,用零去填充图片,因为0乘任何数都为零,所以不会对最终结果造成影响。 如上图,我们来计算一下图片2828,有32个filter时(32组不同权重),每个filter33,步长为1,零填充为1,那么我们最终的输出结果是多少?H2=(28-3+2)/1+1=28,w2=28,然后高等于过滤器数,然后最终的矩阵为[28,28,32],然后对比输入的[28,28,1],就好像将[28,28,1]堆叠了32个一样,所以形象的称为卷积。 多通道图片-外围补充与多Filter 当识别的图片是彩色时,通道数为3,假设有一个filter,这里面有三个33的权重,每个33权重扫描一个图片,只要保证输出结果只有一个就行,因为一个filter对应一个输出output,那么我怎么能保证输出是一个33呢??很简单,将上图每一组权重与自己压着的33的部分相乘,会得到一个值,将这三组权重得到得这个值相加填入最终的33得feature map对应的位置!就想上图所示得样子,最终结果绿框圈起来得-1就是3组权重与分别与自己压着得3*3矩阵相乘并求和而得来的!! 卷积API

    激活函数-Relu

    为什么要这个激活函数而不用sigmod? 如上图,这里搞了两层神经元,右边是我加了激活函数所得到的分类图片,如果不加激活函数,是达不到这个效果的,我们就记住以下结论:增加激活函数可以增加网络的非线性分割能力

    池化层(Pooling)计算

    如上图所示,池化就相当于特征抽取,上图44矩阵是卷积后的结果,我们知道卷积后的数据会变复杂,那么我们一定要对他进行池化处理,这样最终的输出结果会简单一些,也就是去除冗余,上图我们把44矩阵分成了四块,最终结果取得分别是四块中最大的,由它去代表自己所在块得特征。

    Full Connected层(全连接层)

    Mnist数字识别卷积实现

    这里我们手动设置有几个卷积层,用的图还是上面那个简单神经网络的28*28的图,具体如何设置请看下图。 实现代码:

    # 定义一个初始化权重的函数 def weight_variables(shape): w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0)) return w # 定义一个初始化偏置的函数 def bias_variables(shape): b = tf.Variable(tf.constant(0.0, shape=shape)) return b def model(): """ 自定义的卷积模型 :return: """ # 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.int32, [None, 10]) # 2、一卷积层 卷积: 5*5*1,32个,strides=1 激活: tf.nn.relu 池化 with tf.variable_scope("conv1"): # 随机初始化权重, 偏置[32] w_conv1 = weight_variables([5, 5, 1, 32]) b_conv1 = bias_variables([32]) # 对x进行形状的改变[None, 784] [None, 28, 28, 1] x_reshape = tf.reshape(x, [-1, 28, 28, 1]) # [None, 28, 28, 1]-----> [None, 28, 28, 32] x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1, 1, 1, 1], padding="SAME") + b_conv1) # 池化 2*2 ,strides2 [None, 28, 28, 32]---->[None, 14, 14, 32] x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME") # 3、二卷积层卷积: 5*5*32,64个filter,strides=1 激活: tf.nn.relu 池化: with tf.variable_scope("conv2"): # 随机初始化权重, 权重:[5, 5, 32, 64] 偏置[64] w_conv2 = weight_variables([5, 5, 32, 64]) b_conv2 = bias_variables([64]) # 卷积,激活,池化计算 # [None, 14, 14, 32]-----> [None, 14, 14, 64] x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2) # 池化 2*2, strides 2, [None, 14, 14, 64]---->[None, 7, 7, 64] x_pool2 = tf.nn.max_pool(x_relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME") # 4、全连接层 [None, 7, 7, 64]--->[None, 7*7*64]*[7*7*64, 10]+ [10] =[None, 10] with tf.variable_scope("conv2"): # 随机初始化权重和偏置 w_fc = weight_variables([7 * 7 * 64, 10]) b_fc = bias_variables([10]) # 修改形状 [None, 7, 7, 64] --->None, 7*7*64] x_fc_reshape = tf.reshape(x_pool2, [-1, 7 * 7 * 64]) # 进行矩阵运算得出每个样本的10个结果 y_predict = tf.matmul(x_fc_reshape, w_fc) + b_fc return x, y_true, y_predict def conv_fc(): # 获取真实的数据 mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True) # 定义模型,得出输出 x, y_true, y_predict = model() # 进行交叉熵损失计算 # 3、求出所有样本的损失,然后求平均值 with tf.variable_scope("soft_cross"): # 求平均交叉熵损失# 求平均交叉熵损失 loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict)) # 4、梯度下降求出损失 with tf.variable_scope("optimizer"): train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(loss) # 5、计算准确率 with tf.variable_scope("acc"): equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1)) # equal_list None个样本 [1, 0, 1, 0, 1, 1,..........] accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32)) # 定义一个初始化变量的op init_op = tf.global_variables_initializer() # 开启回话运行 with tf.Session() as sess: sess.run(init_op) # 循环去训练 for i in range(1000): # 取出真实存在的特征值和目标值 mnist_x, mnist_y = mnist.train.next_batch(50) # 运行train_op训练 sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y}) print("训练第%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y}))) return None

    以上是我们自己设定的神经网络结构,下面介绍几个现成的神经网络结构。 LeNet:1986年(这个就太老了) AlexNet:2012年 GoogleNet:

    Processed: 0.011, SQL: 10