PSO粒子群代码手搓实现—代码详解版python

news2024/9/28 1:47:59

PSO粒子群算法手搓实现版🚀

        读了博士之后,送算法方向转到了控制方向,然后最近接触到的项目,要用到粒子群算法,然后秉持着我自己一贯的把基础代码自己手写一遍的原则,我自己上网找了一些视频,然后自己根据自己的理解重新写了一份出来,然后又让智普清言,帮我优化了一些细节,最后得到一份符合我自己风格的一个版本,之后如果工作任务上又需要,我也会进一步在我自己的代码上优化修改,给予我自己一份安全感。

粒子群算法(Particle Swarm Optimization,简称PSO)是一种基于群体智能的优化技术。它模拟鸟群或鱼群的社会行为,通过群体中个体之间的信息共享与协同搜索来寻找问题的最优解。在PSO中,每个粒子代表问题空间中的一个候选解,粒子通过跟踪自己的历史最佳位置和整个群体的最佳位置来调整自己的飞行轨迹。这种算法通过迭代过程不断更新粒子的速度和位置,直到找到满足优化目标的最优解或近似最优解。粒子群算法因其实现简单、参数少、收敛速度快等优点,在许多优化问题中得到了广泛应用。


文章目录

1.问题定义


        首先就是定义这个问题,这里用一个求函数最小值的问题,这里使用的是b站上,青青草原灰太狼同学的例子非常感谢这里引用下。
当前有一个函数,函数定义如下。
f ( x ) = x s i n ( x ) c o n ( 2 x ) − 2 x s i n ( x ) + 3 x i n ( 4 x ) f(x)=xsin(x)con(2x)-2xsin(x)+3xin(4x) f(x)=xsin(x)con(2x)2xsin(x)+3xin(4x)
目标:在 x ∈ [ 0 , 50 ] x\in[0,50] x[0,50]区间内找到令 f ( x ) f(x) f(x)的值最小的点, x ∗ x^* x表示满足条件的最优解(最小值)。

x ∗ = arg ⁡ min ⁡ x ∈ [ 0 , 50 ] f ( x ) x^* = \arg \min_{x \in [0, 50]} f(x) x=argx[0,50]minf(x)
函数图像如下:
在这里插入图片描述

可以看到实际上值最小的点应该是在45左右的一个点。

2.粒子群算法参数表


这个表方便大家之后看流程图和代码的时候进行对照。

参数名称本文使用的符号参数解释
总群大小 N N N粒子的数量
维度 d d d每个粒子有多少个参数
迭代次数 g e r ger ger多少次搜索之后算法停止
位置限制 l i m i t \boldsymbol{limit} limit限制每个粒子参数搜索区间
速度限制 v _ l i m i t \boldsymbol{v\_limit} v_limit限制每个粒子搜索速度的上下限
惯性权重 w w w受粒子当前的状态影响的程度
自学习因子 c 1 c_1 c1受粒子自己历史最优状态影响程度
群体学习因子 c 2 c_2 c2受集体搜索到的最优状态的影响程度
种群位置 x \boldsymbol{x} x记录所有粒子当前的位置状态
种群速度 v \boldsymbol{v} v记录所有粒子当前的搜索速度
个体历史最佳位置 x b e s t _ l o c a t i o n \boldsymbol{x_{best\_location}} xbest_location记录每个粒子自己搜索到的最优位置
个体历史最佳适应度 x b e s t \boldsymbol{x_{best}} xbest记录每个粒子自己搜索到的最优适应度(函数值)
全局最佳位置 g b e s t _ l o c a t i o n \boldsymbol{g_{best\_location}} gbest_location记录群体搜索到的最优位置
全局最佳适应度 g b e s t \boldsymbol{g_{best}} gbest记录群体搜索到的最优适应度(函数值)
随机系数 r 1 \boldsymbol{r_1} r1用于调整粒子向其个体历史最佳位置移动的步长
随机系数 r 2 \boldsymbol{r_2} r2用于调整粒子向其全局最佳最佳位置移动的步长

3.粒子群算法流程图


在这里插入图片描述

3.1速度 v \boldsymbol{v} v的更新公式

        速度更新公式是整个PSO粒子群算法的核心,我使用我的变量命令方式写出了这个公式,之后使用智谱清言辅助我通俗的解释一下。
v = w ⋅ v + c 1 ⋅ r 1 ⋅ ( x b e s t _ l o c a t i o n − x ) + c 2 ⋅ r 2 ⋅ ( g b e s t _ l o c a t i o n − x ) \boldsymbol{v} = w \cdot \boldsymbol{v} + c_1 \cdot \boldsymbol{r_1} \cdot (\boldsymbol{x_{best\_location}} - \boldsymbol{x}) + c_2 \cdot \boldsymbol{r_2} \cdot (\boldsymbol{g_{best\_location}} - \boldsymbol{x}) v=wv+c1r1(xbest_locationx)+c2r2(gbest_locationx)

  • v \boldsymbol{v} v:这是粒子的速度,它决定了粒子在解空间中移动的快慢和方向。
  • w w w:这是惯性权重,它决定了粒子保持之前速度的倾向。如果 w \boldsymbol{w} w较大,粒子会更多地保持原来的速度;如果 w \boldsymbol{w} w较小,粒子会更容易改变速度和方向。
  • c 1 c_1 c1 c 2 c_2 c2:这两个是学习因子,也称为加速常数。它们分别控制粒子向自己的历史最佳位置(个体经验)和全局最佳位置(群体经验)移动的强度。
  • r 1 \boldsymbol{r_1} r1 r 2 \boldsymbol{r_2} r2:这两个是随机数,它们在 [ 0 , 1 ] [0, 1] [0,1]范围内均匀分布,增加了粒子移动的随机性,帮助算法探索解空间,避免陷入局部最优。
  • x b e s t _ l o c a t i o n \boldsymbol{x_{best\_location}} xbest_location:这是粒子自身历史找到的最佳位置,也就是粒子自己认为最好的解。
  • g b e s t _ l o c a t i o n \boldsymbol{g_{best\_location}} gbest_location:这是整个粒子群历史找到的最佳位置,也就是整个群体认为最好的解。

现在,让我们来看公式中的各个部分:

  1. w ⋅ v w \cdot \boldsymbol{v} wv:这部分表示粒子当前的速度,它将影响粒子的下一步移动。
  2. c 1 ⋅ r 1 ⋅ ( x b e s t _ l o c a t i o n − x ) c_1 \cdot \boldsymbol{r_1} \cdot (\boldsymbol{x_{best\_location}} - \boldsymbol{x}) c1r1(xbest_locationx):这部分表示粒子向自己的最佳位置移动的倾向。粒子会根据随机数r1和学习因子c1来调整移动的幅度。
  3. c 2 ⋅ r 2 ⋅ ( g b e s t _ l o c a t i o n − x ) c_2 \cdot \boldsymbol{r_2} \cdot (\boldsymbol{g_{best\_location}} - \boldsymbol{x}) c2r2(gbest_locationx):这部分表示粒子向全局最佳位置移动的倾向。同样,粒子会根据随机数r2和学习因子c2来调整移动的幅度。

3.2位置 x \boldsymbol{x} x的更新公式

x = x + v \boldsymbol{x} = \boldsymbol{x}+\boldsymbol{v} x=x+v

4.完整代码&结果图


这次我打算先给出代码结果,然后最后再逐步解释每一步代码的意思。

4.1 完整代码

import numpy as np
import matplotlib.pyplot as plt

# 适应度函数
f = lambda x: x * np.sin(x) * np.cos(2 * x) - 2 * x * np.sin(x) + 3 * x * np.sin(4 * x)

N = 20  # 初始种群大小
d = 1  # 初始化定位粒子维度
ger = 100  # 迭代次数

limit = np.array([0, 50])  # 位置限制:设置粒子运行的位置的限制
v_limit = np.array([-10, 10])  # 速度限制:设置例子移动速度的上下值

w = 0.8  # 惯性权重
c1 = 0.5  # 自学习因子
c2 = 0.5  # 群体学习因子

# 初始化种群位置
x = limit[0] + (limit[1] - limit[0]) * np.random.rand(N, d)

# 初始化种群的速度
v = np.random.rand(N, d) * (v_limit[1] - v_limit[0]) + v_limit[0]
# 初始化每个个体的历史最佳位置
x_best_location = x.copy()
# 初始化个体历史最佳适应度
x_best = np.ones(N) * np.inf

g_best = np.inf  # 初始化全局最佳适应度
g_best_location = None  # 初始化全局最最佳位置

# 用于存储每一轮的结果
iter_result = []

for i in range(ger):
    fx = f(x).reshape(-1)  # 计算当前函数的适应度
    better_indices = fx < x_best
    x_best_location[better_indices] = x[better_indices]
    x_best[better_indices] = fx[better_indices]

    # 更新全局最优解
    if np.min(x_best) < g_best:
        g_best = np.min(x_best)
        g_best_location = x_best_location[np.argmin(x_best)]

    # 速度更新公式
    r1 = np.random.rand(N, d)   #随机系数
    r2 = np.random.rand(N, d)   #随机系数
    v = w * v + c1 * r1 * (x_best_location - x) + c2 * r2 * (np.expand_dims(g_best_location, axis=0) - x)

    # 粒子移动速度的边界约束处理
    v = np.clip(v, v_limit[0], v_limit[1])

    # 种群位置的更新
    x = x + v
    # 位置边界处理
    x = np.clip(x, limit[0], limit[1])

    iter_result.append(g_best)

print("g_best_location", g_best_location)
print("g_best", g_best)


plt.plot(iter_result,'b')
plt.xlabel("Number of iterations")
plt.ylabel("Fitness")
plt.grid()
plt.show()

4.2 迭代曲线

在这里插入图片描述

4.3 全局最优解和最优适应度(函数值)

g_best_location [45.20773182]
g_best -251.0638321801182

在这里插入图片描述
把搜索到的点绘制在原来的函数图像上,可以看到收敛的效果还是不错的。
在这里插入图片描述

5.代码分解详解


5.1参数初始化部分

  • 导入库
import numpy as np
import matplotlib.pyplot as plt
  • 使用匿名函数关键字构造适应度函数
# 适应度函数
f = lambda x: x * np.sin(x) * np.cos(2 * x) - 2 * x * np.sin(x) + 3 * x * np.sin(4 * x)
  • 基础初始化部分
N = 20  # 初始化种群个数
d = 1  # 每个粒子的数据维度
ger = 100  # 迭代次数

limit = np.array([0, 50])  # 设置粒子运行的位置的限制
v_limit = np.array([-10, 10])  # 设置例子移动速度的上下值

w = 0.8  # 移动的惯性权重
c1 = 0.5  # 自学习因子
c2 = 0.5  # 群体学习因子
  • 初始化种群位置

        这里要解释下,为什么要用这个公式来初始化种群位置,我之前在我的SMOTE算法的介绍里介绍过这个公式,他的作用是确保所有种群中每一个粒子的初始位置都在我们设定好的搜索区域的范围内,np.random.rand其中numpy的这个方法生成的所有的数都是在0和1之间的,np.random.rand(N, d)生成的的其实是一个维度为 ( N × d ) (N×d) (N×d)的矩阵,其中所有的元素大小都为在0和1之间,这部分可能稍微难理解一点可以多停下多思考一些

x = limit[0] + (limit[1] - limit[0]) * np.random.rand(N, d)
  • 对于 x 1 , x 2 \quad x_1,x_2\quad x1,x2如果 λ ∈ [ 0 , 1 ] \lambda\in[0,1]\quad λ[0,1] λ x 1 + ( 1 − λ ) x 2 \lambda x_1+(1-\lambda)x_2\quad λx1+(1λ)x2一定在 x 1 和 x 2 x_1和x_2 x1x2的连线上,其中 λ x 1 + ( 1 − λ ) x 2 \lambda x_1+(1-\lambda)x_2 λx1+(1λ)x2也可以转换为 x 2 + λ ( x 1 − x 2 ) x_2+\lambda(x_1-x_2) x2+λ(x1x2)或者 x 1 + λ ( x 2 − x 1 ) x_1+\lambda(x_2-x_1) x1+λ(x2x1)下图中 x 3 x_3 x3 x 1 x_1 x1 x 2 x_2 x2连接线上的一点,用初中的移项等知识就一定可以求到一个 λ \lambda λ
    请添加图片描述

  • 初始化种群速度
    种群位置好理解的化,这个就也很好理解了和上面的是一样的

v = np.random.rand(N, d) * (v_limit[1] - v_limit[0]) + v_limit[0]
  • 初始化每个个体的历史最佳位置的缓存变量。
    其实是我们单独需要一个变量来存储历史最佳位置,但是如果直接使用x_best_location = x,会导致两个变量的地址一致,修改一个就等于同时修改两个,因此需要加一个.copy 将数据拷贝到另一块地址,将x_best_loactionx隔离开,避免后续更新的过程中出现混乱。
x_best_location = x.copy()
  • 初始化用于保存个体最佳适应度的一个缓存变量。

        因为我们的目标是找到最小值,也就是适应度的值越小我们认为适应度更优,发现适应度更优之后去更新粒子的个体最优适应度,所以我们把起始的所有的粒子的最优适应度都设置为无穷大,其实也是可以直接设置成初始函数值,不过那样会在初始化的时候多一步批量计算,直接设置成无穷大,也不影响计算结果。

x_best = np.ones(N) * np.inf
  • 初始化全局最优适应度和全局最优位置
    上面的理解了,下面的也就差不多一个道理
g_best = np.inf  # 初始化全局最优适应度
g_best_location = None  # 初始化全局最优解位置
  • 定义一个空列表用于存储每一轮的结果,用于最后的绘图
iter_result = []

5.2迭代部分

for i in range(ger):
    fx = f(x).reshape(-1)  # 计算当前函数的适应度
    better_indices = fx < x_best
    x_best_location[better_indices] = x[better_indices]
    x_best[better_indices] = fx[better_indices]

    # 更新全局最优解
    if np.min(x_best) < g_best:
        g_best = np.min(x_best)
        g_best_location = x_best_location[np.argmin(x_best)]

    # 速度更新公式
    r1 = np.random.rand(N, d)
    r2 = np.random.rand(N, d)
    v = w * v + c1 * r1 * (x_best_location - x) + c2 * r2 * (np.expand_dims(g_best_location, axis=0) - x)

    # 粒子移动速度的边界约束处理
    v = np.clip(v, v_limit[0], v_limit[1])

    # 种群位置的更新
    x = x + v
    # 位置边界处理
    x = np.clip(x, limit[0], limit[1])

    iter_result.append(g_best)

        首先,经过匿名函数输出fx之后,fx,的维度是N个1维向量(实际上出来的是2维),不是1个N维的向量,为了方便后面的计算,所以需要加一个.reshape(-1),把输出降成1维。

fx = f(x).reshape(-1)

        然后这三个是个体最优适应度和个体最优位置,直接使用的是,numpy内置的索引功能,然后索引复制,有python基础的话,说到这应该能理解了,具体可以打断点然后单步调试一下,每个变量的变化。

    better_indices = fx < x_best
    x_best_location[better_indices] = x[better_indices]
    x_best[better_indices] = fx[better_indices]

        然后是更新全局最优解,这个就是基本的逻辑判断,np.argmin()的作用是返回一个数组中最小值的索引,然后x_best_location[np.argmin(x_best)]通过这个索引来获得全局最优的位置。

    if np.min(x_best) < g_best:
        g_best = np.min(x_best)
        g_best_location = x_best_location[np.argmin(x_best)]

        然后是速度更新,更新前先随机生成两个随机因子矩阵然后,更新速度的时候乘进去。

    r1 = np.random.rand(N, d)
    r2 = np.random.rand(N, d)
    v = w * v + c1 * r1 * (x_best_location - x) + c2 * r2 * (np.expand_dims(g_best_location, axis=0) - x)

        然后就是边界限制np.clip就可以直接对数组内的元素实现上下界约束的功能,比Matlab优雅多了。

    # 粒子移动速度的边界约束处理
    v = np.clip(v, v_limit[0], v_limit[1])

下面是位置更新,和约束,约束部分和上面同理。

    # 种群位置的更新
    x = x + v
    # 位置边界处理
    x = np.clip(x, limit[0], limit[1])

用列表记录这次迭代之后的最优结果。

    iter_result.append(g_best)

最后是打印和绘图。

print("g_best_location", g_best_location)
print("g_best", g_best)

plt.plot(iter_result,'b')
plt.xlabel("Number of iterations")
plt.ylabel("Fitness")
plt.grid()
plt.show()

6.结束


        虽然之前也接触过,不过这也是第一次完成的记录一个群智能优化算法的使用流程,之后估计在项目中也会用到,如果有需要看看自己再写一些其他的群智能优化算法。

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

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

相关文章

通过反思性反馈增强和提升大模型

人工智能咨询培训老师叶梓 转载标明出处 尽管通过人类反馈的强化学习&#xff08;RLHF&#xff09;在使LLMs与人类偏好对齐方面展现出潜力&#xff0c;但这种方法往往只会导致表面的对齐&#xff0c;优先考虑风格上的变化而非提升LLMs在下游任务中的表现。而且偏好的不明确可能…

【漏洞复现】公交IC卡收单管理系统 SQL注入致RCE漏洞复现

》》》产品描述《《《 公交IC卡收单 管理系统Q是城市公共交通领域中不可或缺的一部分&#xff0c;它通过集成先进的集成电路技术(IC卡)实现了乘客便捷的支付方式&#xff0c;并有效提高了公共交通运营效率。系统集成了发卡、充值、消费、数据采集、查询和注销等多个功能模块&am…

走进上海郭培高定会馆:以冠珠华脉、华珍筑就至臻至性的艺术空间

“我热爱高级时装&#xff0c;因为她是一种生命的停驻。我希望我的高级时装成为馆藏级的精品&#xff0c;殿堂级的珍宝&#xff0c;成为传世杰作。” ——郭培 中国唯一一位法国高定公会受邀会员&#xff0c;曾荣登《TIME》时代周刊全球100位最具影响力人物榜单。纽约时报评价…

Error:Decorators are not valid here. 使用Angular中的装饰器

Decorators are not valid here&#xff0c;项目中出现这个提示信息&#xff0c;说明装饰器未知错误、或者在不支持的元素上使用了装饰器。 如下图所示&#xff0c;我在NgModule装饰器后面加了一个导出方法&#xff0c;加完之后控制台提示了如下错误&#xff1a;Error TS1206&a…

基于Spring Boot+Vue的减肥健康管理系统设计和实现【原创】(BMI算法,协同过滤算法、图形化分析)

&#x1f388;系统亮点&#xff1a;图形化分析、BMI算法&#xff0c;协同过滤算法&#xff1b; 一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构&#xff1a;B/S架构 运行环境&#xff1a;win10/win11、jdk17 前端&#xff1a…

GLIPv2

GLIPv2 论文《GLIPv2: Unifying Localization and Vision-Language Understanding》、代码 3.3.1简介 GLIPv2和GLIPv1架构基本一样&#xff0c;只是融合了更多的任务和数据集。从论文题目 Unifying Localization and Vision-Language Understanding可以看出&#xff0c;其统一了…

精密机械代加工的特点和优势

在现代工业生产中&#xff0c;精密机械代加工扮演着至关重要的角色。它为众多企业提供了高质量、高精度的机械零部件加工服务&#xff0c;满足了不同行业对精密机械产品的需求。以下是时利和将详细介绍精密机械代加工的特点和优势。 一、特点 1.高精度加工 精密机械代加工的首要…

DK5V100R10SL贴片TO252功率12V4.3A同步整流芯片

概述DK5V100R10SL是一款简单高效率的同步整流芯片&#xff0c;只有A&#xff0c;K两个功能引脚&#xff0c;分别对应肖特基二极管PN管脚。芯片内部集成了100V功率NMOS管&#xff0c;可以大幅降低二极管导通损耗&#xff0c;提高整机效率&#xff0c;取代或替换目前市场上等规的…

ResNet50V2:口腔癌分类

本文为为&#x1f517;365天深度学习训练营内部文章 原作者&#xff1a;K同学啊 一 ResNet和ResNetV2对比 改进点&#xff1a;(a)original表示原始的ResNet的残差结构&#xff0c;(b)proposed表示新的ResNet的残差结构&#xff0c;主要差别就是(a)结构先卷积后进行BN和激活函数…

栈及笔试题

目录 栈的实现 1、数组栈 2、链式栈 栈的创建 栈的打印 内存泄漏 栈溢出 练习 有效的括号 栈的实现 栈后入先出 1、数组栈 &#xff08;最佳实现&#xff0c;且访问数据的时候CPU告诉访存命中率比较高&#xff0c;因为地址连续存放&#xff0c;访问时CPU从cache里一…

货币单位换算 - 华为OD统一考试(E卷)

2024华为OD机试(E卷+D卷)最新题库【超值优惠】Java/Python/C++合集 题目描述 记账本上记录了若干条多国货币金额,需要转换成人民币分(fen),汇总后输出。 每行记录一条金额,金额带有货币单位,格式为数字+单位,可能是单独元,或者单独分,或者元与分的组合。 要求将这些…

解决QT开发由于中文导致的编译错误以及输出内容乱码问题

在进行QT程序开发时&#xff0c;大家可能或者一定会遇到的问题就是中文乱码问题&#xff0c;这个乱码问题可能是在你看代码的显示上&#xff0c;也可能在程序的输出上&#xff0c;甚至还有可能导致你的代码直接编译失败&#xff0c;都有可能和中文编码有关&#xff0c;还有一些…

力扣(leetcode)每日一题 2207 字符串中最多数目的子序列

题干 2207. 字符串中最多数目的子序列 给你一个下标从 0 开始的字符串 text 和另一个下标从 0 开始且长度为 2 的字符串 pattern &#xff0c;两者都只包含小写英文字母。 你可以在 text 中任意位置插入 一个 字符&#xff0c;这个插入的字符必须是 pattern[0] 或者 pattern…

提升论文质量必备!2024年顶尖8款AI写作工具!

各位好&#xff01;在这个信息化迅速发展的年代&#xff0c;AI技术已经成为我们学术探索的重要辅助力量。本次&#xff0c;我将向大家展示2024年八款必备的尖端AI应用。这些工具不仅能极大提升我们撰写学术论文的效率&#xff0c;还能改善研究的质量。 首先我们来看“梅子AI论…

Langgraph 的 Planning Agent 深度解析

在人工智能领域&#xff0c;智能代理&#xff08;agent&#xff09;的设计愈发重要。尤其在面对复杂任务时&#xff0c;规划&#xff08;planning&#xff09;技术成为智能代理的核心能力之一。Langgraph 是一个专为构建智能代理而设计的框架&#xff0c;结合了自然语言处理&am…

2024年项目经理不容错过的资源:全面测试管理工具指南与精选实例

随着软件开发的快速发展&#xff0c;测试管理工具在项目经理的日常工作中扮演着越来越重要的角色。2024年&#xff0c;哪些测试管理工具是项目经理不能错过的呢&#xff1f;本文将为您带来一份全面指南&#xff0c;帮助您找到最佳选择。 在软件开发过程中&#xff0c;测试是确保…

鸿蒙开发(NEXT/API 12)【硬件(接入手写套件)】手写功能开发

接入手写套件后&#xff0c;可以在应用中创建手写功能界面。界面包括手写画布和笔刷工具栏两部分&#xff0c;手写画布部分支持手写笔和手指的书写效果绘制&#xff0c;笔刷工具栏部分提供多种笔刷和编辑工具&#xff0c;并支持对手写功能进行设置。接入手写套件后将自动开启一…

机器学习方法实现水果分类(零基础小白向),手工提取水果图片特征,不一样的特征提取方法

文章目录 零、前言&#xff1a;一、什么是特征向量&#xff1f;二、数据准备三、构建数据集1、什么是数据集&#xff1f;2、图片对应的标签&#xff1f;3、特征提取方法&#xff08;1&#xff09;生成固定正方形&#xff08;2&#xff09;特征提取实现 四、建立模型五、自定义数…

【Python】遇见的问题:为项目选择的 Python 解释器无效

一、问题说明 导入项目文件后&#xff0c;提示“为项目选择的 Python 解释器无效” 二、问题原因 暂时不知道 三、解决办法 第一步&#xff1a;添加本地解释器 第二步&#xff1a;点击确定 位置&#xff1a;当前项目所在目录 基础解释器&#xff1a;python.exe所在目录 第三…

五子棋双人对战项目(2)——登录模块

目录 一、数据库模块 1、创建数据库 2、使用MyBatis连接并操作数据库 编写后端数据库代码 二、约定前后端交互接口 三、后端代码编写 文件路径如下&#xff1a; UserAPI&#xff1a; UserMapper&#xff1a; 四、前端代码 登录页面 login.html&#xff1a; 注册页面…