深度学习笔记(续)——数值稳定性、模型初始化与激活函数

news2024/11/28 1:32:39

深度学习笔记[续]——数值稳定性、模型初始化与激活函数

  • 引言
    • 回顾:没有激活函数参与,输入输出分布的变化情况
    • 存在激活函数的情况
      • 假设激活函数是线性函数
      • 激活函数的底层逻辑
    • 总结

引言

继续上一节介绍激活函数在神经网络前馈/反向传播中的作用。

回顾:没有激活函数参与,输入输出分布的变化情况

在神经网络前馈/反向传播过程中没有激活函数的参与,各隐藏层之间的均值方差变化情况表示如下:
依然描述 t t t层神经元输出 h i ( t ) h_i^{(t)} hi(t) t − 1 t-1 t1层神经元输入 h j ( t − 1 ) h_{j}^{(t-1)} hj(t1)之间的关系。

已知
各权重在该该层内的权重空间内是‘独立同分布’;
各层输入/输出特征在对应特征空间中同分布,但是否独立未知。
权重和特征分布属于不同的空间(权重空间/特征空间),它们必然相互独立。

  • t t t各神经元内权重 W i ⇔ j ( t ) ( i = 1 , 2 , ⋯   , j = 1 , 2 , ⋯   ) \mathcal W_{i \Leftrightarrow j}^{(t)}(i=1,2,\cdots,j=1,2,\cdots) Wij(t)(i=1,2,,j=1,2,)独立同分布,且分布均值 0 0 0方差 γ t \gamma_t γt
    E [ W i ⇔ j ( t ) ] = 0 Var [ W i ⇔ j ( t ) ] = γ t \mathbb E[\mathcal W_{i \Leftrightarrow j}^{(t)}] = 0 \quad \text{Var} [\mathcal W_{i \Leftrightarrow j}^{(t)}] = \gamma_t E[Wij(t)]=0Var[Wij(t)]=γt
  • t t t层神经元输入 h j ( t − 1 ) ( j = 1 , 2 , ⋯   ) h_j^{(t-1)}(j=1,2,\cdots) hj(t1)(j=1,2,)以及输出 h i ( t ) ( t = 1 , 2 , ⋯   ) h_i^{(t)}(t=1,2,\cdots) hi(t)(t=1,2,)均服从各自分布。这里以 t t t层输出为例:
    E [ h i ( t ) ] = 0 Var [ h i ( t ) ] = a \mathbb E[h_i^{(t)}] = 0 \quad \text{Var}[h_i^{(t)}] = a E[hi(t)]=0Var[hi(t)]=a
    同理,对应反向传播过程中 h i ( t ) h_i^{(t)} hi(t)梯度的均值和方差表示为:
    E [ ∂ L ∂ h i ( t ) ] = 0 Var [ ∂ L ∂ h i ( t ) ] = b \mathbb E \left[\frac{\partial \mathcal L}{\partial h_i^{(t)}}\right] = 0 \quad \text{Var} \left[\frac{\partial \mathcal L}{\partial h_i^{(t)}}\right] = b E[hi(t)L]=0Var[hi(t)L]=b

前馈计算过程: h j ( t − 1 ) ⇒ h i ( t ) h_j^{(t-1)} \Rightarrow h_i^{(t)} hj(t1)hi(t)

  • 均值结果:
    输入与输出的均值结果无变化: ⇒ E [ h i ( t ) ] = E [ h j ( t − 1 ) ] = 0 \Rightarrow \mathbb E[h_i^{(t)}] = \mathbb E [h_{j}^{(t-1)}] = 0 E[hi(t)]=E[hj(t1)]=0
    E [ h i ( t ) ] = E [ ∑ j W i ⇔ j ( t ) ⋅ h j ( t − 1 ) ] = ∑ j E [ W i ⇔ j ( t ) ] ⋅ E [ h j ( t − 1 ) ] = 0 \mathbb E[h_i^{(t)}] = \mathbb E \left[\sum_{j} \mathcal W_{i \Leftrightarrow j}^{(t)} \cdot h_j^{(t-1)}\right] = \sum_j \mathbb E [\mathcal W_{i \Leftrightarrow j}^{(t)}] \cdot \mathbb E [h_j^{(t-1)}] = 0 E[hi(t)]=E[jWij(t)hj(t1)]=jE[Wij(t)]E[hj(t1)]=0
  • 方差结果:
    输入与输出的方差结果存在偏差,其中 n t − 1 n_{t-1} nt1表示 t t t层输入神经元数量。
    Var [ h i ( t ) ] = n t − 1 ⋅ γ t ⋅ Var [ h j ( t − 1 ) ] \text{Var} [h_i^{(t)}] = n_{t-1} \cdot \gamma_t \cdot \text{Var}[h_j^{(t-1)}] Var[hi(t)]=nt1γtVar[hj(t1)]

反向传播过程: ∂ L ∂ h i ( t ) ⇒ ∂ L ∂ h j ( t − 1 ) \begin{aligned}\frac{\partial \mathcal L}{\partial h_i^{(t)}} \Rightarrow \frac{\partial \mathcal L}{\partial h_j^{(t-1)}}\end{aligned} hi(t)Lhj(t1)L

  • 均值结果:
    同上,依然没有变化: ⇒ E [ ∂ L ∂ h j ( t − 1 ) ] = E [ ∂ L ∂ h i ( t ) ] = 0 \Rightarrow \begin{aligned}\mathbb E \left[\frac{\partial \mathcal L}{\partial h_j^{(t-1)}}\right] = \mathbb E \left[\frac{\partial \mathcal L}{\partial h_i^{(t)}}\right] = 0\end{aligned} E[hj(t1)L]=E[hi(t)L]=0
    E [ ∂ L ∂ h j ( t − 1 ) ] = E [ ∂ L ∂ h i ( t ) ⋅ ∂ h i ( t ) ∂ h j ( t − 1 ) ] = E [ ∂ L ∂ h i ( t ) ] ⋅ E [ W i ⇐ j ( t ) ] ⏟ 0 = 0 \begin{aligned}\mathbb E \left[\frac{\partial \mathcal L}{\partial h_j^{(t-1)}}\right]\end{aligned} = \mathbb E \left[\frac{\partial \mathcal L}{\partial h_i^{(t)}} \cdot \frac{\partial h_i^{(t)}}{\partial h_j^{(t-1)}}\right] = \mathbb E \left[\frac{\partial \mathcal L}{\partial h_i^{(t)}}\right] \cdot \underbrace{\mathbb E \left[\mathcal W_{i \Leftarrow j}^{(t)}\right]}_{0} = 0 E[hj(t1)L]=E[hi(t)Lhj(t1)hi(t)]=E[hi(t)L]0 E[Wij(t)]=0
  • 方差结果:
    和前馈计算相似。 n t n_t nt表示 t t t层神经元的数量。
    Var [ ∂ L ∂ h j ( t − 1 ) ] = n t ⋅ γ t ⋅ Var [ ∂ L ∂ h i ( t ) ] \text{Var} \left[\frac{\partial \mathcal L}{\partial h_j^{(t-1)}}\right] = n_t \cdot \gamma_t \cdot \text{Var} \left[\frac{\partial \mathcal L}{\partial h_i^{(t)}}\right] Var[hj(t1)L]=ntγtVar[hi(t)L]

至此,可以发现,在没有激活函数,也就是纯粹的线性计算过程中,无论是前馈/反向传播过程,每一层分布的方差均在发生偏移。如果我们希望在传播过程中满足分布不变,则需要同时满足两个等式:
{ n t − 1 ⋅ γ t = 1 n t ⋅ γ t = 1 \begin{cases} n_{t-1} \cdot \gamma_t = 1 \\ n_{t} \cdot \gamma_t = 1 \end{cases} {nt1γt=1ntγt=1

Xavier \text{Xavier} Xavier方法

很明显,上述两个等式在神经网络中很难同时满足——该层的输入和输出神经元数量必须相同。
Xavier \text{Xavier} Xavier方法给出一个折中的方式: γ t ⋅ n t − 1 + n t 2 = 1 ⇒ γ t = 2 n t − 1 + n t \begin{aligned}\gamma_t \cdot \frac{n_{t-1} + n_t}{2} = 1 \Rightarrow \gamma_t = \frac{2}{n_{t-1} + n_{t}}\end{aligned} γt2nt1+nt=1γt=nt1+nt2从而通过折中方式选择 t t t层权重的方差 γ t \gamma_t γt

也就是说,当前网络层的输入、输出神经元数量确定后,使用其确定参数 γ t \gamma_t γt,并使用该参数来构建随机分布作为初始化分布:
也就是关于权重 W ( t ) \mathcal W^{(t)} W(t)的先验分布。

  • 如果使用高斯分布,有:
    W ( t ) ∼ N [ 0 , 2 n t − 1 + n t ] \begin{aligned}\mathcal W^{(t)} \sim \mathcal N \left[0,\sqrt{\frac{2}{n_{t-1} + n_t}} \right]\end{aligned} W(t)N[0,nt1+nt2 ]
  • 如果使用均匀分布,有:
    均匀分布的方差表示为 ( b − a ) 2 12 \begin{aligned}\frac{(b - a)^2}{12}\end{aligned} 12(ba)2,其中 a , b a,b a,b表示均匀分布范围。
    W ( t ) ∼ U [ − 6 n t − 1 + n t , 6 t − 1 + n t ] \mathcal W^{(t)} \sim \mathcal U \left[- \sqrt{\frac{6}{n_{t-1} + n_t}},\sqrt{\frac{6}{_{t-1} + n_t}}\right] W(t)U[nt1+nt6 ,t1+nt6 ]

从而通过这种权重初始化的方式尽量使各层的输入、输出分布的方差信息保持一致。

存在激活函数的情况

假设激活函数是线性函数

从上帝视角观察,自然不会使用线性函数作为激活函数。因为它无法学习到非线性信息。这里仅讨论如果线性函数作为激活函数,它会产生什么样的影响。

假设激活函数 σ ( x ) = α ⋅ x + β \sigma(x) = \alpha \cdot x + \beta σ(x)=αx+β,并且有:
{ Z ( t ) = W ( t ) ⋅ h ( t − 1 ) h ( t ) = σ ( Z ( t ) ) \begin{cases} \mathcal Z^{(t)} = \mathcal W^{(t)} \cdot h^{(t-1)} \\ h^{(t)} = \sigma(\mathcal Z^{(t)}) \end{cases} {Z(t)=W(t)h(t1)h(t)=σ(Z(t))

  • 此时,计算前馈传播过程中 h i ( t ) h_i^{(t)} hi(t)期望结果 E [ h i ( t ) ] \mathbb E [h_i^{(t)}] E[hi(t)]
    其中 Z i ( t ) \mathcal Z_i^{(t)} Zi(t)表示线性计算过程中第 i i i个神经元的输出结果。
    { Z i ( t ) = ∑ j W i ⇔ j ( t ) ⋅ h j ( t − 1 ) E [ h i ( t ) ] = E [ α ⋅ Z i ( t ) + β ] = α ⋅ E [ ∑ j W i ⇔ j ( t ) ⋅ h j ( t − 1 ) ] + β = α + ∑ j E [ W i ⇔ j ( t ) ] ⋅ E [ h j ( t − 1 ) ] ⏟ = 0 + β = β \begin{cases} \begin{aligned} \mathcal Z_i^{(t)} & = \sum_j \mathcal W_{i \Leftrightarrow j}^{(t)} \cdot h_j^{(t-1)}\\ \mathbb E [h_i^{(t)}] & = \mathbb E [\alpha \cdot \mathcal Z_i^{(t)} + \beta] \\ & = \alpha \cdot \mathbb E \left[\sum_j \mathcal W_{i \Leftrightarrow j}^{(t)} \cdot h_j^{(t-1)}\right] + \beta \\ & = \alpha + \underbrace{\sum_j \mathbb E [\mathcal W_{i \Leftrightarrow j}^{(t)}] \cdot \mathbb E[h_j^{(t-1)}]}_{=0} + \beta \\ & = \beta \end{aligned} \end{cases} Zi(t)E[hi(t)]=jWij(t)hj(t1)=E[αZi(t)+β]=αE[jWij(t)hj(t1)]+β=α+=0 jE[Wij(t)]E[hj(t1)]+β=β
    可以看出,激活后的结果与激活前存在 β \beta β偏差。但由于我们希望 E [ h i ( t ) ] = E [ Z i ( t ) ] = 0 \mathbb E [h_i^{(t)}] = \mathbb E [\mathcal Z_i^{(t)}] = 0 E[hi(t)]=E[Zi(t)]=0,因而有: β = 0 \beta = 0 β=0
    也就是激活前与激活后的均值相同。
  • 计算前馈传播过程中 h i ( t ) h_i^{(t)} hi(t)方差结果 Var [ h i ( t ) ] \text{Var}[h_i^{(t)}] Var[hi(t)]
    Var [ h i ( t ) ] = E [ ( h i ( t ) ) 2 ] − [ E ( h i ( t ) ) ] 2 ⏟ β 2 = E [ ( α ⋅ Z i ( t ) + β ) 2 ] − β 2 = α 2 ⋅ { E [ ( Z i ( t ) ) 2 ] − [ E ( Z i ( t ) ) ] 2 ⏟ = 0 } ⏟ = Var ( Z i ( t ) ) + 2 α β E ( Z i ( t ) ) ⏟ = 0 + E ( β 2 ) − β 2 ⏟ = 0 = α 2 ⋅ Var ( Z i ( t ) ) \begin{aligned} \text{Var}[h_i^{(t)}] & = \mathbb E \left[(h_i^{(t)})^2\right] - \underbrace{\left[\mathbb E(h_i^{(t)})\right]^2}_{\beta^2} \\ & = \mathbb E \left[(\alpha \cdot \mathcal Z_i^{(t)} + \beta)^2\right] - \beta^2 \\ & = \alpha^2 \cdot \underbrace{\left\{\mathbb E \left[(\mathcal Z_i^{(t)})^2\right] - \underbrace{\left[\mathbb E(\mathcal Z_i^{(t)})\right]^2}_{=0}\right\}}_{=\text{Var}(\mathcal Z_i^{(t)})} + 2 \alpha\beta \underbrace{\mathbb E (\mathcal Z_i^{(t)})}_{=0} + \underbrace{\mathbb E(\beta^2)- \beta^2}_{=0} \\ & = \alpha^2 \cdot \text{Var}(\mathcal Z_i^{(t)}) \end{aligned} Var[hi(t)]=E[(hi(t))2]β2 [E(hi(t))]2=E[(αZi(t)+β)2]β2=α2=Var(Zi(t)) E[(Zi(t))2]=0 [E(Zi(t))]2 +2αβ=0 E(Zi(t))+=0 E(β2)β2=α2Var(Zi(t))
    可以看做是激活后的结果相较于激活前结果扩大了 α 2 \alpha^2 α2倍。同理,我们同样希望激活前激活后的方差相同:
    α 2 ⋅ Var ( Z i ( t ) ) = Var ( Z i ( t ) ) ⇒ α = 1 \alpha^2 \cdot \text{Var}(\mathcal Z_i^{(t)}) = \text{Var}(\mathcal Z_i^{(t)}) \Rightarrow \alpha = 1 α2Var(Zi(t))=Var(Zi(t))α=1

综上,可以看出,如果要维持输出分布 均值 0 0 0,方差为某常数 的情况,我们的线性激活函数只能是:
好像做了一些什么,又好像什么都没做~就是一个恒等映射,当然 α \alpha α − 1 -1 1,相当于将输出向量的方向完全倒置。
σ ( x ) = x \sigma(x) = x σ(x)=x

关于它的反向传播过程,与正向结果相同,这里就不赘述了。

激活函数的底层逻辑

从上面的逻辑,我们会发现:如果激活函数是线性的,那么为了输入、输出维持在一个相对稳定的条件下,它只能选择恒等函数 ( Identity Function ) (\text{Identity Function}) (Identity Function)

但恒等函数它的作用很明显。它能够让输入、输出分布之间保持稳定。但我们也希望能够通过前馈计算产生出一些非线性信息,从而通过反向传播,使模型参数拟合更加复杂的函数。
这里的意思是可理解为:恒等函数和非线性信息两者是矛盾的。但是它们的优点我们都想要。

关于一些常见的激活函数,使用泰勒公式进行展开:
其中 O \mathcal O O表示函数的复杂程度。其中 O \mathcal O O x x x指数越大,函数的‘非线性程度’越复杂。
{ Sigmoid ( x ) = 1 2 + 1 4 x − 1 48 x 3 + O ( x 5 ) Tanh ( x ) = 0 + x − 1 3 x 3 + O ( x 5 ) ReLU ( x ) = 0 + x x ≥ 0 \begin{cases} \begin{aligned} \text{Sigmoid}(x) & = \frac{1}{2} + \frac{1}{4}x - \frac{1}{48}x^3 + \mathcal O(x^5) \\ \text{Tanh}(x) & = 0 + x - \frac{1}{3}x^3 + \mathcal O(x^5) \\ \text{ReLU}(x) & = 0 + x \quad x \geq 0 \end{aligned} \end{cases} Sigmoid(x)Tanh(x)ReLU(x)=21+41x481x3+O(x5)=0+x31x3+O(x5)=0+xx0
它们的函数图像表示如下:
常见激活函数
对比泰勒展开式与函数图像,可以发现:

  • Tanh \text{Tanh} Tanh激活函数 ReLU \text{ReLU} ReLU激活函数一次项系数均是 1 1 1,这导致在函数图像中存在一个小区间(红色椭圆标注的位置),这个小区间几乎支持恒等映射

  • 神经网络计算隐藏层输出的分布时,相当大一部分的结果聚集在 0 0 0点附近。也就是说,神经网络所拟合的非线性结果是基于线性结果的基础上,增加函数的复杂度(变量的高次项)得到的结果。因此,我们希望尽可能满足低次项分布稳定的基础上,去学习高次项特征(距离 0 0 0的结果)的非线性信息,最终得到拟合的复杂函数

    不否认的是, Sigmoid \text{Sigmoid} Sigmoid函数作为激活函数并没有 ReLU,Tanh \text{ReLU,Tanh} ReLU,Tanh函数优秀,核心原因在于 0 0 0附近它没有实现恒等映射

  • 尝试最 Sigmoid \text{Sigmoid} Sigmoid函数做一些修改:
    ScaledSigmoid ( x ) = 4 × Sigmoid ( x ) − 2 \text{ScaledSigmoid}(x) = 4 \times \text{Sigmoid}(x) - 2 ScaledSigmoid(x)=4×Sigmoid(x)2
    其对应函数图像表示如下:
    修改后的Sigmoid函数经过这样的修改后,其泰勒展开式的一次项是 1 1 1,该函数也存在了在 0 0 0附近恒等映射的条件。

总结

这里和深度学习笔记——数值稳定性、模型初始化与激活函数一同总结:

  • 通过权重初始化激活函数的调整来维持输出分布数值的稳定性。

  • (核心)这个稳定性这里使用隐藏层输入、输出分布之间的差异表示。主要通过参数:均值和方差进行描述。

    获取非线性信息维持数值稳定这两件事情是矛盾的:
    个人理解:权重自身能够直接影响稳定性————只要该值 ≠ 1 \neq 1 =1,本层的输出分布和输入分布就会存在差异。

    • 如果过于强调稳定性:最终的结果相当于激活函数是一个恒等映射——反向传播中,学不到描述复杂函数的有效的梯度信息;
      这个结果导致函数‘过于简单’————欠拟合。
    • 如果过于强调非线性:前馈计算过程中,经过每一层的输出分布差异是较大的。这种情况,更容易出现梯度消失/梯度爆炸,并且泰勒展开式高次项的权重系数过高,导致模型结果过拟合
  • 优秀的激活函数就是既要维持分布稳定,又要能够使模型学习到非线性特征的非线性函数。

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

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

相关文章

Google IO 2023推出Android Studio官方AI工具Studio Bot

Google推出Android Studio官方AI工具Studio Bot Studio Bot 简介 在2023 Google I/O大会上,Google 宣布在 Android Studio 中推出了一款名为 Studio Bot 的新 AI 功能,它将为开发者提供更高效、智能的开发体验。Studio Bot 是一个基于机器学习的助手&a…

想要快速进入车载测试?这份车载面试题集锦送给你,建议收藏!

1.道路测试流程 测试场地 1.测试场地有哪些? 对于一些要求不太高/简单的测试场景可以找一些封闭的场地,如断头路或者是城市所在地当地政府提供的诸如智能网联专用道路之类的测试道路,对于复杂或相对要求高一些的测试场景可以到专业的国家智…

【运维杂谈】如何将ios镜像挂载到Linux系统中?

本期我们实现将CentOS7.9系统镜像挂载到Linux系统当中,首先明确什么是挂载,我理解的挂载就是把系统镜像与Linux操作系统建立直接的联系,将镜像的顶级目录连接到Linux根目录下的某一目录中,就好比我们Windows系统插入一张光盘&…

C++学习记录——이십삼 哈希表

文章目录 1、unordered_map unordered_set2、哈希表1、闭散列2、开散列(拉链法/哈希桶)继续优化 3、封装unordered和迭代器 1、unordered_map unordered_set C11提供,功能和map、set完全类似,不过它们底层实现是红黑树&#xff0…

JDBC~

文章目录 JDBCJDBC API详解DriverManagerConnectionStatementResultSetPreparedStatementPreparedStatement原理 JDBC JDBC就是使用JAVA语言操作关系型数据库的一套API JDBC是java处理数据库的接口 JDBC API详解 DriverManager 驱动管理类: 注册驱动,获取数据库连接…

Cplex的数据类型结构及基本语法功能

本序列将会重开一门新的序列----数学求解器cplex,文章不做简单介绍,不灌水,直接给大家进行讲述如何上手实操,并有针对性的给出相应案例分析。 OPL编程 OPL是ILOG团队为运筹学专家量身定制的一种优化建模语言,语法相对简单&#x…

C++系列之入门基础知识

💗 💗 博客:小怡同学 💗 💗 个人简介:编程小萌新 💗 💗 如果博客对大家有用的话,请点赞关注再收藏 🌞 命名空间 常见域的种类 常见的域的种类有:全局域,局部…

快速构建springboot项目

需求:浏览器发送 /hello 请求,服务器接受请求并处理,响应 Hello World 字符串分析 构建 Spring Boot 项目,事实上建立的就是一个 Maven 项目 1.创建maven 工程 在 IDEA上新建一个空的jar类型 的 maven 工程 2.修改pom.xml 1.在…

【Tkinter.Floodgauge】当程序需要长时间运行,可以用这个组件显示进度【文末附源码地址】

文章目录 效果展示源码解析导包Floodgauge组件界面初始化创建窗口修改数值运行 源码地址 效果展示 我在使用tkinter进行界面化操作的时候,会遇到运行很慢的程序,比如:爬虫下载视频、压缩解压文件,这些操作会很耗时间。 Floodgau…

力扣 ~ JavaScript ~ 35. 搜索插入位置

《跃动青春》好可爱的女孩子的友谊哇 35. 搜索插入位置 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: …

redis(12)

1)添加地理位置坐标:已经添加的数据,无法再添加 geoadd key 经度 纬度 变量名字 geoadd china:city 121.47 31.23 shanghai 2)获取指定地区的坐标值: geopos key member(变量名字) geopos china:city shnaghai 3)获取到两个坐标之间的距离,后面是可选参…

95后的自述,文科女吃上IT饭了,历经5个月学习成功上岸软件测试......

想不到我一个女文科生也能吃上IT饭,真的是太香了!!! 程序员的待遇怎么这么好!(请大家原谅我没有见过市面的感叹,对于我这种刚上岗的新手而言,能够在厦门这个全国工资房价比最低的地方…

景区手绘图的配准、切图及上传

目录 1 增加一个项目 2 基础配置 3 获取自动上传需要的3个参数 3.1 生成切片上传验证码 3.2 按F5刷新页面 3.3 查看验证码以及其他2个参数 4 配准 5 切图 6 到迅达平台看一下切图效果 7 软件免费下载 这个免费客户端专用于迅达平台,对手绘图背景进行配准&…

java 调用 python 方法

目录 1.JPython 1.1 JPython介绍 1.2 JPython实践 2.使用Runtime.getRuntime()执行python脚本文件,推荐使用 一个项目可能需要用到人工智能算法,在java后端中需要调用python算法,这篇文章就简单介绍一下其中的两种java调用python方法。 …

一个简单的基于QT的图像浏览器

以前学习前端的时候,对于多张图片的布局一般使用瀑布流布局(CSS总结——瀑布流布局_css 瀑布流_黑白程序员的博客-CSDN博客),然后再通过懒加载(如何实现图片懒加载,预加载!! - 简书&…

AutoDL使用百度网盘来进行数据的交互

文章目录 1. 简介 2. 操作2.1. 设置密码2.1.1. 登录网盘 2.2. 访问网盘中的数据2.3. 将数据放入到网盘中 1. 简介 AutoDL上面其实是可以直接使用百度网盘、阿里云盘等公共网盘的,这样传资料的时候就不用通过Xshell慢悠悠的传输了,如果有百度网盘会员的话…

[MTK7621] dhcp.script 脚本分析

该脚本只要完成IP地址、DNS和路由设置。由udhcpc程序调用。调用的函数在下面两个文件中定义: . /lib/functions.sh:定义了一些基础操作,例如配置文件获取等 . /lib/netifd/netifd-proto.sh:定义了IP、DNS和路由的处理函数 在dhcp.…

关于Photoshop中的【Stable-Diffusion WEBUI】插件:Auto.Photoshop.SD.plugin

文章目录 (零)前言(一)PS的插件(1.1)安装(1.2)简评 (零)前言 本篇主要提到Photoshop中的Stable-Diffusion WEBUI插件,相对WEBUI并不算好用&#x…

MySQL 数据库面试题

TOC 1. MySQL 的内连接、左连接、右连接有有什么区别? inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集。 left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记…

STM32F401RET6 LQFP64 (Nucleo-F401RE) uart 打印输出

STM32F401RET6 LQFP64 (Nucleo-F401RE) uart 打印输出 1.STM32F401RET6 芯片情况 2.板子硬件 电源部分,开发板可利用JP5跳帽座子来选择使用USB供电或者使用管脚座子的外部Vin进行供电,无论是哪种供电,都需要经过U4的5V转成3.3V的LDO的再给S…