神经网络实战前言

应用广泛

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

未来可期

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

产业革命

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

机器学习概念

  • 机器学习不等价与人工智能
  • 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 npclass NeuralNetwork:def__init__(self,x,y):self.input=xself.weights1=np.random.rand(self.input.shape[1],4)self.weights2=np.random.rand(4,1)self.y=yself.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 npclass NeuralNetwork:def__init__(self,x,y):self.input=xself.weights1=np.random.rand(self.input.shape[1],4)self.weights2=np.random.rand(4,1)self.y=yself.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 npdef 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=xself.weights1=np.random.rand(self.input.shape[1],4)self.weights2=np.random.rand(4,1)self.y=yself.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 ruled_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_weights1self.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()

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode_Java_排序系列(1)(题目+思路+代码)

目录 349.两个数组的交集 350. 两个数组的交集 II 349.两个数组的交集 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1], nums2…

Leetcode刷题【每日n题】(5)

题目一 思路分析 二分查找法&#xff1a; 要查找目标数的算术平方根k&#xff0c;则K*k <x,则可以利用二分法查找0-x之间的数&#xff0c;看是否与其匹配。 代码实现 class Solution {public int mySqrt(int x) {//使用二分查找int left0,rightx,ans-1;while(left<righ…

稀碎从零算法笔记Day14-LeetCode:同构字符串

题型&#xff1a;字符串、哈希表 链接&#xff1a;205. 同构字符串 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那…

面试经典150题【71-80】

文章目录 面试经典150题【71-80】112.路径总和129.求根节点到叶子节点的数字之和124.二叉树中的最大路径和&#xff08;要思考&#xff09;173.二叉树迭代搜索器222.完全二叉树节点的个数236.二叉树的最近公共祖先199.二叉树的右视图637.二叉树的层平均值102.二叉树的层序遍历1…

企业战略管理 找准定位 方向 使命 边界 要干什么事 要做多大的生意 资源配置投入

AI突破千行百业&#xff0c;也难打破护城河 作为每个企业或个人的立命生存之本&#xff0c;有的企业在某个领域长期努力筑起了高高的护城河。 战略是什么&#xff1f;用处&#xff0c;具体内容 企业战略是指企业为了实现长期目标&#xff0c;制定的总体规划和长远发展方向。…

Qdrant 向量数据库的部署以及如何在 .NET 中使用 TLS 安全访问

本文介绍如何使用 Docker 部署 Qdrant 向量数据库&#xff0c;以及其相关的安全配置&#xff0c;并演示如何使用 .NET 通过 TLS 安全访问 Qdrant 向量数据库。 文章目录 1. 背景2. Qdrant 向量数据库的部署2.1 Qdrant 向量数据库的安全配置2.2 使用 Docker 部署安全的 Qdrant 向…

[QT]自定义的QtabWidget

需求 最近有一个需求就是一个QTabWidget要求有四个tab页在左侧用于显示主页面&#xff0c;在右侧有一个关于按钮&#xff0c;点击后用于弹出窗口显示一些程序相关信息。主要是怎么实现右侧按钮 相关代码 #ifndef MYTABWIDGET_H #define MYTABWIDGET_H#include <QWidget&g…

【联邦学习综述:概念、技术】

出自——联邦学习综述&#xff1a;概念、技术、应用与挑战。梁天恺 1*&#xff0c;曾 碧 2&#xff0c;陈 光 1 从两个方面保护隐私数据 硬件层面 可 信 执 行 环 境 &#xff08;Trusted Execution Environment&#xff0c;TEE&#xff09;边 缘 计 算&#xff08;Edge Com…

宝塔一键迁移报错创建失败问题完美解决

很多站长朋友在使用宝塔面板迁移的时候总是出错&#xff0c;如图&#xff1a; 遇到这样的问题不要慌&#xff0c;我们已经完美处理&#xff0c;详细解决教程&#xff1a;宝塔一键迁移报错问题完美解决教程

Golang-channel合集——源码阅读、工作流程、实现原理、已关闭channel收发操作、优雅的关闭等面试常见问题。

前言 面试被问到好几次“channel是如何实现的”&#xff0c;我只会说“啊&#xff0c;就一块内存空间传递数据呗”…所以这篇文章来深入学习一下Channel相关。从源码开始学习其组成、工作流程及一些常见考点。 NO&#xff01;共享内存 Golang的并发哲学是“要通过共享内存的…

【UVM_phase objection_2024.03.08

phase 棕色&#xff1a;function phase 不消耗仿真时间 绿色&#xff1a;task phase 消耗仿真时间 run_phase与右边的phase并行执行&#xff0c;右边的phase&#xff08;run_time phase&#xff09;依次执行&#xff1a; List itemreset_phase对DUT进行复位&#xff0c;初始…

Java 虚拟线程截止 2024-3-10 在 OpenJDK 还没有解决消息的问题

之前的文章《虚拟线程目前不推荐上生产的个人思考》&#xff0c;总结了几个目前的问题&#xff1a; 1. synchronized 的 pin 线程引发的问题比预期严重&#xff0c;或者等到 OpenJDK 修复&#xff0c;或者很多 Java 库要改&#xff08;尤其是 JDBC 驱动这种&#xff09;。目前…