【深度学习 | 感知器 MLP(BP神经网络)】掌握感知的艺术: 感知器和MLP-BP如何革新神经网络

news2024/12/28 5:42:12

在这里插入图片描述

🤵‍♂️ 个人主页: @AI_magician
📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。
👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!🐱‍🏍
🙋‍♂️声明:本人目前大学就读于大二,研究兴趣方向人工智能&硬件(虽然硬件还没开始玩,但一直很感兴趣!希望大佬带带)

在这里插入图片描述

该文章收录专栏
[✨— 《深入解析机器学习:从原理到应用的全面指南》 —✨]

感知器 (Perceptron) & MLP-BP神经网络

阅读参考文献:

一个非常有趣的讲解 (感知器是一种单层神经网络,而多层感知器则称为神经网络。): https://towardsdatascience.com/what-the-hell-is-perceptron-626217814f53

感知器

感知器是神经网络的 Fundamentals

在1977年由Frank Roseblatt 所发明的感知器是最简单的ANN架构之一(线性函数加上硬阈值这里阈值不一定是0),受在一开始的生物神经元模型启发(XOR问题逻辑问题),称之为阈值逻辑单元(TLU,threshold logistic unit) 或线性阈值单元(LTU,linear threshold unit),其是一个使用阶跃函数的神经元来计算,可被用于线性可分二分类任务,也可设置多个感知器输出实现多输出分类以输出n个二进制结果(缺点是各种类别关系无法学习),一般来说还会添加一个偏置特征1来增加模型灵活性。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tq1dFdVw-1692271552392)(core algorithm.assets/FXo8u7JaQAANoNm.png)]

在感知器中引入一个偏置特征神经元1的目的是为了增加模型的灵活性和表达能力。这个偏置特征对应于一个固定且始终为1的输入,其对应的权重称为偏置项(bias)。通过调整偏置项的权重,我们可以控制 TLU 的决策边界在特征空间中平移或倾斜。(正常来说的话,这个偏置项都是在每个神经元当中所存在,而不是作为单独一个输入存在,能更灵活)

在感知器中,将偏置特征固定为1的选择是为了方便计算和表示。

当我们引入一个偏置特征时,可以将其视为与其他输入特征一样的维度,并赋予它一个固定的值1。这样做有以下几个好处:

  1. 方便计算:将偏置项乘以1相当于直接使用权重来表示该偏置项。在进行加权求和并应用阈值函数时,不需要额外操作或考虑。
  2. 参数统一性:通过将偏置项作为一个独立的权重进行处理,使得所有输入特征(包括原始输入和偏置)具有相同的形式和统一性
  3. 简洁明了:固定为1的偏置特征能够简化模型参数表示,并使其更易理解和解释。

请注意,在实际应用中,对于某些任务可能需要调整默认值1以适应数据分布或优化模型性能。但基本原则仍然是保持一个常数值作为额外输入特征,并且通常会根据具体情况对其进行学习或调整。

具体来说,引入偏置特征1有以下几个原因:

  1. 平移决策边界:通过调整偏置项的权重,可以使得决策边界沿着不同方向平移。如果没有偏置项,则决策边界将必须过原点(0, 0)。

  2. 控制输出截距:当所有其他输入都为零时,只有存在偏置项才能使感知器产生非零输出

  3. 增强模型表达能力:引入一个额外维度后,在某些情况下会更容易找到合适分割样本空间线性超平面位置

    总之,在感知器中引入偏置特征1可以使模型更加灵活,能够适应不同的决策边界位置,并增加了模型对输入数据的表达能力。

其中,Siegrid Lowel非常著名的一句话“一同激活的神经元联系在一起”(Hebb的思想,一个生物元经常触发另外一个神经元,二者关系增强),故此Rosenblatt基于该规则提出一种感知器训练算法,其加强了有助于减少错误的连接,如果预测错了,比如预测目标是1,预测到0,就会增强对应神经元权重和偏置,如果预测目标是0,预测到1,就会减小。(根据阶跃函数性质值越大为1,值小为0)

以下是感知器训练算法的步骤(只有一层神经网络):

  1. 初始化参数:初始化权重向量 w 和偏置 b 为零或者随机小数。(一般来说感知器个数不多情况下,个数多则可以使用如神经网络的初始化如He初始化等)
  2. 对每个训练样本进行迭代:
    • 计算预测输出 y_hat = sign(w * x + b),其中 w 是权重向量,x 是输入特征向量,b 是偏置项,并且 sign() 函数表示取符号(正负,二分类为例)。
    • 更新权重和偏置:
      • 如果 y_hat 等于实际标签 y,则无需更新参数
      • 如果 y_hat 不等于实际标签 y,则根据下面的规则更新参数:
        • 权重更新规则:w = w + η * (y - y_hat) * x,其中 η 是学习率(控制每次更新的步长)。
        • 偏置更新规则:b = b + η * (y - y_hat)。(偏移)

这个过程会不断迭代直到所有样本被正确分类或达到预定的停止条件(如达到最大迭代次数)。从以下我们就可以看到线性可分的感知机训练过程和线性不可分的感知机训练过程,在线性不可分的情况下,泛化能力较差。

在这里插入图片描述

鸢尾花多分类案例

Sci-learn: https://scikit-learn.org/stable/auto_examples/datasets/plot_iris_dataset.html`

Wikipedia: https://en.wikipedia.org/wiki/Iris_flower_data_set

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LvR9TPcr-1692271552393)(core algorithm.assets/image-20230817123141139.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5KYWMoyw-1692271552394)(core algorithm.assets/image-20230817123152718.png)]

我们从以上的可视化就可以知道,用Perceptorn分类必然效果不好,因为其线性不可分

不使用库实现感知器一对多策略多分类鸢尾花数据集任务的代码:

import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score


class Perceptron:
    """设计架构
    1. 初始化基本超参数
    2. 根据算法模型抽象化权重训练流程
    3. 训练中细分单个样本训练和预测中细分单个样本预测以实现多样本训练和预测"""
    def __init__(self, learning_rate=0.1, num_epochs=20):
        self.learning_rate = learning_rate
        self.num_epochs = num_epochs

    def train(self, X, y):
        # 添加偏置项到输入数据中
        X = np.insert(X, 0, 1, axis=1)

        # 初始化权重为随机值
        np.random.seed(42)
        self.weights = []

        # 训练模型(每个类别都有自己独立的感知器)
        for class_label in set(y): # 集合去重
            binary_labels = np.where(y == class_label, 1, -1) # True is 1 or False is  -1
#             print(binary_labels)
            weights_class = self.train_single_perceptron(X, binary_labels)
            self.weights.append(weights_class)

    def train_single_perceptron(self, X, y):
        weights = np.random.rand(X.shape[1]) # 随机初始化后训练(每个样本的特征数)
        for _ in range(self.num_epochs): #轮次
            for i in range(len(X)):
                prediction = self.predict_single_sample(X[i], weights) # 数据和权重求解
                error = y[i]-prediction
                # 更新权重
                update = self.learning_rate*error*X[i]
                weights += update
        return weights

    def predict_single_sample(self, x, weights):
        """receive x and weights return step function"""
        activation_value = np.dot(x, weights)
        return 1 if activation_value >= 0 else -1 # step function (corressponds to the previous binary_labels)

    def predict(self, X_test):
        X_test = np.insert(X_test, 0, 1, axis=1) # 同样需要插入偏置神经元1
        predictions = []
        for i in range(len(X_test)):
            class_predictions = []
            for perceptron_weights in self.weights:
                class_predictions.append(self.predict_single_sample(X_test[i], perceptron_weights))
            predicted_class = np.argmax(class_predictions) # 如果一样大返回最先的下标
#             print(class_predictions) 
#             print(predicted_class)
            predictions.append(predicted_class)
        return predictions


# 加载鸢尾花数据集(数据顺序排列,一定要打乱,泛化能力)
data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=42) # 
# X_train, X_test, y_train, y_test = data.data[:120,:],data.data[120:,:],data.target[:120],data.target[120:] # , random_state=42
# 创建感知器对象并训练模型
perceptron = Perceptron()
perceptron.train(X_train, y_train)

# 使用测试数据集进行预测
predictions = perceptron.predict(X_test)
print(np.array(predictions))
print(y_test)
# print(type(y_test))

accuary = sum(predictions == y_test)/len(y_test) 
accuary = accuracy_score(y_test,predictions)
print(accuary)

输出

[1 0 1 0 1 0 0 2 1 1 2 0 0 0 0 0 2 1 1 2 0 2 0 2 2 2 1 2 0 0]
[1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0]
0.8333333333333334

使用库实现感知器分类鸢尾花数据集任务的代码:

from sklearn.linear_model import Perceptron

# 加载鸢尾花数据集
data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    data.data, data.target, test_size=0.2, random_state=42) # 随机数一样的话,随机结果是一样的
# data.data[:120,:],data.data[120:,:],data.target[:120],data.target[120:] #

# 创建并训练感知器模型
perceptron = Perceptron(eta0=0.1, max_iter=100)
perceptron.fit(X_train, y_train)

# 使用测试数据集进行预测
predictions = perceptron.predict(X_test)
print(predictions)
print(y_test)

accuary = sum(predictions == y_test)/len(y_test)
print(accuary)

输出:

[1 0 2 0 1 0 0 2 1 0 2 0 0 0 0 0 2 0 0 2 0 2 0 2 2 2 2 2 0 0]
[1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0]
0.8

sklearn.linear_model.Perceptron的参数:

  • penalty: 惩罚项(默认值:None)。可以选择"l1"或"l2"来应用L1或L2正则化,也可以选择None不应用任何惩罚项。

  • alpha: 正则化强度(默认值:0.0001)。较大的alpha表示更强的正则化。

  • fit_intercept: 是否拟合截距(默认值:True)。如果设置为False,则模型将不会拟合截距。

  • max_iter: 最大迭代次数(默认值:1000)。指定在达到收敛之前要执行的最大迭代次数。

  • tol: 收敛容忍度(默认值:1e-3)。指定停止训练时目标函数改善小于该阈值时的容忍程度。

  • shuffle: 是否在每个周期重新打乱数据顺序(默认值:True)。

  • eta0: 初始学习率(默认值:1.0)。控制权重更新速度的学习率。较低的初始学习率可能有助于稳定模型收敛过程,但训练时间可能变长。

  • random_state: 随机种子。提供一个整数以保证结果可重复性,或者设置为None以使用随机状态。

  • verbose: 是否打印详细输出(默认值:0)。设置为1时,会定期打印出损失函数的值。

在这两个例子中,我们都使用了鸢尾花数据集,并将其分为训练和测试数据。然后,我们创建了一个感知器对象(自定义或Scikit-Learn提供的),并使用train()方法(自定义)或fit()方法(Scikit-Learn)来训练模型。最后,在测试数据上使用predict()方法来生成预测结果。(其中我们还可以设置一些超参数达到优化的目的)

扩展:

MLPClassifier和Keras中的Dense层都用于实现多层感知器(Multi-Layer Perceptron)模型。

在Scikit-Learn库中,MLPClassifier是一个基于神经网络的分类器,它使用反向传播算法进行训练,并可以处理多类别分类问题。你可以通过指定不同的参数来配置隐藏层、激活函数、优化算法等。

而在Keras库中,Dense层也被用作构建神经网络模型的一部分。它定义了全连接层(fully connected layer),其中每个输入节点与输出节点之间都有权重连接。你可以通过设置不同的参数来调整该层的大小、激活函数等。

虽然两者具有相似的功能,但由于框架和接口不同,它们在代码编写上可能会有所差异。因此,在使用时需要根据所选框架来适当调整代码。

总体上说,“MLPClassifier”和Keras中“Dense”层都是为了实现多层感知器模型而设计的工具,在不同框架下提供了类似功能但语法略有差异。

应用场景

相比其他机器学习算法,感知器具有以下优势:

  1. 简单而高效:感知器算法非常简单且易于实现,计算速度快
  2. 对噪声数据鲁棒:由于其使用了阶跃函数作为激活函数,在处理带有噪声数据时表现较好
  3. 支持在线学习:感知器是一种在线学习算法,可以逐步更新权重和阈值,并在每次迭代中对新样本进行训练。

然而,感知器也存在一些局限性:

  1. 仅适用于线性可分问题:由于其基于线性模型,在处理非线性可分问题时无法取得良好的结果
  2. 只能进行二分类:感知器只能用于二分类任务,并不能直接扩展到多类别分类问题上。
  3. 对输入特征缩放敏感:感知器对输入特征的缩放比较敏感,如果特征之间的尺度差异较大(因为结果是根据值的大小决定的,所以在使用前需要数据特征归一化或者标准化),可能会影响算法的性能。

在实际应用中,当面对非线性可分问题时,可以考虑使用其他更复杂的模型,如支持向量机、神经网络等。这些模型具有更强大的表示能力,并且能够处理更为复杂和抽象的关系。然而,在某些简单问题上,感知器仍然是一个有效且高效的选择。

总结起来就是,感知器适用于解决线性可分二分类问题,并且具有简单、高效和鲁棒等优点。但它无法处理非线性可分问题,并且只能进行二分类任务。对于不同类型或更复杂的问题,可以考虑使用其他更适合的方法。

BP神经网络

BP神经网络,指的是用了**“BP算法”进行训练的“多层感知器模型”(MLP)。**并为了TLU感知机算法正常工 作,对MLP的架构进行了修改,即将阶跃函数替换成其他激活函数,如tanhRelu。这里之所以用反向传播是因为多层的感知机无法再用感知机学习规则来训练.
在这里插入图片描述

						  🤞到这里,如果还有什么疑问🤞
					🎩欢迎私信博主问题哦,博主会尽自己能力为你解答疑惑的!🎩
					 	 🥳如果对你有帮助,你的赞是对博主最大的支持!!🥳

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用教程|CloudQuery: 数据库操作管控云平台初体验

😀前言 前言:就在刚刚,在一个技术交流群里了解到了一场活动:CloudQuery 社区的有奖征文活动。除了有丰厚的礼物,使用过程中还有技术同学的支持。但是 CloudQuery 这个产品我也没有过多的了解,抱着对产品的好…

AndroidStudio升级Gradle之坑

最近在做旧工程的升级,原来的Gradle版本是4.6的,需要升级到7.6,JDK从8升级到17,一路淌了很多坑,逐个记录下吧 1、Maven仓库需要升级到https 你会遇到这个报错 Using insecure protocols with repositories, without …

item_search-按关键字搜索淘宝商品

一、接口参数说明: item_search-按关键字搜索淘宝商品,点击更多API调试,请移步注册API账号点击获取测试key和secret 公共参数 请求地址: https://api-gw.onebound.cn/taobao/item_search 名称类型必须描述keyString是调用key(点…

边缘计算节点BEC典型实践:如何快速上手PC-Farm服务器?

百度智能云边缘计算节点BEC(Baidu Edge Computing)基于运营商边缘节点和网络构建,一站式提供靠近终端用户的弹性计算资源。边缘计算节点在海外覆盖五大洲,在国内覆盖全国七大区、三大运营商。BEC通过就近计算和处理,大…

【Linux命令详解 | tar命令】 tar命令用于打包和解压文件,常用于备份和压缩文件

文章标题 简介一,参数列表二,使用介绍1. 打包文件和目录2. 解包归档文件3. 压缩归档文件4. 列出归档文件内容5. 排除特定文件6. 保留文件权限和所有权7. 保留时间戳8. 增量备份9. 使用文件列表10. 压缩级别控制 总结 简介 在Linux中,tar命令…

游戏出海工具都有哪些?

游戏出海是一个复杂的过程,需要运用多种工具来进行市场分析、推广、本地化等工作。以下是一些常用的游戏出海工具: 一、必备工具: 1、游戏平台:要想进行游戏出海运营,游戏平台时必不可少的,选择游戏平台时…

一节网课中有哪些“黑科技”,猿辅导给出了这样的答案

近年来,AI正以润物细无声的方式重塑多个行业的面貌,教育行业也不例外。同时,随着Chat GPT对社会带来的冲击不断加强,AI教育已经成为整个行业不可逆转的趋势。作为最早踏入智能教育领域的企业之一,猿辅导深谙技术革新对…

如何正确使用生成式 AI?

推荐:使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 在过去几年中,数据的创建速度呈指数级增长,这主要意味着数字世界的日益扩散。 估计吧?仅在过去两年中,世界上90%的数据就产生了。 我们以各种形式与互…

Android 命令行如何运行 JAR 文件

​ 最近有位老哥问了一个问题,说如果将java的jar文件在Android中执行?这个其实很简单的一个问题,直接写个App放里面不就可以了么?但是人家说没有App,直接使用命令行去运行。说明这个需求的时候,把我给整懵了…

人尽其才、数尽其用,Smartbi Eagle智慧数据运营平台全新亮相

数据是企业数字化转型的基石,也是赢得未来的核心资产和竞争力。数字化转型的关键,是在全公司建立一种数据驱动的组织和机制,营造数据文化的氛围,让更多的用户、在更多的场景中,有意愿、有能力使用数据,从而…

COMSOL光电仿真专题第三十五期线上通知

培训背景: COMSOL多物理场仿真软件以高效的计算性能和杰出的多场耦合分析能力实现了精确的数值仿真,已被广泛应用于各个领域的科学研究以及工程计算,为工程界和科学界解决了复杂的多物理场建模问题。光电作为物理类专业课程中极为重要的一部…

Jmeter 快速生成测试报告

我们使用Jmeter工具进行接口测试或性能测试后一般是通过察看结果数、聚合报告等监听器来查看响应结果。如果要跟领导汇报测试结果,无法直接通过监听器的结果来进行展示和汇报,因为太low了,因此测试完成后去整理一个数据齐全且美观的报告是非常…

OSM模型案例:以游戏陪练app为例

OSM模型的概念 O指目标Objective:整个业务、乃至局部的小功能 能解决什么问题,提供什么样的用户价值,满足用户什么需求? S指策略Strategy:如何达成目标,以什么方式达成目标? M指度量Measure&…

RabbitMq-发布确认高级(避坑指南版)

在初学rabbitMq的时候,伙伴们肯定已经接触到了“发布确认”的概念,但是到了后期学习中,会接触到“springboot”中使用“发布确认”高级的概念。后者主要是解决什么问题呢?或者是什么样的场景引出这样的概念呢? 在生产环…

前端原生写自定义旋转变换轮播图

html部分&#xff1a; <div class"banner_box"><div class"swiperWrapper" v-show"bannerList.length>0"><div class"swiper-item" :id"swiperSlide${index}" :class"{active:index0,next:index1,pr…

耗资170亿美元?三星电子在得克萨斯州建设新的半导体工厂

据报道&#xff0c;三星电子在得克萨斯州泰勒市建设的新的半导体工厂预计将于2024年下半年投入运营。这座工厂将成为三星电子在美国的第二座芯片代工厂&#xff0c;与位于得克萨斯州奥斯汀市的第一座工厂相距不远。 此次投资将耗资约170亿美元&#xff0c;显示了三星电子在半导…

Linux驱动之利用ioctl函数和字符设备驱动对象分布注册点亮小灯

实验结果 头文件代码 #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t; #define PHY_LED1_ADDR 0X50006000 #define PHY_LED2_ADDR 0X5…

激活函数总结(十一):激活函数补充(Absolute、Bipolar、Bipolar Sigmoid)

激活函数总结&#xff08;十一&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 Absolute激活函数2.2 Bipolar激活函数2.3 Bipolar Sigmoid激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、…

多维时序 | MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测

多维时序 | MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测基本介绍模型特点程序设计参考资料 基本介绍 本次运行测试环境MATLAB2021b&#xff0c;MATLAB实现PSO-CNN-BiLSTM多变量时间序列预测。代码说明&#xff1a…

掌握渗透测试,从Web漏洞靶场搭建开始

渗透测试切忌纸上谈兵&#xff0c;学习渗透测试知识的过程中&#xff0c;我们通常需要一个包含漏洞的测试环境来进行训练。而在非授权情况下&#xff0c;对于网站进行渗透测试攻击&#xff0c;是触及法律法规的&#xff0c;所以我们常常需要自己搭建一个漏洞靶场&#xff0c;避…