使用Pytorch从零开始构建Normalizing Flow

news2024/11/28 7:30:38

在这里插入图片描述
归一化流 (Normalizing Flow) (Rezende & Mohamed,2015)学习可逆映射 f : X → Z f: X \rightarrow Z f:XZ, 在这里X是我们的数据分布,Z是选定的潜在分布。

归一化流是生成模型家族的一部分,其中包括变分自动编码器 (VAE) (Kingma & Welling, 2013)和生成对抗网络 (GAN) (Goodfellow 等人, 2014)。一旦我们学会了映射 f f f,我们通过采样生成数据 z ~ p Z z~p_Z zpZ, 然后应用逆变换, f − 1 ( z ) = X G e n f^{-1}(z)=X_{Gen} f1(z)=XGen

在本博客中,为了更好地理解归一化流,我们将介绍算法的理论并在 PyTorch 中实现流模型。但首先,让我们来看看归一化流的优点和缺点。

注意:如果您对生成模型之间的比较不感兴趣,您可以跳至“归一化流的工作原理”。

为什么要归一化流

有了 VAE 和 GAN 所显示的惊人结果,为什么要使用归一化流?我们列出了以下优点。(注:大部分优点来自 GLOW 论文(Kingma & Dhariwal,2018))

  • NF 优化数据的精确对数似然, l o g ( p X ) log(p_X) log(pX
    • VAE 优化下限 (ELBO)
    • GAN 学会欺骗鉴别器网络
  • NF 推断精确的潜变量值z,这对于下游任务很有用。
    • VAE 推断潜变量值的分布
    • GAN 没有潜在分布
  • 具有节省内存的潜力,NF 梯度计算按其深度恒定缩放。
    • VAE 和 GAN 的梯度计算都与其深度线性缩放
  • NF 只需要一个编码器即可学习。
    • VAE 需要编码器和解码器网络
    • GAN 需要生成网络和判别网络

但请记住妈妈所说的话:“天下没有免费的午餐”。

归一化流的一些缺点如下:

  • 可逆性和高效雅可比计算的要求限制了模型架构。
    • 稍后会详细介绍……
  • 与其他生成模型相比,NF 的资源/研究较少。
    • 写这个博客的原因!
  • NF 生成结果仍然落后于 VAE 和 GAN。

现在让我们深入了解一些理论!

归一化流如何工作

在本节中,我们简要回顾一下归一化流的核心。

变量的概率分布变化

考虑一个随机变量 X ∈ R d X \in \mathbb{R}^d XRd (我们的数据分布)和可逆变换 f : R d ↦ R d f: \mathbb{R}^d \mapsto \mathbb{R}^d f:RdRd
那么有一个随机变量 Z ∈ R d Z \in \mathbb{R}^d ZRd 是从 X X X 通过 f f f 映射而来。
进一步的,
P ( X = x ) = P ( f ( X ) = f ( x ) ) = P ( Z = z ) (0) P(X = x) = P(f(X) = f(x)) = P(Z = z)\tag{0} P(X=x)=P(f(X)=f(x))=P(Z=z)(0)
现在考虑一些X上的某个区间 β \beta β,那么存在Z上一定的区间 β ′ \beta^{\prime} β 使得
P ( X ∈ β ) = P ( Z ∈ β ′ ) (1) P(X \in \beta) = P(Z \in \beta^{\prime})\tag{1} P(Xβ)=P(Zβ)(1)
∫ β p X d x = ∫ β ′ p Z d z (2) \int_{\beta} p_X dx = \int_{\beta^{\prime}} p_Z dz\tag{2} βpXdx=βpZdz(2)
为了简单起见,我们考虑单个区域。
d x ⋅ p X ( x ) = d z ⋅ p Z ( z ) (3) dx \cdot p_X(x) = dz \cdot p_Z(z) \tag{3} dxpX(x)=dzpZ(z)(3)
p X ( x ) = ∣ d z d x ∣ ⋅ p Z ( z ) (4) p_X(x) = \mid\dfrac{dz}{dx}\mid \cdot p_Z(z) \tag{4} pX(x)=∣dxdzpZ(z)(4)
注意:我们应用绝对值来保持相等,因为根据概率公理 p X p_X pX p Z p_Z pZ永远都是正的。
p X ( x ) = ∣ d f ( x ) d x ∣ ⋅ p Z ( f ( x ) ) (5) p_X(x) = \mid\dfrac{df(x)}{dx}\mid \cdot p_Z(f(x)) \tag{5} pX(x)=∣dxdf(x)pZ(f(x))(5)
p X ( x ) = ∣ d e t ( d f d x ) ∣ ⋅ p Z ( f ( x ) ) (6) p_X(x) = \mid det(\dfrac{df}{dx}) \mid \cdot p_Z(f(x)) \tag{6} pX(x)=∣det(dxdf)pZ(f(x))(6)
注意:我们使用行列式来推广到多元情况( d > 1 d>1 d>1)
log ⁡ ( p X ( x ) ) = log ⁡ ( ∣ d e t ( d f d x ) ∣ ) + log ⁡ ( p Z ( f ( x ) ) ) (7) \log(p_X(x)) = \log(\mid det(\dfrac{df}{dx}) \mid) + \log(p_Z(f(x))) \tag{7} log(pX(x))=log(det(dxdf))+log(pZ(f(x)))(7)
为我们的随机变量建模X,我们需要最大化等式(7)的右侧。
分解方程式:

  • log ⁡ ( ∣ d e t ( d f d x ) ∣ ) \log(\mid det(\dfrac{df}{dx}) \mid) log(det(dxdf)) 是拉伸/变化 f f f的量
    适用于概率分布 p X p_X pX
    • 此项是雅可比矩阵的对数行列式 d f d x \dfrac{df}{dx} dxdf。我们将雅可比矩阵的行列式称为雅可比行列式。
  • log ⁡ ( p Z ( f ( x ) ) ) \log(p_Z(f(x))) log(pZ(f(x))) 限制 f f f 为将 x x x转换到 p Z p_Z pZ.

由于对Z没有任何限制,我们可以选择 p Z p_Z pZ, 通常,我们选择 p Z p_Z pZ为高斯分布。

单一功能并不能令我满意。我渴望更多。

顺序应用多个函数

我将向您展示如何顺序应用多个函数。
z n z_n zn是顺序应用n个函数到 x ∼ p X x \sim p_X xpX的结果。
z n = f n ∘ ⋯ ∘ f 1 ( x ) (8) z_n = f_n \circ \dots \circ f_1(x) \tag{8} zn=fnf1(x)(8)
f = f n ∘ ⋯ ∘ f 1 (9) f = f_n \circ \dots \circ f_1 \tag{9} f=fnf1(9)
利用链式法则,我们可以用方程(8)修改方程(7)得到方程(10), 如下。
log ⁡ ( p X ( x ) ) = log ⁡ ( ∣ d e t ( d f d x ) ∣ ) + log ⁡ ( p Z ( f ( x ) ) ) (7) \log(p_X(x)) = \log(\mid det(\dfrac{df}{dx}) \mid) + \log(p_Z(f(x))) \tag{7} log(pX(x))=log(det(dxdf))+log(pZ(f(x)))(7)
log ⁡ ( p X ( x ) ) = log ⁡ ( ∏ i = 1 n ∣ d e t ( d z i d z i − 1 ) ∣ ) + log ⁡ ( p Z ( f ( x ) ) ) (10) \log(p_X(x)) = \log(\prod_{i=1}^{n} \mid det(\dfrac{dz_i}{dz_{i-1}}) \mid) + \log(p_Z(f(x)))\tag{10} log(pX(x))=log(i=1ndet(dzi1dzi))+log(pZ(f(x)))(10)
其中,为了简洁, x ≜ z 0 x \triangleq z_0 xz0
log ⁡ ( p X ( x ) ) = ∑ i = 1 n log ⁡ ( ∣ d e t ( d z i d z i − 1 ) ∣ ) + log ⁡ ( p Z ( f ( x ) ) ) (11) \log(p_X(x)) = \sum_{i=1}^{n} \log(\mid det(\dfrac{dz_i}{dz_{i-1}}) \mid) + \log(p_Z(f(x))) \tag{11} log(pX(x))=i=1nlog(det(dzi1dzi))+log(pZ(f(x)))(11)
我们希望雅可比项易于计算,因为我们需要计算它n次。

为了有效计算雅可比行列式,函数 f i f_i fi(对应 z i z_i zi)被选择为具有下三角雅可比矩阵或上三角雅可比矩阵。由于三角矩阵的行列式是其对角线的乘积,因此很容易计算。

现在您已经了解了归一化流的一般理论,让我们来浏览一些 PyTorch 代码。

归一化流家族

在这篇文章中,我们将重点关注RealNVP(Dinh 等人,2016)。

尽管还有许多其他流函数,例如 NICE (Dinh et al., 2014)和 GLOW (Kingma & Dhariwal, 2018)。对于想要了解更多信息的同学,可以参考前面的博文。

RealNVP Flows

我们考虑单个 R-NVP 函数 f : R d → R d f: \mathbb{R}^d \rightarrow \mathbb{R}^d f:RdRd, 其中输入 x ∈ R d \mathbf{x} \in \mathbb{R}^d xRd, 输出 z ∈ R d \mathbf{z} \in \mathbb{R}^d zRd

快速回顾一下,为了优化我们的功能 f f f 以建模我们的数据分布 p X p_X pX, 我们想知道前向传递 f f f,以及雅可比行列式 ∣ d e t ( d f d x ) ∣ \mid det(\dfrac{df}{dx}) \mid det(dxdf)

然后我们想知道函数的反函数 f − 1 f^{-1} f1, 所以我们可以转换采样的潜在值 z ∼ p Z z \sim p_Z zpZ 到我们的数据分布 p X p_X pX,生成新样本!

前向传递

f ( x ) = z (12) f(\mathbf{x}) = \mathbf{z}\tag{12} f(x)=z(12)
前向传递是复制值同时拉伸和移动其他值的组合。首先我们选择一些任意值$ k$ (满足 0 < k < d 0<k<d 0<k<d) 分割我们的输入。
RealNVPs 前向传播如下:
z 1 : k = x 1 : k (13) \mathbf{z}_{1:k} = \mathbf{x}_{1:k} \tag{13} z1:k=x1:k(13)
z k + 1 : d = x k + 1 : d ⊙ exp ⁡ ( σ ( x 1 : k ) ) + μ ( x 1 : k ) (14) \mathbf{z}_{k+1:d} = \mathbf{x}_{k+1:d} \odot \exp(\sigma(\mathbf{x}_{1:k})) + \mu(\mathbf{x}_{1:k})\tag{14} zk+1:d=xk+1:dexp(σ(x1:k))+μ(x1:k)(14)
这里 σ , μ : R k → R d − k \sigma, \mu: \mathbb{R}^k \rightarrow \mathbb{R}^{d-k} σ,μ:RkRdk是任意函数。因此,我们会选择σ和μ两者都作为深度神经网络。下面是一个简单实现的 PyTorch 代码。

def forward(self, x):
    x1, x2 = x[:, :self.k], x[:, self.k:] 

    sig = self.sig_net(x1)
    mu = self.mu_net(x1)

    z1 = x1
    z2 = x2 * torch.exp(sig) + mu
    z = torch.cat([z1, z2], dim=-1)
    
    # log(p_Z(f(x)))
    log_pz = self.p_Z.log_prob(z)
    
    #...
view raw

对数雅可比行列式

该函数的雅可比行列式 d f d x \dfrac{df}{d\mathbf{x}} dxdf:
[ I d 0 d z k + 1 : d d x 1 : k diag ( exp ⁡ [ σ ( x 1 : k ) ] ) ] (15) \begin{bmatrix}I_d & 0 \\ \frac{d z_{k+1:d}}{d \mathbf{x}_{1:k}} & \text{diag}(\exp[\sigma(\mathbf{x}_{1:k})]) \end{bmatrix} \tag{15} [Iddx1:kdzk+1:d0diag(exp[σ(x1:k)])](15)
雅可比矩阵的对数行列式将是:
log ⁡ ( det ⁡ ( d f d x ) ) = log ⁡ ( ∏ i = 1 d − k ∣ exp ⁡ [ σ i ( x 1 : k ) ] ∣ ) (16) \log(\det(\dfrac{df}{d\mathbf{x}})) = \log(\prod_{i=1}^{d-k} \mid\exp[\sigma_i(\mathbf{x}_{1:k})]\mid) \tag{16} log(det(dxdf))=log(i=1dkexp[σi(x1:k)])(16)
log ⁡ ( ∣ det ⁡ ( d f d x ) ∣ ) = ∑ i = 1 d − k log ⁡ ( exp ⁡ [ σ i ( x 1 : k ) ] ) (17) \log(\mid\det(\dfrac{df}{d\mathbf{x}})\mid) = \sum_{i=1}^{d-k} \log(\exp[\sigma_i(\mathbf{x}_{1:k})]) \tag{17} log(det(dxdf))=i=1dklog(exp[σi(x1:k)])(17)
log ⁡ ( ∣ det ⁡ ( d f d x ) ∣ ) = ∑ i = 1 d − k σ i ( x 1 : k ) (18) \log(\mid\det(\dfrac{df}{d\mathbf{x}})\mid) = \sum_{i=1}^{d-k} \sigma_i(\mathbf{x}_{1:k}) \tag{18} log(det(dxdf))=i=1dkσi(x1:k)(18)

# single R-NVP calculation
def forward(x): 
  #...
  log_jacob = sig.sum(-1)
  #...
  
  return z, log_pz, log_jacob

# multiple sequential R-NVP calculation
def forward(self, x):
  log_jacobs = []
  z = x
  
  for rvnp in self.rvnps:
      z, log_pz, log_j = rvnp(z)
      log_jacobs.append(log_j)

  return z, log_pz, sum(log_jacobs)

反向

f − 1 ( z ) = x (19) f^{-1}(\mathbf{z}) = \mathbf{x}\tag{19} f1(z)=x(19)
与其他流程相比,RealNVP 的优势之一是易于反转 F \mathbf{F} F进入 F − 1 \mathbf{F}^{-1} F1,我们使用等式 (14) 的前向传递将其表述如下:
x 1 : k = z 1 : k (20) \mathbf{x}_{1:k} = \mathbf{z}_{1:k} \tag{20} x1:k=z1:k(20)
x k + 1 : d = ( z k + 1 : d − μ ( x 1 : k ) ) ⊙ exp ⁡ ( − σ ( x 1 : k ) ) (21) \mathbf{x}_{k+1:d} = (\mathbf{z}_{k+1:d} - \mu(\mathbf{x}_{1:k})) \odot \exp(-\sigma(\mathbf{x}_{1:k})) \tag{21} xk+1:d=(zk+1:dμ(x1:k))exp(σ(x1:k))(21)
⇔ x k + 1 : d = ( z k + 1 : d − μ ( z 1 : k ) ) ⊙ exp ⁡ ( − σ ( z 1 : k ) ) (22) \Leftrightarrow \mathbf{x}_{k+1:d} = (\mathbf{z}_{k+1:d} - \mu(\mathbf{z}_{1:k})) \odot \exp(-\sigma(\mathbf{z}_{1:k})) \tag{22} xk+1:d=(zk+1:dμ(z1:k))exp(σ(z1:k))(22)

def inverse(self, z):
  z1, z2 = z[:, :self.k], z[:, self.k:] 
  
  sig = self.sig_net(z1)
  mu = self.mu_net(z1)
  
  x1 = z1
  x2 = (z2 - mu) * torch.exp(-sig)
  
  x = torch.cat([x1, x2], dim=-1)
  return x

小结

瞧,R-NVP 的配方完成了!

总而言之,我们现在知道如何计算 F ( X ) F(\mathbf{X}) F(X), log ⁡ ( ∣ det ⁡ ( d f d x ) ∣ ) \log(\mid\det(\dfrac{df}{d\mathbf{x}})\mid) log(det(dxdf)) 以及 f − 1 ( z ) f^{-1}(\mathbf{z}) f1(z)

下面是Github中完整的 jupyter 笔记本,其中包含用于模型优化和数据生成的 PyTorch 代码。

注意:在笔记本中,多层 R-NVP 在正向/反向传递之前翻转输入,以获得更具表现力的模型。

优化模型

log ⁡ ( p X ( x ) ) = log ⁡ ( ∣ d e t ( d f d x ) ∣ ) + log ⁡ ( p Z ( f ( x ) ) ) log ⁡ ( p X ( x ) ) = ∑ i = 1 n log ⁡ ( ∣ d e t ( d z i d z i − 1 ) ∣ ) + log ⁡ ( p Z ( f ( x ) ) ) \log(p_X(x)) = \log(\mid det(\dfrac{df}{dx}) \mid) + \log(p_Z(f(x))) \\ \log(p_X(x)) = \sum_{i=1}^{n} \log(\mid det(\dfrac{dz_i}{dz_{i-1}}) \mid) + \log(p_Z(f(x))) log(pX(x))=log(det(dxdf))+log(pZ(f(x)))log(pX(x))=i=1nlog(det(dzi1dzi))+log(pZ(f(x)))

for _ in range(epochs):
  optim.zero_grad()
  
  # forward pass
  X = get_batch(data)
  z, log_pz, log_jacob = model(X)
  
  # maximize p_X(x) == minimize -p_X(x)
  loss = -(log_jacob + log_pz).mean()
  losses.append(loss)

  # backpropigate loss
  loss.backward()
  optim.step()

从模型生成数据

z ∼ p Z x g e n = f − 1 ( z ) z \sim p_Z \\ x_{gen} = f^{-1}(z) zpZxgen=f1(z)

# p_Z - gaussian
mu, cov = torch.zeros(2), torch.eye(2)
p_Z = MultivariateNormal(mu, cov)

# sample 3000 points (z ~ p_Z)
z = p_Z.rsample(sample_shape=(3000,))

# invert f^-1(z) = x
x_gen = model.inverse(z)

结论

总之,我们学习了如何使用可逆函数将数据分布建模为选定的潜在分布 f f f。我们使用变量变化公式发现,为了对数据进行建模,我们必须最大化 f f f的雅可比行列式,同时也约束 f f f到我们的潜在分布。然后我们将这个概念扩展到顺序应用多个函数 f n ∘ ⋯ ∘ f 0 f_n\circ \cdots \circ f_0 fnf0。最后,我们了解了RealNVP流程的理论和实现。

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

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

相关文章

PostgreSQL+patroni+etcd+haproxy+keepalived高可用

PostgreSQLpatronietcdhaproxykeepalived 高可用架构 部署环境 部署postgresql-15 一主二从&#xff1a; role主机组件主库 node203 192.168.56.203 pg15.5 Patroni、Etcd&#xff0c;haproxy、keepalived 从库 node204 192.168.56.204 pg15.5 Patroni、Etcd&#xff0c;ha…

Java(七)(Lambda表达式,正则表达式,集合(Collection,Collection的遍历方式))

目录 Lambda表达式 省略写法(要看懂) 正则表达式 语法 案例 正则表达式的搜索替换和分割内容 集合进阶 集合体系结构 Collection Collection的遍历方式 迭代器 增强for循环 Lambda表达式遍历Collection List集合 ArrayList LinkedList 哈希值 HashSet底层原理 …

ArcGIS中基于人口数据计算人口密度的方法

文章目录 一、密度分析原理二、点密度分析三、线密度分析四、核密度分析一、密度分析原理 密度分析是指根据输入的要素数据集计算整个区域的数据聚集状况,从而产生一个联系的密度表面。通过密度计算,将每个采样点的值散步到整个研究区域,并获得输出栅格中每个像元的密度值。…

R语言实现Lasso回归

一、Lasso回归 Lasso 回归&#xff08;Least Absolute Shrinkage and Selection Operator Regression&#xff09;是一种用于线性回归和特征选择的统计方法。它在回归问题中加入了L1正则化项&#xff0c;有助于解决多重共线性&#xff08;多个特征高度相关&#xff09;和特征选…

Java中有几种基本数据类型以及转换方式【Java面经(1)】

问&#xff1a;Java中有几种基本数据类型呢&#xff1f;以及它们之间的转换方式。详细介绍下 总共有8种基本数据类型 byte 、short 、long 、float 、double 、boolean 、char 详细类型以及字节数&#xff1a; 基本数据类型的转换方式 自动类型转换&#xff1a;小–>大 byt…

Vue快速实践总结 · 上篇

文章目录 模板语法数据绑定事件处理计算属性监视属性&#xff08;监听器&#xff09;条件渲染列表渲染数据监视原理内置指令总结生命周期组件化编程组件使用步骤组件的嵌套this指向单文件组件ref、props 脚手架(Vue CLI)render函数 参考自己的Vue专栏以及Vue官方文档 模板语法 …

stm32 42步进电机 上位机示例

脉冲到底是个啥东西&#xff1f;步进电机一直说发脉冲 步进电机通过接收脉冲信号来实现精确的位置控制。脉冲是一种短暂的电信号&#xff0c;它的变化可以触发步进电机转动一定的角度或步进。步进电机控制系统会根据输入的脉冲信号来精确定位和控制步进电机的转动&#xff0c;每…

Android平台GB28181设备接入模块开发填坑指南

技术背景 为什么要开发Android平台GB28181设备接入模块&#xff1f;这个问题不再赘述&#xff0c;在做Android平台GB28181客户端的时候&#xff0c;媒体数据这块&#xff0c;我们已经有了很好的积累&#xff0c;因为在此之前&#xff0c;我们就开发了非常成熟的RTMP推送、轻量…

rsyslog出现Unit rsyslog.service is masked不可用问题解决

博主在测试将日志发送到日志服务器的功能时遇到了rsyslog服务不可用的问题&#xff0c;具体来说&#xff0c;就是执行systemctl restart rsyslog或者 service rsyslog restart命令时&#xff0c;出现了标题中所述的Unit rsyslog.service is masked问题。网上查找了很多资料&…

云服务器上部署 Web 项目及端口异常处理

文章目录 1. 在云服务器的 MySQL(MariaDB) 中, 建库建表2. 微调代码3. 打包4. 把 war 包 拷贝到云服务器上端口被占用处理 1. 在云服务器的 MySQL(MariaDB) 中, 建库建表 在云服务器中进入 MySQL mysql -u root -p把之前本地写好的 SQL 代码一粘贴即可 例如: -- 这个文件主要…

【Python】用三种方法创建tkinter桌面窗口

Python的tkinter是Python的标准GUI库之一&#xff0c;它是一个开源的、跨平台的GUI工具包&#xff0c;可以用于创建桌面应用程序。 tkinter提供了许多常见的GUI组件&#xff0c;例如按钮、文本框、标签、列表框等等&#xff0c;可以轻松地创建各种类型的桌面应用程序。它还支持…

go atexit源码分析

文章目录 atexit源码解析UML类图样例一: 程序退出之前执行注册函数1.1 流程图1.2 代码分析 样例二&#xff1a;使用cancel取消注册函数2.1 cancel流程图2.2 代码分析 样例三&#xff1a;使用Fatal/Fatalln/Fatal执行注册函数3.1 Fatal/Fatalln/Fatal流程图3.2 代码分析 atexit源…

什么是LASSO回归,怎么看懂LASSO回归的结果

随着机器学习的发展&#xff0c;越来越多SCI文章都使用了更多有趣、高效的统计方法来进行分析&#xff0c;LASSO回归就是其中之一。很多小伙伴听说过LASSO&#xff0c;但是对于LASSO是什么&#xff0c;有什么用&#xff0c;怎么才能实现&#xff0c;大家可能一头雾水。今天的文…

每日一题2023.11.26——个位数统计【PTA】

题目要求&#xff1a; 输入格式&#xff1a; 每个输入包含 1 个测试用例&#xff0c;即一个不超过 1000 位的正整数 N。 输出格式&#xff1a; 对 N 中每一种不同的个位数字&#xff0c;以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。…

【华为数通HCIP | 网络工程师】821-IGP高频题、易错题之OSPF(7)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

blender 3D眼球结构

角膜&#xff08;Cornea&#xff09;&#xff1a;眼球的前部&#xff0c;透明的曲面&#xff0c;负责折射光线。虹膜&#xff08;Iris&#xff09;&#xff1a;眼睛的颜色部分&#xff0c;控制瞳孔大小以调整进入眼睛的光量。瞳孔&#xff08;Pupil&#xff09;&#xff1a;虹膜…

S25FL系列FLASH读写的FPGA实现

文章目录 实现思路具体实现子模块实现top模块 测试Something 实现思路 建议读者先对 S25FL-S 系列 FLASH 进行了解&#xff0c;我之前的博文中有详细介绍。 笔者的芯片具体型号为 S25FL256SAGNFI00&#xff0c;存储容量 256Mb&#xff0c;增强高性能 EHPLC&#xff0c;4KB 与 6…

快速幂算法详解(C++实现)

文章目录 1. 什么是快速幂2. 暴力求解代码实现缺陷分析 3. 优化一&#xff1a;取模运算的性质4. 优化二&#xff1a;快速幂算法的核心思想5. 终极优化&#xff1a;位运算优化6. 源码 这篇文章我们来一起学习一个算法——快速幂算法。 1. 什么是快速幂 顾名思义&#xff0c;快速…

中海油“海安杯”一站到底知识竞赛真的很有特色

中海油“海安杯”一站到底知识竞赛规格高&#xff0c;赛制复杂&#xff0c;天纵知识竞赛系统为此次知识竞赛提供了软件支持。本次竞赛设置选手区和擂台区两个区域。比赛共分为五个轮次&#xff0c;五个轮次选手区所有参赛选手均需答题。 第一轮&#xff1a;“脱颖而出” 所有参…

叠加原理(superposition principle)

叠加原理&#xff08;superposition principle&#xff09;指对线性系统而言&#xff0c;两个或多个输入产生的输出&#xff0c;等于这几个输入单独引起的输出的和&#xff0c;即输入的叠加等于各输入单独引起的输出的叠加。 例如&#xff0c;如果输入产生的输出是&#xff0c;…