网站的前端开发,网站模,网站底部优化字,openshift安装wordpress文章目录 多层深度神经网络一.黑箱#xff1a;深层神经网络的不可解释性二.多元神经网络#xff1a; 层与 h ( z ) h(z) h(z)三.激活函数 多层深度神经网络
从单层到多层是神经网络发展史上的重大变化#xff0c;层的增加彻底将神经网络的性能提升到了另一个高度#xff0… 文章目录 多层深度神经网络一.黑箱深层神经网络的不可解释性二.多元神经网络 层与 h ( z ) h(z) h(z)三.激活函数 多层深度神经网络
从单层到多层是神经网络发展史上的重大变化层的增加彻底将神经网络的性能提升到了另一个高度正确理解层的意义对于我们自主构建神经网络有很重要的作用学会利用层是避免浪费计算资源以及提升神经网络效果的关键。
一.黑箱深层神经网络的不可解释性 首先从结构上来看多层神经网络比单层神经网络多出了“中间层”。中间层常常被称为隐藏层hidden layer理论上来说可以有无限层所以在图像表示中经常被省略。层数越多神经网络的模型复杂度越高一般也认为更深的神经网络可以解决更加复杂的问题。在学习中通常我们最多只会设置3~5个隐藏层但在实际工业场景中会更多。还记得这张图吗当数据量够大时现代神经网络层数越深效果越好。
在一个神经网络中更靠近输入层的层级相对于其他层级叫做上层更靠近输出层的则相对于其他层级叫做下层。若从输入层开始从左向右编号则输入层为第0层输出层为最后一层。除了输入层以外每个神经元中都存在着对数据进行处理的数个函数。在我们的例子异或门XOR中隐藏层中的函数是NAND函数和OR函数也就是线性回归的加和函数阶跃函数输出层上的函数是AND函数。 对于所有神经元和所有层而言加和函数的部分都是一致的都得到结果 z z z因此我们需要关注的是加和之外的那部分函数。在隐藏层中这个函数被称为激活函数符号为 h ( z ) h(z) h(z)在输出层中这个函数只是普通的连接函数我们定义为是 g ( z ) g(z) g(z)。我们的数据被逐层传递每个下层的神经元都必须处理上层的神经元中的 h ( z ) h(z) h(z)处理完毕的数据整个流程本质是一个嵌套计算结果的过程。
在神经网络中任意层上都有至少一个神经元最上面的是常量神经元连接常量神经元的箭头上的参数是截距 b b b剩余的是特征神经元连接这些神经元的箭头上的参数都是权重 ω \omega ω。神经元是从上至下进行编号需要注意的是常量神经元与特征神经元是分别编号的。和从0开始编号的层数不同神经元是从1开始编号的。在异或门的例子中含有1的偏差神经元是1号偏差神经元含有特征 x 1 x_1 x1的神经元则是1号特征神经元。
除了神经元和网络层权重、偏差、神经元上的取值也存在编号。这些编号规律分别如下 二.多元神经网络 层与 h ( z ) h(z) h(z)
我们首先想要发问的隐藏层的作用。在之前的XOR函数中我们提出”多层神经网络能够描绘出一条曲线 作为决策边界以此为基础处理单层神经网络无法处理的复杂问题“这可能让许多人产生了“是增加层 数帮助了神经网络”的错觉。实际上并非如此。 在神经网络的隐藏层中存在两个关键的元素一个是加和函数 另一个是 。除了输入层之外 任何层的任何神经元上都会有加和的性质因为神经元有“多进单出”的性质可以一次性输入多个信 号但是输出只能有一个因此输入神经元的信息必须以某种方式进行整合否则神经元就无法将信息 传递下去而最容易的整合方式就是加和 。因此我们可以认为加和 是神经元自带的性质只要增加 更多的层就会有更多的加和。但是 的存在却不是如此即便隐藏层上没有 或 是一个恒 等函数神经网络依然可以从第一层走到最后一层。让我们来试试看在XOR中假设隐藏层上没有 的话 会发生什么 xorgate torch.tensor([0,1,1,0],dtypetorch.float32)
def AND(X): w torch.tensor([-0.2,0.15, 0.15], dtype torch.float32) zhat torch.mv(X,w) #下面这一行就是阶跃函数的表达式注意AND函数是在输出层所以保留输出层的阶跃函数g(z) andhat torch.tensor([int(x) for x in zhat 0],dtypetorch.float32) return andhat def OR(X): w torch.tensor([-0.08,0.15,0.15], dtype torch.float32) #在这里我修改了b的数 值 zhat torch.mv(X,w) #注释掉阶跃函数相当于h(z)是恒等函数 #yhat torch.tensor([int(x) for x in zhat 0],dtypetorch.float32) return zhatdef NAND(X): w torch.tensor([0.23,-0.15,-0.15], dtype torch.float32) zhat torch.mv(X,w) #注释掉阶跃函数相当于h(z)是恒等函数 #yhat torch.tensor([int(x) for x in zhat 0],dtypetorch.float32) return zhat def XOR(X): #输入值 input_1 X #中间层 sigma_nand NAND(input_1) sigma_or OR(input_1) x0 torch.tensor([[1],[1],[1],[1]],dtypetorch.float32) #输出层input_2 torch.cat((x0,sigma_nand.view(4,1),sigma_or.view(4,1)),dim1) y_and AND(input_2) #print(NANE:,y_nand) #print(OR:,y_or) return y_andXOR(X)很明显此时XOR函数的预测结果与真实的xorgate不一致。当隐藏层的 是恒等函数或不存在时叠 加层并不能够解决XOR这样的非线性问题。从数学上来看这也非常容易理解。 从输出层到第一层 Z 1 W 1 ∗ X b 1 ∑ 1 h ( Z 1 ) ∵ h ( z ) 为恒等函数 ∴ ∑ 1 [ σ 1 1 σ 2 1 ] [ z 1 1 z 1 2 ] Z^1 W^1 * X b^1 \sum^1 h(Z^1) \\ \because h(z)为恒等函数 \\ \therefore \sum^1 \begin{bmatrix} \sigma_1^1\\ \sigma_2^1 \end{bmatrix} \begin{bmatrix} z^1_1\\ z^2_1 \end{bmatrix} Z1W1∗Xb1∑1h(Z1)∵h(z)为恒等函数∴∑1[σ11σ21][z11z12]
从第1层到输出层 Z 2 W 2 ∗ ∑ B 2 [ z 2 1 ] [ w 1 → 1 1 → 2 w 1 → 2 1 → 2 ] ∗ [ σ 1 1 σ 1 2 ] [ b 1 → 1 1 → 2 ] . . . x 1 W 1 x 2 W 2 B 其中 W 1 W 2 和 B 都是常数 Z^2 W^2* \sum B^2 \\ \begin{bmatrix} z^1_2\\ \end{bmatrix} \begin{bmatrix} w^{1\to2}_{1\to1} w^{1\to2}_{1\to2} \end{bmatrix} * \begin{bmatrix} \sigma_1^1\\ \sigma_1^2 \end{bmatrix} \begin{bmatrix} b^{1\to2}_{1\to1} \end{bmatrix} \\ ... \\ x_1W_1 x_2W_2 B其中W1W2和B都是常数 Z2W2∗∑B2[z21][w1→11→2w1→21→2]∗[σ11σ12][b1→11→2]...x1W1x2W2B其中W1W2和B都是常数
不难发现最终从输出层输出的结果和第一层的输出结果 x 1 w 1 1 x 2 w 2 2 b 1 2 x_1w_1^1 x_2w_2^2 b_1^2 x1w11x2w22b12是类似的只不过是乘以特征 x 1 , x 2 x_1,x_2 x1,x2的具体数值不同。在没有 h ( z ) h(z) h(z)时在层中流动的数据被做了仿射变换affine transformation仿射变换后得到的依然是一个线性方程而这样的方程不能解决非线性问题。可见“层”本身不是神经网络解决非线性问题的关键层上的h(z)才是。从上面的例子和数学公式中可以看出如果 h ( z ) h(z) h(z)是线性函数或不存在那增加再多的层也没有用。
那是不是任意非线性函数作为 h ( z ) h(z) h(z)都可以解决问题呢让我们来试试看在XOR例子中如果不使用阶跃函数而使用sigmoid函数作为 h ( z ) h(z) h(z) 会发生什么。 def AND(X): w torch.tensor([-0.2,0.15, 0.15], dtype torch.float32)zhat torch.mv(X,w) #下面这一行就是阶跃函数的表达式注意AND函数是在输出层所以保留输出层的阶跃函数g(z) andhat torch.tensor([int(x) for x in zhat 0],dtypetorch.float32) return andhatdef OR(X): w torch.tensor([-0.08,0.15,0.15], dtype torch.float32) #在这里我修改了b的数 值 zhat torch.mv(X,w) #h(z), 使用sigmoid函数 sigma torch.sigmoid(zhat) return sigmadef NAND(X): w torch.tensor([0.23,-0.15,-0.15], dtype torch.float32) zhat torch.mv(X,w) #h(z), 使用sigmoid函数 sigma torch.sigmoid(zhat) return sigmadef XOR(X): #输入值 input_1 X #中间层 sigma_nand NAND(input_1) sigma_or OR(input_1) x0 torch.tensor([[1],[1],[1],[1]],dtypetorch.float32) #输出层 input_2 torch.cat((x0,sigma_nand.view(4,1),sigma_or.view(4,1)),dim1) y_and AND(input_2) #print(NANE:,y_nand) #print(OR:,y_or) return y_and XOR(X) 可以发现如果将 h ( z ) h(z) h(z)换成sigmoid函数XOR结构的神经网络同样会失效可见即便是使用了 也不一定能够解决曲线分类的问题。在不适合的非线性函数加持下神经网络的层数再多也无法起效。所以 h ( z ) h(z) h(z)是真正能够让神经网络算法“活起来”的关键没有搭配合适 h ( z ) h(z) h(z)的神经网络结构是无用的而 h ( z ) h(z) h(z)正是神经网络中最关键的概念之一激活函数activation function。
三.激活函数 激活函数 在人工神经网络的神经元上根据一组输入定义该神经元的输出结果的函数就是激活函数。激活 函数一般都是非线性函数它出现在神经网络中除了输入层以外的每层的每个神经元上。 机器学习中常用的激活函数只有恒等函数identity function阶跃函数signsigmoid 函数ReLUtanhsoftmax这六种其中Softmax与恒等函数几乎不会出现在隐藏层上Sign、Tanh几乎不会出现在输出层上ReLU与Sigmoid则是两种层都会出现并且应用广泛。 在这里我们将总结性声明一下输出层的g(z)与隐藏层 的h(z)之间的区别以帮助大家获得更深的理解 虽然都是激活函数但隐藏层和输出层上的激活函数作用是完全不一样的。输出层的激活函数 是为了让神经网络能够输出不同类型的标签而存在的。其中恒等函数用于回归sigmoid函数用于 二分类softmax用于多分类。换句说 g ( z ) g(z) g(z)仅仅与输出结果的表现形式有关与神经网络的效果无关也因此它可以使用线性的恒等函数。但隐藏层的激活函数就不同了如我们之前尝试的 XOR隐藏层上的激活函数 h ( z ) h(z) h(z)的选择会影响神经网络的效果而线性的 h ( z ) h(z) h(z)是会让神经网络的结构失效的。 在同一个神经网络中 与 可以是不同的并且在大多数运行回归和多分类的神经网络时 他们也的确是不同的。每层上的 可以是不同的但是同一层上的激活函数必须一致。
现在我们来试试看隐藏层上的 h ( z ) h(z) h(z)是阶跃函数而输出层的 g ( z ) g(z) g(z)是sigmoid的情况。如果XOR网络依然有效就证明了 g ( z ) g(z) g(z)的变化对神经网络结果输出无影响。反之则说明 g ( z ) g(z) g(z)也影响神经网络输出结果。
#如果g(z)是sigmoid函数而h(z)是阶跃函数
#输出层以0.5为sigmoid的阈值
def AND(X): w torch.tensor([-0.2,0.15, 0.15], dtype torch.float32) zhat torch.mv(X,w) sigma torch.sigmoid(zhat) andhat torch.tensor([int(x) for x in sigma 0.5],dtypetorch.float32) return andhat
#隐藏层OR与NAND都使用阶跃函数作为h(z)
def OR(X): w torch.tensor([-0.08,0.15,0.15], dtype torch.float32) #在这里修改了b的数值 zhat torch.mv(X,w) yhat torch.tensor([int(x) for x in zhat 0],dtypetorch.float32) return yhat def NAND(X): w torch.tensor([0.23,-0.15,-0.15], dtype torch.float32) zhat torch.mv(X,w) yhat torch.tensor([int(x) for x in zhat 0],dtypetorch.float32) return yhatdef XOR(X): #输入值 input_1 X #中间层sigma_nand NAND(input_1) sigma_or OR(input_1) x0 torch.tensor([[1],[1],[1],[1]],dtypetorch.float32) #输出层 input_2 torch.cat((x0,sigma_nand.view(4,1),sigma_or.view(4,1)),dim1) y_and AND(input_2) #print(NANE:,y_nand) #print(OR:,y_or) return y_andXOR(X)
从结果可以看出只要隐藏层的 h ( z ) h(z) h(z)是阶跃函数XOR网络就一定能有效这与输出层 g ( z ) g(z) g(z)是什么函数完全无关。从这里开始若没有特别说明当我们提到“激活函数”时特指隐藏层上的激活函数 h ( z ) h(z) h(z)。当需要表达输出层上的激活函数时我们需称其为“输出层激活函数”out_activation。