当前位置: 首页 > news >正文

深入浅出横向联邦学习、纵向联邦学习、联邦迁移学习

深入浅出解析横向联邦学习(Horizontal Federated Learning)、纵向联邦学习(Vertical Federated Learning)和联邦迁移学习(Federated Transfer Learning)

有多个机构(比如几家不同的银行,或者几家医院)都拥有一些数据,他们希望联合起来训练一个更强大的机器学习模型,但出于隐私保护或法规要求,他们不能直接把数据共享出来。联邦学习就是为了解决这个问题而提出的。它的核心思想是“数据不动模型动”,即数据保留在本地,参与方共同训练模型。

在这个大框架下,根据数据分布的不同,主要可以分为横向联邦学习和纵向联邦学习。而联邦迁移学习则是在此基础上,解决数据特征或样本不足的问题。

横向联邦学习 (Horizontal Federated Learning, HFL)

  • 核心特点:特征相似,样本不同。
    • 打个比方: 想象一下,有几所不同地区的小学,他们都想联合训练一个更好的学生成绩预测模型。这些学校记录的学生信息(特征)是相似的,比如都有学生的年龄、性别、各科成绩、出勤率等。但是,每个学校的学生群体(样本)是完全不同的。
  • 数据分布: 参与方的数据库结构(特征)相同,但数据记录(样本)不同。就像将数据表格水平切分,每个参与方持有一部分行。
  • 如何工作:
    1. 初始化: 一个中心服务器(协调者)初始化一个全局模型,并将模型分发给各个参与方。
    2. 本地训练: 每个参与方利用本地数据训练这个模型,得到各自的模型更新(比如梯度或模型参数)。
    3. 模型聚合: 参与方将加密后的模型更新发送给中心服务器。服务器对收集到的模型更新进行聚合(例如,通过加权平均,如经典的FedAvg算法),形成一个新的、更优的全局模型。
    4. 模型更新: 服务器将聚合后的新模型再分发给各个参与方。
    5. 迭代: 重复步骤2-4,直到模型收敛或达到预设的训练轮次。
  • 典型应用场景:
    • 智能手机输入法预测: 不同用户手机上的输入习惯数据特征相似(都是文字序列),但具体输入的内容(样本)不同。Google的Gboard输入法就是横向联邦学习的典型应用。
    • 多家分行的零售业务预测: 不同分行的客户特征相似,但客户群体不同。
  • 优势: 算法设计相对灵活,可扩展性强。
  • 挑战: 需要处理数据异构性(不同参与方数据分布可能不完全一致)、设备异构性(不同设备计算能力和网络状况不同)以及通信效率问题。

纵向联邦学习 (Vertical Federated Learning, VFL)

  • 核心特点:样本重叠,特征不同。
    • 打个比方: 想象一下,在同一个城市,有一家银行和一家电商平台,它们都想针对同一批用户(样本重叠)联合训练一个更精准的信用风险评估模型。银行拥有用户的收支行为、信用评级等特征,而电商平台拥有这些用户的购买历史、浏览行为等特征。它们的用户群体有交集,但掌握的数据维度(特征)不同。
  • 数据分布: 参与方的数据库记录(样本)有交集,但数据结构(特征)不同。就像将数据表格垂直切分,每个参与方持有一部分列。
  • 如何工作:
    1. 数据对齐: 首先,在加密状态下找出参与方之间共有的用户样本。这通常通过隐私集合求交(Private Set Intersection, PSI)等技术实现。
    2. 协同训练:
      • 假设有两个参与方A和B,以及一个可选的协调者C(在两方场景下,协调者可能不是必需的)。
      • 在训练过程中,模型被拆分到不同的参与方。每一方基于自己拥有的特征计算中间结果(比如梯度的一部分)。
      • 这些中间结果在加密状态下进行交换和聚合,以计算总的梯度和损失,从而更新模型参数。
      • 这个过程需要复杂的加密技术(如同态加密、安全多方计算)来保护各方数据的隐私,确保任何一方都无法获取对方的原始特征数据,也无法推断出对方的中间计算结果。
    3. 模型共享: 最终,各方都能获得一个更强大的联合模型的部分,或者是一个完整的模型(取决于具体实现)。
  • 典型应用场景:
    • 跨机构金融风控: 银行和保险公司针对共同客户进行风险评估。
    • 智慧医疗: 不同医院拥有同一病人的不同类型的医疗数据(如一家有影像数据,另一家有基因数据)。
    • 精准营销: 零售商和广告平台针对共同用户进行用户画像和广告推荐。
  • 优势: 能够利用不同来源的互补特征,构建更全面的模型。
  • 挑战: 系统复杂度较高,需要解决数据对齐、加密计算、多方协调等问题。对参与方的数量和网络通信要求也较高。

联邦迁移学习 (Federated Transfer Learning, FTL)

  • 核心特点:特征和样本都可能只有少量重叠,甚至没有重叠,但需要利用已有知识。
    • 打个比方: 想象一下,一家位于A国的银行已经基于其本地数据训练了一个还不错的信用评分模型。现在,一家位于B国的新银行,其客户数据(样本)和A国银行完全不同,甚至记录的客户信息(特征)也不完全一样(比如由于法规不同,可收集的特征有差异)。B国银行希望利用A国银行已有的模型知识,在保护数据隐私的前提下,快速训练一个适用于B国本地情况的信用评分模型。
  • 数据分布: 参与方之间的数据特征和样本ID重叠都很少,或者一个参与方有丰富的标签数据,而另一个参与方数据虽多但标签不足。
  • 如何工作:
    • FTL 将联邦学习和迁移学习结合起来。迁移学习的核心思想是将一个领域(源领域)学习到的知识应用到另一个相关但不同的领域(目标领域)。
    • 在FTL中,通常会利用一个在源数据上预训练好的模型(或其一部分知识),在联邦学习的框架下,帮助目标领域的参与方训练模型,即使目标领域数据量较小或标签稀疏。
    • 例如,可以将源领域模型的参数作为目标领域模型的初始化,或者在联邦学习过程中,共享和迁移一部分能够泛化的特征表示。
    • 为了保护隐私,FTL 同样需要加密技术(如同态加密)来保护模型参数或中间结果的交换。
  • 典型应用场景:
    • 解决冷启动问题: 新业务或新地区缺乏足够数据时,可以借助其他相关业务或地区的模型知识。
    • 利用无标签数据: 当一方有大量有标签数据,另一方只有无标签数据时,可以通过FTL进行联合建模。
    • 跨领域知识迁移: 例如,将在图像识别领域学到的知识迁移到医疗影像分析。
  • 与HFL/VFL的关系:
    • FTL 可以看作是HFL或VFL在特定场景下的扩展。当HFL或VFL的参与方面临数据不足、特征不完全匹配或需要利用外部知识时,就可以引入迁移学习的机制,演变成FTL。
    • 例如,在纵向联邦学习的场景中,如果一方的特征非常稀疏,可以借助另一方更丰富的特征信息进行知识迁移。
  • 优势: 能够克服数据或标签不足的限制,提升模型在小样本或新领域的学习效果。
  • 挑战: 需要找到合适的迁移策略,确保迁移的知识是有效的,并避免负迁移(即损害模型性能)。隐私保护机制的设计也更为复杂。

总结与比较:

特性横向联邦学习 (HFL)纵向联邦学习 (VFL)联邦迁移学习 (FTL)
数据划分特征相同,样本不同 (按行划分)样本相同,特征不同 (按列划分)特征和样本可能都只有少量或无重叠
核心思想聚合不同样本上的模型更新聚合不同特征下的模型信息,利用样本交集在联邦框架下进行知识迁移,解决数据或标签不足问题
隐私技术加密模型更新 (如梯度)隐私集合求交,加密中间计算结果 (如同态加密, MPC)加密技术 (如同态加密等),迁移知识表示
协调者通常需要中心服务器进行模型聚合可能需要协调者,两方场景下可去中心化取决于具体的HFL或VFL基础架构,可能需要协调者
主要挑战数据异构性,通信开销,设备异构性数据对齐,加密计算复杂度,多方协调找到有效的迁移策略,避免负迁移,复杂的隐私保护机制
适用场景用户群体不同但业务特征相似的场景 (如不同银行的同类业务)用户群体有交集但各方掌握用户不同维度特征的场景 (如银行与电商合作)数据稀疏、标签不足、需要跨领域知识共享的场景
  • 横向联邦学习: 大家做的事情一样(特征相似),但服务的人不一样(样本不同)。
  • 纵向联邦学习: 大家服务的人有交集(样本重叠),但每个人做的事情不一样(特征不同)。
  • 联邦迁移学习: 我这里数据不够或者不完全对口,能不能借鉴一下别人(或别的场景)已经学到的经验,同时大家的数据都不泄露。

好的,下面我将为横向联邦学习(HFL)、纵向联邦学习(VFL)和联邦迁移学习(FTL)分别提供 PyTorch 风格的伪代码案例。这些案例旨在帮助初学者理解核心思想,会简化一些复杂的加密和通信细节。

代码案例

  • 伪代码: 这不是可以直接运行的完整代码,而是为了阐释核心逻辑。旨在帮助初学者理解核心思想,简化了一些复杂的加密和通信细节。实际应用要复杂得多,尤其是在安全和效率方面。
  • 简化处理: 实际的联邦学习系统会涉及更复杂的通信协议、加密算法(如安全多方计算MPC、同态加密HE)、梯度压缩、参与方管理等。这里我们主要关注数据和模型的交互流程。
  • PyTorch 风格: 代码会采用 PyTorch 的常用模式,如torch.nn.Moduletorch.optim等。

1. 横向联邦学习 (Horizontal Federated Learning - HFL) 伪代码

场景: 多个客户端(如手机、医院)拥有结构相同但样本不同的数据,共同训练一个模型。

import torch
import torch.nn as nn
import torch.optim as optim
from typing import List, Tuple# --- 定义全局模型 (所有客户端和服务器使用相同的模型结构) ---
class SimpleModel(nn.Module):def __init__(self):super(SimpleModel, self).__init__()self.fc = nn.Linear(10, 1) # 假设输入特征维度为10,输出为1def forward(self, x):return self.fc(x)# --- 模拟客户端 ---
class HFLClient:def __init__(self, client_id: int, local_data: List[Tuple[torch.Tensor, torch.Tensor]], learning_rate: float):self.client_id = client_idself.local_data = local_data # (特征, 标签) 列表self.model = SimpleModel() # 每个客户端拥有一个本地模型副本self.optimizer = optim.SGD(self.model.parameters(), lr=learning_rate)self.criterion = nn.MSELoss() # 假设是回归任务def set_global_model_weights(self, global_weights):"""从服务器同步全局模型权重"""self.model.load_state_dict(global_weights)def local_train(self, epochs: int):"""在本地数据上训练模型"""self.model.train()for epoch in range(epochs):for features, labels in self.local_data:self.optimizer.zero_grad()outputs = self.model(features)loss = self.criterion(outputs, labels)loss.backward()self.optimizer.step()print(f"客户端 {self.client_id} 本地训练完成.")return self.model.state_dict() # 返回训练后的本地模型权重# --- 模拟服务器 ---
class HFLServer:def __init__(self):self.global_model = SimpleModel()def aggregate_models(self, client_model_weights: List[dict], client_data_sizes: List[int]) -> dict:"""聚合来自客户端的模型权重 (例如,使用联邦平均 FedAvg)client_model_weights: 列表,每个元素是一个客户端的模型 state_dictclient_data_sizes: 列表,每个元素是对应客户端的数据量大小,用于加权平均"""total_data_size = sum(client_data_sizes)aggregated_weights = self.global_model.state_dict() # 初始化为当前全局模型# 清零聚合权重for key in aggregated_weights.keys():aggregated_weights[key] = torch.zeros_like(aggregated_weights[key])# 加权平均for i, weights in enumerate(client_model_weights):weight_factor = client_data_sizes[i] / total_data_sizefor key in weights.keys():aggregated_weights[key] += weights[key] * weight_factorself.global_model.load_state_dict(aggregated_weights)print("服务器:模型聚合完成。")return aggregated_weightsdef get_global_model_weights(self) -> dict:return self.global_model.state_dict()# --- HFL 伪代码执行流程 ---
if __name__ == "__main__":# 0. 初始化NUM_CLIENTS = 3LOCAL_EPOCHS = 5NUM_ROUNDS = 10 # 联邦学习的轮次LEARNING_RATE = 0.01# 1. 模拟数据和客户端# 假设每个客户端有100个样本,每个样本10个特征clients_data = [[(torch.randn(1, 10), torch.randn(1, 1)) for _ in range(100)] for _ in range(NUM_CLIENTS)]client_data_sizes = [len(data) for data in clients_data]clients = [HFLClient(client_id=i, local_data=clients_data[i], learning_rate=LEARNING_RATE) for i in range(NUM_CLIENTS)]server = HFLServer()# 2. 联邦学习迭代for round_num in range(NUM_ROUNDS):print(f"\n--- 联邦学习轮次 {round_num + 1}/{NUM_ROUNDS} ---")current_global_weights = server.get_global_model_weights()local_model_weights_list = []# 2.1. 分发模型并进行本地训练for client in clients:client.set_global_model_weights(current_global_weights) # 同步全局模型local_weights = client.local_train(LOCAL_EPOCHS)local_model_weights_list.append(local_weights)# 2.2. 聚合模型new_global_weights = server.aggregate_models(local_model_weights_list, client_data_sizes)# new_global_weights 会在下一轮开始时分发print("\n--- 横向联邦学习完成 ---")final_model = server.global_model# 可以在这里评估 final_model 的性能

2. 纵向联邦学习 (Vertical Federated Learning - VFL) 伪代码

场景: 两个或多个参与方拥有相同样本ID的不同特征。他们需要协同训练一个模型。

简化假设:

  • 我们假设只有两个参与方 A 和 B。
  • 模型结构被逻辑上划分为两部分,一部分处理A的特征,另一部分处理B的特征,然后结果结合起来预测。
  • 加密和安全计算被高度简化:实际VFL中,梯度和中间结果的交换需要同态加密或安全多方计算等技术保护。这里我们仅展示概念。
  • 通常会有一个协调者(或其中一方扮演协调者角色)来同步和聚合加密的梯度/损失。
import torch
import torch.nn as nn
import torch.optim as optim
from typing import Dict, Tuple# --- 假设的整体模型结构 (逻辑上) ---
# Input_A (来自参与方A的特征) -> Model_Part_A -> Intermediate_A ---
#                                                               | --- (结合) ---> Prediction_Layer -> Output
# Input_B (来自参与方B的特征) -> Model_Part_B -> Intermediate_B ---# --- 参与方 A 的模型部分 ---
class ModelPartA(nn.Module):def __init__(self, input_dim_a: int, output_dim_a: int):super(ModelPartA, self).__init__()self.fc_a = nn.Linear(input_dim_a, output_dim_a)# self.output_dim_a = output_dim_a # 中间表示的维度def forward(self, x_a: torch.Tensor) -> torch.Tensor:return torch.relu(self.fc_a(x_a)) # 假设的中间表示# --- 参与方 B 的模型部分 ---
class ModelPartB(nn.Module):def __init__(self, input_dim_b: int, output_dim_b: int):super(ModelPartB, self).__init__()self.fc_b = nn.Linear(input_dim_b, output_dim_b)# self.output_dim_b = output_dim_bdef forward(self, x_b: torch.Tensor) -> torch.Tensor:return torch.relu(self.fc_b(x_b))# --- 顶层模型 (通常由协调者或其中一方持有,用于结合和预测) ---
class TopModel(nn.Module):def __init__(self, intermediate_dim_a: int, intermediate_dim_b: int, output_dim: int):super(TopModel, self).__init__()self.fc_top = nn.Linear(intermediate_dim_a + intermediate_dim_b, output_dim)def forward(self, intermediate_a: torch.Tensor, intermediate_b: torch.Tensor) -> torch.Tensor:combined_intermediate = torch.cat((intermediate_a, intermediate_b), dim=1)return self.fc_top(combined_intermediate)# --- 模拟参与方 A ---
class VFLPartyA:def __init__(self, data_a: Dict[str, torch.Tensor], input_dim_a: int, output_dim_a: int, learning_rate: float):self.data_a = data_a # 字典,key为样本ID,value为A的特征self.model_part_a = ModelPartA(input_dim_a, output_dim_a)self.optimizer_a = optim.SGD(self.model_part_a.parameters(), lr=learning_rate)# 在实际VFL中,A通常不会直接看到标签和计算完整的损失def forward_a(self, sample_ids: List[str]) -> Dict[str, torch.Tensor]:"""计算A部分的中间输出"""self.model_part_a.train() # 或者 eval() 取决于阶段intermediate_outputs_a = {}for sample_id in sample_ids:features_a = self.data_a[sample_id]intermediate_outputs_a[sample_id] = self.model_part_a(features_a)return intermediate_outputs_a # {sample_id: intermediate_tensor_a}def backward_a(self, gradients_on_intermediate_a: Dict[str, torch.Tensor], intermediate_outputs_a_for_grad: Dict[str, torch.Tensor]):"""根据从协调者(或B)处获得的关于A中间输出的梯度,来更新A的模型部分。gradients_on_intermediate_a: {sample_id: grad_tensor}intermediate_outputs_a_for_grad: {sample_id: intermediate_tensor_a} - 这些是前向传播时产生的输出,需要它们来反向传播"""self.optimizer_a.zero_grad()total_loss_surrogate = torch.tensor(0.0, requires_grad=True) # 代理损失for sample_id in gradients_on_intermediate_a.keys():# 实际中,这里需要复杂的加密和安全计算# 简化:直接使用梯度和中间输出进行反向传播intermediate_a = intermediate_outputs_a_for_grad[sample_id]grad = gradients_on_intermediate_a[sample_id]# .backward() 需要一个标量,或者对每个输出元素提供梯度# 这里我们假设 grad 是对应 intermediate_a 的梯度intermediate_a.backward(gradient=grad)self.optimizer_a.step()print("参与方 A:模型部分已更新。")# --- 模拟参与方 B (通常持有标签,并与协调者一起计算损失和梯度) ---
class VFLPartyB_and_Coordinator: # 简化,将B和协调者功能合并def __init__(self, data_b: Dict[str, torch.Tensor], labels: Dict[str, torch.Tensor],input_dim_b: int, output_dim_b: int,intermediate_dim_a: int, top_model_output_dim: int, learning_rate: float):self.data_b = data_b # key为样本ID,value为B的特征self.labels = labels   # key为样本ID,value为标签self.model_part_b = ModelPartB(input_dim_b, output_dim_b)self.top_model = TopModel(intermediate_dim_a, output_dim_b, top_model_output_dim)self.optimizer_b = optim.SGD(self.model_part_b.parameters(), lr=learning_rate)self.optimizer_top = optim.SGD(self.top_model.parameters(), lr=learning_rate)self.criterion = nn.MSELoss() # 假设回归任务def forward_b_and_top(self, intermediate_outputs_a: Dict[str, torch.Tensor], sample_ids: List[str]) \-> Tuple[Dict[str, torch.Tensor], Dict[str, torch.Tensor], Dict[str, torch.Tensor]]:"""计算B部分的中间输出,并结合A的中间输出通过顶层模型得到预测"""self.model_part_b.train()self.top_model.train()predictions = {}intermediate_outputs_b = {}final_outputs_for_loss = {}for sample_id in sample_ids:features_b = self.data_b[sample_id]inter_a = intermediate_outputs_a[sample_id]inter_b = self.model_part_b(features_b)intermediate_outputs_b[sample_id] = inter_b# detach inter_a because Party B should not compute gradients for Party A's model directly# Gradients for inter_a will be computed and sent back securely.final_pred = self.top_model(inter_a.detach().requires_grad_(), inter_b)predictions[sample_id] = final_predfinal_outputs_for_loss[sample_id] = final_predreturn predictions, intermediate_outputs_b, final_outputs_for_lossdef compute_loss_and_gradients(self, predictions: Dict[str, torch.Tensor], sample_ids: List[str]) \-> Tuple[torch.Tensor, Dict[str, torch.Tensor], Dict[str, torch.Tensor]]:"""计算损失,并为B和顶层模型计算梯度,同时计算传递给A的(加密)梯度"""self.optimizer_b.zero_grad()self.optimizer_top.zero_grad()total_loss = torch.tensor(0.0)# 存储传递给A的梯度 (对A中间输出的梯度)gradients_for_a_intermediate = {}# 存储传递给B的梯度 (对B中间输出的梯度)gradients_for_b_intermediate = {} # 实际上会直接用于B的优化器batch_loss = torch.tensor(0.0, requires_grad=True)intermediate_a_list_for_grad = []intermediate_b_list_for_grad = [] # for Party B's model_part_b update# 在VFL中,通常是逐样本或小批量处理,并安全地聚合梯度# 这里简化为在一个循环中累积损失processed_predictions = []processed_labels = []for sample_id in sample_ids:pred = predictions[sample_id] # This tensor was (inter_a.detach().requires_grad_(), inter_b) -> top_modellabel = self.labels[sample_id]processed_predictions.append(pred)processed_labels.append(label)# Stack for batch loss computationif not processed_predictions:return torch.tensor(0.0), {}, {}batch_predictions_tensor = torch.cat(processed_predictions)batch_labels_tensor = torch.cat(processed_labels)loss = self.criterion(batch_predictions_tensor, batch_labels_tensor)loss.backward() # 这会计算顶层模型参数的梯度,以及 inter_a.grad 和 inter_b.grad# 提取梯度# 注意:实际中这里的梯度交换需要加密!# .grad 属性是在执行 backward() 后填充的# 需要追溯到创建这些tensor的地方idx = 0for sample_id in sample_ids:# This part is tricky in pseudocode as requires_grad_() was on a detached tensor.# For simplicity, assume we can get grads w.r.t. inputs of top_model# A more accurate way would be to re-run parts of the forward pass or use hooks.# Conceptual: Get gradient w.r.t. inter_a that went into top_model# This is a simplification. Real VFL uses secure protocols.# We'll simulate by getting the .grad of the detached inter_a if PyTorch allows,# or more practically, by re-evaluating a small graph or using hooks.# For pseudocode, let's assume Party B can securely compute and send this.# Suppose top_model.fc_top.weight has shape [output_dim, intermediate_dim_a + intermediate_dim_b]# Grad w.r.t. inter_a would be related to loss's grad w.r.t. top_model's output,# then backpropagated through fc_top.# Simplification: We assume these gradients are somehow securely computed and made available.# Let's imagine `predictions[sample_id].grad_fn` allows access to input grads.# Or, more realistically, Party B calculates dL/d(inter_a) and dL/d(inter_b)# and sends dL/d(inter_a) (encrypted) to Party A.# Conceptual placeholder for secure gradient computation for A:# grad_for_a = compute_encrypted_gradient_for_A(loss_details, inter_a_used_in_top_model)# For pseudocode, let's assume we can derive it:# This is highly abstract:grad_for_a_placeholder = torch.randn_like(intermediate_outputs_a[sample_id]) # Placeholder!gradients_for_a_intermediate[sample_id] = grad_for_a_placeholderidx +=1self.optimizer_b.step()self.optimizer_top.step()print(f"参与方 B/协调者:损失计算完毕,模型B和Top已更新。梯度已准备好发往A。损失: {loss.item()}")return loss, gradients_for_a_intermediate# --- VFL 伪代码执行流程 ---
if __name__ == "__main__":# 0. 定义维度INPUT_DIM_A = 5INPUT_DIM_B = 7INTERMEDIATE_DIM_A = 10INTERMEDIATE_DIM_B = 12TOP_MODEL_OUTPUT_DIM = 1LEARNING_RATE = 0.01NUM_SAMPLES = 50NUM_ROUNDS = 10# 1. 模拟数据 (样本ID对齐)sample_ids = [f"sample_{i}" for i in range(NUM_SAMPLES)]data_a = {sid: torch.randn(1, INPUT_DIM_A) for sid in sample_ids}data_b = {sid: torch.randn(1, INPUT_DIM_B) for sid in sample_ids}labels = {sid: torch.randn(1, TOP_MODEL_OUTPUT_DIM) for sid in sample_ids}# 2. 初始化参与方party_a = VFLPartyA(data_a, INPUT_DIM_A, INTERMEDIATE_DIM_A, LEARNING_RATE)party_b_and_coordinator = VFLPartyB_and_Coordinator(data_b, labels, INPUT_DIM_B, INTERMEDIATE_DIM_B,INTERMEDIATE_DIM_A, TOP_MODEL_OUTPUT_DIM, LEARNING_RATE)# 3. VFL 迭代训练for round_num in range(NUM_ROUNDS):print(f"\n--- 纵向联邦学习轮次 {round_num + 1}/{NUM_ROUNDS} ---")current_sample_ids_batch = sample_ids # 在实际中可能是小批量# 3.1 参与方A进行前向传播intermediate_a_outputs = party_a.forward_a(current_sample_ids_batch)# 实际中: intermediate_a_outputs 会被加密发送给 B/协调者# 3.2 参与方B/协调者进行前向传播,计算损失和梯度# Party B receives (encrypted) intermediate_a_outputspredictions, intermediate_b_outputs, final_outputs_for_loss_dict = \party_b_and_coordinator.forward_b_and_top(intermediate_a_outputs, current_sample_ids_batch)# Party B/Coordinator computes loss and gradients for its parts and for A's intermediate output# The gradients for A's intermediate output (gradients_for_a) would be encrypted.loss, gradients_for_a = party_b_and_coordinator.compute_loss_and_gradients(final_outputs_for_loss_dict, current_sample_ids_batch)# 3.3 参与方A进行反向传播# Party A receives (encrypted) gradients_for_a and its own intermediate_a_outputs used in that forward passparty_a.backward_a(gradients_for_a, intermediate_a_outputs)# Note: intermediate_a_outputs are needed again for the backward pass in PyTorch# if they were not retained with requires_grad=True during Party A's forward pass.# For simplicity, we pass them again.print("\n--- 纵向联邦学习完成 ---")# 最终模型由 party_a.model_part_a, party_b_and_coordinator.model_part_b,# 和 party_b_and_coordinator.top_model 共同组成。

VFL 伪代码的关键点说明:

  • 数据对齐: sample_ids 的使用强调了纵向联邦中样本是对齐的。
  • 模型拆分: ModelPartA, ModelPartB, TopModel 体现了模型被逻辑拆分到不同参与方。
  • 中间结果交换: intermediate_a_outputs 从A传递到B(协调者)。
  • 梯度交换: gradients_for_a 从B(协调者)传递回A。
  • 隐私保护(高度简化): 伪代码中没有实现加密,但实际操作中,所有交换的中间结果和梯度都必须加密。gradients_for_a_placeholder 明确指出了这是一个需要安全计算的占位符。.detach().requires_grad_() 是一个尝试在概念上分离计算图但仍允许后续计算梯度的技巧,但实际的VFL梯度传递更为复杂。

3. 联邦迁移学习 (Federated Transfer Learning - FTL) 伪代码

场景: 存在一个预训练好的模型(源领域知识)。多个客户端(目标领域)拥有少量或特征不完全匹配的数据,他们希望利用预训练模型,在联邦学习的框架下进行微调。

简化假设:

  • 我们采用类似横向联邦学习的架构。
  • 源模型和目标模型的结构相似,或者目标模型使用了源模型的部分层。
  • 迁移方式:微调预训练模型。
import torch
import torch.nn as nn
import torch.optim as optim
from typing import List, Tuple# --- 定义基础模型结构 (源模型和目标模型可以共享此结构或部分结构) ---
class BaseModel(nn.Module):def __init__(self, input_dim: int, hidden_dim: int, output_dim: int):super(BaseModel, self).__init__()self.feature_extractor = nn.Sequential(nn.Linear(input_dim, hidden_dim),nn.ReLU(),# nn.Linear(hidden_dim, hidden_dim), # 更多层# nn.ReLU())self.classifier = nn.Linear(hidden_dim, output_dim)def forward(self, x):features = self.feature_extractor(x)output = self.classifier(features)return output# --- 模拟FTL客户端 ---
class FTLClient:def __init__(self, client_id: int, local_data: List[Tuple[torch.Tensor, torch.Tensor]],base_model_weights: dict, learning_rate: float,input_dim: int, hidden_dim: int, output_dim: int):self.client_id = client_idself.local_data = local_data # (特征, 标签)self.model = BaseModel(input_dim, hidden_dim, output_dim)# 1. 加载预训练权重 (迁移学习的关键步骤)self.model.load_state_dict(base_model_weights, strict=False) # strict=False 允许部分加载print(f"客户端 {self.client_id}: 已加载预训练模型权重。")# 2. (可选) 冻结部分层 - 例如,只微调分类器# for param in self.model.feature_extractor.parameters():#     param.requires_grad = False# print(f"客户端 {self.client_id}: 特征提取层已冻结。")self.optimizer = optim.SGD(filter(lambda p: p.requires_grad, self.model.parameters()), lr=learning_rate)self.criterion = nn.CrossEntropyLoss() # 假设是分类任务def set_global_model_weights(self, global_weights: dict):"""从服务器同步全局模型权重 (在联邦微调过程中)"""self.model.load_state_dict(global_weights) # 严格加载,因为结构应该匹配def local_finetune(self, epochs: int) -> dict:"""在本地数据上微调模型"""self.model.train()for epoch in range(epochs):for features, labels in self.local_data:self.optimizer.zero_grad()outputs = self.model(features)loss = self.criterion(outputs, labels.long().squeeze()) # CrossEntropyLoss期望long类型的标签loss.backward()self.optimizer.step()print(f"客户端 {self.client_id} 本地微调完成.")return self.model.state_dict() # 返回微调后的本地模型权重# --- 模拟FTL服务器 (与HFL服务器类似,但初始模型是预训练的) ---
class FTLServer:def __init__(self, pretrained_global_model_weights: dict):# 服务器持有的全局模型,初始状态为预训练模型self.global_model = BaseModel(INPUT_DIM, HIDDEN_DIM, OUTPUT_DIM) # 确保维度一致self.global_model.load_state_dict(pretrained_global_model_weights)print("服务器:已初始化全局模型为预训练模型。")def aggregate_models(self, client_model_weights: List[dict], client_data_sizes: List[int]) -> dict:"""聚合来自客户端的模型权重 (FedAvg)"""total_data_size = sum(client_data_sizes)aggregated_weights = self.global_model.state_dict()for key in aggregated_weights.keys():# 只聚合那些参与训练的参数 (例如,如果部分层被冻结,它们不应改变)# 但通常在联邦平均中,我们还是聚合所有参数,本地冻结是客户端策略aggregated_weights[key] = torch.zeros_like(aggregated_weights[key])for i, weights in enumerate(client_model_weights):weight_factor = client_data_sizes[i] / total_data_sizefor key in weights.keys():if key in aggregated_weights: # 确保key存在aggregated_weights[key] += weights[key] * weight_factorself.global_model.load_state_dict(aggregated_weights)print("服务器:模型聚合完成。")return aggregated_weightsdef get_global_model_weights(self) -> dict:return self.global_model.state_dict()# --- FTL 伪代码执行流程 ---
if __name__ == "__main__":# 0. 定义参数和模型维度INPUT_DIM = 20HIDDEN_DIM = 50OUTPUT_DIM = 5 # 假设目标任务有5个类别NUM_CLIENTS = 2LOCAL_EPOCHS_FTL = 3NUM_ROUNDS_FTL = 5LEARNING_RATE_FTL = 0.001# 1. 模拟一个预训练好的源模型 (通常在大的通用数据集上训练得到)# 假设这是我们从别处加载的预训练模型权重print("正在加载/模拟预训练模型...")source_model_for_pretraining = BaseModel(INPUT_DIM, HIDDEN_DIM, OUTPUT_DIM) # 结构可能与目标任务输出维度不同,或特征维度不同# 实际中,这里的权重是训练好的# 为了伪代码,我们只取其初始权重作为“预训练”# 或者,如果特征维度/输出维度不同,需要更复杂的迁移策略(如只迁移特征提取器)# 为简单起见,假设源和目标任务的BaseModel结构兼容进行权重加载pretrained_weights = source_model_for_pretraining.state_dict()print("预训练模型权重已准备好。")# 2. 模拟目标领域的客户端数据 (可能数据量较小)# 假设每个客户端有20个样本,每个样本特征维度为INPUT_DIMclients_target_data = [[(torch.randn(1, INPUT_DIM), torch.randint(0, OUTPUT_DIM, (1,))) for _ in range(20)]for _ in range(NUM_CLIENTS)]client_target_data_sizes = [len(data) for data in clients_target_data]# 3. 初始化服务器和客户端ftl_server = FTLServer(pretrained_global_model_weights=pretrained_weights)ftl_clients = [FTLClient(client_id=i,local_data=clients_target_data[i],base_model_weights=ftl_server.get_global_model_weights(), # 初始时,客户端也从服务器获取预训练模型learning_rate=LEARNING_RATE_FTL,input_dim=INPUT_DIM, hidden_dim=HIDDEN_DIM, output_dim=OUTPUT_DIM) for i in range(NUM_CLIENTS)]# 4. 联邦迁移学习迭代 (微调过程)for round_num in range(NUM_ROUNDS_FTL):print(f"\n--- 联邦迁移学习轮次 {round_num + 1}/{NUM_ROUNDS_FTL} ---")current_global_weights = ftl_server.get_global_model_weights()local_model_weights_list = []# 4.1 分发全局模型并进行本地微调for client in ftl_clients:client.set_global_model_weights(current_global_weights) # 同步聚合后的模型local_weights = client.local_finetune(LOCAL_EPOCHS_FTL)local_model_weights_list.append(local_weights)# 4.2 聚合模型new_global_weights = ftl_server.aggregate_models(local_model_weights_list, client_target_data_sizes)print("\n--- 联邦迁移学习完成 ---")final_ftl_model = ftl_server.global_model# 可以在这里评估 final_ftl_model 在目标任务上的性能

FTL 伪代码的关键点说明:

  • 预训练模型: pretrained_weights 代表了从源领域获取的知识。
  • 权重加载: 客户端在初始化时加载预训练权重 (self.model.load_state_dict(base_model_weights, strict=False))。strict=False 允许在源模型和目标模型结构不完全一致时加载匹配的部分(例如,只加载特征提取器)。
  • 本地微调: local_finetune 函数执行在本地小数据集上的训练。
  • 选择性冻结: 注释中提到了可以冻结预训练模型的部分层,只微调顶层,这是迁移学习中常用的技巧。
  • 联邦平均: 服务器端的聚合过程与HFL类似,但聚合的是微调后的模型。

相关文章:

深入浅出横向联邦学习、纵向联邦学习、联邦迁移学习

深入浅出解析横向联邦学习(Horizontal Federated Learning)、纵向联邦学习(Vertical Federated Learning)和联邦迁移学习(Federated Transfer Learning) 有多个机构(比如几家不同的银行&#x…...

vue复杂数据类型多层嵌套的监听

vue复杂数据类型多层嵌套的监听 本来看前辈的做法是watch的嵌套,遇到这种复杂的数据结构还是不多,分享一下前辈的做法 let stopChildWatchList [] // 用于存放每个子监听器watch(() > data,(val) > {// 清除旧监听stopChildWatchList.forEach(…...

windows系统中下载好node无法使用npm

原因是 Windows PowerShell禁用导致的npm无法正常使用 解决方法管理员打开Windows PowerShell 输入Set-ExecutionPolicy -Scope CurrentUser RemoteSigned 按Y 确认就解决了...

使用 Docker 部署 React + Nginx 应用教程

目录 1. 创建react项目结构2. 创建 .dockerignore3. 创建 Dockerfile4. 创建 nginx.conf5. 构建和运行6. 常用命令 1. 创建react项目结构 2. 创建 .dockerignore # 依赖目录 node_modules npm-debug.log# 构建输出 dist build# 开发环境文件 .git .gitignore .env .env.local …...

顶层设计-IM系统架构

一、系统总体架构概览 即时通讯(IM)系统的核心目标,是让用户可以随时随地稳定地发送和接收消息。为了支撑成千上万用户同时在线交流,我们需要将整个系统划分成多个专职模块,每个模块只负责一件事情,彼此协同…...

Maven Deploy的依赖与引用方的依赖不同

提供的依赖:dependency:tree - com.alibaba.csp:sentinel-springboot-starter:jar:3.0.1-SNAPSHOT:compile [INFO] | - com.alibaba.csp:sentinel-datasource-nacos:jar:3.0.1:compile [INFO] | - com.alibaba.csp:sentinel-datasource-extension:jar:3.0.1:compil…...

如何让 Google 收录 Github Pages 个人博客

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ 如何确认自己的网站有没有被 google 收录 假设网址是:https://cyrus-studio.github.io/blog 搜索:site:https://cyrus-studio.github…...

物体雅克比、空间雅克比、解析雅克比、几何雅克比

在机器人学中,雅可比矩阵是连接广义坐标速度与末端执行器速度的关键工具。根据应用场景和参考系的不同,雅可比矩阵可分为物体雅可比(Body Jacobian)、空间雅可比(Space Jacobian)、解析雅可比(A…...

PCL PolygonMesh 与 TextureMesh 源码阅读与简单测试

Title: PCL PolygonMesh 与 TextureMesh 源码阅读与简单测试 文章目录 I . PolygonMesh1. PolygonMesh 结构体2. Vertices 结构体与点云索引3. 测试 PolygonMesh II. TextureMesh1. TextureMesh 结构体2. TexMaterial 结构体3. 纹理坐标与纹理坐标索引4. 测试 TextureMesh 以下…...

CSS面试题汇总

在前端开发领域,CSS 是一项不可或缺的技术。无论是页面布局、样式设计还是动画效果,CSS 都扮演着重要的角色。因此,在前端面试中,CSS 相关的知识点往往是面试官重点考察的内容。为了帮助大家更好地准备面试,本文汇总了…...

光谱相机的空间分辨率和时间分辨率

一、空间分辨率 ‌定义与参数‌ ‌概念‌:指单个像素对应实际地物的最小尺寸,常用地面采样距离(GSD,单位:米)或像素大小(单位:微米)表示。 ‌分类‌: 高空…...

【研0学习计划表】

前言 以下学习计划并不固定: 1.若当前阶段的学习任务学习结束,对下一阶段的学习计划进行适当调整,提前进入下一阶段学习任务。 若当前阶段学习任务未完成,则根据每一阶段的学习情况,进行学习总结,然后对下…...

还没用过智能文档编辑器吗?带有AI插件的ONLYOFFICE介绍

在当今激烈的数字化竞争中,文档处理效率直接影响企业的决策与响应速度。然而,许多办公平台仅支持基础流程,查阅、批注和修改仍需借助外部工具,增加了操作复杂性和沟通成本。本文将探讨如何在自己的网站、平台、系统或者服务中集成…...

机器学习前言2

1.机器学习 2.机器学习模型 3.模型评价方法 4.如何选择合适的模型 介绍 机器学习(Machine Learning, ML)是人工智能(AI)的核心分支,致力于通过数据和算法让计算机系统自动“学习”并改进性能,而无需显式编…...

在多个SpringBoot程序中./相对路径下隐患、文件覆盖问题

概述 两个 Spring Boot 应用生成的配置文件被覆盖,是因为 ​相对路径的解析依赖于当前工作目录(Working Directory)​,而你可能在运行应用时未正确设置各自的工作目录。以下是具体原因和解决方案: 原因分析 ​相对路径…...

弦理论的额外维度指的是什么,宇宙中有何依据

弦理论中的额外维度是解释微观世界与宏观宇宙矛盾的关键假设之一。它们并非科幻中的平行宇宙,而是通过严谨的数学框架提出,并可能留下可观测的宇宙学痕迹。以下是具体解析: 一、弦理论为何需要额外维度? 数学自洽性要求 弦理论中…...

FC7300 GPT MCAL 配置引导

一、配置约束 FCPIT:仅FC7240型号芯片支持。如果GPT模块与PWM/ICU/OCU模块使用相同的FTU实例,配置工具将报告一个错误。如果GPT通道使用FTU,时钟源来自PCC,则GptFtuChannelClkSrc必须选择GPT_FTU_BUS_CLK。二、MCU 组件 - 配置WDG采用的定时器时钟 Examle:WDG选用AONTIMER…...

LangFlow技术深度解析:可视化编排LangChain应用的新范式 -(2)流编辑器系统

Flow Editor System | langflow-ai/langflow | DeepWiki 流编辑器系统 相关源文件 流编辑器系统是 Langflow 的核心交互式组件,允许用户直观地创建、编辑和管理 LLM 驱动的应用程序。它提供了一个直观的画布,用户可以在其中添加节点、将其与边缘连接并…...

okcc呼叫中心系统搭建的方案方式

传统企业呼叫中心多采用 PC和手机软件,很难与客户保持良好的沟通。因此,需要建设一套呼叫中心系统来实现与客户实时有效沟通。那么,呼叫中心搭建的方案方式有哪些呢?下面详细介绍一下。 呼叫中心系统的搭建方式需根据企业规模、预算和业务需…...

asp.net IHttpHandler 对分块传输编码的支持,IIs web服务器后端技术

IHttpHandler,不支持分块传输编码(Chunked Transfer)吧? IHttpHandler 对分块传输编码的支持 实际上,IHttpHandler 完全支持分块传输编码(Chunked Transfer Encoding),但具体行为取…...

芍药BAHD酰基转移酶-文献精读128

PoDPBT, a BAHD acyltransferase, catalyses the benzoylation in paeoniflorin biosynthesis in Paeonia ostii PoDPBT,一种BAHD酰基转移酶,在芍药(Paeonia ostii)中催化芍药苷生物合成中的苯甲酰化反应。 摘要 PoDPBT是属于BA…...

GTS-400 系列运动控制器板卡介绍(三十三)---运动程序单线程累加求和

运动控制器函数库的使用 运动控制器驱动程序、dll 文件、例程、Demo 等相关文件请通过固高科技官网下载,网 址为:www.googoltech.com.cn/pro_view-3.html 1 Windows 系统下动态链接库的使用 在 Windows 系统下使用运动控制器,首先要安装驱动程序。在安装前需要提前下载运动…...

C# 面向对象 构造函数带参无参细节解析

继承类构造时会先调用基类构造函数,不显式调用基类构造函数时,默认调用基类无参构造函数,但如果基类没有写无参构造函数,会无法调用从而报错;此时,要么显式的调用基类构造函数,并按其格式带上参…...

数字化工厂升级引擎:Modbus TCP转Profinet网关助力打造柔性生产系统

在当今的工业自动化领域,通信协议扮演着至关重要的角色。Modbus TCP和Profinet是两种广泛使用的工业通信协议,它们分别在不同的应用场景中发挥着重要作用。然而,有时我们可能需要将这两种协议进行转换,以实现不同设备之间的无缝通…...

【编译原理】词法分析器

//简单实现,伪代码 int code,value; strToken :" "; //置strToken为空串 GetChar();GetBC(); if(IsLetter()) beginwhile(IsLetter() or IsDigit())beginConcat();GetChar();endRetract();code:Reserve();if(code0)beginvalue:InsertId(strToken);retu…...

记录一次vue项目页面内嵌iframe页面实现跨域上传和下载附件的功能

功能背景:项目部署在外网,然后其中有一个功能需要上传下载附件,附件是上传到华为云对象存储服务OBS中(私有云),所以采用iframe嵌套页面的方式解决跨域问题。 实现思路: 1、父窗口封装一个组件专…...

【Win32 API】 lstrcpyA()

作用 将字符串复制到指定的字符串缓冲区。 函数 LPSTR lstrcpyA(LPSTR lpString1, LPCSTR lpString2); 参数 lpString1 类型:LPTSTR 一个缓冲区,用于接收由 lpString2 参数指向的字符串的内容。 缓冲区必须足够大才能包含字符串,包括终止…...

报表控件stimulsoft教程:如何在报表和仪表板中创建热图

Stimulsoft Ultimate (原Stimulsoft Reports.Ultimate)是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能,Stimulsoft Ultimate包含了…...

Axure疑难杂症:剖析面包屑导航“用户不迷路”(玩转导航)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:剖析面包屑导航“用户不迷路” 主要内容:面包屑导航各种做法 应用场景:页面导航、页面路径、用户选择路径、…...

中exec()函数因$imagePath参数导致的命令注入漏洞

exec(zbarimg -q . $imagePath, $barcodeList, $returnVar); 针对PHP中exec()函数因$imagePath参数导致的命令注入漏洞,以下是安全解决方案和最佳实践: 一、漏洞原理分析 直接拼接用户输入$imagePath到系统命令中,攻击者可通过注入特殊字…...

HTML常用标签用法全解析:构建语义化网页的核心指南

HTML作为网页开发的基石&#xff0c;其标签的合理使用直接影响页面的可读性、SEO效果及维护性。本文系统梳理HTML核心标签的用法&#xff0c;结合语义化设计原则与实战示例&#xff0c;助你构建规范、高效的网页结构。 一、基础结构与排版标签 1.1 文档结构 <!DOCTYPE htm…...

【Linux】动静态库链接原理

&#x1f4dd;前言&#xff1a; 这篇文章我们来讲讲Linux——动静态库链接原理 &#x1f3ac;个人简介&#xff1a;努力学习ing &#x1f4cb;个人专栏&#xff1a;Linux &#x1f380;CSDN主页 愚润求学 &#x1f304;其他专栏&#xff1a;C学习笔记&#xff0c;C语言入门基础…...

Axure设计的“广东省网络信息化大数据平台”数据可视化大屏

在数据驱动决策的时代&#xff0c;数据可视化大屏成为了展示数据、洞察趋势的重要工具。今天&#xff0c;让我们一同深入了解由Axure设计的“广东省网络信息化大数据平台”数据可视化大屏&#xff0c;看看它如何通过精心的布局和丰富的图表类型&#xff0c;将复杂的数据以直观易…...

linux安装宝塔面板到数据盘

操作很简单&#xff0c;假如数据盘挂载在cipan1&#xff0c;在数据盘新建目录www&#xff0c;为了方便对应。 执行一下命令&#xff0c;创建软连接 ln -s /cipan1/www www 此时&#xff0c;根目录就出现了www文件夹 下面正常安装宝塔即可...

数学实验(Matlab编程基础)

一、函数文件 Matlab编程基础 Matlab作为一种广泛应用于科学计算的工具软件&#xff0c;不仅具有强大的数值计算、符号计算、矩阵运算能力和丰富的绘图功能&#xff0c;同时也具有和C、FORTRAN等高级语言一样进行程序设计 利用Matlab的程序控制功能&#xff0c;可以将有关Ma…...

不同坐标系下MATLAB绘制阵列的方向图

不同坐标系下MATLAB绘制阵列的方向图 球坐标系&#xff0c;极坐标系、直角坐标系 文章目录 前言一、极坐标系二、球坐标系三、直角坐标系总结 前言 \;\;\;\;\; 在阵列信号处理和天线设计中&#xff0c;方向图&#xff08;Pattern&#xff09;是描述波束形成性能的关键工具&…...

python可视化:北方省市人口流动与春运数据综合分析5

python可视化&#xff1a;北方省市人口流动与春运数据综合分析5 一、北方省市常住人口数据及变化趋势&#xff08;2023-2024第一季度&#xff09; 1. 主要城市常住人口数据&#xff08;按城市等级分类&#xff09; 城市类型2023Q1常住人口(万)2024Q1常住人口(万)变化量(万)变…...

Java并发编程-线程池(四)

文章目录 线程池实现原理WorkerWorker 核心设计总结 runWorker(Worker w)总结 线程池实现原理 上一篇我们看了 addWork 方法&#xff0c;那接下来就让我们详细看看内部类Worker。 Worker private final class Workerextends AbstractQueuedSynchronizerimplements Runnable …...

力扣热题——最长相邻不相等子序列 |

题目要求从字符串数组 words 中选出一个最长的子序列&#xff0c;使得该子序列中相邻字符串对应的 groups 数组中的值不同。通过贪心算法&#xff0c;可以高效地解决该问题。具体步骤为&#xff1a;初始化一个结果列表&#xff0c;遍历 words 数组&#xff0c;检查当前字符串的…...

筑牢信息安全防线:涉密计算机与互联网隔离的理论实践与风险防控

在数字化时代&#xff0c;信息安全已成为国家安全体系的重要组成部分。涉密计算机作为承载敏感信息的核心载体&#xff0c;其安全防护工作直接关系到国家利益与社会稳定。违规连接互联网这一行为&#xff0c;如同在严密的防护体系中打开一扇危险的"暗门"&#xff0c;…...

sqli-labs靶场29-31关(http参数污染)

目录 前言 less29&#xff08;单引号http参数污染&#xff09; less30&#xff08;双引号http参数污染&#xff09; less31(双引号括号http参数污染) 前言 在JSP中&#xff0c;使用request.getParameter("id")获取请求参数时&#xff0c;如果存在多个同名参数&a…...

基于Linux环境实现Oracle goldengate远程抽取MySQL同步数据到MySQL

基于Linux环境实现Oracle goldengate远程抽取MySQL同步数据到MySQL 场景说明&#xff1a; 先有项目需要读取生产库数据&#xff0c;但是不能直接读取生产库数据&#xff0c;需要把生产数据同步到一个中间库&#xff0c;下游系统从中间库读取数据。 生产库mysql - OGG - 中间库…...

linux,我启动一个springboot项目, 用java -jar xxx.jar ,但是没多久这个java进程就会自动关掉

当使用 java -jar xxx.jar & 启动 Spring Boot 项目后进程自动关闭时&#xff0c;可能由多种原因导致。以下是常见排查步骤和解决方案&#xff1a; 一、查看日志定位原因 进程异常关闭通常会在控制台或日志中留下线索&#xff0c;建议先获取完整日志&#xff1a; 1. 查看…...

pytorch 14.3 Batch Normalization综合调参实践

文章目录 一、Batch Normalization与Batch_size综合调参二、复杂模型上的Batch_normalization表现1、BN对复杂模型&#xff08;sigmoid&#xff09;的影响2、模型复杂度对模型效果的影响3、BN对复杂模型&#xff08;tanh&#xff09;的影响 三、包含BN层的神经网络的学习率优化…...

供应链安全检测系列技术规范介绍之一|软件成分分析

软件成分分析的概念及意义 软件成分分析Software Compostition Analysis&#xff08;SCA&#xff09;是一种用于管理开源组件应用安全的方法。软件成分分析系统可以快速跟踪和分析应用软件的开源组件&#xff0c;发现相关组件、支持库以及它们之间直接和间接依赖关系&#xff0…...

pytorch 15.1 学习率调度基本概念与手动实现方法

文章目录 一、学习率对模型训练影响 二、学习率调度基本概念与手动实现方法1.模型调度基本概念2.手动实现学习率调度3.常用学习率调度思路 从本节开始&#xff0c;我们将介绍深度学习中学习率优化方法。学习率作为模型优化的重要超参数&#xff0c;在此前的学习中&#xff0c;我…...

c++ 类的语法4

测试析构函数、虚函数、纯虚函数&#xff1a; void testClass5() {class Parent {public:Parent(int x) { cout << "Parent构造: " << x << endl; }~Parent() {cout << "调用Parent析构函数" << endl;}virtual string toSt…...

品铂科技在UWB行业地位综述(2025年更新)

一、行业领先地位‌ ‌国内UWB领域头部企业‌ 在2025年中国UWB企业综合实力排行榜中位列第一&#xff0c;技术研发、市场份额及行业影响力均处于领先地位。连续多年获评中国物联网产业联盟“中国最有影响力物联网定位企业”。 2.‌全球技术竞争力‌ .2016年IPSN微软国际室内…...

muduo库EventLoop模块详解

muduo库EventLoop模块深度解析 EventLoop是muduo网络库实现Reactor模型的核心调度中枢&#xff0c;负责驱动整个事件循环机制&#xff0c;协调Poller、Channel、TimerQueue等组件的工作。其设计遵循"One Loop Per Thread"原则。 一、核心职责与设计思想 1. 核心职责…...

循环导入(Circular Import) 错误

ImportError: cannot import name event_type_data_tree from partially initialized module routers.ticket (most likely due to a circular import) (E:\ai12345\backend\app\routers\ticket.py) 这是什么错&#xff0c;中文回答 这个错误是 循环导入&#xff08;Circular …...