机器学习笔记 第五章神经网络

5.1 神经元模型

定义:神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所作出的交互反应。

比较具有代表性的模型就是"M-P神经元模型",如图5.1所示,中间的圆圈表示当前神经元,而该神经元又与其他n个神经元连接,并且产生一个输出y。该"M-P神经元模型"的实现流程如下:

神经元接收n个其他神经元出来的输入信号,每个输入信号乘以相应的连接权重;

将以上结果进行求和,再和当前神经元的阈值比较;

若大于,则通过"激活函数"产生输出,否则,不产生输出。

理想中的激活函数是阶跃函数,"1"表示神经元兴奋,"0"表示神经元抑制。由于该阶跃函数不连续不光滑,所以一般用函数来替代,如下图所示。

5.2 感知机与多层网络

定义:感知机由两层神经元组成,分别为输入层和输出层,输入层接收输入信号并且传送给输出层,输出层则是M-P神经元。

作用:能够简易地实现与、或、非逻辑运算。

一般地,给定训练数据集,权重以及阈值已知,感知机学习规则就是对于训练样例,如果当前的感知机输出为,那么权重将如此调整

其中是学习率。从上面的式子可以看出,当,感知机预测正确,感知机没变化;否则要根据错误程度进行权重调整。

如图5.6所示,常见神经网络分为以下两种层级结构。

单隐层前馈网络:输入层只是接受输入,不进行函数处理,隐层与输出层包含功能神经元,且隐层只有一层;

单隐层前馈网络:隐层含有多层,神经元之间不存在同层连接,也不存在跨层连接。

神经网络的学习过程其实就是根据训练数据来调整"连接权"以及每个神经元的阈值,也就是说神经网络学习的就是连接权和阈值的合理调整,使得模型可以比较精准地完成任务。

5.3 误差逆传播算法

感知机学习规则不足以应付多层网络的学习,需要足够强大的学习算法误差逆传播算法,简称BP算法。给定训练集,即输入示例由d个属性描述,输出l维实值向量。如图5.7所示,由d个输入神经元、l个输出神经元、q个隐层神经元组成的多层前馈网络结构,其中输出层阈值用表示,隐层阈值用表示,输入层与隐层连接权用表示,隐层与输出层连接权用表示,则隐层第h个神经元收到的输入为

输出层第j个神经元接收到的输入为

对训练例,神经网络的输出为,其中

均方误差为

BP算法基于梯度下降策略,对目标的负梯度方向对参数进行调整,有

根据的定义,显然有

Sigmoid函数有一个很好的性质

得到BP算法中关于的更新公式

类似的

其中

图5.8给出了BP算法的工作流程

值得注意的是,BP算法的主要目标是最小化训练集D的累积误差,即

累积BP算法与标准BP算法都很常用。一般来说,标准BP算法每次更新只针对单个样例,为了达到相同的累积误差极小点,需要更多次数的迭代。累积BP算法直接针对累积误差最小化,其参数更新的频率低得多。但在很多任务中,往往是累积BP算法和标准BP算法混合使用。

由于BP神经网络强大的表示能力,经常导致过拟合,训练误差降低同时,测试误差也可能上升,为此,有两种策略可以缓解BP网络的过拟合。

"早停":将数据分成训练集和验证集,训练集计算梯度、连接权和阈值,验证集估计误差。若训练误差连续a轮的变化小于b,则停止训练;若训练误差降低、验证误差升高,则停止训练。

正则化:其基本思想是在误差目标函数中增加一个用于描述网络复杂度的部分。

表示第k个训练样例上的误差,表示连接权和阈值,则误差目标函数改变为

通过以下代码,我们将实现一个具有单个隐藏层的神经网络,并使用Sigmoid激活函数。这个示例将包括前向传播、计算损失、反向传播和参数更新。

python 复制代码
import numpy as np  

# Sigmoid激活函数  
def sigmoid(x):  
    return 1 / (1 + np.exp(-x))  

# Sigmoid函数的导数  
def sigmoid_derivative(x):  
    return x * (1 - x)  

class SimpleNeuralNetwork:  
    def __init__(self, input_size, hidden_size, output_size):  
        # 初始化权重  
        self.input_size = input_size  
        self.hidden_size = hidden_size  
        self.output_size = output_size  
        
        # 权重初始化  
        self.weights_input_hidden = np.random.rand(self.input_size, self.hidden_size)  
        self.weights_hidden_output = np.random.rand(self.hidden_size, self.output_size)  
        
        # 偏置初始化  
        self.bias_hidden = np.random.rand(1, self.hidden_size)  
        self.bias_output = np.random.rand(1, self.output_size)  

    def forward(self, X):  
        # 前向传播  
        self.hidden_layer_activation = np.dot(X, self.weights_input_hidden) + self.bias_hidden  
        self.hidden_layer_output = sigmoid(self.hidden_layer_activation)  

        self.output_layer_activation = np.dot(self.hidden_layer_output, self.weights_hidden_output) + self.bias_output  
        output = sigmoid(self.output_layer_activation)  

        return output  

    def backward(self, X, y, output, learning_rate):  
        # 反向传播  
        output_error = y - output  
        output_delta = output_error * sigmoid_derivative(output)  

        hidden_layer_error = output_delta.dot(self.weights_hidden_output.T)  
        hidden_layer_delta = hidden_layer_error * sigmoid_derivative(self.hidden_layer_output)  

        # 更新权重和偏置  
        self.weights_hidden_output += self.hidden_layer_output.T.dot(output_delta) * learning_rate  
        self.bias_output += np.sum(output_delta, axis=0, keepdims=True) * learning_rate  

        self.weights_input_hidden += X.T.dot(hidden_layer_delta) * learning_rate  
        self.bias_hidden += np.sum(hidden_layer_delta, axis=0, keepdims=True) * learning_rate  

    def train(self, X, y, epochs, learning_rate):  
        for epoch in range(epochs):  
            output = self.forward(X)  
            self.backward(X, y, output, learning_rate)  

            # 每1000次epoch打印损失  
            if epoch % 1000 == 0:  
                loss = np.mean(np.square(y - output))  # 均方误差  
                print(f'Epoch {epoch}, Loss: {loss}')  

# 示例训练数据  
if __name__ == "__main__":  
    # 输入数据(XOR数据集)  
    X = np.array([[0, 0],  
                  [0, 1],  
                  [1, 0],  
                  [1, 1]])  

    # 目标输出  
    y = np.array([[0],  
                  [1],  
                  [1],  
                  [0]])  

    # 创建神经网络  
    nn = SimpleNeuralNetwork(input_size=2, hidden_size=2, output_size=1)  

    # 训练神经网络  
    nn.train(X, y, epochs=10000, learning_rate=0.1)  

    # 测试模型  
    print("预测结果:")  
    print(nn.forward(X))  

首先,对以上代码进行说明,Sigmoid函数及其导数用于激活神经元,SimpleNeuralNetwork类实现了神经网络的结构与训练方法,使用XOR数据集训练模型,并输出预测结果。

  • __init__:初始化网络的参数(权重和偏置)。
  • forward:前向传播,用于计算网络的输出。
  • backward:误差反向传播,并更新网络参数。
  • train:训练网络,进行多次迭代以拟合数据。

将代码保存到文件中并运行,结果将展示模型如何学习并打印出每千个epochs的损失和最终的预测结果。通过调节隐层大小、学习率和训练轮数,可以观察不同设置下模型的表现。


参考文献:《机器学习》周志华

相关推荐
t198751282 小时前
神经网络控制的多方法融合:PID、模型预测控制(MPC)与自适应策略
人工智能·深度学习·神经网络
EchoL、2 小时前
浅谈当下深度生成模型:从VAE、GAN、Diffusion、Flow Matching到世界模型
人工智能·神经网络·生成对抗网络
小白探索世界欧耶!~2 小时前
用iframe实现单个系统页面在多个系统中复用
开发语言·前端·javascript·vue.js·经验分享·笔记·iframe
坠金2 小时前
方差、偏差
人工智能·机器学习
brent4232 小时前
DAY47 简单CNN
深度学习·神经网络·cnn
551只玄猫2 小时前
新编大学德语1第三版笔记 第3课Studentenleben
笔记·德语·外语·德语a1·德语笔记·自学德语·新编大学德语
奋斗者1号2 小时前
MQTT连接失败定位步骤
开发语言·机器学习·网络安全
能源系统预测和优化研究2 小时前
传统机器学习(如xgboost、随机森林等)和深度学习(如LSTM等)在时间序列预测各有什么优缺点?
深度学习·随机森林·机器学习
owlion2 小时前
如何将视频文案整理成学习笔记
人工智能·python·机器学习·语言模型·自然语言处理
AI街潜水的八角3 小时前
基于keras框架的MobileNet深度学习神经网络垃圾识别分类系统源码
深度学习·神经网络·keras