模型评估与调优(PyTorch)
文章目录
- 模型评估方法
- 混淆矩阵
- 混淆矩阵中的指标
- ROC曲线(受试者工作特征)
- AUC
- R平方
- 残差
- 均方误差(MSE)
- 均方根误差(RMSE)
- 平均绝对误差(MAE)
- 模型调优方法
- 交叉验证(CV)
- 交叉验证方法
- Holdout验证
- K折交叉验证
- 留一验证
- 十折交叉验证
- 网格搜索交叉验证
- 随机搜索
- PyTorch实现交叉验证
- 源代码地址
- 代码内容
- 准确度为0的问题分析和解决
- 解决方法:
- ❌ 原始错误原因分析
- 1. 数据分布不合理
- 2. 训练集和验证集无区分性
- 3. 模型无法收敛到有效解
- ✅ 修改后为何能解决问题?
- 📌 总结
模型评估方法
混淆矩阵
- 混淆矩阵是机器学习中统计分类模型预测结果的表,它以矩阵形式将数据集中的记录按照真实的类别与分类模型预测的类别进行汇总,其中矩阵的行表示真实值,矩阵的列表示模型的预测值。
- 在机器学习中,正样本就是使模型得出正确结论的例子,负样本是使得模型得出错误结论的例子。
- 建立一个二分类的混淆矩阵,假如宠物店有10只动物,其中6只狗,4只猫,现在有一个分类器将这10只动物进行分类,分类结果为5只狗,5只猫,分类结果的混淆矩阵为:
混淆矩阵 | 预测值:正(狗) | 预测值:负(猫) |
---|---|---|
真实值:正(狗) | 5 | 1 |
真实值:负(猫) | 0 | 4 |
混淆矩阵中的指标
- TP(TruePositive):被判定为正样本,事实上也是正样本。真的正样本也叫真阳性。
- FN(FalseNegative):被判定为负样本,但事实上是正样本。假的负样本也叫假阴性。
- FP(FalsePositive):被判定为正样本,但事实上是负样本。假的正样本也叫假阳性。
- TN(TrueNegative):被判定为负样本,事实上也是负样本。真的负样本也叫真阴性。
混淆矩阵 | 预测值:正(狗) | 预测值:负(猫) |
---|---|---|
真实值:正(狗) | TP | FN |
真实值:负(猫) | FP | TN |
ROC曲线(受试者工作特征)
- ROC曲线的全称是“受试者工作特征”,常用来衡量分类学习器的好坏。如果一个学习器的ROC曲线能将另一个学习器的ROC曲线完全包括,则说明该学习器的性能优于另一个学习器。ROC曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变。
- ROC曲线的横轴表示FPR,即错误地预测为正例的概率,纵轴表示TPR,即正确地预测为正例的概率,二者的计算公式如下:
F P R = F P F P + T N T P R = T P T P + F N FPR=\frac{FP}{FP+TN} \qquad TPR=\frac{TP}{TP+FN} FPR=FP+TNFPTPR=TP+FNTP
AUC
- AUC是一个数值,它是ROC曲线与坐标轴围成的面积。TPR越大、FPR越小,模型效果越好,ROC曲线就越靠近左上角,表明模型效果越好,AUC值越大,极端情况下为1。由于ROC曲线一般都处于 y = x y=x y=x直线的上方,因此 A U C AUC AUC的取值范围一般在 0.5 0.5 0.5和 1 1 1之间。
- 在部分场景下ROC曲线不能直观说明分类器的效果,使用AUC值作为评价标准可以只管说明分类器的效果。
- AUC值越大,当前的分类算法越有可能将正样本排在负样本前面,即能够更好地分类,可以从AUC判断分类器(预测模型)优劣的标准。
- UC=1,是完美分类器,采用这个预测模型时,存在至少一个阈值能得出完美预测。绝大多数预测的场合不存在完美分类
- 0.5<AUC<1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,有预测价值。
- AUC=0.5,跟随机猜测一样,模型没有预测价值。
- AUC<0.5,比随机猜测还差
R平方
- 判定系数R平方(决定系数)是指在线性回归中,回归可解释离平方和与总离差平方和的比值,其数值等于相关系数R的平方。
- 判定系数是一个解释性系数,在回归分析中,其主要作用是评估回归模型对因变量y产生变化的解释程度(判定系数R平方是评估模型好坏的指标)。
- R平方的取值范围为 0 1 0~1 0 1,通常以百分数表示,如回归模型的R平方等于 0.7 0.7 0.7,那么表示此回归模型对预测结果的可解释程度为70%。一般认为,R平方大于0.75,表示模型拟合度很好,可解释程度较高;R平方小于0.5,表示模型拟合有问题,不宜进行回归分析。
-
问题: 在多元回归中,R²(判定系数)有一个明显缺点:只要增加自变量(哪怕是不相关的变量),R²就会变大。这会导致模型看起来拟合得很好,但实际上可能加入了无用的变量,反而降低了模型的可靠性。
-
解决方法:为了修正这个问题,我们使用调整后的R²。它会根据样本量(n)和自变量个数(k)自动惩罚无意义的变量,避免R²被高估。计算公式如下:
调整后的 R 2 = 1 − ( 1 − R 2 ) × n − 1 n − k − 1 \text{调整后的} R^2 = 1 - (1 - R^2) \times \frac{n-1}{n-k-1} 调整后的R2=1−(1−R2)×n−k−1n−1
关键点:
- R²的缺陷:单纯增加变量就会提高R²,即使变量没用。
- 调整原理:公式中的 n − 1 n − k − 1 \frac{n-1}{n-k-1} n−k−1n−1 会惩罚变量过多的模型(k越大,分母越小,整体值越大,从而降低R²)。
- 效果:只有真正有用的变量才会提升调整后的R²,垃圾变量会被过滤掉。
-
在回归分析(尤其是多元回归)中,调整后的R²比普通R²更准确,因为它会惩罚无用的自变量,避免模型“虚高”的拟合效果。因此,我们通常用调整后的R²来评估模型的真实拟合度。
-
调整后的R²是否合格?临界值:0.5
- 如果调整后的R² ≥ 0.5,说明模型拟合效果尚可。
- 如果调整后的R² < 0.5,说明模型解释力较弱,需要检查: 已使用的自变量是否真的影响因变量?是否遗漏了重要的自变量?
残差
- 残差在数理统计中指实际观测值估计值之间的差,它蕴涵了有关模型基本假设的重要信息。如果回归模型正确的话,可以将残差看作误差的观测值。
- 回归算法的残差评价指标有均方误差(Mean Squared Error,MSE)、均方根误差(Root Mean Square Error,RMSE),平均绝对误差(Mean Absolute Error,MAE)。
均方误差(MSE)
- 均方误差(MSE)表示预测值和观测值之间差异(残差平方)的平均值。(线性回归的损失函数,线性回归的目的就是让这个损失函数的数值最小。)
M S E = 1 m ∑ i = 1 m ( y ^ i − y i ) 2 MSE=\frac{1}{m}\sum_{i=1}^{m}(\hat y_i-y_i)^2 MSE=m1i=1∑m(y^i−yi)2
均方根误差(RMSE)
- 均方根误差(RMSE)表示预测值和观测值之间差异(残差)的样本标准差。
R M S E = M S E = 1 m ∑ i = 1 m ( y ^ i − y i ) 2 RMSE=\sqrt{MSE}=\sqrt{\frac{1}{m}\sum_{i=1}^{m}(\hat y_i-y_i)^2} RMSE=MSE=m1i=1∑m(y^i−yi)2
平均绝对误差(MAE)
- 平均绝对误差(MAE)表示预测值和观测值之间绝对误差的平均值。MAE是一种线性分数,所有个体差异在平均值上的权重都相等,而RMSE相比MAE,会对高的差异惩罚更多。
M A E = 1 m ∑ i = 1 m ∣ y ^ i − y i ∣ MAE=\frac{1}{m}\sum_{i=1}^{m}|\hat y_i - y_i| MAE=m1i=1∑m∣y^i−yi∣
模型调优方法
交叉验证(CV)
- 交叉验证(Cross Validation,CV)或者循估计,是一种统计学上将数据样本切割成较小子集的实用方法,主要用于数据建模。
- 交叉验证的基本思想:将原始数据进行分组,一部分作为训练集,另外一部分作为验证集。首先用训练集对分类器进行训练,再利用验证集来测试训练得到的模型,以此评价分类器的性能指标,使用交叉验证的目的得到可到稳定的模型。
交叉验证方法
Holdout验证
- Holdout验证将原始数据随机分为两组,一组作为训练集,另一组作为验证集,利用训练集训练分类器,然后利用验证集验证模型,记录最后的分类准确率,以此作为分类器的性能指标。
K折交叉验证
- K折交叉验证将初始采样分割成K个子样本,一个单独的子样本被保留作为验证模型的数据,其他K-1个样本用来训练。交叉验证重复K次,每个子样本验证一次,平均K次的结果,最终得到一个单一估测。优势在于,同时重复运用随机产生的子样本进行训练和验证,每次的结果验证一次。
留一验证
- 留一验证指只使用原本样本中的一项当作验证数据,而剩余的则留下当作训练数据。这个步骤一直持续到每个样本都被当作一次验证数据。事实上,这等同于K折交叉验证,其中K为原样本个数。
十折交叉验证
- 十折交叉验证用来测试算法的准确性。将数据集分成10份,轮流将其中9份作为训练数据,1份作为测试数据。每次试验都会得出相应的正确率。10次结果的正确率的平均值作为算法精度的估计,一般还需要进行多次10折交叉验证(例如10次10折交叉验证),再求其均值,作为算法的最终准确性估计。
网格搜索交叉验证
- 网格搜索交叉验证(GridSearchC):部分:网格搜索(GridSearch)和交叉验证(CV)。网格搜索搜索的是参数,即在指定的参数范围内,按步长依次调整参数,利用调整的参数训练模型,从所有的参数中找到在验证集上精度最高的,这其实是一个训练和比较的过程。
- 网格搜索可以保证在指定的参数范围内找到精度最高的参数,它要求遍历所有可能的参数的组合,在面对大数据集和多参数的情况下,非常耗时。所以网格搜索适用于三四个(或者更少)超参数,用户列出一个较小的超参数值域,这些超参数值域的笛卡儿积为一组超参数。
随机搜索
- 在搜索超参数时,如果超参数个数较少可以采用网格搜索。但当超参数个数比较多时,如果仍然采用网格搜索,搜索时间将呈指数上升。随机搜索的方法,随机在超参数空间中搜索几十甚至几百个点,其中就有可能有比较小的值。
- 随机搜索不是尝试所有可能的组合,而是通过选择每一个超参数的一个随机值的特定数量的随机组合,方便通过设定搜索次数控制超参数搜索的计算量等。对于有连续变量的参数,随机搜索会将其当成一个分布进行采样。
PyTorch实现交叉验证
源代码地址
- 交叉验证源代码地址
代码内容
import torch
from torch import nn
from torch.utils.data import DataLoader, TensorDataset
import torch.nn.functional as f# 构造训练集
train_x = torch.rand(100, 28, 28)
train_y = torch.randn(100, 28, 28)
train_x = torch.cat((train_x, train_y), dim=0)
# 构造标签 前100个元素为1 后100个元素为0
labels = [1] * 100 + [0] * 100
# 将标签列转为张量
labels = torch.tensor(labels, dtype=torch.long)# 设置网络结构
"""
__init__方法中定义三个全连接层:fc1、fc2和fc3。
forward方法实现前向传播过程,对输入数据进行展平,通过全连接层和激活函数进行处理。
num_flat_features方法用于计算输入数据的展平特征数量。
"""
class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(28 * 28, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 2)def forward(self, x):# 将输入张量x展平为一维张量,并计算展平后的特征数量x = x.view(-1, self.num_flat_features(x))x = f.relu(self.fc1(x))x = f.relu(self.fc2(x))x = self.fc3(x)return x# 计算输入x的展平特征数量的函数def num_flat_features(self, x):size = x.size()[1:] # 获取输入x除了第一个维度外的尺寸num_features = 1 # 初始化特征数量为1for s in size: # 遍历尺寸列表num_features *= s # 计算特征数量return num_features # 返回特征数量# 训练集数据处理
class train_data_set(TensorDataset):def __init__(self, train_features, train_labels):self.x_data = train_features # 保存训练特征self.y_data = train_labels # 保存训练标签self.len = len(train_labels) # 保存训练样本数量# 获取训练数据def __getitem__(self, index):return self.x_data[index], self.y_data[index]# 获取训练数据数量def __len__(self):return self.len# 设置损失函数
loss_func = nn.CrossEntropyLoss()"""
get_k_fold_data函数用于将数据集分为K折,并返回当前折的训练集数据、训练集标签、验证集数据和验证集标签。
"""# 设置k划分
def get_k_fold_data(k, i, x, y):"""获取k折交叉验证数据:param k: 折数:param i: 当前折的索引:param x: 输入的数据:param y: 标签:return:x_train(torch.Tensor):训练集数据y_train(torch.Tensor):训练集标签x_valid(torch.Tensor):验证集数据y_valid(torch.Tensor):验证集标签"""assert k > 1fold_size = x.shape[0] // k # 每折的大小x_train, y_train = None, Nonefor j in range(k):idx = slice(j * fold_size, (j + 1) * fold_size)x_part, y_part = x[idx, :], y[idx]if j == i:x_valid, y_valid = x_part, y_partelif x_train is None:x_train, y_train = x_part, y_partelse:x_train = torch.cat((x_train, x_part), dim=0)y_train = torch.cat((y_train, y_part), dim=0)return x_train, y_train, x_valid, y_valid"""
k_fold函数则在K折交叉验证中循环训练模型,并计算和累积每折的训练集和验证集的损失与准确度。
"""
def k_fold(k, x_train, y_train, num_epochs=3, learning_rate=0.001, weight_decay=0.1, batch_size=5):"""进行k折验证:param k: 折数:param x_train: 训练数据:param y_train: 训练标签:param num_epochs: 训练轮数 默认值为3:param learning_rate: 学习率 默认值为0.001:param weight_decay: 权重衰减 默认值为0.1:param batch_size: 批次大小 默认为5:return:train_loss_sum(float):训练集损失总和valid_loss_sum(float):验证集损失总和train_acc_sum(float):训练集准确度总和valid_acc_sum(float):验证集准确度总和"""train_loss_sum, valid_loss_sum = 0.0, 0.0train_acc_sum, valid_acc_sum = 0.0, 0.0for i in range(k):data = get_k_fold_data(k, i, x_train, y_train)net = Net() # 创建网络实例train_ls, valid_ls = train(net, *data, num_epochs, learning_rate, weight_decay, batch_size)print('*' * 10, '第', i + 1, '折', '*' * 10)print('训练集损失:%.6f' % train_ls[-1][0], '训练集准确度:%.4f' % valid_ls[-1][1],'测试集损失:%.6f' % valid_ls[-1][0], '测试集准确度:%.4f' % valid_ls[-1][1])train_loss_sum += train_ls[-1][0]valid_loss_sum += valid_ls[-1][0]train_acc_sum += train_ls[-1][1]valid_acc_sum += valid_ls[-1][1]print('#' * 5, '最终k折交叉验证结果', '#' * 5)print('训练集累积损失:%.4f' % (train_loss_sum / k), '训练集累积准确度:%.4f' % (train_acc_sum / k),'测试集累积损失:%.4f' % (valid_loss_sum / k), '测试集累积准确度:%.4f' % (valid_acc_sum / k))return train_loss_sum, valid_loss_sum, train_acc_sum, valid_acc_sum# 设置训练函数def train(net, train_features, train_labels, test_features, test_labels, num_epochs, learning_rate, weight_decay,batch_size):"""设置训练函数:param net: 神经网络模型:param train_features: 训练数据特征:param train_labels: 训练数据标签:param test_features: 测试数据特征:param test_labels: 测试数据标签:param num_epochs: 训练轮数:param learning_rate: 学习率:param weight_decay: 权重衰减:param batch_size: 批次大小:return:train_ls: 训练集的损失和准确度损失test_ls: 测试集的损失和准确度列表"""# 初始化训练集和测试集的损失和准确度列表train_ls, test_ls = [], []# 创建训练数据集和数据加载器dataset = train_data_set(train_features, train_labels)train_iter = DataLoader(dataset, batch_size, shuffle=True)# 创建优化器optimizer = torch.optim.Adam(params=net.parameters(), lr=learning_rate, weight_decay=weight_decay)# 遍历每个训练轮次for epoch in range(num_epochs):# 遍历每个批次for X, y in train_iter:output = net(X)loss = loss_func(output, y)optimizer.zero_grad()loss.backward()optimizer.step()# 将当前轮次的训练集损失和准确度添加到列表train_ls.append(log_rmse(0, net, train_features, train_labels))# 测试集损失和准确度添加到列表中if test_labels is not None:test_ls.append(log_rmse(1, net, test_features, test_labels))# 返回训练集和测试集的损失和准确度列表return train_ls, test_ls# 设置准确度计算函数
def log_rmse(flag, net, x, y):"""计算对数均方根误差和准确度的函数:param flag: 0表示训练集,1表示测试集:param net: 评估的模型:param x: 数据特征:param y: 数据标签:return:loss.data.item(): 损失值accuracy: 准确度"""# 如果是测试集,设置网络为评估模式if flag == 1:net.eval()# 前向传播 获取预测结果output = net(x)result = torch.max(output, 1)[1].view(y.size())# 计算正确预测的数量corrects = (result.data == y.data).sum().item()# 计算准确度accuracy = corrects * 100.0 / len(y)# 计算损失loss = loss_func(output, y)# 如果是测试集,设置网络为训练模式net.train()return loss.data.item(), accuracyif __name__ == '__main__':"""执行k折交叉验证"""# 调用交叉验证函数k_fold(10, train_x, labels)
********** 第 1 折 **********
训练集损失:0.039320 训练集准确度:100.0000 测试集损失:0.024422 测试集准确度:100.0000
********** 第 2 折 **********
训练集损失:0.042435 训练集准确度:100.0000 测试集损失:0.024841 测试集准确度:100.0000
********** 第 3 折 **********
训练集损失:0.043264 训练集准确度:100.0000 测试集损失:0.024778 测试集准确度:100.0000
********** 第 4 折 **********
训练集损失:0.033361 训练集准确度:100.0000 测试集损失:0.018814 测试集准确度:100.0000
********** 第 5 折 **********
训练集损失:0.039068 训练集准确度:100.0000 测试集损失:0.024000 测试集准确度:100.0000
********** 第 6 折 **********
训练集损失:0.039641 训练集准确度:95.0000 测试集损失:0.370682 测试集准确度:95.0000
********** 第 7 折 **********
训练集损失:0.040322 训练集准确度:95.0000 测试集损失:0.447232 测试集准确度:95.0000
********** 第 8 折 **********
训练集损失:0.038236 训练集准确度:95.0000 测试集损失:0.425054 测试集准确度:95.0000
********** 第 9 折 **********
训练集损失:0.036090 训练集准确度:95.0000 测试集损失:0.414253 测试集准确度:95.0000
********** 第 10 折 **********
训练集损失:0.037329 训练集准确度:100.0000 测试集损失:0.353675 测试集准确度:100.0000
##### 最终k折交叉验证结果 #####
训练集累积损失:0.0389 训练集累积准确度:100.0000 测试集累积损失:0.2128 测试集累积准确度:98.0000
准确度为0的问题分析和解决
********** 第 1 折 ********** 训练集损失:0.690276 训练集准确度:0.0000 测试集损失:0.714697 训练集准确度:0.0000 ********** 第 2 折 ********** 训练集损失:0.686439 训练集准确度:0.0000 测试集损失:0.777147 测试集准确度:0.0000
解决方法:
train_y = torch.rand(100, 28, 28)
将其修改为:
train_y = torch.randn(100, 28, 28)
❌ 原始错误原因分析
1. 数据分布不合理
torch.rand
:生成的是[0, 1)
区间内的均匀分布随机数。torch.randn
:生成的是标准正态分布(均值为0,方差为1)的随机数,取值范围更广。
- 在模型中:模型期望学习区分两类样本(标签为 0 和 1)。如果输入数据(如
train_x
和train_y
)都是从相同分布(如rand
)生成的,那么这两类样本之间没有可区分的特征模式。更严重的是,rand
数据集中在 [0,1] 区间,导致模型输出难以区分两个类别,从而准确率始终为 0。
2. 训练集和验证集无区分性
- 原始
train_x
和train_y
都使用了torch.rand
,它们本质上是同一类数据,只是被人为地赋予了不同的标签。这种构造方式使得模型无法学到任何有意义的分类边界。
3. 模型无法收敛到有效解
- 因为输入数据缺乏类别间的差异性,损失函数无法下降到合理值。准确率一直为 0 是模型无法识别任何样本类别的直接体现。
✅ 修改后为何能解决问题?
将 train_y = torch.rand(100, 28, 28)
改为:
train_y = torch.randn(100, 28, 28)
带来的变化包括:
对比项 | torch.rand | torch.randn |
---|---|---|
分布类型 | 均匀分布 | 正态分布 |
数值范围 | [0, 1) | 大致 [-3, 3] |
样本差异性 | 小 | 大 |
是否适合用于分类任务 | 否 | 是 |
- 通过使用
torch.randn
,train_x
和train_y
的数据分布出现明显差异,这为模型提供了可学习的特征差异。因此,模型可以逐渐学习如何区分这两个类别,准确率也随之提升。
📌 总结
错误点 | 原因 | 影响 | 解决方案 |
---|---|---|---|
使用 torch.rand 构造数据 | 数据分布单一、无类别差异 | 模型无法学习分类边界 | 改用 torch.randn 提供更大差异性 |
缺乏真实数据 | 输入无语义信息 | 模型无法收敛 | 使用真实图像数据(如 MNIST)效果更佳 |
相关文章:
模型评估与调优(PyTorch)
文章目录 模型评估方法混淆矩阵混淆矩阵中的指标ROC曲线(受试者工作特征)AUCR平方残差均方误差(MSE)均方根误差(RMSE)平均绝对误差(MAE) 模型调优方法交叉验证(CV&#x…...
sockaddr结构体详解
在网络编程中,sockaddr 结构体用于表示套接字的地址信息。由于不同协议(如 IPv4、IPv6、Unix 域套接字)的地址格式不同,实际使用中通常通过以下三种变体结构来处理不同类型的地址: 1. 通用地址结构:struct …...

Seata源码—7.Seata TCC模式的事务处理一
大纲 1.Seata TCC分布式事务案例配置 2.Seata TCC案例服务提供者启动分析 3.TwoPhaseBusinessAction注解扫描源码 4.Seata TCC案例分布式事务入口分析 5.TCC核心注解扫描与代理创建入口源码 6.TCC动态代理拦截器TccActionInterceptor 7.Action拦截处理器ActionIntercept…...

【语法】C++的map/set
目录 平衡二叉搜索树 set insert() find() erase() swap() map insert() 迭代器 erase() operator[] multiset和multimap 在之前学习的STL中,string,vector,list,deque,array都是序列式容器,它们的…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Live View Kit (3)
1.问题描述: 通过Push Kit创建实况窗之后,再更新实况窗失败,平台查询提示“实况窗端更新失败,通知未创建或已经过期”。 解决方案: 通过Push Kit更新实况窗内容的过程是自动更新的。客户端在创建本地实况窗后&#…...

vue vite textarea标签按下Shift+Enter 换行输入,只按Enter则提交的实现思路
注意input标签不能实现,需要用textarea标签 直接看代码 <template><textareav-model"message"keydown.enter"handleEnter"placeholder"ShiftEnter 换行,Enter 提交"></textarea> </template>&l…...
MySQL多线程备份工具mysqlpump详解!
MySQLPUMP备份工具详解 1. 概述 MySQLPump 是 MySQL 5.7 引入的一个客户端备份工具,用于替代传统的 mysqldump 工具。它提供了并行处理、进度状态显示、更好的压缩支持等新特性,能够更高效地执行 MySQL 数据库备份操作。 2. 主要特性 并行处理&#x…...
创建信任所有证书的HttpClient:Java 实现 HTTPS 接口调用,等效于curl -k
在 Java 生态中,HttpClient 和 Feign 都是调用第三方接口的常用工具,但它们的定位、设计理念和使用场景有显著差异。以下是详细对比: DIFF1. 定位与抽象层级 特性HttpClientFeign层级底层 HTTP 客户端库(处理原始请求/响应&#…...
Redisson分布式集合原理及应用
Redisson是一个用于Redis的Java客户端,它简化了复杂的数据结构和分布式服务的使用。 适用场景对比 数据结构适用场景优点RList消息队列、任务队列、历史记录分布式共享、阻塞操作、分页查询RMap缓存、配置中心、键值关联数据支持键值对、分布式事务、TTLRSet去重集…...

深入理解 PlaNet(Deep Planning Network):基于python从零实现
引言:基于模型的强化学习与潜在动态 基于模型的强化学习(Model-based Reinforcement Learning)旨在通过学习环境动态的模型来提高样本效率。这个模型可以用来进行规划,让智能体在不需要与真实环境进行每一次决策交互的情况下&…...
精益数据分析(75/126):用户反馈的科学解读与试验驱动迭代——Rally的双向验证方法论
精益数据分析(75/126):用户反馈的科学解读与试验驱动迭代——Rally的双向验证方法论 在创业的黏性阶段,用户反馈是优化产品的重要依据,但如何避免被表面反馈误导?如何将反馈转化为可落地的迭代策略&#x…...

仿腾讯会议——视频发送接收
1、 添加音频模块 2、刷新图片,触发重绘 3、 等比例缩放视频帧 4、 新建视频对象 5、在中介者内定义发送视频帧的函数 6、完成发送视频的函数 7、 完成开启/关闭视频 8、绑定视频的信号槽函数 9、 完成开启/关闭视频 10、 完成发送视频 11、 完成刷新图片显示 12、完…...

从3.7V/5V到7.4V,FP6291在应急供电智能门锁中的应用
在智能家居蓬勃发展的当下,智能门锁以其便捷、安全的特性,成为现代家庭安防的重要组成部分。在智能门锁电量耗尽的情况下,应急电源外接移动电源(USB5V输入) FP6291升压到7.4V供电可应急开锁。增强用户在锁具的安全性、…...
java后端-海外登录(谷歌/FaceBook)
前言 由于最近公司的项目要在海外运行,因此需要对接海外的登录,目前就是谷歌和facebook两种,后面支付也是需要的,后续再进行书写 谷歌登录 这个相对比较容易,而且只提供给安卓即可,废话就不多说了,直接贴解决方案 引入maven依赖 <dependency> <groupId>com.go…...

【人工智障生成日记1】从零开始训练本地小语言模型
🎯 从零开始训练本地小语言模型:MiniGPT TinyStories(4090Ti) 🧭 项目背景 本项目旨在以学习为目的,从头构建一个完整的本地语言模型训练管线。目标是: ✅ 不依赖外部云计算✅ 完全本地运行…...

Selenium-Java版(frame切换/窗口切换)
frame切换/窗口切换 前言 切换到frame 原因 解决 切换回原来的主html 切换到新的窗口 问题 解决 回到原窗口 法一 法二 示例 前言 参考教程:Python Selenium Web自动化 2024版 - 自动化测试 爬虫_哔哩哔哩_bilibili 上期文章:Sel…...

一文深度解析:Pump 与 PumpSwap 的协议机制与技术差异
在 Solana 链上,Pump.fun 和其延伸产品 PumpSwap 构成了 meme coin 发行与流通的两大核心场景。从初期的游戏化发行模型,到后续的自动迁移与交易市场,Pump 系列协议正在推动 meme coin 从“爆发性投机”走向“协议化运营”。本文将从底层逻辑…...

星云智控v1.0.0产品发布会圆满举行:以创新技术重构物联网监控新生态
星云智控v1.0.0产品发布会圆满举行:以创新技术重构物联网监控新生态 2024年5月15日,成都双流蛟龙社区党群服务中心迎来了一场备受业界瞩目的发布会——优雅草科技旗下”星云智控v1.0.0”物联网AI智控系统正式发布。本次发布会吸引了包括沃尔沃集团、新希…...

SpringBoot(一)--- Maven基础
目录 前言 一、初始Maven 1.依赖管理 2.项目构建 3.统一项目结构 二、IDEA集成Maven 1.Maven安装 2.创建Maven项目 2.1全局设置 2.2 创建SpringBoot项目 2.3 常见问题 三、单元测试 1.JUnit入门 2.断言 前言 Maven 是一款用于管理和构建Java项目的工具ÿ…...

基于FPGA控制电容阵列与最小反射算法的差分探头优化设计
在现代高速数字系统测试中,差分探头的信号完整性直接影响测量精度。传统探头存在阻抗失配导致的信号反射问题,本文提出一种通过FPGA动态控制电容阵列,结合最小反射算法的优化方案,可实时调整探头等效容抗,将信号反射损…...

kakfa 基本了解
部署结构 Kafka 使用zookeeper来协商和同步,但是kafka 从版本3.5正式开始deprecate zookeeper, 同时推荐使用自带的 kraft. 而从4.0 开始则不再支持 zookeeper。 所以 kafka 是有control plane 和 data plane 的。 data plane 就是broker,control plane…...
基于Browser Use + Playwright 实现AI Agent操作Web UI自动化
Browser Use是什么 Browser Use是一个开源项目官网:Browser Use - Enable AI to control your browser,专为大语言模型(LLM)设计的只能浏览器工具,能够让AI像人类一样自然的浏览和操作网页,支持多标签页管…...

Origin绘制多因子柱状点线图
多因子柱状点线图是一种结合柱状图和点线图的复合图表,常用于同时展示多个因子(变量)在不同分组下的分布和趋势变化。 适用场景: (1)比较多个因子在不同分组中的数值大小(柱状图)&a…...

Web漏洞扫描服务的特点与优势:守护数字时代的安全防线
在数字化浪潮中,Web应用程序的安全性已成为企业业务连续性和用户信任的核心要素。随着网络攻击手段的不断升级,Web漏洞扫描服务作为一种主动防御工具,逐渐成为企业安全体系的标配。本文将从特点与优势两方面,解析其价值与应用场景…...
iOS 直播技术及优化
iOS直播技术的实现和优化涉及多个技术环节,需结合协议选择、编解码方案、播放器技术及性能调优等多方面。 一、核心技术实现 协议选择与传输优化 HLS(HTTP Live Streaming):苹果官方推荐,基于HTTP分片传输,…...

抛弃传统P2P技术,EasyRTC音视频基于WebRTC打造教育/会议/远程巡检等场景实时通信解决方案
一、方案背景 随着网络通信发展,实时音视频需求激增。传统服务器中转方式延迟高、资源消耗大,WebP2P技术由此兴起。EasyRTC作为高性能实时通信平台,集成WebP2P技术,实现低延迟、高效率音视频通信,广泛应用于教育、医疗…...

俄罗斯军总参情报局APT28组织瞄准援乌后勤供应链发起全球网络攻击
2025年5月,由美国、英国、欧盟和北约网络安全与情报机构联合发布的最新网络安全公告披露,俄罗斯军总参情报局(GRU)第85特别服务中心第26165部队(又称APT28、Fancy Bear、Forest Blizzard和BlueDelta)正持续…...

杰发科技AC7801——PWM获取固定脉冲个数
测试通道6 在初始化时候打开通道中断 void PWM1_GenerateFrequency(void) {PWM_CombineChConfig combineChConfig[1]; //组合模式相关结构体PWM_IndependentChConfig independentChConfig[2];//独立模式相关结构体PWM_ModulationConfigType pwmConfig; //PWM模式相关结构体PWM…...

MacBookPro上macOS安装第三方应用报错解决方案:遇到:“无法打开“XXX”,因为无法确定(验证)开发者身份?怎么解决
MacBook Pro 上 macOS 安装第三方应用报错解决方案 —— 彻底搞定「无法打开“XXX”,因为无法确定开发者身份」 适用系统:macOS Catalina 10.15 ~ macOS Sonoma 14.x 适用机型:Intel / Apple Silicon 全系 MacBook Pro 文章目录 **MacBook P…...
MVC和MVVM架构的区别
MVC和MVVM都是前端开发中常用的设计模式,都是为了解决前端开发中的复杂性而设计的,而MVVM模式则是一种基于MVC模式的新模式。 MVC(Model-View-Controller)的三个核心部分:模型、视图、控制器相较于MVVM(Model-View-ViewModel)的三个核心部分…...