【AI學習】RadioDiff:代碼學習

之前學習了RadioDiff這篇論文,最近在復刻相關代碼。

這段代碼實現了一個基于潛在擴散模型(Latent Diffusion Model, LDM)的訓練框架。借助DeepSeek總體學習一下:

1. 整體結構

代碼主要分為以下幾個部分:

  • 參數解析和配置加載(parse_args, load_conf
  • 主訓練函數(main
  • 訓練器類(Trainer
  • 主程序入口

2. 主要組件

2.1 模型架構
  1. AutoencoderKL:變分自編碼器,用于將圖像編碼到潛在空間
  2. Unet:條件UNet模型,用于擴散過程
  3. LatentDiffusion:將VAE和UNet組合在一起的潛在擴散模型
2.2 訓練流程
  1. 加載配置文件和模型
  2. 準備數據集和數據加載器
  3. 初始化訓練器
  4. 執行訓練循環

3. 詳細解釋

3.1 參數和配置
def parse_args():parser = argparse.ArgumentParser(description="training vae configure")parser.add_argument("--cfg", help="experiment configure file name", type=str, required=True)args = parser.parse_args()args.cfg = load_conf(args.cfg)return args
  • 使用argparse解析命令行參數,主要接受一個配置文件路徑
  • load_conf函數加載YAML配置文件
3.2 主函數
def main(args):cfg = CfgNode(args.cfg)# 初始化VAE模型first_stage_model = AutoencoderKL(...)# 初始化UNet模型if model_cfg.model_name == 'cond_unet':from denoising_diffusion_pytorch.mask_cond_unet import Unetunet = Unet(...)# 初始化擴散模型if model_cfg.model_type == 'const_sde':from denoising_diffusion_pytorch.ddm_const_sde import LatentDiffusionldm = LatentDiffusion(...)# 統計模型參數vae_params = count_params(first_stage_model)unet_params = count_params(unet)ldm_total_params = count_params(ldm)# 準備數據集和數據加載器if data_cfg['name'] == 'edge':dataset = EdgeDataset(...)dl = DataLoader(...)# 初始化訓練器并開始訓練trainer = Trainer(...)trainer.train()
3.3 Trainer類

Trainer類負責整個訓練過程的管理,主要功能包括:

  1. 初始化

    • 設置混合精度訓練
    • 準備模型、數據加載器、優化器
    • 初始化EMA(指數移動平均)模型
    • 設置學習率調度器
  2. 訓練循環

    def train(self):while self.step < self.train_num_steps:# 梯度累積for ga_ind in range(self.gradient_accumulate_every):batch = next(self.dl)# 訓練步驟loss, log_dict = self.model.training_step(batch)# 反向傳播self.accelerator.backward(loss)# 參數更新self.opt.step()self.opt.zero_grad()self.lr_scheduler.step()# EMA更新self.ema.update()# 定期保存和采樣if self.step % self.save_and_sample_every == 0:self.save(milestone)# 生成樣本圖像all_images, *_ = self.model.sample(...)tv.utils.save_image(all_images, ...)
    
  3. 關鍵功能

    • 梯度累積:通過多次前向傳播累積梯度再更新參數
    • 混合精度訓練:使用accelerator自動管理
    • EMA:保持模型的平滑版本,提高穩定性
    • 定期采樣:生成樣本圖像監控訓練進度
3.4 模型保存和加載
def save(self, milestone):data = {'step': self.step,'model': self.accelerator.get_state_dict(self.model),'opt': self.opt.state_dict(),'ema': self.ema.state_dict(),...}torch.save(data, f'model-{milestone}.pt')def load(self, milestone):data = torch.load(...)model.load_state_dict(data['model'])self.opt.load_state_dict(data['opt'])...

4. 關鍵技術點

  1. 潛在擴散模型

    • 先在潛在空間進行擴散過程,再通過VAE解碼
    • 降低計算成本,提高生成質量
  2. 條件生成

    • UNet支持條件輸入(cond_in_dim, cond_dim等參數)
    • 可用于圖像到圖像轉換任務
  3. 分布式訓練

    • 使用Accelerator庫簡化多GPU訓練
    • 支持混合精度訓練
  4. 訓練技巧

    • EMA模型平滑
    • 學習率調度
    • 梯度裁剪

5. 配置文件

代碼通過YAML文件配置模型和訓練參數,包括:

  • 模型架構參數
  • 訓練超參數
  • 數據路徑和預處理設置

6. 應用場景

這段代碼適用于:

  • 圖像生成
  • 圖像修復
  • 圖像到圖像轉換
  • 其他基于擴散模型的生成任務

總結來說,這是一個完整的潛在擴散模型訓練框架,包含了從數據加載、模型定義、訓練循環到結果保存的全流程實現,支持分布式訓練和各種訓練優化技術。

完整代碼

import yaml
import argparse
import math
import torch
from lib import loaders
import torch.nn as nn
from tqdm.auto import tqdm
from denoising_diffusion_pytorch.ema import EMA
from accelerate import Accelerator, DistributedDataParallelKwargs
from torch.utils.tensorboard import SummaryWriter
from denoising_diffusion_pytorch.utils import *
import torchvision as tv
from denoising_diffusion_pytorch.encoder_decoder import AutoencoderKL
# from denoising_diffusion_pytorch.transmodel import TransModel
from denoising_diffusion_pytorch.data import *
from torch.utils.data import DataLoader
from multiprocessing import cpu_count
from fvcore.common.config import CfgNode
from taming.modules.util import count_params
os.environ["CUDA_VISIBLE_DEVICES"]="1"def parse_args():parser = argparse.ArgumentParser(description="training vae configure")parser.add_argument("--cfg", help="experiment configure file name", type=str, required=True)# parser.add_argument("")args = parser.parse_args()args.cfg = load_conf(args.cfg)return argsdef load_conf(config_file, conf={}):with open(config_file) as f:exp_conf = yaml.load(f, Loader=yaml.FullLoader)for k, v in exp_conf.items():conf[k] = vreturn confdef main(args):cfg = CfgNode(args.cfg)# logger = create_logger(root_dir=cfg['out_path'])# writer = SummaryWriter(cfg['out_path'])model_cfg = cfg.modelfirst_stage_cfg = model_cfg.first_stagefirst_stage_model = AutoencoderKL(ddconfig=first_stage_cfg.ddconfig,lossconfig=first_stage_cfg.lossconfig,embed_dim=first_stage_cfg.embed_dim,ckpt_path=first_stage_cfg.ckpt_path,)if model_cfg.model_name == 'cond_unet':from denoising_diffusion_pytorch.mask_cond_unet import Unetunet_cfg = model_cfg.unetunet = Unet(dim=unet_cfg.dim,channels=unet_cfg.channels,dim_mults=unet_cfg.dim_mults,learned_variance=unet_cfg.get('learned_variance', False),out_mul=unet_cfg.out_mul,cond_in_dim=unet_cfg.cond_in_dim,cond_dim=unet_cfg.cond_dim,cond_dim_mults=unet_cfg.cond_dim_mults,window_sizes1=unet_cfg.window_sizes1,window_sizes2=unet_cfg.window_sizes2,fourier_scale=unet_cfg.fourier_scale,cfg=unet_cfg,)else:raise NotImplementedErrorif model_cfg.model_type == 'const_sde':from denoising_diffusion_pytorch.ddm_const_sde import LatentDiffusionelse:raise NotImplementedError(f'{model_cfg.model_type} is not surportted !')ldm = LatentDiffusion(model=unet,auto_encoder=first_stage_model,train_sample=model_cfg.train_sample,image_size=model_cfg.image_size,timesteps=model_cfg.timesteps,sampling_timesteps=model_cfg.sampling_timesteps,loss_type=model_cfg.loss_type,objective=model_cfg.objective,scale_factor=model_cfg.scale_factor,scale_by_std=model_cfg.scale_by_std,scale_by_softsign=model_cfg.scale_by_softsign,default_scale=model_cfg.get('default_scale', False),input_keys=model_cfg.input_keys,ckpt_path=model_cfg.ckpt_path,ignore_keys=model_cfg.ignore_keys,only_model=model_cfg.only_model,start_dist=model_cfg.start_dist,perceptual_weight=model_cfg.perceptual_weight,use_l1=model_cfg.get('use_l1', True),cfg=model_cfg,)# 統計VAE(AutoencoderKL)vae_params = count_params(first_stage_model)print(f"擴散模型中的VAE參數量: {vae_params / 1e6:.2f}M")# 統計UNetunet_params = count_params(unet)print(f"UNet參數量: {unet_params:,}")print(f"UNet參數量: {unet_params / 1e6:.2f}M")# 統計整個擴散模型(包括UNet、VAE等)ldm_total_params = count_params(ldm)print(f"擴散模型總參數量: {ldm_total_params:,}")print(f"擴散模型總參數量: {ldm_total_params / 1e6:.2f}M")data_cfg = cfg.dataif data_cfg['name'] == 'edge':dataset = EdgeDataset(data_root=data_cfg.img_folder,image_size=model_cfg.image_size,augment_horizontal_flip=data_cfg.augment_horizontal_flip,cfg=data_cfg)elif data_cfg['name'] == 'radio':dataset = loaders.RadioUNet_c(phase="train")else:raise NotImplementedErrordl = DataLoader(dataset, batch_size=data_cfg.batch_size, shuffle=True, pin_memory=True,num_workers=data_cfg.get('num_workers', 2))train_cfg = cfg.trainertrainer = Trainer(ldm, dl, train_batch_size=data_cfg.batch_size,gradient_accumulate_every=train_cfg.gradient_accumulate_every,train_lr=train_cfg.lr, train_num_steps=train_cfg.train_num_steps,save_and_sample_every=train_cfg.save_and_sample_every, results_folder=train_cfg.results_folder,amp=train_cfg.amp, fp16=train_cfg.fp16, log_freq=train_cfg.log_freq, cfg=cfg,resume_milestone=train_cfg.resume_milestone,train_wd=train_cfg.get('weight_decay', 1e-4))if train_cfg.test_before:if trainer.accelerator.is_main_process:with torch.no_grad():for datatmp in dl:breakif isinstance(trainer.model, nn.parallel.DistributedDataParallel):all_images, *_ = trainer.model.module.sample(batch_size=datatmp['cond'].shape[0],cond=datatmp['cond'].to(trainer.accelerator.device),mask=datatmp['ori_mask'].to(trainer.accelerator.device) if 'ori_mask' in datatmp else None)elif isinstance(trainer.model, nn.Module):all_images, *_ = trainer.model.sample(batch_size=datatmp['cond'].shape[0],cond=datatmp['cond'].to(trainer.accelerator.device),mask=datatmp['ori_mask'].to(trainer.accelerator.device) if 'ori_mask' in datatmp else None)# all_images = torch.cat(all_images_list, dim = 0)nrow = 2 ** math.floor(math.log2(math.sqrt(data_cfg.batch_size)))tv.utils.save_image(all_images, str(trainer.results_folder / f'sample-{train_cfg.resume_milestone}_{model_cfg.sampling_timesteps}.png'), nrow=nrow)torch.cuda.empty_cache()trainer.train()passclass Trainer(object):def __init__(self,model,data_loader,train_batch_size=16,gradient_accumulate_every=1,train_lr=1e-4,train_wd=1e-4,train_num_steps=100000,save_and_sample_every=1000,num_samples=25,results_folder='./results',amp=False,fp16=False,split_batches=True,log_freq=20,resume_milestone=0,cfg={},):super().__init__()ddp_handler = DistributedDataParallelKwargs(find_unused_parameters=True)self.accelerator = Accelerator(split_batches=split_batches,mixed_precision='fp16' if fp16 else 'no',kwargs_handlers=[ddp_handler],)self.enable_resume = cfg.trainer.get('enable_resume', False)self.accelerator.native_amp = ampself.model = modelassert has_int_squareroot(num_samples), 'number of samples must have an integer square root'self.num_samples = num_samplesself.save_and_sample_every = save_and_sample_everyself.batch_size = train_batch_sizeself.gradient_accumulate_every = gradient_accumulate_everyself.log_freq = log_freqself.train_num_steps = train_num_stepsself.image_size = model.image_size# dataset and dataloader# self.ds = Dataset(folder, mask_folder, self.image_size, augment_horizontal_flip = augment_horizontal_flip, convert_image_to = convert_image_to)# dl = DataLoader(self.ds, batch_size = train_batch_size, shuffle = True, pin_memory = True, num_workers = cpu_count())dl = self.accelerator.prepare(data_loader)self.dl = cycle(dl)# optimizerself.opt = torch.optim.AdamW(filter(lambda p: p.requires_grad, model.parameters()),lr=train_lr, weight_decay=train_wd)lr_lambda = lambda iter: max((1 - iter / train_num_steps) ** 0.96, cfg.trainer.min_lr)self.lr_scheduler = torch.optim.lr_scheduler.LambdaLR(self.opt, lr_lambda=lr_lambda)# for logging results in a folder periodicallyif self.accelerator.is_main_process:self.results_folder = Path(results_folder)self.results_folder.mkdir(exist_ok=True, parents=True)self.ema = EMA(model, ema_model=None, beta=0.999,update_after_step=cfg.trainer.ema_update_after_step,update_every=cfg.trainer.ema_update_every)# step counter stateself.step = 0# prepare model, dataloader, optimizer with acceleratorself.model, self.opt, self.lr_scheduler = \self.accelerator.prepare(self.model, self.opt, self.lr_scheduler)self.logger = create_logger(root_dir=results_folder)self.logger.info(cfg)self.writer = SummaryWriter(results_folder)self.results_folder = Path(results_folder)resume_file = str(self.results_folder / f'model-{resume_milestone}.pt')if os.path.isfile(resume_file):self.load(resume_milestone)def save(self, milestone):if not self.accelerator.is_local_main_process:returnif self.enable_resume:data = {'step': self.step,'model': self.accelerator.get_state_dict(self.model),'opt': self.opt.state_dict(),'lr_scheduler': self.lr_scheduler.state_dict(),'ema': self.ema.state_dict(),'scaler': self.accelerator.scaler.state_dict() if exists(self.accelerator.scaler) else None}# data_only_model = {'ema': self.ema.state_dict(),}torch.save(data, str(self.results_folder / f'model-{milestone}.pt'))else:data = {'model': self.accelerator.get_state_dict(self.model),}torch.save(data, str(self.results_folder / f'model-{milestone}.pt'))def load(self, milestone):assert self.enable_resume; 'resume is available only if self.enable_resume is True !'accelerator = self.acceleratordevice = accelerator.devicedata = torch.load(str(self.results_folder / f'model-{milestone}.pt'),map_location=lambda storage, loc: storage)model = self.accelerator.unwrap_model(self.model)model.load_state_dict(data['model'])if 'scale_factor' in data['model']:model.scale_factor = data['model']['scale_factor']self.step = data['step']self.opt.load_state_dict(data['opt'])self.lr_scheduler.load_state_dict(data['lr_scheduler'])if self.accelerator.is_main_process:self.ema.load_state_dict(data['ema'])if exists(self.accelerator.scaler) and exists(data['scaler']):self.accelerator.scaler.load_state_dict(data['scaler'])def train(self):accelerator = self.acceleratordevice = accelerator.devicewith tqdm(initial=self.step, total=self.train_num_steps, disable=not accelerator.is_main_process) as pbar:while self.step < self.train_num_steps:total_loss = 0.total_loss_dict = {'loss_simple': 0., 'loss_vlb': 0., 'total_loss': 0., 'lr': 5e-5}for ga_ind in range(self.gradient_accumulate_every):# data = next(self.dl).to(device)batch = next(self.dl)for key in batch.keys():if isinstance(batch[key], torch.Tensor):batch[key].to(device)if self.step == 0 and ga_ind == 0:if isinstance(self.model, nn.parallel.DistributedDataParallel):self.model.module.on_train_batch_start(batch)else:self.model.on_train_batch_start(batch)with self.accelerator.autocast():if isinstance(self.model, nn.parallel.DistributedDataParallel):loss, log_dict = self.model.module.training_step(batch)else:loss, log_dict = self.model.training_step(batch)loss = loss / self.gradient_accumulate_everytotal_loss += loss.item()loss_simple = log_dict["train/loss_simple"].item() / self.gradient_accumulate_everyloss_vlb = log_dict["train/loss_vlb"].item() / self.gradient_accumulate_everytotal_loss_dict['loss_simple'] += loss_simpletotal_loss_dict['loss_vlb'] += loss_vlbtotal_loss_dict['total_loss'] += total_loss# total_loss_dict['s_fact'] = self.model.module.scale_factor# total_loss_dict['s_bias'] = self.model.module.scale_biasself.accelerator.backward(loss)total_loss_dict['lr'] = self.opt.param_groups[0]['lr']describtions = dict2str(total_loss_dict)describtions = "[Train Step] {}/{}: ".format(self.step, self.train_num_steps) + describtionsif accelerator.is_main_process:pbar.desc = describtionsif self.step % self.log_freq == 0:if accelerator.is_main_process:# pbar.desc = describtions# self.logger.info(pbar.__str__())self.logger.info(describtions)accelerator.clip_grad_norm_(filter(lambda p: p.requires_grad, self.model.parameters()), 1.0)# pbar.set_description(f'loss: {total_loss:.4f}')accelerator.wait_for_everyone()self.opt.step()self.opt.zero_grad()self.lr_scheduler.step()if accelerator.is_main_process:self.writer.add_scalar('Learning_Rate', self.opt.param_groups[0]['lr'], self.step)self.writer.add_scalar('total_loss', total_loss, self.step)self.writer.add_scalar('loss_simple', loss_simple, self.step)self.writer.add_scalar('loss_vlb', loss_vlb, self.step)accelerator.wait_for_everyone()self.step += 1# if self.step >= int(self.train_num_steps * 0.2):if accelerator.is_main_process:self.ema.to(device)self.ema.update()if self.step != 0 and self.step % self.save_and_sample_every == 0:milestone = self.step // self.save_and_sample_everyself.save(milestone)self.model.eval()# self.ema.ema_model.eval()with torch.no_grad():# img = self.dl# batches = num_to_groups(self.num_samples, self.batch_size)# all_images_list = list(map(lambda n: self.model.module.validate_img(ns=self.batch_size), batches))if isinstance(self.model, nn.parallel.DistributedDataParallel):# all_images = self.model.module.sample(batch_size=self.batch_size)all_images, *_ = self.model.module.sample(batch_size=batch['cond'].shape[0],cond=batch['cond'],mask=batch['ori_mask'] if 'ori_mask' in batch else None)elif isinstance(self.model, nn.Module):# all_images = self.model.sample(batch_size=self.batch_size)all_images, *_ = self.model.sample(batch_size=batch['cond'].shape[0],cond=batch['cond'],mask=batch['ori_mask'] if 'ori_mask' in batch else None)# all_images = torch.clamp((all_images + 1.0) / 2.0, min=0.0, max=1.0)# all_images = torch.cat(all_images_list, dim = 0)# nrow = 2 ** math.floor(math.log2(math.sqrt(self.batch_size)))nrow = 2 ** math.floor(math.log2(math.sqrt(batch['cond'].shape[0])))tv.utils.save_image(all_images, str(self.results_folder / f'sample-{milestone}.png'), nrow=nrow)self.model.train()accelerator.wait_for_everyone()pbar.update(1)accelerator.print('training complete')if __name__ == "__main__":args = parse_args()main(args)pass

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/917313.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/917313.shtml
英文地址,請注明出處:http://en.pswp.cn/news/917313.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【專題十七】多源 BFS

&#x1f4dd;前言說明&#xff1a; 本專欄主要記錄本人的基礎算法學習以及LeetCode刷題記錄&#xff0c;按專題劃分每題主要記錄&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代碼&#xff1b;&#xff08;2&#xff09;優質解法 優質代碼&#xff1b;&#xff…

京東零售在智能供應鏈領域的前沿探索與技術實踐

近日&#xff0c;“智匯運河 智算未來”2025人工智能創新創業大會在杭州召開。香港工程科學院院士、香港大學副校長、研究生院院長、講座教授、京東零售供應鏈首席科學家申作軍教授與供應鏈算法團隊技術總監戚永志博士受邀出席并擔任《AI智慧物流與供應鏈分享會》聯席主席&…

MyBatisPlus之CRUD接口(IService與BaseMapper)

MyBatisPlus之CRUD接口—IService與BaseMapper一、BaseMapper與IService的關系二、BaseMapper核心方法詳解2.1 新增操作&#xff08;Insert&#xff09;2.2 查詢操作&#xff08;Select&#xff09;2.3 更新操作&#xff08;Update&#xff09;2.4 刪除操作&#xff08;Delete&…

axios請求的取消

axios請求的取消解決&#xff1a;axios請求的取消解決&#xff1a;axios請求的取消 在使用 Axios 發起請求時&#xff0c;有時候你可能需要取消這些請求&#xff0c;比如當組件銷毀時或者用戶操作導致不再需要獲取之前發起的請求結果。Axios 支持通過 Cancel Token 取消請求。 …

深入理解C++中的Lazy Evaluation:延遲計算的藝術

在編程世界里&#xff0c;“最好的運算就是從未執行的運算” —— 這句話深刻揭示了性能優化的核心思路。如果一個計算過程最終不會被使用&#xff0c;那么提前執行它就是純粹的資源浪費。這種思想衍生出了 Lazy Evaluation&#xff08;緩式評估&#xff09; 技術&#xff1a;延…

php完整處理word中表單數據的方法

使用php基礎方式實現word中表單處理<?php/*** zipFile 類用于處理 .docx 文件的解壓、修改和重新打包*/ class zipFile {/** var ZipArchive ZIP 文件對象 */private $zipFile;/** var string 臨時目錄路徑 */private $tempDir;/** var string 嵌入的 Excel 文件臨時目錄路…

Node.js 操作 MongoDB

目錄 Node.js 操作 MongoDB 一、什么是 MongoDB&#xff1f; 二、MongoDB 的功能概覽 三、MongoDB 的安裝與啟動 安裝 MongoDB&#xff08;以本地安裝為例&#xff09; 啟動 MongoDB 四、Node.js 如何連接 MongoDB&#xff1f; 使用 Mongoose ODM 工具 建立連接 五、…

先學Python還是c++?

選擇先學Python還是C&#xff0c;取決于你的學習目標、應用場景和職業規劃。以下是兩者的對比分析和建議&#xff0c;幫助你做出更適合自己的選擇&#xff1a;一、核心差異對比維度PythonC學習曲線簡單易上手&#xff08;語法接近自然語言&#xff09;復雜&#xff08;需理解指…

Trae + Notion MCP:將你的Notion數據庫升級為智能對話機器人

前言 Notion作為一款功能強大的信息管理工具&#xff0c;被廣泛用于項目跟蹤、知識庫構建和數據整理。然而&#xff0c;隨著數據量的增長&#xff0c;我們常常會發現自己陷入了重復和繁瑣的操作中。比如&#xff0c;為了找到符合特定條件的幾條數據&#xff0c;需要在龐大的數…

【iOS】retain/release底層實現原理

文章目錄前言前情知識retain和release的實現原理&#xff08;MRC手動管理&#xff09;retain&#xff08;MRC手動管理&#xff09;retain源碼內聯函數rootRetain源碼相關的sidetable_tryRetain()方法retain底層工作流程總結releaserelease源碼內聯函數rootRelease源碼小結前言 …

文件同步神器-rsync命令講解

rsync 是一個強大的文件同步與傳輸工具&#xff0c;廣泛用于本地或遠程服務器之間的高效文件備份、鏡像或同步。其核心優勢是通過增量傳輸?&#xff08;僅傳輸文件差異部分&#xff09;和壓縮減少數據傳輸量&#xff0c;同時支持保留文件元數據&#xff08;如權限、時間戳、所…

Rust: 工具鏈版本更新

遇到 cargo build --release 錯誤&#xff0c;比如&#xff0c;當前 Rust 工具鏈版本&#xff08;1.78.0&#xff09;低于依賴項所需的最低版本&#xff08;部分依賴要求 ≥1.82.0&#xff09;。以下是系統化的解決方案&#xff1a; &#x1f527; 一、升級 Rust 工具鏈&#x…

Prompt-to-Prompt| 修改Attention會有“反向傳播”或梯度計算?

需要注意的幾個問題&#xff1a;額外計算開銷&#xff1a;Cross-Attention Control原因&#xff1a;Prompt-to-Prompt的編輯方法需要動態干預交叉注意力&#xff08;Cross-Attention&#xff09;層的權重&#xff0c;這會引入額外的計算和顯存占用&#xff1a;需要緩存注意力矩…

電商API接口的優勢、數據采集方法及功能說明

一、電商API接口的核心優勢1. 高效性與準確性數據采集效率&#xff1a;API通過標準化參數&#xff08;如商品ID、類目&#xff09;直接獲取結構化數據&#xff08;JSON/XML&#xff09;&#xff0c;無需解析HTML&#xff0c;減少誤差。例如&#xff0c;采集1000條商品信息&…

iOS企業簽名掉簽,iOS企業簽名掉簽了怎么辦?

不能上架到App Store的iOS應用 &#xff0c;幾乎每一個開發者的選擇都是通過iOS簽名這種內測渠道來完成APP的上架任務&#xff0c;最常用的就是企業簽名、超級簽名以及TF上架&#xff0c;其中最受歡迎的當屬于企業簽名了。不過企業簽名會出現掉簽的現象&#xff0c;那么企業簽名…

存儲成本深度優化:冷熱分層與生命周期管理——從視頻平臺年省200萬實踐解析智能存儲架構

一、冷熱分層&#xff1a;存儲成本優化的核心邏輯1.1 數據訪問的“二八定律”據行業統計&#xff0c;80%的訪問集中在20%的熱數據上&#xff0c;而超過90天的歷史數據訪問頻率下降70%以上。某視頻平臺存儲超10PB媒體文件&#xff0c;未分層前年存儲成本高達680萬元&#xff0c;…

Java設計模式之《備忘錄模式》

目錄 1. 概念 1.1、定義 1.2、適用場景 2、角色劃分 3、實現 1、Originator&#xff08;發起人&#xff09; 2、Memento&#xff08;備忘錄&#xff09; 3、Caretaker&#xff08;管理者&#xff09; 4、使用示例 4、優缺點 4.1、優點 4.2、缺點 前言 備忘錄模式是…

SpringBoot 多環境配置

在實際項目開發中&#xff0c;不同環境往往有不同的配置需求&#xff1a; 開發環境&#xff08;dev&#xff09;&#xff1a;本地調試&#xff0c;連接測試數據庫&#xff1b;測試環境&#xff08;test&#xff09;&#xff1a;接口聯調&#xff0c;接近真實場景&#xff1b;生…

延凡智慧醫院數字孿生平臺

延凡智慧醫院數字孿生平臺是延凡科技依托物聯網、數字孿生、AI 算法及邊緣計算技術打造的醫療場景全要素數字化解決方案&#xff0c;通過構建醫院物理實體與虛擬空間的實時映射&#xff0c;實現醫療資源優化、運營效率提升及患者體驗升級。一、平臺價值&#xff08;一&#xff…

談談WebAssembly、PWA、Web Workers的作用和場景

WebAssembly、PWA 和 Web Workers 是現代 Web 開發中提升性能、擴展能力的重要技術&#xff0c;各自解決不同場景的問題&#xff0c;以下結合實際使用經驗分析&#xff1a;一、WebAssembly&#xff08;Wasm&#xff09;&#xff1a;高性能代碼執行作用&#xff1a;WebAssembly …