1.神经网络基础知识

news2024/9/22 2:12:18

所有有用的计算机系统都有一个输入和一个输出, 并在输入和输出之间进行某种类型的计算。 神经网络也是如此。

当我们不能精确知道一些事情如何运作时, 我们可以尝试使用模型来估计其运作方式, 在模型中, 包括了我们可以调整的参数。 如果我们不知道如何将千米转换为英里, 那么我们可以使用线性函数作为模型, 并使用可调节的梯度值作为参数。

改进这些模型的一种好方法是, 基于模型和已知真实示例之间的比较, 得到模型偏移的误差值, 调整参数——迭代。


我们使用简单的数学, 理解了线性分类器输出误差值和可调节斜率参数之间的关系。 也就是说, 我们知道了在何种程度上调整斜率, 可以消除输出误差值:
y = A x y=Ax y=Ax

E = ( Δ A ) x E=(\Delta A)x E=(ΔA)x

使用朴素的调整方法会出现一个问题, 即改进后的模型只与最后一次训练样本最匹配, “有效地”忽略了所有以前的训练样本。

image-20230825223804481

解决这个问题的一种好方法是使用学习率, 调节改进速率, 这样单一的训练样本就不能主导整个学习过程。
Δ A = 学习率 L ( E / x ) \Delta A={\text{学习率}}L(E/x) ΔA=学习率L(E/x)
来自真实世界的训练样本可能充满噪声或包含错误。 适度更新有助于限制这些错误样本的影响。


线性分类器可以学习部分布尔函数:

image-20230825224216722

如果数据本身不是由单一线性过程支配, 那么一个简单的线性分类器不能对数据进行划分。 例如, 由逻辑XOR运算符支配的数据说明了这一点。

但是解决方案很容易, 你只需要使用多个线性分类器来划分由单一直线无法分离的数据。

image-20230825224246752


生物大脑的基本单元——即神经元——可以接收一个电输入,输出另一个电信号,但是我们不能将神经元表示为线性函数,因为神经元不会立即反应, 而是会抑制输入, 直到输入增强,强大到可以触发输出。 你可以这样认为, 在产生输出之前, 输入必须到达一个阈值。

image-20230825230346774

我们可以使用更平滑的S形函数制作神经网络

image-20230825230443868

S函数,有时也称为逻辑函数:
y = 1 1 + e − x y=\frac{1}{1+e^{-x}} y=1+ex1
当然,生物神经元可以接受许多输入,在函数中,对于所有这些输入, 我们只需对它们进行相加,得到最终总和, 作为S函数的输入, 然后输出结果。 这实际上反映了神经元的工作机制。

image-20230825231204029

每个神经元接受来自其之前多个神经元的输入,并且如果神经元被激发了, 它也同时提供信号给更多的神经元。

将这种自然形式复制到人造模型的一种方法是, 构建多层神经元, 每一层中的神经元都与在其前后层的神经元互相连接。

image-20230825231316729

我们可以在多层神经元的连接上添加权重,从而弱化或放大信号,其权重值会随着神经网络的学习而按需变化,因此对于解决特定任务所需最小数量的连接冗余几个连接,也无伤大雅,因为它们的权重会逐渐接近零,即断开了链接。

image-20230825234906484


为了简化神经网络的计算,我们使用矩阵

image-20230825235119252

第一个矩阵包含两层节点之间的权重。 第二个矩阵包含第一层输入层的信号。 通过两个矩阵相乘, 我们得到的答案是输入到第二层节点组合调节后的信号。

image-20230825235150779
组合调节后的信号 X = 权重矩阵 W ⋅ 输入矩阵 I {\text{组合调节后的信号}}X={\text{权重矩阵}}W \cdot {\text{输入矩阵}}I 组合调节后的信号X=权重矩阵W输入矩阵I
表达式X = W I适用于前后层之间的计算,之后对X矩阵的各值带入S函数计算即可


最左边的输入为输入层,最右边的输出为输出层,中间的多层为隐藏层


我们可以通过输出的误差来反向调节输入(反向传播),一种思想就是在所有造成误差的节点中平分误差,另一种思想是不等分误差。 与前一种思想相反, 我们为较大链接权重的连接分配更多的误差,因为这些链接对造成误差的贡献较大。
误差 e 1 ⋅ w 1 , 1 w 1 , 1 + w 2 , 2 {\text{误差}}e_1 \cdot {\frac {w_{1,1}}{w_{1,1}+w_{2,2}} } 误差e1w1,1+w2,2w1,1
对于多层网络,我们从最终输出层往回工作,对于隐藏层的节点, 我们没有目标值或所希望的输出值。 我们只有最终输出层节点的目标值, 这个目标值来自于训练样本数据。隐藏层第一个节点具有两个链接, 这两个链接将这个节点连接到两个输出层节点。 我们知道, 沿着各个链接可以分割输出误差, 就像我们先前所做的一样。 这意味着, 对于中间层节点的每个链接, 我们得到了某种误差值。 我们可以重组这两个链接的误差, 形成这个节点的误差。 实际上我们没有中间层节点的目标值, 因此这种方法算得上第二最佳方法

image-20230826103416874
e h i d d e n , 1 = 链接 w 1 , 1 上的分割误差 + 链接 w 1 , 2 上的分割误差 = e o u t p u t , 1 ⋅ w 1 , 1 w 1 , 1 + w 2 , 2 + e o u t p u t , 2 ⋅ w 1 , 2 w 1 , 1 + w 2 , 2 \begin{aligned} e_{hidden,1} &= {\text{链接}}w_{1,1}上的分割误差 + {\text{链接}}w_{1,2}上的分割误差 \\ &=e_{output,1} \cdot {\frac {w_{1,1}}{w_{1,1}+w_{2,2}}} + e_{output,2} \cdot {\frac {w_{1,2}}{w_{1,1}+w_{2,2}}} \end{aligned} ehidden,1=链接w1,1上的分割误差+链接w1,2上的分割误差=eoutput,1w1,1+w2,2w1,1+eoutput,2w1,1+w2,2w1,2
image-20230826104030405

我们可以为隐藏层的误差构建矩阵,从而简化运算

image-20230826105155199

分数的分母是一种归一化因子。 如果我们忽略了这个因子, 那么我们仅仅失去后馈误差的大小。

image-20230826105231291

实践证明, 这种相对简单的误差信号反馈方式, 与我们先前相对复杂的方式一样有效。


知道了误差,我们使用梯度下降——每走一步就观察地形,一步步下山——的方式更新权重,同时,要更好地到达目标,我们要动态地变化“步幅”,这就需要使用合适的误差函数:

image-20230826114106696

我们更喜欢使用第三种误差函数, 而不喜欢使用第二种误差函数, 原因有以下几点:

  1. 使用误差的平方, 我们可以很容易使用代数计算出梯度下降的斜率。
  2. 误差函数平滑连续, 这使得梯度下降法很好地发挥作用——没有间断, 也没有突然的跳跃。
  3. 越接近最小值, 梯度越小, 这意味着, 如果我们使用这个函数调节步长, 超调的风险就会变得较小。

要使用梯度下降的方法, 现在我们需要计算出误差函数相对于权重的斜率。此处,我们感兴趣的是, 误差函数是如何依赖于神经网络中的链接权重的。 换句话说:“误差对链接权重的改变有多敏感? ”
∂ E ∂ w j , k \frac{\partial E}{\partial w_{j,k}} wj,kE
这个表达式表示了当权重 wj,k 改变时, 误差E是如何改变的。 这是误差函数的斜率, 也就是我们希望使用梯度下降的方法到达最小值的方向。

image-20230826153052402

首先展开误差函数, 这是对目标值和实际值之差的平方进行求和, 这是针对所有n个输出节点的和。
∂ E ∂ w j , k = ∂ ∑ n ( t n − o n ) 2 ∂ w j , k \frac{\partial E}{\partial w_{j,k}}={\frac{\partial \sum_n(t_n-o_n)^2}{\partial w_{j,k}}} wj,kE=wj,kn(tnon)2
节点n的输出 on 只取决于连接到这个节点的链接, 因此我们可以直接简化这个表达式。这意味着, 由于 wj,k 是链接到节点k的权重, 因此节点k的输出 ok 只取决于权重 wj,k ,除了权重 wj,k 所链接的节点(也就是 ok )外,我们可以从和中删除所有的 on , 这就完全删除了令人厌烦的求和运算。
∂ E ∂ w j , k = ∂ ( t k − o k ) 2 ∂ w j , k \frac{\partial E}{\partial w_{j,k}}={\frac{\partial(t_k-o_k)^2}{\partial w_{j,k}}} wj,kE=wj,k(tkok)2
使用链式法则可得
∂ E ∂ w j , k = ∂ ( t k − o k ) 2 ∂ o k ⋅ ∂ o k ∂ w j , k = − 2 ( t k − o k ) ⋅ ∂ o k ∂ w j , k \begin{aligned} \frac{\partial E}{\partial w_{j,k}}&={\frac{\partial(t_k-o_k)^2}{\partial o_k}} \cdot {\frac{\partial o_k}{\partial w_{j,k}}}\\ &=-2(t_k - o_k)\cdot {\frac{\partial o_k}{\partial w_{j,k}}} \end{aligned} wj,kE=ok(tkok)2wj,kok=2(tkok)wj,kok
ok 是节点k的输出,是在连接输入信号上进行加权求和, 在所得到结果上应用S函数得到的结果。
∂ E ∂ w j , k = − 2 ( t k − o k ) ⋅ ∂ s i g m o i d ( ∑ j w j , k ⋅ o j ) ∂ w j , k \frac{\partial E}{\partial w_{j,k}}=-2(t_k - o_k) \cdot {\frac{\partial {sigmoid(\sum_jw_{j,k}\cdot o_j)}}{\partial w_{j,k}}} wj,kE=2(tkok)wj,ksigmoid(jwj,koj)
oj 是前一个隐藏层节点的输出, 而不是最终层的输出 ok

S函数的微分公式:
∂ s i g m o i d ( x ) ∂ x = s i g m o i d ( x ) ⋅ ( 1 − s i g m o i d ( x ) ) \frac{\partial sigmoid(x)}{\partial x}=sigmoid(x) \cdot (1-sigmoid(x)) xsigmoid(x)=sigmoid(x)(1sigmoid(x))
带入可得:
∂ E ∂ w j , k = − 2 ( t k − o k ) ⋅ ∂ s i g m o i d ( ∑ j w j , k ⋅ o j ) ∂ ∑ j w j , k ⋅ o j ⋅ ∂ ∑ j w j , k ⋅ o j ∂ w j , k = − 2 ( t k − o k ) ⋅ s i g m o i d ( ∑ j w j , k ⋅ o j ) ⋅ ( 1 − s i g m o i d ( ∑ j w j , k ⋅ o j ) ) ⋅ ∂ ∑ j w j , k ⋅ o j ∂ w j , k = − 2 ( t k − o k ) ⋅ s i g m o i d ( ∑ j w j , k ⋅ o j ) ⋅ ( 1 − s i g m o i d ( ∑ j w j , k ⋅ o j ) ) ⋅ o j \begin{aligned} \frac{\partial E}{\partial w_{j,k}}&=-2(t_k - o_k) \cdot {\frac{\partial {sigmoid(\sum_jw_{j,k}\cdot o_j)}}{\partial \sum_jw_{j,k}\cdot o_j}}\cdot {\frac{\partial \sum_jw_{j,k}\cdot o_j}{\partial w_{j,k}}}\\ &=-2(t_k - o_k) \cdot sigmoid(\sum_jw_{j,k}\cdot o_j)\cdot (1-sigmoid(\sum_jw_{j,k}\cdot o_j))\cdot {\frac{\partial \sum_jw_{j,k}\cdot o_j}{\partial w_{j,k}}}\\ &=-2(t_k - o_k) \cdot sigmoid(\sum_jw_{j,k}\cdot o_j)\cdot (1-sigmoid(\sum_jw_{j,k}\cdot o_j))\cdot o_j \end{aligned} wj,kE=2(tkok)jwj,kojsigmoid(jwj,koj)wj,kjwj,koj=2(tkok)sigmoid(jwj,koj)(1sigmoid(jwj,koj))wj,kjwj,koj=2(tkok)sigmoid(jwj,koj)(1sigmoid(jwj,koj))oj
去掉倍数2。我们只对误差函数的斜率方向感兴趣, 这样我们就可以使用梯度下降的方法, 因此可以去掉2。
∂ E ∂ w j , k = − ( t k − o k ) ⋅ s i g m o i d ( ∑ j w j , k ⋅ o j ) ( 1 − s i g m o i d ( ∑ j w j , k ⋅ o j ) ) ⋅ o j \frac{\partial E}{\partial w_{j,k}}=-(t_k - o_k) \cdot sigmoid(\sum_jw_{j,k}\cdot o_j)(1-sigmoid(\sum_jw_{j,k}\cdot o_j))\cdot o_j wj,kE=(tkok)sigmoid(jwj,koj)(1sigmoid(jwj,koj))oj
第一部分, 非常简单, 就是(目标值-实际值),我们对此已经很清楚了。 第二部分,在sigmoid中的求和表达式也很简单, 就是进入最后一层节点的信号,我们可以称之为 ik , 这样它看起来比较简单。 这是应用激活函数之前, 进入节点的信号。 最后一部分是前一隐藏层节点j的输出。

我们所得到的这个表达式, 是为了优化隐藏层和输出层之间的权重。 现在, 我们需要完成工作, 为输入层和隐藏层之间的权重找到类似的误差斜率
∂ E ∂ w i , j = − ( e j ) ⋅ s i g m o i d ( ∑ i w i , j ⋅ o i ) ( 1 − s i g m o i d ( ∑ i w i , j ⋅ o i ) ) ⋅ o i \frac{\partial E}{\partial w_{i,j}}=-(e_j) \cdot sigmoid(\sum_iw_{i,j}\cdot o_i)(1-sigmoid(\sum_iw_{i,j}\cdot o_i))\cdot o_i wi,jE=(ej)sigmoid(iwi,joi)(1sigmoid(iwi,joi))oi
第一部分的(目标值-实际值)误差,现在变成了隐藏层节点中重组的向后传播误差,正如在前面所看到的那样, 我们称之为 ej 。sigmoid部分可以保持不变, 但是内部的求和表达式指的是前一层, 因此求和的范围是所有由权重调节的进入隐藏层节点j的输入。 我们可以称之为 ij 。现在,最后一部分是第一层节点的输出 oi , 这碰巧是输入信号。

我们使用学习因子调节变化, 我们可以根据特定的问题, 调整这个学习因子。 当我们建立线性分类器,它作为避免被错误的训练样本拉得太远的一种方式, 同时也为了保证权重不会由于持续的超调而在最小值附近来回摆动。
new w j , k = old w j , k − α ⋅ ∂ E ∂ w j , k {\text{new}w_{j,k}}={\text{old}}w_{j,k}-\alpha \cdot {\frac{\partial E}{\partial w_{j,k}}} newwj,k=oldwj,kαwj,kE
更新后的权重 wj,k 是由刚刚得到误差斜率取反来调整旧的权重而得到的。正如我们先前所看到的,如果斜率为正,我们希望减小权重,如果斜率为负,我们希望增加权重,因此,我们要对斜率取反。

通过矩阵计算:

image-20230826161832815

权重改变矩阵中包含的值, 这些值可以调整链接权重 wj,k ,这个权重链接了当前层节点j与下一层节点k。你可以发现,表达式中的第一项使用下一层(节点k)的值,最后一项使用前一层(节点j)的值

权重更新矩阵有如下的矩阵形式, 这种形式可以让我们通过计算机编程语言高效地实现矩阵运算。

image-20230826162327765


S激活函数,如果输入变大,函数会变得平坦,由于我们使用梯度学习新的权重, 因此一个平坦的激活函数会出问题。

权重的改变取决于激活函数的梯度,小梯度意味着限制神经网络学习的能力,这就是所谓的饱和神经网络。 这意味着,我们应该尽量保持小的输入。同时还取决于输入信号 oj ,因此,我们也不应
该让输入信号太小。当计算机处理非常小或非常大的数字时,可能会丧失精度,因此,使用非常小的值也会出现问题。

重新调整输入值,将其范围控制在0.0到1.0。输入0会将 oj 设置为0,这样权重更新表达式就会等于0,从而造成学习能力的丧失, 因此在某些情况下, 我们会将此输入加上一个小小的偏移, 如0.01,避免输入0带来麻烦。


S激活函数的输出不可能大于1.0、小于0。如果我们将目标值设置在这些不可能达到的范围, 训练网络将会驱使更大的权重, 以获得越来越大的输出, 而这些输出实际上是不可能由激活函数生成的。 这使得网络饱和, 因此我们知道这种情况是很糟糕的。

因此, 我们应该重新调整目标值, 匹配激活函数的可能输出, 注意避开激活函数不可能达到的值。虽然, 常见的使用范围为0.0~1.0, 但是由于0.0和1.0这两个数也不可能是目标值, 并且有驱动产生过大的权重的风险, 因此一些人也使用0.01~0.99的范围。


内部链接的权重应该是随机的, 值较小, 但要避免零值。 如果节点的传入链接较多, 有一些人会使用相对复杂的规则, 如减小这些权重的大小。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/936644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4-1-netty

非阻塞io 服务端就一个线程,可以处理无数个连接 收到所有的连接都放到集合channelList里面 selector是有事件集合的 对server来说优先关注连接事件 遍历连接事件

list(介绍与实现)

目录 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modififiers 1.2.6 list的迭代器失效 2. list的模拟实现 2.1 模拟实现list 2.2 list的反向迭代器 1.…

Python 潮流周刊#17:Excel 终于支持 Python 了、Meta 重磅开源新项目、Mojo 新得 1 亿美元融资...

△点击上方“Python猫”关注 ,回复“1”领取电子书 你好,我是猫哥。这里每周分享优质的 Python、AI 及通用技术内容,大部分为英文。标题取自其中三则分享,不代表全部内容都是该主题,特此声明。 本周刊由 Python猫 出品…

内核模块添加功能及使用(静态、动态)

一、向内核添加新功能 1.1 静态加载法&#xff1a; 即新功能源码与内核其它代码一起编译进uImage文件内 新功能源码与Linux内核源码在同一目录结构下 在linux-3.14/driver/char/目录下编写myhello.c&#xff0c;文件内容如下&#xff1a; #include <linux/module.h> #i…

如何使用腾讯云服务器搭建网站?

使用腾讯云服务器搭建网站全流程&#xff0c;包括轻量应用服务器和云服务器CVM建站教程&#xff0c;轻量可以使用应用镜像一键建站&#xff0c;云服务器CVM可以通过安装宝塔面板的方式来搭建网站&#xff0c;腾讯云服务器网分享使用腾讯云服务器建站教程&#xff0c;新手站长搭…

【深度学习】Pytorch训练过程中损失值出现NaN

项目场景 利用Pytorch框架&#xff0c;结合FEDformer开源代码&#xff08;https://github.com/MAZiqing/FEDformer&#xff09;&#xff0c;将自己的数据集作为输入训练模型。 问题描述 训练过程中&#xff0c;发现打印出来的Train loss, Test loss, Test loss中&#xff0c…

【产品文档】团队介绍PPT模板

今天和大家免费分享团队介绍的PPT模板。团队介绍是向他人展示团队的实力、专业性和能力的重要方式。通过一个有力的团队介绍&#xff0c;您可以突出团队的成员、经验、技能和取得的成就&#xff0c;从而增加信任、吸引合作伙伴、客户或投资者的兴趣 【模板预览】 动态演示效果…

API管理风险:如何确保您的API安全与可靠?

API管理风险&#xff1a;如何确保您的API安全与可靠&#xff1f; 随着数字化时代的到来&#xff0c;应用程序接口&#xff08;API&#xff09;在现代软件开发中发挥着关键的作用。然而&#xff0c;API管理过程中存在着各种潜在的风险。本文将探讨如何有效地管理和缓解这些风险…

前端将file文件传给后台,后台将文件传给前台(包含上传下载)

前端将file文件传给后台&#xff0c;后台将文件传给前台&#xff08;包含上传下载&#xff09; 在开发过程中&#xff0c;经常会遇见对文件的处理。 例如&#xff1a;在上传、下载文件时&#xff0c;需要在前端选完文件传到后台传到服务器&#xff1b;或者文件从后台&#xf…

001微信小程序云开发 API数据库-导入/导出

文章目录 微信小程序云开发 API数据库-导入案例代码微信小程序云开发API数据库-导出案例代码 微信小程序云开发 API数据库-导入 随着移动互联网的普及&#xff0c;微信小程序已经成为一种受欢迎的应用形式。微信小程序云开发 API 数据库是微信小程序的一项重要功能&#xff0c…

msvcp140.dll重新安装的解决方法,msvcp140.dll丢失解决方案

今天&#xff0c;我将向大家传授一种与我们的日常生活紧密相连的技巧——解决msvcp140.dll重新安装的方法。在这个信息爆炸的时代&#xff0c;每个人就像是在纷繁复杂的电脑问题中航行的船只&#xff0c;随时可能遭遇各种故障和问题。 首先&#xff0c;让我们来了解一下msvcp14…

Modbus转Profinet网关应用在自动上料机案例

该案例中的自动上料机通过使用Modbus转Profinet网关实现了与1200PLC和G120变频器的通信。这种通信方式能够实现设备之间的数据交换和控制命令传输&#xff0c;大大提升了自动上料机的运行效率和精度。通过使用该网关&#xff0c;1200PLC可以准确地向G120变频器发送控制命令&…

RK3399平台开发系列讲解(存储篇)Linux 存储系统的 I/O 栈

平台内核版本安卓版本RK3399Linux4.4Android7.1🚀返回专栏总目录 文章目录 一、Linux 存储系统全景二、Linux 存储系统的缓存沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 Linux 存储系统的 I/O 原理。 一、Linux 存储系统全景 我们可以把 Linux 存储系…

vue2 路由进阶,VueCli 自定义创建项目

一、声明式导航-导航链接 1.需求 实现导航高亮效果 如果使用a标签进行跳转的话&#xff0c;需要给当前跳转的导航加样式&#xff0c;同时要移除上一个a标签的样式&#xff0c;太麻烦&#xff01;&#xff01;&#xff01; 2.解决方案 vue-router 提供了一个全局组件 router…

2000-2021年上市公司绿色投资环保投资与营业收入之比数据(原始数据+计算代码+计算结果)

2000-2021年上市公司绿色投资环保投资与营业收入之比数据&#xff08;原始数据计算代码计算结果&#xff09; 1、时间&#xff1a;2000-2021年 2、来源&#xff1a;上市公司年报 3、指标&#xff1a;证券代码、企业名称、年份、管理费用环保投资、管理费用环保投资/营业收入…

ARTS打卡第二周之链表环的检测、gdb中disassemble的使用、底层学习建议、学习分享

Algorithm 题目&#xff1a;链表中环的检测 自己的分析见博客《检测链表中是否存在环》 Review disassemble command是我读的一篇英语文章&#xff0c;这篇文章主要是介绍gdb反汇编命令的使用和参数。自己为了能够演示这篇文章里边的内容&#xff0c;特意自己使用汇编语言编…

枫叶时代:《超能一家人》喜剧电影引发观众无限笑点

近期&#xff0c;由浙江开心麻花影业有限公司、中国电影股份有限公司和上海阿里巴巴影业有限公司三家公司联合出品的喜剧电影《超能一家人》引起了观众们的热烈关注。这部影片由宋阳导演执导&#xff0c;他曾执导过备受好评的作品《羞羞的铁拳》。时长108分钟的《超能一家人》以…

Modbus转Profinet网关与流量变送器兼容转ModbusTCP协议博图配置

首先&#xff0c;我们需要明确电磁流量计的通信协议是Modbus&#xff0c;而西门子1200PLC的通信协议是Profinet。这两种协议在功能和特性上存在一定的差异&#xff0c;因此需要使用兴达易控Modbus转Profinet网关设备进行转换。兴达易控的XD-MDPN100是Profinet转ModbusTCP的网关…

402. 移掉 K 位数字

链接&#xff1a; 402. 移掉 K 位数字 题解&#xff1a; class Solution { public:string removeKdigits(string num, int k) {vector<char> stk;for (auto& digit: num) {while (stk.size() > 0 && stk.back() > digit && k) {stk.pop_bac…