简单多层全连接神经网络

1.简单多层全链接前向网络

1.1模拟神经元

        脑神经元收到一个输入的信号,经过不同的突触、信号进入神经元,接着通过神经元内部的激活处理,最后沿着神经元的轴突输出一个信号,这个轴突通过与下一个神经元的突触相连,从而将输出信号传到下一个神经元。

       在神经网络的计算模型中,输入信号就是我们的输入数据,模型的参数就相当于突触,然后输入信号传入神经元就像是输入的数据和模型参数进行线性组合,然后经过激活函数,最后传出模型。

1.2单层神经网络分类器

        一个神经元可以对一个输入进行不同的操作,可以是“喜欢(激活变大),或者是“不喜欢(激活变小)”,正是由于激活函数的作用,我们可以将一层神经网络用作分类器,正样本就让激活函数激活变大,负样本就让激活函数激活变小。

1.3激活函数

⑴Sigmoid

        Sigmoid非线性激活函数的数学表达式是\sigma (x)=\frac{1}{1+e^{-x}},Sigmoid函数是将一个实数转化为0~1之间输出,但该函数近几年很少有人再使用了,原因是因为Sigmoid有两大缺点。

        缺点1:Sigmoid函数会造成梯度消失,Sigmoid函数在靠近1和0的两端时,梯度会几乎变成0,如果梯度接近0,那么没有任何信息来更新参数,这样就会造成模型不收敛。另外在初始化权重参数的时候也需要小心,如果初始化的太大,那么经过激活函数也会使得大多数神经元变得饱和,没有办法更新参数。

        缺点2:Sigmoid输出不是以0为均值,这就会导致经过Sigmoid激活函数之后的输出,作为后面一层网络的输入的时候是非0均值的,这个时候如果输入进入下一层神经元的时候全是正的,那么就会导致梯度全都是正的,那么更细参数的时候永远都是正梯度。

⑵Tanh

        Tanh激活函数是上面Sigmoid激活函数的变形,其数学表达式为tanh(x)=2\sigma (2x)-1,图形如下图所

       它将输入数据转换到了-1~1之间,它将输出变成了0均值,一定程度上解决了sigmoid函数的第二个缺点,但是仍然上也存在着梯度下降的问题,因此实际上Tanh总是比Sigmoid更好。

⑶ReLU

       ReLU激活函数近几年越来越流行,它的数学表达式为f(x)=max(0,x),其实就是将大于0的保留,小于0的变成0,如下图:

       优点:

       (1)ReLu激活函数能够极大地加速随机梯度下降法的收敛速度,因为他是线性的,且不存在梯度消失的问题。

       (2)相比于Sigmoid和Tanh函数的复杂计算而言,ReLu的计算方法更简单,只需要一个阈值过滤就可以得到结果,不需要进行一大堆复杂计算。

        缺点: 

        训练的时候很脆弱,比如一个很大的梯度,经过ReLu激活函数,更新参数之后,会使得这个神经元不会对任何数据有激活现象,此时ReLu的梯度将是0,参数也不会发生更新实际操作中,可以通过设置比较小的学习率来避免这个问题。

⑷Leaky ReLu

       Leaky ReLu激活函数是ReLu激活函数的变式,主要是为了修复ReLu激活函数中训练比较脆弱这个问题,不将x<0的变成0,而是把它变成一个很小的负斜率,比如0.01,它的数学形式表示为f(x)=I(x<0)(\alpha (x))+I(x\geqslant 0)(x),其中,\alpha是一个很小的参数。但是这个激活函数效果众说纷纭,有的说好有的说不好。

⑸Maxout

        这种激活函数是max(w1x+b1,w2x+b2)这种Maxout类型,ReLu是Maxout的一种特殊形式,因此Maxout既有ReLu的优点,也避免了ReLu激活函数训练脆弱的缺点,不过他的缺点就是 加倍了模型的参数,会导致模型的存储变大。

1.4神经网络结构

       神经网络是一个由神经元构成的无环图,换句话说一些神经元的输出会变成另外一些神经元的输入,环是不被允许的,因为这样会造成网络中的无限循环,同时,神经网络一般是以层来组织的,最常见的神经网络就是全链接神经网络,两个相邻层中,每一个层的所有神经元和另一个层的所有神经元相连,如下图所示:

1.5模型的表示能力与容量

       从数学的角度来解释神经网络,那么神经网络就是由网格中的参数决定的函数簇,拥有至少一个隐藏层的神经网络可以逼近任何的连续函数,即可以表达任何连续函数。在实际中,我们发现一个三层的全连接神经网络比一个两层的全连接神经网络表现的更好。但是模型容量太大节点太多又会导致过拟合,所有我们希望使用大容量的网络去训练模型,同时运营一些方法来控制网络过拟合。

2.反向传播算法 

       反向传播算法就是一个有效的求解梯度的算法。

2.1链式法则

       比如f(x,y,z)=(x+y)z,我们关心的问题是\frac{\partial f}{\partial x}  \frac{\partial f}{\partial y}  \frac{\partial f}{\partial z},链式法则来告诉我们怎么来求它的值。

从链式法则我们知道,如果需要对其中元素求导,我们可以一层一层的求导,最后将结果乘起来,这就是反向传播的核心。

2.2反向传播算法

      本质上 反向传播算法是链式法则的一个应用,还是上面那个例子,q=x+y,f=qz,可将计算过程表达出来。我们让x,y,z的值分别为-2,5和 -4。

       

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单多层全连接神经网络的 Python 代码示例: ```python import numpy as np class NeuralNetwork: def __init__(self, num_inputs, num_hidden_layers, num_hidden_units, num_outputs): self.num_inputs = num_inputs self.num_hidden_layers = num_hidden_layers self.num_hidden_units = num_hidden_units self.num_outputs = num_outputs # 初始化权重和偏置 self.weights = [] self.biases = [] for i in range(self.num_hidden_layers + 1): if i == 0: self.weights.append(np.random.randn(self.num_inputs, self.num_hidden_units)) self.biases.append(np.zeros((1, self.num_hidden_units))) elif i == self.num_hidden_layers: self.weights.append(np.random.randn(self.num_hidden_units, self.num_outputs)) self.biases.append(np.zeros((1, self.num_outputs))) else: self.weights.append(np.random.randn(self.num_hidden_units, self.num_hidden_units)) self.biases.append(np.zeros((1, self.num_hidden_units))) def sigmoid(self, x): return 1 / (1 + np.exp(-x)) def sigmoid_derivative(self, x): return x * (1 - x) def forward(self, x): self.hidden_outputs = [] self.activations = [] for i in range(self.num_hidden_layers + 1): if i == 0: activation = np.dot(x, self.weights[0]) + self.biases[0] hidden_output = self.sigmoid(activation) self.activations.append(activation) self.hidden_outputs.append(hidden_output) elif i == self.num_hidden_layers: activation = np.dot(self.hidden_outputs[-1], self.weights[-1]) + self.biases[-1] output = self.sigmoid(activation) self.activations.append(activation) self.output = output else: activation = np.dot(self.hidden_outputs[-1], self.weights[i]) + self.biases[i] hidden_output = self.sigmoid(activation) self.activations.append(activation) self.hidden_outputs.append(hidden_output) return self.output def backward(self, x, y, learning_rate): # 反向传播 error = y - self.output delta = error * self.sigmoid_derivative(self.output) self.weights[-1] += learning_rate * np.dot(self.hidden_outputs[-1].T, delta) self.biases[-1] += learning_rate * np.sum(delta, axis=0, keepdims=True) for i in range(self.num_hidden_layers - 1, -1, -1): error = np.dot(delta, self.weights[i+1].T) delta = error * self.sigmoid_derivative(self.hidden_outputs[i+1]) self.weights[i] += learning_rate * np.dot(self.hidden_outputs[i].T, delta) self.biases[i] += learning_rate * np.sum(delta, axis=0, keepdims=True) error = np.dot(delta, self.weights[1].T) delta = error * self.sigmoid_derivative(self.hidden_outputs[0]) self.weights[0] += learning_rate * np.dot(x.T, delta) self.biases[0] += learning_rate * np.sum(delta, axis=0) def train(self, x_train, y_train, num_epochs, learning_rate): for i in range(num_epochs): for j in range(x_train.shape[0]): x = x_train[j] y = y_train[j] output = self.forward(x) self.backward(x, y, learning_rate) def predict(self, x_test): predictions = [] for x in x_test: output = self.forward(x) predictions.append(output) return predictions ``` 这个神经网络有 `num_hidden_layers` 层隐藏层,每层有 `num_hidden_units` 个神经元,输入维度为 `num_inputs`,输出维度为 `num_outputs`。`forward` 方法用于执行前向传播,`backward` 方法用于执行反向传播,`train` 方法用于训练模型,`predict` 方法用于进行预测。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值