5.2 参数管理
目标
- 访问参数,用于调试、诊断和可视化;
- 参数初始化;
- 在不同模型组件间共享参数。
模型:单隐藏层的MLP
import torch
from torch import nnnet = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
X = torch.rand(size=(2, 4))
net(X)
tensor([[-0.0970],[-0.0827]], grad_fn=<AddmmBackward0>)
1 参数访问
从已有模型中访问参数: 检查第二个全连接层的参数
print(net[2].state_dict())
OrderedDict([('weight', tensor([[-0.0427, -0.2939, -0.1894, 0.0220, -0.1709, -0.1522, -0.0334, -0.2263]])), ('bias', tensor([0.0887]))])
结果信息:
- 这个全连接层包含两个参数,分别是该层的权重和偏置
- 两者都存储为单精度浮点数(float32)
note:参数名称允许唯一标识每个参数
1.1 访问目标参数
从第二个全连接层(即第三个神经网络层,第三层)提取偏置
print(type(net[2].bias))
print(net[2].bias)
print(net[2].bias.data)
<class 'torch.nn.parameter.Parameter'>
Parameter containing:
tensor([0.0887], requires_grad=True)
tensor([0.0887])
net[2].weight.grad == None
1.2 一次性访问所有参数
print(*[(name, param.shape) for name, param in net[0].named_parameters()])
print(*[(name, param.shape) for name, param in net.named_parameters()])
(‘weight’, torch.Size([8, 4])) (‘bias’, torch.Size([8]))
(‘0.weight’, torch.Size([8, 4])) (‘0.bias’, torch.Size([8])) (‘2.weight’, torch.Size([1, 8])) (‘2.bias’, torch.Size([1]))
net.state_dict()['2.bias'].data
tensor([0.0887])
解读
列表推导式
- 列表推导式
- 列表推导式 [(name, param.shape) for name, param in net[0].named_parameters()] 遍历该层的所有参数,提取参数的名称和形状。
print(*… ) 中的 * 用于解包列表,将列表中的元素作为多个参数传递给 print 函数,从而将每个参数的名称和形状单独打印出来。
注:列表推导式(List Comprehension)是 Python 中一种简洁、高效创建列表的方式。它允许你使用一行代码快速生成列表,而无需使用传统的循环结构。列表推导式的基本语法结构如:[表达式 for 变量 in 可迭代对象 if 条件]
示例:
squares = [x ** 2 for x in range(10)]
输出print(squares) # 输出:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
- 带条件的列表推导式
- 示例 :生成一个包含 0 到 9 之间的偶数的平方的列表。
- 代码 :
squares_of_evens = [x ** 2 for x in range(10) if x % 2 == 0]
print(squares_of_evens) # 输出:[0, 4, 16, 36, 64]
- 嵌套循环的列表推导式
- 示例 :生成两个列表元素的组合。
combinations = [(x, y) for x in [1, 2, 3] for y in ['a', 'b', 'c']]
print(combinations)
输出:[(1, ‘a’), (1, ‘b’), (1, ‘c’), (2, ‘a’), (2, ‘b’), (2, ‘c’), (3, ‘a’), (3, ‘b’), (3, ‘c’)]
print(*… ) 中的 *
print(*… ) 中的 * 用于解包列表,将列表中的元素作为多个参数传递给 print 函数,从而将每个参数的名称和形状单独打印出来。
1.3 从嵌套块收集参数
1.3.1 在 PyTorch 中构建嵌套的神经网络块
#将输入数据通过两个全连接层和激活函数进行处理,最终输出维度为 4
def block1():return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),nn.Linear(8, 4), nn.ReLU())#将输入数据通过两个全连接层和激活函数进行处理,最终输出维度为 4
def block2():# 创建一个空的 `nn.Sequential` 容器 `net`net = nn.Sequential()# 使用 `for` 循环迭代 4 次,每次调用 `block1()` 函数创建一个新的 `block1` 块for i in range(4):# 在这里嵌套# `add_module` 方法将创建的块添加到 `net` 中,并指定模块的名称为 `'block i'`(其中 `i` 是循环索引)net.add_module(f'block {i}', block1())# `block2` 返回一个包含 4 个 `block1` 块的序列容器return net# 构建一个完整的神经网络模型,包含 block2 返回的块和一个最终的全连接层#`block2()` 返回一个包含 4 个 `block1` 块的序列容器。
# `nn.Linear(4, 1)` 是一个全连接层,输入维度为 4,输出维度为 1。
# `nn.Sequential` 将这两个部分按顺序组合成一个完整的模型。
rgnet = nn.Sequential(block2(), nn.Linear(4, 1))#对输入数据 `X` 进行前向传播,通过整个网络计算输出
#输入数据首先通过 4 个 `block1` 块,每个块包含两个全连接层和激活函数,处理后的数据最终通过最后一个全连接层 `nn.Linear(4, 1)` 得到输出
rgnet(X)
tensor([[0.2596],
[0.2596]], grad_fn=)
1.3.2 执行过程
执行过程
假设输入数据 X
的形状为 (batch_size, 4)
,前向传播的具体执行过程如下:
-
第一个
block1
块- 输入:
X
(形状(batch_size, 4)
) - 第一层全连接层:
nn.Linear(4, 8)
,输出形状为(batch_size, 8)
- ReLU 激活函数:对输出应用 ReLU 激活,输出形状仍为
(batch_size, 8)
- 第二层全连接层:
nn.Linear(8, 4)
,输出形状为(batch_size, 4)
- ReLU 激活函数:对输出应用 ReLU 激活,输出形状仍为
(batch_size, 4)
- 输入:
-
第二个
block1
块- 输入:上一个块的输出(形状
(batch_size, 4)
) - 重复第一个块的处理过程,输出形状仍为
(batch_size, 4)
- 输入:上一个块的输出(形状
-
第三个
block1
块- 输入:上一个块的输出(形状
(batch_size, 4)
) - 重复第一个块的处理过程,输出形状仍为
(batch_size, 4)
- 输入:上一个块的输出(形状
-
第四个
block1
块- 输入:上一个块的输出(形状
(batch_size, 4)
) - 重复第一个块的处理过程,输出形状仍为
(batch_size, 4)
- 输入:上一个块的输出(形状
-
最终全连接层
- 输入:最后一个
block1
块的输出(形状(batch_size, 4)
) - 全连接层:
nn.Linear(4, 1)
,输出形状为(batch_size, 1)
- 输入:最后一个
向前传播流程
rgnet((0): block2((block 0): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU())(block 1): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU())(block 2): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU())(block 3): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU()))(1): Linear(4 -> 1)
)
最终构建的网络 rgnet
是一个由多个嵌套块组成的复杂神经网络。以下是其结构的详细说明:
网络结构
-
block2
块- 包含 4 个
block1
块,每个block1
块的结构如下:nn.Linear(4, 8)
:输入维度 4,输出维度 8 的全连接层。nn.ReLU()
:ReLU 激活函数。nn.Linear(8, 4)
:输入维度 8,输出维度 4 的全连接层。nn.ReLU()
:ReLU 激活函数。
- 包含 4 个
-
最终的全连接层
nn.Linear(4, 1)
:输入维度 4,输出维度 1 的全连接层。
层级关系
rgnet
是一个nn.Sequential
容器,包含两个主要部分:block2
和一个最终的全连接层。block2
本身也是一个nn.Sequential
容器,包含 4 个block1
块。- 每个
block1
块是一个nn.Sequential
容器,包含两个全连接层和两个 ReLU 激活函数。
具体结构
以下是 rgnet
的具体结构示意图:
rgnet((0): block2((block 0): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU())(block 1): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU())(block 2): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU())(block 3): block1((0): Linear(4 -> 8)(1): ReLU()(2): Linear(8 -> 4)(3): ReLU()))(1): Linear(4 -> 1)
)
前向传播流程
假设输入数据 X
的形状为 (batch_size, 4)
,以下是前向传播的具体流程:
-
第一个
block1
块- 输入:
X
(形状(batch_size, 4)
) - 第一层全连接层:
nn.Linear(4, 8)
,输出形状为(batch_size, 8)
- ReLU 激活函数:对输出应用 ReLU 激活,输出形状仍为
(batch_size, 8)
- 第二层全连接层:
nn.Linear(8, 4)
,输出形状为(batch_size, 4)
- ReLU 激活函数:对输出应用 ReLU 激活,输出形状仍为
(batch_size, 4)
- 输入:
-
第二个
block1
块- 输入:上一个块的输出(形状
(batch_size, 4)
) - 重复第一个块的处理过程,输出形状仍为
(batch_size, 4)
- 输入:上一个块的输出(形状
-
第三个
block1
块- 输入:上一个块的输出(形状
(batch_size, 4)
) - 重复第一个块的处理过程,输出形状仍为
(batch_size, 4)
- 输入:上一个块的输出(形状
-
第四个
block1
块- 输入:上一个块的输出(形状
(batch_size, 4)
) - 重复第一个块的处理过程,输出形状仍为
(batch_size, 4)
- 输入:上一个块的输出(形状
-
最终的全连接层
- 输入:最后一个
block1
块的输出(形状(batch_size, 4)
) - 全连接层:
nn.Linear(4, 1)
,输出形状为(batch_size, 1)
- 输入:最后一个
1.3.3 输出
print(rgnet)
输出
Sequential((0): Sequential((block 0): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU())(block 1): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU())(block 2): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU())(block 3): Sequential((0): Linear(in_features=4, out_features=8, bias=True)(1): ReLU()(2): Linear(in_features=8, out_features=4, bias=True)(3): ReLU()))(1): Linear(in_features=4, out_features=1, bias=True)
)
1.3.4 参数访问
rgnet[0][1][0].bias.data
tensor([ 0.1999, -0.4073, -0.1200, -0.2033, -0.1573, 0.3546, -0.2141, -0.2483])
2. 参数初始化
深度学习框架提供默认随机初始化, 也允许我们创建自定义初始化方法, 满足我们通过其他规则实现初始化权重。
2.1 内置初始化
将所有权重参数初始化为标准差为0.01的高斯随机变量, 且将偏置参数设置为0。
def init_normal(m):if type(m) == nn.Linear:nn.init.normal_(m.weight, mean=0, std=0.01)nn.init.zeros_(m.bias)
net.apply(init_normal)
net[0].weight.data[0], net[0].bias.data[0]
(tensor([1., 1., 1., 1.]), tensor(0.))
Xavier初始化方法初始化第一个神经网络层, 然后将第三个神经网络层初始化为常量值42
def init_xavier(m):if type(m) == nn.Linear:nn.init.xavier_uniform_(m.weight)
def init_42(m):if type(m) == nn.Linear:nn.init.constant_(m.weight, 42)net[0].apply(init_xavier)
net[2].apply(init_42)
print(net[0].weight.data[0])
print(net[2].weight.data)
tensor([ 0.5236, 0.0516, -0.3236, 0.3794])
tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])
2.2 自定义初始化
def my_init(m):if type(m) == nn.Linear:print("Init", *[(name, param.shape)for name, param in m.named_parameters()][0])# nn.init.uniform_将张量的值填充为从均匀分布中采样的随机数nn.init.uniform_(m.weight, -10, 10)# 对权重参数进行筛选和调整。具体来说,它会将权重参数矩阵 m.weight.data 中绝对值大于等于 5 的元素保留,而将绝对值小于 5 的元素设置为 0 m.weight.data *= m.weight.data.abs() >= 5# 由于 weight 为均匀分布,所以数值在[-5,5]的概率为1/2,[-10,-5]的概率为1/4,[5,10]的概率为1/4;net.apply(my_init)
net[0].weight[:2]
Init weight torch.Size([8, 4])
Init weight torch.Size([1, 8])
tensor([[5.4079, 9.3334, 5.0616, 8.3095],
[0.0000, 7.2788, -0.0000, -0.0000]], grad_fn=)
net[0].weight.data[:] += 1
net[0].weight.data[0, 0] = 42
net[0].weight.data[0]
tensor([42.0000, 10.3334, 6.0616, 9.3095])
实现特定的初始化分布 :在前面的例子中,定义的初始化分布要求权重值以 1/4 的概率从 U(5,10) 中取值,以 1/2 的概率取 0,以 1/4 的概率从 U(−10,−5) 中取值。通过将权重初始化为 U(−10,10) 内的随机数,然后再执行 m.weight.data *= m.weight.data.abs() >=5,可以筛选出绝对值大于等于 5 的权重值(来自 U(5,10) 或 U(−10,−5) 的分布),而将绝对值小于 5 的权重值设置为 0,从而近似实现目标的初始化分布。
这种方法并不能完全精确地实现目标分布,因为从 U(−10,10) 中采样的权重值经过筛选后,可能会导致最终的权重值分布与目标分布存在一定差异。
3 参数绑定
定义一个稠密层,然后使用它的参数来设置另一个层的参数
shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),shared, nn.ReLU(),shared, nn.ReLU(),nn.Linear(8, 1))
net(X)
# 检查参数是否相同
print(net[2].weight.data[0] == net[4].weight.data[0])net[2].weight.data[0, 0] = 100
# 确保它们实际上是同一个对象,而不只是有相同的值
print(net[2].weight.data[0] == net[4].weight.data[0])
tensor([True, True, True, True, True, True, True, True])
tensor([True, True, True, True, True, True, True, True])
3.1 定义共享层
shared = nn.Linear(8, 8)
首先定义了一个稠密层 shared = nn.Linear(8, 8),这个层的参数将被其他层共享。注意要给共享层一个名称,以便后续可以引用它的参数。
3.2 构建网络结构
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),shared, nn.ReLU(),shared, nn.ReLU(),nn.Linear(8, 1))
通过 nn.Sequential 构建了一个包含多个层的神经网络 net,其中包括两个 Linear 层和多个 ReLU 激活函数层。其中,第三个、第五个神经网络层(即第二个和第三个隐藏层)使用了 shared 层的参数。
3.3 检查参数是否相同
通过比较 net[2].weight.data[0] 和 net[4].weight.data[0],发现它们的值是相同的,这表明这两个层的权重参数是绑定在一起的
print(net[2].weight.data[0] == net[4].weight.data[0])
3.4 修改参数并验证绑定关系
net[2].weight.data[0, 0] = 100
# 确保它们实际上是同一个对象,而不只是有相同的值
print(net[2].weight.data[0] == net[4].weight.data[0])
将 net[2].weight.data[0, 0] 设置为 100 后,再次比较 net[2].weight.data[0] 和 net[4].weight.data[0],发现它们的值仍然相同,这说明它们实际上是同一个对象,而不是仅仅有相同的值。
第一次比较的结果 tensor([True, True, True, True, True, True, True, True, True]) 表示第三个和第五个层的权重参数在初始化后是相同的。
第二次比较的结果同样显示为 tensor([True, True, True, True, True, True, True, True, True]),这进一步验证了它们共享的是同一个参数对象,因为当修改其中一个参数时,另一个参数也随之改变。
3.5 梯度累加
当参数被绑定时,在反向传播过程中,梯度会累加。由于模型参数包含梯度,所以在反向传播期间,第二个隐藏层(即第三个神经网络层)和第三个隐藏层(即第五个神经网络层)的梯度会加在一起,共同影响参数的更新。
总结来说,参数绑定是一种在深度学习中用于共享参数的技术,可以在多个层之间实现参数的共享,减少模型参数量,提高参数的利用率。在 PyTorch 中,通过定义共享层并将其用于多个位置,可以轻松实现参数绑定。同时,需要注意的是,绑定参数在反向传播时梯度会累加。
相关文章:
5.2 参数管理
目标 访问参数,用于调试、诊断和可视化;参数初始化;在不同模型组件间共享参数。 模型:单隐藏层的MLP import torch from torch import nnnet nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1)) X torch.rand(size…...
gvm安装go报错ERROR: Failed to use installed version
这里写自定义目录标题 使用gvm安装版本报错解决方案可以尝试在版本后面添加--binary,例如还不行记得在多切换几个准确的版本 使用gvm安装版本报错 gvm install go1.22 Installing go1.22.0 as go1.22… Compiling… /Users/uncledd2/.gvm/scripts/install: line 9…...

CAElinux系统详解
CAElinux 系统详解:从系统层面到专业应用 一、CAElinux 的定位与核心目标 CAElinux 是一款专门为 计算机辅助工程(CAE) 设计的定制化 Linux 发行版,目标用户为从事工程仿真、数值模拟、高性能计算(HPC)的…...

计算机系统----软考中级软件设计师(自用学习笔记)
目录 1、计算机的基本硬件系统 2、CPU的功能 3、运算器的组成 4、控制器 5、计算机的基本单位 6、进制转换问题 7、原码、反码、补码、移码 8、浮点数 9、寻址方式 10、奇偶校验码 11、海明码 12、循环冗余校验码 13、RISC和CISC 14、指令的处理方式 15、存储器…...

django的权限角色管理(RBAC)
在 Django 中,User、Group 和 Permission 是权限系统的核心组件。下面通过代码示例演示它们的 CRUD(创建、读取、更新、删除) 操作: 一、User 模型 CRUD from django.contrib.auth.models import User# 创建用户 user User.obje…...
新建一个reactnative 0.72.0的项目
npx react-native0.72.0 init ProjectName --version 0.72.0 下面是初始化,并且添加了对应路由的库依赖,Android项目能run起来的版本号 { "name": "ProjectName", "version": "0.0.1", "private&quo…...

线性表-顺序表(Sequential List)
1 线性表 1.1 顺序表(Sequential List) 顺序表并不难理解,主要是知道顺序表是在内存中连续存储的一段数据,知道这个后,相应的算法也就非常简单了。 线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的…...
框架篇八股(自用)
框架篇 Spring框架中的bean不是线程安全的 Scope() singleton单例 prototype多例 一个类中有可修改的成员变量需要考虑线程安全 bean没有可变状态(service类,DAO类) 某种程度单例bean是线程安全的 AOP面向切面编程…...
软考高级《系统架构设计师》知识点(十七)
知识产权和标准化 知识产权基础知识 知识产权是指公民、法人、非法人单位、对自己的创造性智力成果和其他科技成果依法享有的民事权。是智力成果的创造人依法享有的权利和在生产经营活动中标记所有人依法所享有的权利的总称。 知识产权基础知识包含著作权、专利权、商标权、商业…...
在 Envoy 的配置文件中出现的 “@type“ 字段
在 Envoy 的配置文件中出现的 "type" 字段是 Protocol Buffers(Protobuf)的 JSON/YAML 编码规范的一部分,属于 Typed Struct 的表示方式。它的作用是明确指定当前配置对象的 Protobuf 类型,以便 Envoy 正确解析配置。以…...
思维链实现 方式解析
思维链的实现方式 思维链的实现方式除了提示词先后顺序外,还有以下几种: 增加详细的中间步骤提示:通过提供问题解决过程中的详细中间步骤提示,引导模型逐步推导和思考。例如,在解决数学证明题时,提示词可以具体到每一步需要运用的定理、公式以及推理的方向,帮助模型构建…...
计算机网络:什么是Mesh组网以及都有哪些设备支持Mesh组网?
Mesh组网技术详解与实现工具推荐 Mesh组网是一种通过多个节点路由器协同工作,形成覆盖全屋的无线网络的技术。它通过动态路径调整、无缝漫游和自愈能力,解决传统单一路由器覆盖不足的问题,尤其适合大户型、多层住宅或复杂户型环境。以下是Mesh组网的核心原理、实现方式及推…...

【阿里云免费领取域名以及ssl证书,通过Nginx反向代理web服务】
文章目录 前言一、申请域名1.1 访问阿里云官网1.2 输入自定义域名1.3 创建个人模板1.4 支付1元可以使用域名1年1.5 按照提示实名认证1.6 实名认证成功 二、域名解析2.1 选择域名解析2.2 解析设置2.3 快速添加解析2.4 选择对应类型2.5 解析成功 三、申请免费ssl证书3.1 访问阿里…...

数据分析2
五、文件 CSV Comma-Separated Value,逗号分割值。CSV文件以纯文本形式存储表格数据(数字和文本)。 CSV记录间以某种换行符分隔,每条记录由字段组成,字段间以其他字符或字符串分割,最常用逗号或制表符。…...

实战项目5(08)
目录 任务场景一 【r1配置】 【r2配置】 【r3配置】 任务场景二 【r1配置】 【r2配置】 任务场景一 按照下图完成网络拓扑搭建和配置 任务要求: 通过在路由器R1、R2和R3上配置静态路由,实现网络中各终端PC能够正常…...
CSS结构性伪类、UI伪类与动态伪类全解析:从文档结构到交互状态的精准选择
一、结构性伪类选择器:文档树中的位置导航器 结构性伪类选择器是CSS中基于元素在HTML文档树中的层级关系、位置索引或结构特征进行匹配的一类选择器。它们无需依赖具体的类名或ID,仅通过文档结构即可精准定位元素,是实现响应式布局和复杂文档…...

.NET MAUI 基础知识
文章目录 什么是 .NET MAUI?MAUI的核心特点与Xamarin.Forms的区别 开发环境搭建安装Visual Studio 2022安装必要组件配置Android开发环境配置iOS开发环境验证安装 创建第一个MAUI应用创建新项目MAUI项目结构解析理解关键文件运行应用程序简单修改示例使用热重载 MAU…...

佰力博科技与您探讨表面电阻的测试方法及应用领域
表面电阻测试是一种用于测量材料表面电阻值的技术,广泛应用于评估材料的导电性能、静电防护性能以及绝缘性能。 1、表面电阻的测试测试方法: 表面电阻测试通常采用平行电极法、同心圆电极法和四探针法等方法进行。其中,平行电极法通过在试样…...

鹅厂面试数学题
题目 一个圆上随机取三个点,求这三个点构成锐角三角形的概率。 解答 根据圆周角定理,此题目等价为:一条线段长度为1的线段随机取两个点分成三段,任意一段长度均不大于1/2的概率。记前两段的长度为,则第三段的长度为…...
GO语言-导入自定义包
文章目录 1. 项目目录结构2. 创建自定义包3. 初始化模块4. 导入自定义包5. 相对路径导入 在Go语言中导入自定义包需要遵循一定的目录结构和导入规则。以下是详细指南(包含两种方式): 1. 项目目录结构 方法1:适用于Go 1.11 &#…...

java基础-package关键字、MVC、import关键字
1.package关键字: (1)为了更好管理类,提供包的概念 (2)声明类或接口所属的包,声明在源文件首行 (3)包,属于标识符,用小写字母表示 ࿰…...

[6-2] 定时器定时中断定时器外部时钟 江协科技学习笔记(41个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 V 30 31 32 33 34 35 36 37 38 39 40 41...
第五节:对象与原型链:JavaScript 的“类”与“继承”
📌 第五节:对象与原型链:JavaScript 的“类”与“继承” 目标:理解对象创建、原型继承、this 绑定,掌握类语法与原型设计模式,实现模块化组件开发。 一、对象基础:数据的“容器” 1. 对象字面…...
本地的ip实现https访问-OpenSSL安装+ssl正式的生成(Windows 系统)
1.下载OpenSSL软件 网站地址:Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 安装: 一直点击下一步就可以了 2.设置环境变量 在开始菜单右键「此电脑」→「属性」→「高级系统设置」→「环境变量」 在Path 中添加一个: xxxx\OpenSSL-…...
Spring Boot + MyBatis-Plus 高并发读写分离实战
引言 在高并发场景下,单一数据库实例往往成为性能瓶颈。数据库读写分离通过将读操作和写操作分配到不同的数据库实例,有效缓解主库压力,提升系统吞吐量。MyBatis-Plus 作为一款强大的持久层框架,结合 Spring Boot 能够轻松实现读…...
HarmonyOS 【诗韵悠然】AI古诗词赏析APP开发实战从零到一系列(二、项目准备与后台服务搭建)
在开发一款面向HarmonyOS平台的应用程序——【诗韵悠然】AI古诗词赏析APP时,选择了流行Go语言作为后端开发语言,并使用了go-zero微服务框架来搭建服务接口。本文将详细介绍项目准备和后台服务搭建的过程,帮助大家更好地理解和掌握go-zero框架…...

【PmHub后端篇】PmHub中基于自定义注解和AOP的服务接口鉴权与内部认证实现
1 引言 在现代软件开发中,尤其是在微服务架构下,服务接口的鉴权和内部认证是保障系统安全的重要环节。本文将详细介绍PmHub中如何利用自定义注解和AOP(面向切面编程)实现服务接口的鉴权和内部认证,所涉及的技术知识点…...

多模态AI新纪元:Vertex AI Gemini与Spring AI深度集成实践
企业级AI集成进阶:Spring AI与Vertex AI Gemini的配置与调优实战 一、前沿技术:多模态模型的企业级配置范式 在生成式AI技术快速迭代的当下,企业级应用对模型配置的精细化需求日益增长。Vertex AI Gemini作为Google推出的多模态大模型&…...
大语言模型RLHF训练框架全景解析:OpenRLHF、verl、LLaMA-Factory与SWIFT深度对比
引言 随着大语言模型(LLM)参数规模突破千亿级,基于人类反馈的强化学习(RLHF)成为提升模型对齐能力的关键技术。OpenRLHF、verl、LLaMA-Factory和SWIFT作为开源社区的四大标杆框架,分别通过分布式架构、混合…...

开源AI数字人分身克隆小程序源码系统深度剖析:从搭建到应用
在人工智能与小程序生态深度融合的当下,开源 AI 数字人分身克隆小程序源码成为开发者的热门工具。从搭建基础环境到实现实际应用,这一过程涉及多项技术与复杂流程。本文将带您深入剖析开源 AI 数字人分身克隆小程序源码,揭开其从搭建到应用的…...