神经网络实战前言

应用广泛

  • 从人脸识别到网约车,在生活中无处不在

未来可期

  • 无人驾驶技术便利出行
  • 医疗健康改善民生

产业革命

  • 第四次工业革命——人工智能

机器学习概念

  • 机器学习不等价与人工智能
  • 20世纪50年代,人工智能是说机器模仿人类行为的能力

符号人工智能

  • 基于符号,将人类的知识声明为一种计算机可以处理的形式
  • 专家系统发展于人工智能
  • 模拟人类的决策
  • 缺点是:依赖人类专家的知识,解决问题的规则和认知是被编程的

机器学习

  • 通俗讲,机器从已有的数据中学习并对其他数据做预测

机器学习的基础条件

  • 海量的数据存储能力
  • 强大的运算能力

刚开始科学家使用符号人工智能,但是发现研究进展不顺,随着计算机硬件的提升,机器学习的基础条件得到满足后,AI发展迎来春天。

机器学习算法

有监督分类

  • 标记过的训练数据
  • 学习从输入变量映射到目标变量的规则
  • 例如:降雨(目标变量),温度、时间、气压、风速等等就是输入变量

无监督分类

  • 未经标记过的训练数据
  • 学习数据中的关联规则、模式及类别
  • 常见案例是聚类分析

监督分类的案例

  • 区分两种动物,兔子和大象
  • 收集到的数据有速度和体重
  • 兔子的特征是,体重小,速度快
  • 大象的特征是,体重大,速度慢
  • 机器学习算法的任务就是,找到分割兔子和大象的区别,生成决策边界线,将海量的数据一分为二,线就是决策边界。
  • 有了决策边界,就可以对未知的数据集进行预测,判断类型
  • 不同的学习算法会对最终的结果有影响

常用的机器学习方法包括:

  • 神经网络
  • 线性回归
  • 对数概率回归
  • 支持向量机
  • 决策树

机器学习的工作流程

  1. 输入数据
    1. 多个数据源
  2. 数据预处理
    1. 数据整合
    2. 数据编码
    3. 数据换算和标准化
    4. 补充缺失数据
      1. 均值替换缺失值
      2. 基于存在数据预测缺失值
    5. 训练测试数据分割
  3. 数据分析
    1. 数据可视化
    2. 探索性数据分析
      1. 特征工程
      2. 领域知识加入机器学习
  4. 模型构建
    1. 选择学习模型
    2. 调参
    3. 训练模型
    4. 评估模型
  5. 输出结果
    1. 输出未知数据集的预测结果

神经网络

模拟人类大脑神经元

单层神经网络——感知机

核心:数学函数
过程:输入+运算+输出

为什么神经网络好?

通用函数逼近器

现实生活中的问题总能用数学函数来表征,不论函数有多复杂,神经网络都能对这个函数无限逼近(前提:理想的算力)

可扩展性好且灵活

神经网络的不同堆叠方式和排列组合可以解决各种问题,好的程序员对网络的编排更为熟悉。

神经网络的内部工作原理

  • 输入层
  • 一个或者多个的隐藏层
  • 输出层
  • 每层之间包含权重W和偏差b
  • 为每个隐藏层所选择的激活函数σ

Python中训练神经网络

import numpy as np

class NeuralNetwork:
    def__init__(self,x,y):
        self.input=x
        self.weights1=np.random.rand(self.input.shape[1],4)
        self.weights2=np.random.rand(4,1)
        self.y=y
        self.output=np.zeros(self.y.shape)
  1. import numpy as np:导入NumPy库并将其重命名为np,用于处理数组和矩阵等数学运算。

  2. class NeuralNetwork::定义了一个名为NeuralNetwork的类,用于表示神经网络。

  3. def __init__(self, x, y)::定义了类的构造函数,用于初始化神经网络的参数。

  4. self.input = x:将输入数据x保存到类的属性input中。

  5. self.weights1 = np.random.rand(self.input.shape[1], 4):随机初始化输入层到隐藏层之间的权重矩阵,矩阵大小为输入数据的特征数(x的列数)乘以隐藏层的神经元数(这里设定为4)。

  6. self.weights2 = np.random.rand(4, 1):随机初始化隐藏层到输出层之间的权重矩阵,矩阵大小为隐藏层的神经元数(4)乘以输出值。

  7. self.y = y:将输出数据y保存到类的属性y中。

  8. self.output = np.zeros(self.y.shape):初始化一个和输出数据y相同大小的零矩阵,用于保存神经网络的输出值。

两层神经网络的数学内核

\hat{y} = \sigma\left[W_2\sigma(W_1x + b_1) + b_2\right]

其中:
x 是输入向量,
W_1是第一个隐藏层的权重矩阵,b_1是第一个隐藏层的偏置向量,
\sigma是激活函数(如 Sigmoid 函数),
W_2是第二个隐藏层到输出层的权重矩阵,b_2 是输出层的偏置向量,
\hat{y}是神经网络的输出向量。

神经网络的训练包括2个步骤

  1. 前馈:计算预测输出\hat{y}

  2. 反向传播(Backward Propagation):更新权重和偏差

前馈

进行前向传播计算,假设偏差都为0

import numpy as np

class NeuralNetwork:
    def__init__(self,x,y):
        self.input=x
        self.weights1=np.random.rand(self.input.shape[1],4)
        self.weights2=np.random.rand(4,1)
        self.y=y
        self.output=np.zeros(self.y.shape)
    def feedforward(self):
        self.layer1=sigmoid(np.dot(self.input,self.weights1))
        self.layer2=sigmoid(np.dot(self.input,self.weights2))

1. `self.layer1 = sigmoid(np.dot(self.input, self.weights1))`:将输入数据 `self.input` 与第一层的权重矩阵 `self.weights1` 相乘,并通过 Sigmoid 激活函数进行非线性变换,得到第一层的输出 `self.layer1`。这一步表示输入数据经过第一层的处理后的输出。

2. `self.layer2 = sigmoid(np.dot(self.input, self.weights2))`:将输入数据 `self.input` 与第二层的权重矩阵 `self.weights2` 相乘,并通过 Sigmoid 激活函数进行非线性变换,得到第二层的输出 `self.layer2`。这一步表示第一层的输出经过第二层的处理后的输出。

这段代码的目的是计算神经网络的前向传播过程中各层的输出,以便后续计算损失函数和进行反向传播更新权重。值得注意的是,这里的 `sigmoid` 函数是一个自定义的激活函数,用于将神经网络的输出限制在0到1之间。

损失函数

损失函数有多种,目前以平方和误差为例

SSE = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2

平方和误差就是对实际值和预测值之间的差值求和

目标是实现训练神经网络并找到是损失函数最小化的最优权重

反向传播

计算出预测结果的误差(损失),需要找到一种方法将误差在网络中反向传导以便更新权重和偏差。

要找合适的权重和偏差矫正量,需要知道损失函数关于权重及偏差的导数

函数的导数就是函数的斜率

根据导数就可以根据导数的值增加或者减少导数值的方式来调节权重和偏差,这种方法也称为梯度下降法

使用链式法则求损失函数的导数,链式法则封装在keras等机器学习的库中

关键点:由损失函数关于权重的导数(斜率),帮助调整权重

import numpy as np

def sigmoid(x):
    return 1.0/(1+np.exp(-x))
def sigmoid_derivative(x):
    return x*(1.0-x)
class NeuralNetwork:
    def __init__(self,x,y):
        self.input=x
        self.weights1=np.random.rand(self.input.shape[1],4)
        self.weights2=np.random.rand(4,1)
        self.y=y
        self.output=np.zeros(self.y.shape)
    def feedforward(self):
        self.layer1=sigmoid(np.dot(self.input,self.weights1))
        self.output =sigmoid(np.dot(self.layer1,self.weights2))
    def backprop(self):
        #Find the derivative of the loss function with respect to weight2 and weight1 using the chain rule
        d_weights2=np.dot(self.layer1.T,(2*(self.y-self.output)*sigmoid_derivative(self.output)))
        d_weights1=np.dot(self.input.T,(np.dot(2*(self.y-self.output)*sigmoid_derivative(self.output),self.weights2.T)*sigmoid_derivative(self.layer1)))
        self.weights1 +=d_weights1
        self.weights2 +=d_weights2
if __name__=="__main__":
    X=np.array([[0,0,1],
               [0,1,1],
               [1,0,1],
               [1,1,1]])
    y=np.array([[0],[1],[1],[0]])
    nn=NeuralNetwork(X,y)
    
    for i in range(1500):
        nn.feedforward()
        nn.backprop()
    print(nn.output)

这段代码实现了一个简单的神经网络,包括一个输入层、一个隐藏层和一个输出层。以下是每个模块的描述:

  1. import numpy as np: 导入NumPy库,用于处理数组和矩阵等数值计算。

  2. def sigmoid(x): 定义sigmoid激活函数,用于将输入值转换为0到1之间的值。

  3. def sigmoid_derivative(x): 定义sigmoid激活函数的导数,用于反向传播中计算梯度。

  4. class NeuralNetwork: 定义神经网络类,包括初始化方法__init__、前向传播方法feedforward和反向传播方法backprop

    • __init__(self, x, y): 初始化神经网络,包括输入数据x、目标输出y、第一层到第二层的权重weights1和第二层到输出层的权重weights2

    • feedforward(self): 执行神经网络的前向传播,计算输入经过权重后得到的输出。

    • backprop(self): 执行神经网络的反向传播,根据损失函数的梯度更新权重,以减小预测输出与实际输出之间的差距。

  5. if __name__=="__main__"::主程序入口,创建神经网络对象并进行训练。

    • 创建输入数据X和目标输出y

    • 创建神经网络对象nn

    • 循环执行1500次训练迭代,每次迭代包括前向传播和反向传播。

    • 打印训练后的输出结果nn.output

重要点:Sigmoid是激活函数,将函数值压缩到0~1,对于二元问题,就是将预测结果位于0~1

结果精度检验

x1x2x3Y
0010
0111
1011
1110

迭代神经网络1500次,给出了最后的预测结果,与真实值进行对照,同时给出损失迭代-次数图

if __name__=="__main__":
    X=np.array([[0,0,1],
               [0,1,1],
               [1,0,1],
               [1,1,1]])
    y=np.array([[0],[1],[1],[0]])
    nn=NeuralNetwork(X,y)

    losses = []  # 用于记录每次迭代后的损失值

    for i in range(1500):
        nn.feedforward()
        nn.backprop()
        loss = np.mean(np.square(nn.y - nn.output))  # 计算均方误差损失
        losses.append(loss)

    plt.plot(range(1, 1501), losses)  # 绘制损失-迭代次数图
    plt.xlabel('Iterations')
    plt.ylabel('Loss')
    plt.title('Loss vs. Iterations')
    plt.show()

为什么要求平均,不平均代码报错?

在计算损失时,我们通常会计算所有样本的损失值的平均值。这是因为损失是所有样本预测值与真实值之间差值的函数,我们希望损失值能够反映整个数据集的预测准确程度,而不仅仅是单个样本的准确程度。因此,对所有样本的损失值取平均可以更好地衡量整个模型的性能。

预测值       实际值
0.009240
0.972571
0.972011
0.034340

由图片和图表可以看出来,前馈和反向传播算法成功训练的神经网络,且预测值收敛于真实值,且预测值与真实值有一定的误差,这个是在允许范围之内的。

最后

    for i in range(1500):
        nn.feedforward()
        nn.backprop()
        loss = np.mean(np.square(nn.y - nn.output))  # 计算均方误差损失
        losses.append(loss)

这块代码可以在类中进行分装,代码简洁,迁移性、可读性好

def train(self, epochs):
        for i in range(epochs):
            self.feedforward()
            self.backprop()
            loss = np.mean(np.square(self.y - self.output))  # 计算均方误差损失
            self.losses.append(loss)
if __name__=="__main__":
    X=np.array([[0,0,1],
               [0,1,1],
               [1,0,1],
               [1,1,1]])
    y=np.array([[0],[1],[1],[0]])
    nn=NeuralNetwork(X,y)
    
    nn.train(1500)  # 进行1500次训练迭代
    
    plt.plot(range(1, 1501), nn.losses)  # 绘制损失-迭代次数图
    plt.xlabel('Iterations')
    plt.ylabel('Loss')
    plt.title('Loss - Iterations')
    plt.show()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DevOps本地搭建笔记(个人开发适用)

需求和背景 win11 wsl2 armbian(玩客云矿渣),构建个人cicd流水线,提高迭代效率。 具体步骤 基础设施准备 硬件准备:一台笔记本,用于开发和构建部署,一台服务器,用于日常服务运行。 笔记本…

C#,蛇梯问题(Snake and Ladder Problem)的算法与源代码

1 蛇梯问题 Snake and Ladder Problem 给定一个蛇梯板,找出从源单元格或第一个单元格到达目标单元格或最后一个单元格所需的最小掷骰次数。基本上,玩家可以完全控制掷骰子的结果,并希望找出到达最后一个单元格所需的最小掷骰次数。 如果玩…

【大厂AI课学习笔记NO.76】人工智能人才金字塔

人工智能领域,分为源头创新人才、产业研发人才、应用开发人才和实用技能人才。 人工智能领域的人才结构呈现多样化特点,主要可以分为源头创新人才、产业研发人才、应用开发人才和实用技能人才四大类。这四大类人才在人工智能领域的发展中各自扮演着不可或…

Day30:安全开发-JS应用NodeJS指南原型链污染Express框架功能实现审计

目录 环境搭建-NodeJS-解析安装&库安装 功能实现-NodeJS-数据库&文件&执行 安全问题-NodeJS-注入&RCE&原型链 案例分析-NodeJS-CTF题目&源码审计 开发指南-NodeJS-安全SecGuide项目 思维导图 JS知识点: 功能:登录验证&…

常见排序算法(C/C++)--- 动画演示

本篇将介绍一些常见的排序算法,如插入排序:直接插入排序、希尔排序;选择排序:选择排序、堆排序;交换排序:快速排序、冒泡排序;以及最后的归并排序。 对于以上的排序算法,我们总结了每…

VScode的列选

可以用来优化代码排布,让变量整齐成为一排 一、批量复制: 在1处左键单击,然后摁住SHIFTALT键的同时,左键单击2处,即可复制一整块的内容 如果所示 就可以复制了 二、批量输入 在1处左键单击,然后摁住SHI…

Day32:安全开发-JavaEE应用Servlet路由技术JDBCMybatis数据库生命周期

目录 JavaEE-HTTP-Servlet&路由&周期 JavaEE-数据库-JDBC&Mybatis&库 思维导图 Java知识点: 功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等. 框架…

RabbitMQ - 04 - Fanout交换机 (广播)

目录 部署demo项目 什么是Fanout交换机 实现Fanout交换机 1.控制台 声明队列 声明交换机 将交换机与队列绑定 2.编写消费者方法 3.编写生产者测试方法 部署demo项目 通过消息队列demo项目进行练习 相关配置看此贴 http://t.csdnimg.cn/hPk2T 注意 生产者消费者的…

转移表回调函数实现

回调函数实现 计算器的模拟(函数指针数组的使用)(回调函数) 简化 冗余 老的代码的问题就是 冗余 写死 不能完成不同的任务 函数调用的时候只需要知道地址就可以 calc计算器 这里也称之为转移表 #define _CRT_SECURE_NO_WAR…

微信小程序开发系列(二十五)·wxml语法·条件渲染wx:if, wx:elif, wx:else 属性组以及hidden 属性的使用

目录 1. 使用 wx:if、wx:elif、wx:else 属性组 2. 使用 hidden 属性 条件渲染主要用来控制页面结构的展示和隐藏,在微信小程序中实现条件渲染有两种方式: 1. 使用 wx:if, wx:elif, wx:else 属性组 2. 使用 hidden 属性 wx:if 和 hidden 二者的区别: 1. wx…

计算机网络-第4章 网络层(2)

主要内容:网络层提供的两种服务:虚电路和数据报(前者不用)、ip协议、网际控制报文协议ICMP、路由选择协议(内部网关和外部网关)、IPv6,IP多播,虚拟专用网、网络地址转换NAT,多协议标…

背包问题算法

背包问题算法 0-1背包问题二维数组一维数组 完全背包问题二维数组一维数组 多重背包问题一维数组 0-1背包问题 问题:背包的容量为9,有重量分别为[2, 4, 6, 9]的四个物品,价值分别为[3, 4, 5, 6],求背包能装的物品的最大价值是多少…

构建LVS集群

一、集群的基本理论(一)什么是集群 人群或事物聚集:在日常用语中,群集指的是一大群人或事物密集地聚在一起。例如,“人们群集在广场上”,这里的“群集”是指大量人群聚集的现象。 计算机技术中的集群&…

C语言连接【MySQL】

稍等更新图片。。。。 文章目录 安装 MySQL 库连接 MySQLMYSQL 类创建 MySQL 对象连接数据库关闭数据库连接示例 发送命令设置编码格式插入、删除或修改记录查询记录示例 参考资料 安装 MySQL 库 在 CentOS7 下,使用命令安装 MySQL: yum install mysq…

arcgis栅格数据处理3——定义投影(同样适用于其他类型文件)

进行数据连接时可能出现未设置投影无法链接的情况,需要先定义投影 点击最右侧“目录”,弹出带有系统工具的面板,点击“data management tools”点击“投影”,“定义投影”

【轮式平衡机器人】——TMS320F28069片内外设之eCAP

引入 TMS320F28069的eCAP(增强型捕获模块)是一个强大的外设,用于精确测量和捕获输入信号的事件和时间戳。 在电机控制、传感器数据采集和信号处理等应用中,eCAP模块可以用于测量霍尔传感器、编码器或其他数字输入信号的周期、频…

计算表达式x*(2^i)的值math.ldexp(x, i)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 计算表达式x*(2^i)的值 math.ldexp(x, i) [太阳]选择题 关于以下代码输出的结果说法正确的是? import math print("【执行】math.ldexp(3,2)") print(math.ldexp(3,2)) …

2024/3/10总结:数据结构教程:顺序表的创建以及基本的12个操作

首先,按照惯例,欢迎大家边听歌边看本博客!!! 这里是神奇的赛尔号_张杰 (kugou.com) 一.背景:由于是上机实验,直接引用数据结构教程第6版73页的实验题1 修改第6,7,8&am…

CI/CD笔记.Gitlab系列:控制台强制修改root用户密码

CI/CD笔记.Gitlab系列 控制台强制修改root用户密码 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.cs…

SpringBoot中的上传文件接口

SpringBoot中的上传文件 上传文件的操作在有些功能中属于比较常用的环节,这里整理下SpringBoot环境中上传文件的实现方式。 这里实现的是上传文件的后台接口,前端部分可以用测试工具模拟实现,就先不在这里表述了。 Dto层 使用MultipartFile…