如何用 python 代码复现 MATLAB simulink 的 PID

  • MATLAB
    • 在 Simulink 里做以下设置
    • MATLAB 脚本调用示例
  • python 实现
    • 离散 PID 实现(并行形式)
  • Simulink 中两种 PID 结构(并联形式, I-形式)下连续/离散时域里积分增益 I 的表示
    • 并联(Parallel) vs 理想(I-Form),use I*Ts 的勾选
    • 什么时候用连续域 vs 离散域?

MATLAB

首先,MATLAB simulink 的 PID 长这样:
在这里插入图片描述

其中,PID 控制器以 1e-4 的步长运行,而物理模型用固定步长 1e-5 的求解器来集成。

这样,每仿真一次 StopTime = 1e-4,就得到了“10 步模型响应 + 1 次 PID 更新”之后的 Z Z Z V _ I C 1 V\_IC1 V_IC1,非常符合“每个控制电压需要响应 10 次”的需求。

在 Simulink 里做以下设置

  1. Solver

    • 打开 Model Settings (Ctrl+E)Solver
    • TypeFixed-step
    • Solverode4 (Runge–Kutta)(或者其他固定步长求解器)
    • Fixed-step size1e-5
  2. PID Controller

    • 双击 PID 块(或 PID Controller),在 Discrete 模式下
    • Sample time (Ts)1e-4
  3. Rate Transition(可选,但推荐)

    • 在 PID 输出和物理模型输入之间加一个 Rate Transition 块,保证两条不同速率信号安全切换。
    • 默 1e-4 → 1e-5,不用改参数,Simulink 会自动用最近邻保持。
  4. Initial Condition

    • 把物理模型里初始化状态的那一支“Initial Condition”块的初值写成变量 x0(工作区定义)。
  5. To Workspace

    • 用 To Workspace 块把 outZ(物理模型的 Z)和 outV_IC1(PID 输出)导出。

MATLAB 脚本调用示例

%%—— 预先在 base workspace 定义好初始状态和参考值 ——%%
x0 = [...];             % 初始状态向量
Z_reference = 0;        % 参考值恒为 0assignin('base','x0',x0);
assignin('base','Z_reference',Z_reference);%%—— 设置仿真——%%
Ts_ctrl   = 1e-4;       % 控制器采样周期
Ts_solver = 1e-5;       % 求解器步长mdl = 'PID';
open_system(mdl);% 1) 全局求解器
set_param(mdl, ...'Solver',        'ode4', ...         % 固定步长 RK4'FixedStep',     num2str(Ts_solver), ...'StopTime',      num2str(Ts_ctrl)    % 仿真到一个控制步
);% 2) PID 块采样时间
set_param([mdl '/PID Controller'], ...'SampleTime', num2str(Ts_ctrl) ...
);%%—— 运行仿真 ——%%
simOut = sim(mdl, ...'SrcWorkspace','base', ...'SaveOutput','on', ...'ReturnWorkspaceOutputs','on');%%—— 提取最后一步 ——%%
Z_all     = simOut.get('outZ');        % time series
V_IC1_all = simOut.get('outV_IC1');Z     = Z_all(end);
V_IC1 = V_IC1_all(end);fprintf('t=%.0e 时刻: Z = %.6f,  V_IC1 = %.6f\n', Ts_ctrl, Z, V_IC1);

python 实现

对于相同的求解器初始值,如果 MATLAB PID 和 python PID 的 第一步输出相差一个数量级,最常见的坑就是:

在这里插入图片描述

MATLAB PID 块的参数含义可能和你认为的不一样(详见下文 Simulink 中两种 PID 结构中 I 增益的表示)

  • Simulink 默认的 PID 块有好几种形式(Parallel / I-form / P-only …),比如,连续时域中 它的 “I 增益” 在 Parallel 形式下 表示的是 K i s \frac{K_i}{s} sKi。如果直接把块里的 “I 增益” 当成 Python 里的 K i K_i Ki,就会差好几倍。
    在这里插入图片描述
  • 检查双击 Simulink PID 块,看它 是连续时间还是离散时间是 Parallel 形式还是 I-form,然后 把参数转换成 Python 里的 ( K p , K i , K d , N ) (K_p,\,K_i,\,K_d,\,N) (Kp,Ki,Kd,N) 平行形式

对号入座,才能在 Python 里准确还原 MATLAB/Simulink 的 PID 积分行为。

离散 PID 实现(并行形式)

Simulink 的离散 PID Controller 块并不是把连续‐时间的

u ( t ) = − ( K p e + K i ⁣ ∫ e d t + K d e ˙ ) u(t)=-\bigl(K_p e + K_i\!\int e\,dt + K_d\dot e\bigr) u(t)=(Kpe+Kiedt+Kde˙)

简单地用欧拉积分+一阶滤波来近似。它用的是一整套 “ z z z 域” 差分方程:

C ( z ) = P + I T s 1 z − 1 + D N 1 + N T s z − 1 z C(z)\;=\;P \;+\; I\,T_s\frac{1}{z-1} \;+\; D\,\frac{N}{1+N\,T_s}\,\frac{z-1}{z} C(z)=P+ITsz11+D1+NTsNzz1

  1. 积分项

    u I [ k ] = u I [ k − 1 ] + I T s e [ k ] u_I[k]=u_I[k-1]+I\,T_s\;e[k] uI[k]=uI[k1]+ITse[k]

  2. 微分项(带滤波)
    N d = N T s N_d=N\,T_s Nd=NTs,有

    y D [ k ] = 1 1 + N d y D [ k − 1 ] + K d N d 1 + N d ( e [ k ] − e [ k − 1 ] ) y_D[k] =\frac{1}{1+N_d}\,y_D[k-1] \;+\;\frac{K_d\,N_d}{1+N_d}\bigl(e[k]-e[k-1]\bigr) yD[k]=1+Nd1yD[k1]+1+NdKdNd(e[k]e[k1])

  3. 总输出

    u [ k ] = K p e [ k ] + u I [ k ] + y D [ k ] u[k] = K_p\,e[k] + u_I[k] + y_D[k] u[k]=Kpe[k]+uI[k]+yD[k]

而如果在 Python 里用的是连续时间那套,

new_integral = integral + e*dt
derivative  = (N*dt*raw_derivative + prev_filtered)/(1+N*dt)
u =  Kp*e + Ki*integral + Kd*derivative

它们并不等价。

下面这段代码给出了一个跟 Simulink 离散 PID Controller 块 一模一样的差分实现。它对应于块上方显示的 并行形式

C ( z ) = P + I T s 1 z − 1 + D N 1 + N T s z − 1 z , C(z)=P \;+\; I\,T_s\frac{1}{z-1} \;+\; D\frac{N}{1+N\,T_s}\frac{z-1}{z}, C(z)=P+ITsz11+D1+NTsNzz1,

其中 “积分(I)”框里显示的就是 I T s I\,T_s ITs(注意勾选),所以在代码里直接用它来做积分增量积分输出最终的控制量 都被 钳位在 [ − V l i m , V l i m ] [-V_{\rm lim},\,V_{\rm lim}] [Vlim,Vlim] 以内

P P P 项没有啥好说的,首先根据上面说的实现 I I I 项,

# 内部状态
self.uI     = 0.0   # 上一步积分项 u_I[k-1]
self.yD     = 0.0   # 上一步滤波微分 y_D[k-1]
self.e_prev = 0.0   # 上一次误差 e[k-1]
# 积分项(差分形式)
uI_candidate  = self.uI_prev + self.Ki * error   # use I*Ts in simulink
# Anti-windup: limit integral term 将 integral 限在 [-V_lim, +V_lim]
uI_candidate  = torch.clamp(uI_candidate, -self.V_lim, self.V_lim)  

注意,在 Simulink 离散 PID Controller 块中,积分项的更新总是滞后一拍,它遵循“先用上一步(或初始)的状态算输出,再更新状态” 的时序。

在这里插入图片描述
可以在 MATLAB 中只打开 I 控制器实验,会发现第一步的控制器输出为 0。

  1. 初始时刻 t = 0 t=0 t=0 的输出
  • 块会先把“初始积累值” u I [ 0 ] u_I[0] uI[0](默认由 Integrator Initial Condition 参数决定,缺省为 0)和“初始滤波值” y D [ 0 ] y_D[0] yD[0](同样缺省为 0)带入控制律中。
  • 此时即便误差 e [ 0 ] ≠ 0 e[0]\neq0 e[0]=0,积分项 还没有 加上 K i T s ⋅ e [ 0 ] \,K_iT_s\cdot e[0] KiTse[0] 的那部分增量,因此积分输出项是 0;
  1. 在第一个采样周期结束( t = T s t=T_s t=Ts)时
  • Simulink 才会用 e [ 0 ] e[0] e[0] 来更新积分器:
    u I [ 1 ] = u I [ 0 ] + ( K i T s ) e [ 0 ] , u_I[1] = u_I[0] + (K_iT_s)\,e[0], uI[1]=uI[0]+(KiTs)e[0],
    并在此刻把新的 u I [ 1 ] u_I[1] uI[1] 参与下一次输出计算。

forward() 实现改成这样,就能和 Simulink 保持一致:

# 先用 P项、旧滤波、微分项 计算输出
u_unsat = self.Kp*e + self.uI_prev + self.yD# 再更新积分状态,为下一步准备
uI_candidate  = self.uI_prev + self.Ki * error   # use I*Ts in simulink

接下来是微分项 D D D 的实现,

在这里插入图片描述

 # 更新 D 项 —— 前向欧拉离散滤波, 差分方程来源于: yD[k] = yD[k-1] + Ts*( Kd*N*(e[k]-e[k-1])/Ts - N*yD[k-1] )
raw_deriv = (error - self.e_prev) / self.dt
self.yD = self.yD_prev + self.dt * ( self.Kd * self.N * raw_deriv - self.N * self.yD_prev )

Simulink 中两种 PID 结构(并联形式, I-形式)下连续/离散时域里积分增益 I 的表示

先把几个概念理清:

  1. 连续域的 s s s(拉普拉斯算子)

    • 把时间域信号 f ( t ) f(t) f(t) 变换到复频域后,微分 d d t \tfrac{d}{dt} dtd 对应乘以 s s s

      L { x ˙ ( t ) } = s X ( s ) . \mathcal{L}\{\,\dot x(t)\} = s X(s). L{x˙(t)}=sX(s).

    • 因此, K i s \dfrac{K_i}{s} sKi 就是“对误差做积分”—— K i K_i Ki 是积分增益,单位大致是“控制量/(误差×秒)”。

  2. 离散域的 1 z − 1 \tfrac{1}{z-1} z11(差分算子)

    • 把时间序列 x [ k ] x[k] x[k] z z z 变换后,

      Z { x [ k ] − x [ k − 1 ] } = ( 1 − z − 1 ) X ( z ) ⟹ Z { ∑ i = 0 k x [ i ] } = 1 1 − z − 1 X ( z ) = z − 1 1 − z − 1 X ( z ) . \mathcal{Z}\{\,x[k]-x[k-1]\} = (1 - z^{-1})X(z) \quad\Longrightarrow\quad \mathcal{Z}\Bigl\{\sum_{i=0}^k x[i]\Bigr\} = \frac{1}{1-z^{-1}}X(z) = \frac{z^{-1}}{1-z^{-1}}\,X(z)\,. Z{x[k]x[k1]}=(1z1)X(z)Z{i=0kx[i]}=1z11X(z)=1z1z1X(z).

    • 换一种常见写法 1 z − 1 = − z − 1 1 − z − 1 \tfrac{1}{z-1} = -\tfrac{z^{-1}}{1-z^{-1}} z11=1z1z1,它就对应“累加求和”那一块。离散积分项一般写成

      K i T s 1 z − 1 ⟺ u I [ k ] = u I [ k − 1 ] + K i T s e [ k ] . K_i\,T_s\;\frac{1}{z-1} \quad\Longleftrightarrow\quad u_I[k] = u_I[k-1] + K_i\,T_s\,e[k]. KiTsz11uI[k]=uI[k1]+KiTse[k].

    • 这里 T s T_s Ts 是采样周期,把每步的积分增益拉成了和连续域里 K i / s K_i/s Ki/s 数值等价的 “每步累加” 形式。

并联(Parallel) vs 理想(I-Form),use I*Ts 的勾选

特性并联(Parallel)形式I-Form(Ideal)形式
连续时域公式 C ( s ) = K p + K i s + K d N 1 + N 1 s C(s)=K_p + \dfrac{K_i}{s} + K_d\,\frac{N}{1+N \frac{1}{s}} C(s)=Kp+sKi+Kd1+Ns1N C ( s ) = K p + K p T i 1 s + K p K d N 1 + N 1 s C(s)=K_p + \dfrac{K_p}{T_i}\,\dfrac{1}{s} + K_p K_d \frac{N}{1+N \frac{1}{s}} C(s)=Kp+TiKps1+KpKd1+Ns1N
离散时域公式 C ( z ) = K p + K i T s 1 z − 1 + K d N 1 + N T s 1 z − 1 C(z)=K_p + K_i T_s \dfrac{1}{z-1} + K_d \frac{N}{1 + N T_s\frac{1}{z-1}} C(z)=Kp+KiTsz11+Kd1+NTsz11N C ( z ) = K p + K p T s T i 1 z − 1 + K p K d N 1 + N T s 1 z − 1 C(z)=K_p + \dfrac{K_p T_s}{T_i}\,\dfrac{1}{z-1} + K_p K_d \frac{N}{1 + N T_s\frac{1}{z-1}} C(z)=Kp+TiKpTsz11+KpKd1+NTsz11N
离散时域差分实现 u I [ k ] = u I [ k − 1 ] + K i T s e [ k ] \;u_I[k]=u_I[k-1]+K_i\,T_s\,e[k] uI[k]=uI[k1]+KiTse[k] u I [ k ] = u I [ k − 1 ] + K p T s T i e [ k ] \;u_I[k]=u_I[k-1]+\tfrac{K_p\,T_s}{T_i}\,e[k] uI[k]=uI[k1]+TiKpTse[k]
  • 离散模式 下,
    在这里插入图片描述
    • 勾选 “Use I*Ts” 时,PID Controller 块中的“积分 (I)”文本框显示的就是 K i T s K_i\,T_s KiTs,这个数值直接用于差分方程 u I [ k ] = u I [ k − 1 ] + ( K i T s ) e [ k ] \;u_I[k]=u_I[k-1]+(K_iT_s)\,e[k] uI[k]=uI[k1]+(KiTs)e[k]
    • 不勾选 “Use I*Ts”,文本框则显示纯粹的离散积分增益 K i K_i Ki,块会在后台自动再乘以 T s T_s Ts 来进行积分运算,即等效地使用 K i T s K_iT_s KiTs
  • 连续模式 下,无论是否有“Use I*Ts”,文本框显示的都是连续域的积分增益
    K i s \dfrac{K_i}{s} sKi 中的 K i K_i Ki,即单位为“控制量/(误差·秒)”的参数。
结构类型文本框显示(离散)差分方程增量Simulink 帮你做的事
并联(Parallel) K i T s K_iT_s KiTs(勾选 Use I*Ts)
K i K_i Ki(不勾选)
u I [ k ] = u I [ k − 1 ] + ( K i T s ) e [ k ] \;u_I[k]=u_I[k-1]+(K_iT_s)\,e[k] uI[k]=uI[k1]+(KiTs)e[k]若不勾选,块会自动乘以 T s T_s Ts;勾选则用文本框数值直接累加。
理想(I-Form) T i T_i Ti(始终) u I [ k ] = u I [ k − 1 ] + K p T s T i e [ k ] \;u_I[k]=u_I[k-1]+\tfrac{K_p\,T_s}{T_i}\,e[k] uI[k]=uI[k1]+TiKpTse[k]勾选后内部把 T i T_i Ti 换算为 K p T s T i \tfrac{K_pT_s}{T_i} TiKpTs

根据 MATLAB 官方文档,

在这里插入图片描述

Tip

  • 如果你 已经在 并联下直接获得了离散 K i T s K_iT_s KiTs(比如 Simulink 给你的那一栏),就直接拿来用,不要再二次换算
    在并联(Parallel)结构下,Simulink 参数栏 “积分(I)”框里显示的正是 K i T s K_i\,T_s KiTs(离散)或 K i K_i Ki(连续),直接把 Simulink 中读到的 “积分(I)” 值当做 K i T s K_i\,T_s KiTs(离散)或 K i K_i Ki(连续)使用即可。
  • 如果是在 理想(I-Form) 下得到一个积分时间 T i T_i Ti,“积分( I )” 填的是 T i T_i Ti,它会自动在内部换算成 K p T s / T i K_pT_s/T_i KpTs/Ti;python 实现需要再用
    K i , d i s c r e t e = K p T s T i K_{i,\mathrm{discrete}} = \frac{K_p\,T_s}{T_i} Ki,discrete=TiKpTs
    换算成“每步累加增量”。

什么时候用连续域 vs 离散域?

  • 如果把整个闭环模型当成一个离散‐时间系统 —— 比如用

    x k + 1 = e A T s x k + A − 1 ( e A T s − I ) B u k x_{k+1} = e^{A\,T_s}\,x_k \;+\; A^{-1}(e^{A\,T_s}-I)\,B\,u_k xk+1=eATsxk+A1(eATsI)Buk

    这样的精确离散更新公式(基于矩阵指数)来推进状态,那么整个控制器的设计、仿真与实现,就更自然地放在离散时域里:

    • 在每个采样点 k k k 计算误差 e [ k ] e[k] e[k],更新离散 PID 差分方程,输出 u k u_k uk,然后用上面的公式算 x k + 1 x_{k+1} xk+1
    • 这时把 Simulink 里“并联形式”的离散 PID 差分方程直接拿过来用,就保证“数值上一致”。
    • 连续域的 K i / s K_i/s Ki/s 并不直接作用于这个仿真步长里,它只是一个设计思想——真正跑的时候都要离散化。
  • 如果你打算在连续‐时间下设计 PID(比如先用频域调参工具、根轨迹、Bode 曲线,得到 K i , K p , K d K_i,K_p,K_d Ki,Kp,Kd),再把它离散化(如向后差分、双线性变换 Tustin 法、零阶保持 ZOH),那么就先在连续时域下选好参数,然后再用某种离散化方法转换成离散差分形式。

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

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

相关文章

黑马点评--基于Redis实现共享session登录

集群的session共享问题分析 session共享问题:多台Tomcat无法共享session存储空间,当请求切换到不同Tomcat服务时,原来存储在一台Tomcat服务中的数据,在其他Tomcat中是看不到的,这就导致了导致数据丢失的问题。 虽然系…

SkyWalking启动失败:OpenSearch分片数量达到上限的完美解决方案

🚨 问题现象 SkyWalking OAP服务启动时报错: org.apache.skywalking.oap.server.library.module.ModuleStartException: java.lang.RuntimeException: {"error":{"root_cause":[{"type":"validation_exception", "reason&q…

向量数据库选型实战指南:Milvus架构深度解析与技术对比

导读:随着大语言模型和AI应用的快速普及,传统数据库在处理高维向量数据时面临的性能瓶颈日益凸显。当文档经过嵌入模型处理生成768到1536维的向量后,传统B-Tree索引的检索效率会出现显著下降,而现代应用对毫秒级响应的严苛要求使得…

MySQL#秘籍#一条SQL语句执行时间以及资源分析

背景 一条 SQL 语句的执行完,每个模块耗时,不同资源(CPU/IO/IPC/SWAP)消耗情况我该如何知道呢?别慌俺有 - MySQL profiling 1. SQL语句执行前 - 开启profiling -- profiling (0-关闭 1-开启) -- 或者:show variables like prof…

【数据结构】实现方式、应用场景与优缺点的系统总结

以下是编程中常见的数据结构及其实现方式、应用场景与优缺点的系统总结: 一、线性数据结构 1. 数组 (Array) 定义:连续内存空间存储相同类型元素。实现方式:int[] arr new int[10]; // Javaarr [0] * 10 # Python操作: 访问&…

PyTorch中cdist和sum函数使用示例详解

以下是PyTorch中cdist与sum函数的联合使用详解: 1. cdist函数解析 功能:计算两个张量间的成对距离矩阵 输入格式: X1:形状为(B, P, M)的张量X2:形状为(B, R, M)的张量p:距离类型(默认2表示欧式距离)输出:形状为(B, P, R)的距离矩阵,其中元素 d i j d_{ij} dij​表示…

Ansible配置文件常用选项详解

Ansible 的配置文件采用 INI 格式,分为多个模块,每个模块包含特定功能的配置参数。 以下是ansible.cfg配置文件中对各部分的详细解析: [defaults](全局默认配置) inventory 指定主机清单文件路径,默认值为 …

了解FTP搜索引擎

根据资料, FTP搜索引擎是专门搜集匿名FTP服务器提供的目录列表,并向用户提供文件信息的网站; FTP搜索引擎专门针对FTP服务器上的文件进行搜索; 就是它的搜索结果是一些FTP资源; 知名的FTP搜索引擎如下, …

【大模型面试每日一题】Day 28:AdamW 相比 Adam 的核心改进是什么?

【大模型面试每日一题】Day 28:AdamW 相比 Adam 的核心改进是什么? 📌 题目重现 🌟🌟 面试官:AdamW 相比 Adam 的核心改进是什么? #mermaid-svg-BJoVHwvOm7TY1VkZ {font-family:"trebuch…

C++系统IO

C系统IO 头文件的使用 1.使用系统IO必须包含相应的头文件,通常使用#include预处理指令。 2.头文件中包含了若干变量的声明,用于实现系统IO。 3.头文件的引用方式有双引号和尖括号两种,区别在于查找路径的不同。 4.C标准库提供的头文件通常没…

多模态理解大模型高性能优化丨前沿多模态模型开发与应用实战第七期

一、引言 在前序课程中,我们系统剖析了多模态理解大模型(Qwen2.5-VL、DeepSeek-VL2)的架构设计。鉴于此类模型训练需消耗千卡级算力与TB级数据,实际应用中绝大多数的用户场景均围绕推理部署展开,模型推理的效率影响着…

各个网络协议的依赖关系

网络协议的依赖关系 学习网络协议之间的依赖关系具有多方面重要作用,具体如下: 帮助理解网络工作原理 - 整体流程明晰:网络协议分层且相互依赖,如TCP/IP协议族,应用层协议依赖传输层的TCP或UDP协议来传输数据&#…

11.8 LangGraph生产级AI Agent开发:从节点定义到高并发架构的终极指南

使用 LangGraph 构建生产级 AI Agent:LangGraph 节点与边的实现 关键词:LangGraph 节点定义, 条件边实现, 状态管理, 多会话控制, 生产级 Agent 架构 1. LangGraph 核心设计解析 LangGraph 通过图结构抽象复杂 AI 工作流,其核心要素构成如下表所示: 组件作用描述代码对应…

相机--基础

在机器人开发领域,相机种类很多,作为一个机器人领域的开发人员,我们需要清楚几个问题: 1,相机的种类有哪些? 2,各种相机的功能,使用场景? 3,需要使用的相机…

【备忘】 windows 11安装 AdGuardHome,实现开机自启,使用 DoH

windows 11安装 AdGuardHome,实现开机自启,使用 DoH 下载 AdGuardHome解压 AdGuardHome启动 AdGuard Home设置 AdGuardHome设置开机自启安装 NSSM设置开机自启重启电脑后我们可以访问 **http://127.0.0.1/** 设置使用 AdGuardHome DNS 效果图 下载 AdGua…

安装部署配置jenkins

随着现代软件开发流程的不断演进,持续集成(CI)和持续交付(CD)已经成为了开发团队必不可少的工具。而Jenkins作为最为广泛应用的CI/CD工具,能够自动化执行构建、测试、部署等任务。Maven作为Java生态中广泛使用的构建工具,它能够帮助开发人员自动化管理项目的构建、依赖和…

How to balance work and personal life?

How to balance work and personal life? 1. Background2. How to balance work and personal life?References 1. Background Let me introduce /ˌɪntrəˈdjuːs/ the background /ˈbkɡraʊnd/ first. Today we will talk about this topic: How to balance work and …

存储引擎系列--LSM的Compaction研究方法论

本文主要包含以下内容: 1、Compaction 设计空间的四个原语:触发器、数据布局、压缩粒度、数据移动策略。任何已有的compaction策略和新的策略都可以由这个四个原语组建构成。 2、详细介绍这四个原语的定义,策略方法 3、现有的基于LSM的知名系统的compaction策略按照四个原语…

关系数据库基础入门

关系数据库概述 相关名词 1、关系:在关系数据库中,实体以及实体间的联系都是用关系来表示的。类似于程序设计语言中变量的概念。 2、关系模式:是对关系的描述。类似于程序设计语言中类型定义的概念。 3、关系模型:是由若干个关系…

图解BERT

图解 Bert 大家可以访问 图解Bert 获取更加优质的阅读体验。 图解BERT一文还在持续更新中。 环境搭建 按序执行以下命令完成环境搭建: git clone https://github.com/DA-southampton/Read_Bert_Code.git cd Read_Bert_Code conda create -n Read_Bert_Code python3.9.22 co…