热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

tensorflow训练权重不更新_TensorFlow学习Program1——15.权重和偏置更新要点、单层感知机、反向传播算法BPN...

写在前面:关于权重和偏置更新权重W更新采用或-的两种情况可以很明显看到,关于权重更新存在2种情况,本质没什么区别,只不过在自

写在前面:关于权重和偏置更新

e706dc9ecbdfa8b611e1e8045ba59d20.png
权重W更新采用+或-的两种情况
  • 可以很明显看到,关于权重更新存在2种情况,本质没什么区别,只不过在自己写代码手动更新权重和偏置时,这点就很容易混淆出错。本帖第一个单层感知机示例,采用第一种方式;第二个BPN示例,采用第二种方式;
  • 通常情况下&#xff0c;推荐采用第二种。因为一般数学推导中都是写成W&#61;W-dW&#xff0c;这样就和以前的帖子一致<线性回归、逻辑回归与正则化>&#xff0c;避免以后自我矛盾
  • 关于偏置b更新&#xff0c;一般没有数学公式。可以简单看做b&#61;w0&#xff0c;因而不予额外讲述。在本帖第二个代码示例中&#xff0c;b的更新就是采用b&#61;b-db形式。第一个示例中没有b&#xff0c;仅设置了W
  • 我仔细翻看了以往的代码示例&#xff0c;以前的代码都是采用了TF自带的优化器&#xff0c;我们只需设置W和b占位符、赋予Y和Yhat相应值即可&#xff0c;其他的由优化器自我完成。至于设置loss时&#xff0c;对于函数逼近问题&#xff0c;到现在一直只用了平方差(Y-Yhat还是Yhat-Y不重要)&#xff1b;对于分类问题&#xff0c;交叉熵求解的内部细节我们不参与&#xff0c;因此以前这个问题不突出。而此帖&#xff0c;error和权重、偏置更新都由自己手动撸码而成&#xff0c;因此顺序、加减问题就很明显
  • 养成良好习惯&#xff0c;一律采用图示第二种方式

TensorFlow实现单层感知机详解

简单感知机是一个单层神经网络它使用阈值激活函数&#xff0c;正如 Marvin Minsky 在论文中所证明的&#xff0c;它只能解决线性可分的问题(线性可分的定义参见我的别的帖子)。虽然这限制了单层感知机只能应用于线性可分问题&#xff0c;但它具有学习能力已经很好了。当感知机使用阈值激活函数时&#xff0c;不能使用TensorFlow优化器来更新权重(根据上一帖可知&#xff0c;阈值激活函数并不可微&#xff0c;自然不能使用TF中定义的优化器&#xff0c;需要自己编写规则更新权重)。我们将不得不使用权重更新规则&#xff1a;

333ba32356f12b21278712b2c488c270.png
η 是学习率。为了简化编程&#xff0c;当输入固定为 &#43;1 时&#xff0c;偏置可以作为一个额外的权重。那么&#xff0c;上面的公式可以用来同时更新权重和偏置。
  • 仔细研究下面程序&#xff0c;搞清楚为什么这个式子可以用来更新权重。&#xff08;核心原因就是&#xff0c;Y-Yhat<0&#xff0c;即Yhat过大&#xff0c;则dW为负&#xff0c;W&#61;W&#43;dW变小&#xff0c;促使Yhat缩小&#xff1b;反之亦反&#xff09;
  • 研读这个程序和MNIST计算过程(mnist.data每一行是一个图片样本&#xff0c;shape(W)&#61;(m,n)&#61;(784,10), shape(B)&#61;(n,1)&#61;(10,1))&#xff0c;再结合神经元图&#xff0c;就可以很明晰一个结论&#xff1a;输入X中&#xff0c;每一行就是一个样本&#xff0c;X的行数M就是第零层输入层(虚拟节点)和第一层神经元的个数M&#xff0c;第一层中一个神经元用来承接一个样本。每个样本有m个输入的元素即[x1,x2...xm]&#xff0c;相应和m个权重数wi相乘&#xff0c;故W有m行。若有n个输出&#xff0c;接着再和n个偏置数bi相加&#xff0c;故B有n行。
  • 对于回归问题&#xff0c;只有一个输出n&#61;1&#xff0c;故B常为一个数&#xff1b;对于分类问题&#xff0c;会有多个输出结果&#xff0c;如MNIST10个分类n&#61;10&#xff0c;故B为n行1列。(注意为n行1列&#xff0c;而非1行n列&#xff0c;是因为加减法法则缘故&#xff0c;X*W所得大小(55000,10)的张量可以和大小(10,1)的B张量相加减&#xff0c;具体见短句汇总帖)
  • 程序中只创建了一个W和b&#xff0c;故第一层所有神经元所用的W和b张量都是一样的。后续层也是这样吗&#xff1f;估计是的&#xff0c;查一查
  • 综上所述&#xff1a;X大小(M,m)&#xff0c;表M个样本&#xff0c;每个样本m个元素&#xff0c;第一层网络有M个神经元&#xff1b;W大小(m,n)&#xff0c;表每个神经元有m个权重数wi&#xff0c;n个分类&#xff0c;计算X*W后和n个偏置数bi相加

# tensorflow实现单层感知机&#xff0c;是一个单层神经网络。
# 它使用阈值激活函数&#xff0c;只能解决线性可分的问题&#xff0c;不能使用TensorFlow优化器来更新权重
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt# from Activation_Function_Threshold import thresholddef threshold(x):# tf.less返回两个张量各元素比较&#xff08;x# hyper parameters
learn_rate &#61; 0.4
min_err &#61; 1e-3 # minmum accepted error
max_epochs &#61; 100 # maximum epochs# 2.指定训练数据。在这个例子中&#xff0c;取三个输入神经元&#xff08;A&#xff0c;B&#xff0c;C&#xff09;并训练它学习逻辑 AB&#43;BC&#xff1a;
# traning data Y&#61;AB&#43;BC, sum of two linear functions
# 疑问&#xff0c;AB算是线性函数&#xff1f;线性X线性&#61;线性&#xff1f; 好像多项式都算线性&#xff1f;
T, F &#61; 1.0, 0.0
X_in &#61; [[T, T, T, T],[T, T, F, T],[T, F, T, T],[T, F, F, T],[F, T, T, T],[F, T, F, T],[F, F, T, T],[F, F, F, T]]
Y &#61; [[T],[T],[F],[F],[T],[F],[F],[F]]
# 3.定义要用到的变量和用于计算更新的计算图&#xff0c;最后执行计算图
W &#61; tf.Variable(tf.random_normal([4, 1], stddev&#61;2, seed&#61;0))
h &#61; tf.matmul(X_in, W)
Y_hat &#61; threshold(h)
error &#61; Y - Y_hat
mean_error &#61; tf.reduce_mean(tf.square(error))
# 用mean_err作为判断标准&#xff0c;但不用来修订dW
dW &#61; learn_rate * tf.matmul(X_in, error, transpose_a&#61;True)
# shape(dW)&#61;[4,1]&#61;倒置[8,4]*[8,1]&#61;[4,8]*[8,1]
train &#61; tf.assign(W, W &#43; dW)
init &#61; tf.global_variables_initializer()
err &#61; 1
epoch &#61; 0
with tf.Session() as sess:sess.run(init)while err > min_err and epoch

db1f912743ac22e9fbf61c5a04015602.png

那么&#xff0c;如果使用 Sigmoid 激活函数&#xff0c;而不是阈值激活函数&#xff0c;会发生什么&#xff1f;你猜对了&#xff0c;首先&#xff0c;可以使用 TensorFlow 优化器来更新权重。其次&#xff0c;网络将表现得像逻辑回归。

TensorFlow实现反向传播算法详解

反向传播&#xff08;BPN&#xff09;算法是神经网络中研究最多、使用最多的算法之一&#xff0c;它用于将输出层中的误差传播到隐藏层的神经元&#xff0c;然后用于更新权重。学习 BPN 算法可以分成以下两个过程&#xff1a;

  1. 正向传播&#xff1a;输入被馈送到网络&#xff0c;信号从输入层通过隐藏层传播到输出层。在输出层&#xff0c;计算误差和损失函数。
  2. 反向传播&#xff1a;在反向传播中&#xff0c;首先计算输出层神经元损失函数的梯度&#xff0c;然后计算隐藏层神经元损失函数的梯度。接下来用梯度更新权重。

这两个过程重复迭代直到收敛。

实现公式

首先给网络提供 M 个训练对&#xff08;X&#xff0c;Y&#xff09;&#xff0c;X 为输入&#xff0c;Y 为期望的输出。输入通过激活函数 g(h) 和隐藏层传播到输出层。输出 Yhat是网络的输出&#xff0c;得到 error&#61;Y-Yhat。其损失函数 J(W) 为

5d5e68bcef502cd50b23ea0b3f16ab8e.png

其中&#xff0c;i 取遍所有输出层的神经元&#xff08;1 到 N&#xff09;。然后可以使用 J(W) 的梯度并使用链式法则求导&#xff0c;来计算连接第 i 个输出层神经元到第 j 个隐藏层神经元的权重 Wij的变化

07ca514f1ec8b70106ba756a5ba5e707.png

这里&#xff0c;Oj是隐藏层神经元的输出&#xff0c;h 表示隐藏层的输入值。这很容易理解&#xff0c;但现在怎么更新连接第 n 个隐藏层的神经元 k 到第 n&#43;1 个隐藏层的神经元 j 的权值 Wjk&#xff1f;过程是相同的&#xff1a;将使用损失函数的梯度和链式法则求导&#xff0c;但这次计算 Wjk&#xff1a;

69367d5c7c41e24eaab845d92e8726cf.png

现在已经有方程了&#xff0c;看看如何在TensorFlow中做到这一点。在这里&#xff0c;还是使用 MNIST 数据集&#xff08;http://yann.lecun.com/exdb/MNIST/&#xff09;。

具体实现过程

6bab5cf4769021c2ee1a9327ba1d6577.png
对照标记理解程序即可。一个疑问是&#xff0c;程序中并不存在除以M求平均&#xff0c;难道多阶张量自动体现这个意味&#xff1f;
f53a7586424062bc7c9be2d863f52e31.png
此外&#xff0c;偏置b的更新梯度数学式是怎么推导的&#xff1f;查一下。这里根据程序总结出更新公式&#xff0c;有意思的是更新b的程序中体现了平均之意

# MNIST数据集是分类问题的标准。本例用TensorFlow实现反向传播算法
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist &#61; input_data.read_data_sets(&#39;A:/software/Anaconda3/Lib/site-packages/tensorflow/examples/tutorials/mnist/MNIST_data&#39;, one_hot&#61;True)# 1. 定义超参数和其他常量。
# 每个手写数字的尺寸是 28×28&#61;784 像素。数据集被分为 10 类&#xff0c;以 0 到 9 之间的数字表示。这两点是固定的。
# 学习率、最大迭代周期数、每次批量训练的批量大小以及隐藏层中的神经元数量都是超参数。
# 可以通过调整这些超参数&#xff0c;看看它们是如何影响网络表现的&#xff1a;
n_input &#61; 784
n_classes &#61; 10
max_epochs &#61; 1000
learn_rate &#61; 0.5
batch_size &#61; 10
seed &#61; 0
n_hidden &#61; 30 # Number of neurons in the hidden layer# 2. 定义Sigmoid函数s(x)的导数来进行权重更新,其导数为s(x)*(1-s(x))
def sigmaprime(x):return tf.multiply(tf.sigmoid(x), tf.subtract(tf.constant(1.0), tf.sigmoid(x)))# 3. 为训练数据创建占位符
x_in &#61; tf.placeholder(tf.float32, [None, n_input])
y &#61; tf.placeholder(tf.float32, [None, n_classes])# 4. 创建模型
def multilayer_perceptron(x, weights, biases):# Hidder layer with RELU activationh_layer_1 &#61; tf.add(tf.matmul(x, weights[&#39;h1&#39;]), biases[&#39;h1&#39;])out_layer_1 &#61; tf.sigmoid(h_layer_1)# output layer with linear activationh_out &#61; tf.add(tf.matmul(out_layer_1, weights[&#39;out&#39;]), biases[&#39;out&#39;])return tf.sigmoid(h_out), h_out, out_layer_1, h_layer_1# 5. 定义权重和偏置变量
weights &#61; {&#39;h1&#39;: tf.Variable(tf.random_normal([n_input, n_hidden], seed&#61;seed)),&#39;out&#39;: tf.Variable(tf.random_normal([n_hidden, n_classes], seed&#61;seed))}
biases &#61; {&#39;h1&#39;: tf.Variable(tf.random_normal([1, n_hidden], seed&#61;seed)),&#39;out&#39;: tf.Variable(tf.random_normal([1, n_classes], seed&#61;seed))}# 6. 为正向传播、误差、梯度和更新计算创建计算图&#xff1a;
# Forward pass
y_hat, h_2, o_1, h_1 &#61; multilayer_perceptron(x_in, weights, biases)
# error
err &#61; y_hat - y
# backward pass
delta_2 &#61; tf.multiply(err, sigmaprime(h_2))
delta_w_2 &#61; tf.matmul(tf.transpose(o_1), delta_2)
wtd_error &#61; tf.matmul(delta_2, tf.transpose(weights[&#39;out&#39;]))
delta_1 &#61; tf.multiply(wtd_error, sigmaprime(h_1))
delta_w_1 &#61; tf.matmul(tf.transpose(x_in), delta_1)eta &#61; tf.constant(learn_rate)
# 7.更新权重update weights
# 注意为什么这里是 W&#61;W-dW,而不是W&#61;W&#43;dW。因为当err&#61;y_hat-y,就是W&#61;W-dW&#xff0c;当err&#61;y-y_hat,则W&#61;W&#43;dW
step &#61; [tf.assign(weights[&#39;h1&#39;], tf.subtract(weights[&#39;h1&#39;], tf.multiply(eta, delta_w_1))),tf.assign(biases[&#39;h1&#39;], tf.subtract(biases[&#39;h1&#39;], tf.multiply(eta, tf.reduce_mean(delta_1, axis&#61;[0])))),tf.assign(weights[&#39;out&#39;], tf.subtract(weights[&#39;out&#39;], tf.multiply(eta, delta_w_2))),tf.assign(biases[&#39;out&#39;], tf.subtract(biases[&#39;out&#39;], tf.multiply(eta, tf.reduce_mean(delta_2, axis&#61;[0])))),]
# 8.定义计算精度accuracy和初始化
acc_mat &#61; tf.equal(tf.argmax(y_hat, 1), tf.argmax(y, 1))
accuracy &#61; tf.reduce_sum(tf.cast(acc_mat, tf.float32))
init &#61; tf.global_variables_initializer()# 9.执行
with tf.Session() as sess:sess.run(init)for epoch in range(max_epochs):batch_xs, batch_ys &#61; mnist.train.next_batch(batch_size)sess.run(step, feed_dict&#61;{x_in: batch_xs, y: batch_ys})if epoch % 100 &#61;&#61; 0:acc_test &#61; sess.run(accuracy, feed_dict&#61;{x_in: mnist.test.images, y: mnist.test.labels})acc_train &#61; sess.run(accuracy, feed_dict&#61;{x_in: mnist.train.images, y: mnist.train.labels})# 训练集和测试集样本大小分别为55000和10000&#xff0c;这里所求精度即向满分55000和10000靠齐&#xff0c;除以550和100就可获得相对百分数# 也有写600的&#xff0c;认为训练集为60000&#xff0c;但是我验证了&#xff0c;是train&#61;55000, validation&#61;5000print(&#39;Epoch:{0} accuracy train%:{1} accuracy test%: {2}&#39;.format(epoch, acc_train / 550, (acc_test / 100)))

解读分析

在这里&#xff0c;训练网络时的批量大小为batchsize&#61;10&#xff0c;如果增加批量的值&#xff0c;网络性能就会下降(为什么会下降&#xff1f;不理解)另外&#xff0c;需要在测试数据集上检测训练好的网络的精度&#xff0c;这里测试数据集的大小是 10000。

单隐藏层多层感知机在训练数据集上的准确率为 84.45&#xff0c;在测试数据集上的准确率为 92.1。这是好的&#xff0c;但不够好。MNIST 数据集被用作机器学习中分类问题的基准。接下来&#xff0c;看一下如何使用 TensorFlow 的内置优化器影响网络性能。

推荐阅读

  • MNIST 数据集&#xff1a;http://yann.lecun.com/exdb/mnist/
  • 反向传播算法的简化讲解&#xff1a;http://neuralnetworksanddeeplearning.com/chap2.html
  • 反向传播算法的另一个直观解释&#xff1a;http://cs231n.github.io/optimization-2/
  • 反向传播算法的详细信息&#xff0c;以及如何将它应用于不同的网络&#xff1a;https://page.mi.fu-berlin.de/rojas/neural/chapter/K7.pdf



推荐阅读
  • 从2019年AI顶级会议最佳论文,探索深度学习的理论根基与前沿进展 ... [详细]
  • Python多线程编程技巧与实战应用详解 ... [详细]
  • 本文探讨了一种高效的算法,用于生成所有数字(0-9)的六位组合,允许重复使用数字,并确保这些组合的和等于给定的整数N。该算法通过优化搜索策略,显著提高了计算效率,适用于大规模数据处理和组合优化问题。 ... [详细]
  • 每年,意甲、德甲、英超和西甲等各大足球联赛的赛程表都是球迷们关注的焦点。本文通过 Python 编程实现了一种生成赛程表的方法,该方法基于蛇形环算法。具体而言,将所有球队排列成两列的环形结构,左侧球队对阵右侧球队,首支队伍固定不动,其余队伍按顺时针方向循环移动,从而确保每场比赛不重复。此算法不仅高效,而且易于实现,为赛程安排提供了可靠的解决方案。 ... [详细]
  • Python 实战:异步爬虫(协程技术)与分布式爬虫(多进程应用)深入解析
    本文将深入探讨 Python 异步爬虫和分布式爬虫的技术细节,重点介绍协程技术和多进程应用在爬虫开发中的实际应用。通过对比多进程和协程的工作原理,帮助读者理解两者在性能和资源利用上的差异,从而在实际项目中做出更合适的选择。文章还将结合具体案例,展示如何高效地实现异步和分布式爬虫,以提升数据抓取的效率和稳定性。 ... [详细]
  • 本文汇集了我在网络上搜集以及在实际面试中遇到的前端开发面试题目,并附有详细解答。无论是初学者还是有一定经验的开发者,都应深入理解这些问题背后的原理,通过系统学习和透彻研究,逐步形成自己的知识体系和技术框架。 ... [详细]
  • 在 Vue 应用开发中,页面状态管理和跨页面数据传递是常见需求。本文将详细介绍 Vue Router 提供的两种有效方式,帮助开发者高效地实现页面间的数据交互与状态同步,同时分享一些最佳实践和注意事项。 ... [详细]
  • 本文探讨了在Python中使用序列号字符串进行高效模式替换的方法。具体而言,通过将HTML标签中的`&`替换为`{n}`,并生成形如`[tag, {n}]`的哈希原始字符串。示例字符串为:“这是一个字符串。这是另一部分。”该方法能够有效提升替换操作的性能和可读性。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 掌握PHP编程必备知识与技巧——全面教程在当今的PHP开发中,了解并运用最新的技术和最佳实践至关重要。本教程将详细介绍PHP编程的核心知识与实用技巧。首先,确保你正在使用PHP 5.3或更高版本,最好是最新版本,以充分利用其性能优化和新特性。此外,我们还将探讨代码结构、安全性和性能优化等方面的内容,帮助你成为一名更高效的PHP开发者。 ... [详细]
  • Nginx不仅是一款轻量级的高性能Web服务器,还具备出色的负载均衡和反向代理功能。它支持复杂的正则匹配规则、动静内容分离以及灵活的URL重写功能,使得配置和管理更加便捷高效。此外,Nginx提供了多种负载均衡算法,如轮询、加权轮询、最少连接数等,以满足不同应用场景的需求。 ... [详细]
  • 如何在PHP中有效实现和管理互斥锁机制(PHP锁) ... [详细]
  • Python与R语言在功能和应用场景上各有优势。尽管R语言在统计分析和数据可视化方面具有更强的专业性,但Python作为一种通用编程语言,适用于更广泛的领域,包括Web开发、自动化脚本和机器学习等。对于初学者而言,Python的学习曲线更为平缓,上手更加容易。此外,Python拥有庞大的社区支持和丰富的第三方库,使其在实际应用中更具灵活性和扩展性。 ... [详细]
  • Android目录遍历工具 | AppCrawler自动化测试进阶(第二部分):个性化配置详解
    终于迎来了“足不出户也能为社会贡献力量”的时刻,但有追求的测试工程师绝不会让自己的生活变得乏味。与其在家消磨时光,不如利用这段时间深入研究和提升自己的技术能力,特别是对AppCrawler自动化测试工具的个性化配置进行详细探索。这不仅能够提高测试效率,还能为项目带来更多的价值。 ... [详细]
  • 【Python爬虫实操】 不创作小说,专精网站内容迁移,超高效!(含源代码)
    本文详细介绍了如何利用Python爬虫技术实现高效网站内容迁移,涵盖前端、后端及Android相关知识点。通过具体实例和源代码,展示了如何精准抓取并迁移网站内容,适合对Python爬虫实战感兴趣的开发者参考。 ... [详细]
author-avatar
手机用户2502894731
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有