在 AMD GPU 上构建深度学习推荐模型
Deep Learning Recommendation Models on AMD GPUs — ROCm Blogs
2024 年 6 月 28 日 发布者 Phillip Dang
在这篇博客中,我们将演示如何在支持 ROCm 的 AMD GPU 上使用 PyTorch 构建一个简单的深度学习推荐模型 (DLRM)。
简介
DLRM 位于推荐系统和深度学习的交汇处,利用神经网络在庞大的数据集中预测用户与物品的交互。它是一种强大的工具,在各种领域中个性化推荐,从电子商务到内容流媒体平台。
正如 《深度学习推荐模型:个性化和推荐系统》 中讨论的那样,DLRM 具有几个组件:
-
多个嵌入表将稀疏特征(每个特征一个)映射到密集表示。
-
一个底部多层感知器 (MLP),将密集特征转换为与嵌入向量长度相同的密集表示。
-
一个特征交互层,计算所有嵌入向量和处理后的密集特征之间的点积。
-
一个顶部多层感知器 (MLP),输入交互特征与原始处理后的密集特征串联,并输出对数 (logits)。
以下图表总结了 DLRM 的架构,来自 《深度学习推荐模型:深度探究》。
DLRM 与其他深度学习网络的区别之一是它“在结构上以一种模仿因子分解机的方式特定地交互嵌入,通过只考虑最终 MLP 中成对嵌入之间点积产生的交叉项来显著减少模型的维度”[参考文献]。这使 DLRM 相比于其他网络如 Deep 和 Cross 大幅减少了模型的维度。
本博客强调简单性。我们将通过一个简单的数据集来预测展示广告的点击率,构建一个基本的 DLRM 架构,并为理解其内部工作原理提供坚实的基础。鼓励用户调整和扩展模型,探索更多复杂性,以适应他们的具体需求。
前提条件
-
ROCm
-
PyTorch
-
Linux 操作系统
-
An AMD GPU
确保系统识别到你的 GPU:
! rocm-smi --showproductname
================= ROCm System Management Interface ================ ========================= Product Info ============================ GPU[0] : Card series: Instinct MI210 GPU[0] : Card model: 0x0c34 GPU[0] : Card vendor: Advanced Micro Devices, Inc. [AMD/ATI] GPU[0] : Card SKU: D67301 =================================================================== ===================== End of ROCm SMI Log =========================
检查是否安装了正确版本的 ROCm.
! apt show rocm-core -a
Package: rocm-core Version: 5.7.0.50700-63~22.04 Priority: optional Section: devel Maintainer: ROCm Dev Support <rocm-dev.support@amd.com> Installed-Size: 94.2 kB Homepage: https://github.com/RadeonOpenCompute/ROCm Download-Size: 7030 B APT-Manual-Installed: no APT-Sources: http://repo.radeon.com/rocm/apt/5.7 jammy/main amd64 Packages Description: Radeon Open Compute (ROCm) Runtime software stack
确保 PyTorch 也识别到 GPU:
import torch print(f"number of GPUs: {torch.cuda.device_count()}") print([torch.cuda.get_device_name(i) for i in range(torch.cuda.device_count())])
number of GPUs: 1 ['AMD Radeon Graphics']
数据集
以下内容是基于原始 DLRM 论文 中介绍的,我们将使用 Criteo 数据集 来预测广告点击率 (CTR)。我们将预测用户在访问页面时点击给定广告的概率。
数据字段包含以下内容:
-
Label - 目标变量,指示广告是否被点击(1)或未被点击(0)。
-
I1-I13 - 一共13列整数特征(主要是计数特征)。
-
C1-C26 - 一共26列分类特征。这些特征的值已被哈希成32位以进行匿名化处理。
这些特征的具体语义未被披露,这在匿名化数据集中是常见的做法,以保护隐私和专有信息。为方便起见,我们已经下载了数据并将其包含在我们的代码库中。让我们安装和导入所需的库,并加载数据集。
! pip install --upgrade pip ! pip install --upgrade pandas ! pip install --upgrade scikit-learn
import torch import torch.nn as nn import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder, MinMaxScaler from torch.utils.data import DataLoader, TensorDataset from tqdm import tqdm
columns = ["label", *(f"I{i}" for i in range(1, 14)), *(f"C{i}" for i in range(1, 27))] df = pd.read_csv("../data/dac_sample.txt", sep="\t", names=columns ).fillna(0)
预处理
我们的预处理步骤包括对稀疏和类别特征进行序数编码,并对密集和数值特征进行最小-最大缩放。
sparse_cols = ["C" + str(i) for i in range(1, 27)] dense_cols = ["I" + str(i) for i in range(1, 14)]data = df[sparse_cols + dense_cols] data = data.astype(str) for feat in sparse_cols:lbe = LabelEncoder()data[feat] = lbe.fit_transform(data[feat]) mms = MinMaxScaler(feature_range=(0, 1)) data[dense_cols] = mms.fit_transform(data[dense_cols]) print(data.sample(5))
C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 ... I4 I5 I6 I7 I8 I9 I10 I11 I12 I13 33714 8 289 12798 19697 23 10 2279 86 2 2505 ... 0.000000 0.001729 0.013812 0.000000 0.000000 0.001027 0.000000 0.000000 0.0 0.000000 41376 8 21 6057 20081 23 5 6059 27 2 2505 ... 0.011990 0.002585 0.008840 0.000795 0.001283 0.020220 0.000000 0.028846 0.0 0.000762 21202 8 62 23836 24608 41 5 2305 8 2 2933 ... 0.004796 0.000136 0.002701 0.000568 0.005987 0.003633 0.166667 0.019231 0.0 0.003355 89866 8 113 42768 7421 23 11 827 48 2 2505 ... 0.002398 0.000118 0.000491 0.000114 0.002138 0.002133 0.166667 0.009615 0.0 0.000152 19993 327 78 31306 11660 23 0 6837 27 2 8905 ... 0.007194 0.001740 0.001105 0.002612 0.001497 0.002448 0.000000 0.038462 0.0 0.000457
我们还移除了一些类别数过多的稀疏特征,在这个数据集中大约有10,000个类别。按照Kaggle的社区讨论中的推荐,当稀疏特征的类别数超过了10,000时,模型性能的提升是微乎其微的,而且这只会不必要地增加参数的数量。
# 获取每个分类特征的类别数 num_categories = [len(data[c].unique()) for c in sparse_cols]# 只保留类别数少于10K的分类特征 indices_to_keep = [i for i, num in enumerate(num_categories) if num <= 10000] num_categories_kept = [num_categories[i] for i in indices_to_keep] sparse_cols_kept = [sparse_cols[i] for i in indices_to_keep]
最后,我们将数据拆分为训练集和测试集,然后将它们转换成 torch
张量并创建相应的数据加载器。
device = "cuda" if torch.cuda.is_available() else "cpu" batch_size = 128# 拆分数据集 X_train, X_test, y_train, y_test = train_test_split(data, df["label"], test_size=0.2, random_state=42 )# 转换成张量 # 训练集 X_train_sparse = torch.tensor(X_train[sparse_cols_kept].values, dtype=torch.long).to(device ) X_train_dense = torch.tensor(X_train[dense_cols].values, dtype=torch.float).to(device) y_train = torch.tensor(y_train.values, dtype=torch.float).unsqueeze(1).to(device)# 测试集 X_test_sparse = torch.tensor(X_test[sparse_cols_kept].values, dtype=torch.long).to(device) X_test_dense = torch.tensor(X_test[dense_cols].values, dtype=torch.float).to(device) y_test = torch.tensor(y_test.values, dtype=torch.float).unsqueeze(1).to(device)# 创建训练数据的DataLoader train_dataset = TensorDataset(X_train_sparse, X_train_dense, y_train) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) # 创建测试数据的DataLoader test_dataset = TensorDataset(X_test_sparse, X_test_dense, y_test) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
建模
让我们为我们的DLRM设置一些超参数:
device = "cuda" if torch.cuda.is_available() else "cpu" num_epochs = 10 lr = 3e-4 batch_size = 128 hidden_size = 32 embd_dim = 16
现在我们准备创建我们的DLRM。为了简化,底部和顶部的MLP将是一个简单的3层(输入、隐藏、输出)神经网络,并使用ReLU激活函数。
class FeatureInteraction(nn.Module):def __init__(self):super(FeatureInteraction, self).__init__()def forward(self, x):feature_dim = x.shape[1]concat_features = x.view(-1, feature_dim, 1)dot_products = torch.matmul(concat_features, concat_features.transpose(1, 2))ones = torch.ones_like(dot_products)mask = torch.triu(ones)out_dim = feature_dim * (feature_dim + 1) // 2flat_result = dot_products[mask.bool()]reshape_result = flat_result.view(-1, out_dim)return reshape_resultclass DLRM(torch.nn.Module):def __init__(self,embd_dim,num_categories,num_dense_feature,hidden_size,):super(DLRM, self).__init__()# 为每个分类特征创建具有相同嵌入维度的嵌入self.embeddings = nn.ModuleList([nn.Embedding(num_cat, embd_dim) for num_cat in num_categories])self.feat_interaction = FeatureInteraction()self.bottom_mlp = nn.Sequential(nn.Linear(in_features=num_dense_feature, out_features=hidden_size),nn.ReLU(),nn.Linear(hidden_size, embd_dim),)num_feat = (len(num_categories) * embd_dim + embd_dim) # 包括分类特征和数值特征num_feat_interact = num_feat * (num_feat + 1) // 2 # interaction featurestop_mlp_in = (num_feat_interact + embd_dim) # 交互特征与数值特征连接self.top_mlp = nn.Sequential(nn.Linear(in_features=top_mlp_in, out_features=hidden_size),nn.ReLU(),nn.Linear(hidden_size, 1),)def forward(self, x_cat, x_num):B = x_cat.shape[0]num_sparse_feat = x_cat.shape[1]# 查找分类特征的嵌入embed_x = torch.concat([self.embeddings[i](x_cat[:, i]).unsqueeze(1)for i in range(num_sparse_feat)]) # B, num_sparse_feat, embedding dimembed_x = embed_x.view(B, -1) # B, num_sparse_feat * embedding dim# 获取底部的数值特征dense_x = self.bottom_mlp(x_num) # B, embedding dim# 与嵌入连接x = torch.concat([embed_x, dense_x], dim=-1) # B, (num_sparse_feat+1) * embedding dim# 获取二阶交互特征x = self.feat_interaction(x) # B, n*(n+1) // 2# 与数值特征结合x = torch.concat([x, dense_x], dim=-1)# 通过顶部MLPx = self.top_mlp(x) # B, 1return x
让我们实例化我们的模型,并定义我们的损失函数和优化器。
# 实例化模型、损失函数和优化器 model = DLRM(embd_dim=embd_dim,num_categories=num_categories_kept,num_dense_feature=len(dense_cols),hidden_size=hidden_size, ) model.to(device) criterion = torch.nn.BCEWithLogitsLoss() optimizer = torch.optim.Adam(model.parameters(), lr=lr)print(f"running on {device}") print(sum(p.numel() for p in model.parameters()) / 1e6, "M parameters") print(model)
输出示例:
running on cuda 2.195553 M parameters DLRM((embeddings): ModuleList((0): Embedding(541, 16)(1): Embedding(497, 16)(2): Embedding(145, 16)(3): Embedding(12, 16)(4): Embedding(7623, 16)(5): Embedding(257, 16)(6): Embedding(3, 16)(7): Embedding(3799, 16)(8): Embedding(2796, 16)(9): Embedding(26, 16)(10): Embedding(5238, 16)(11): Embedding(10, 16)(12): Embedding(2548, 16)(13): Embedding(1303, 16)(14): Embedding(4, 16)(15): Embedding(11, 16)(16): Embedding(14, 16)(17): Embedding(51, 16)(18): Embedding(9527, 16))(feat_interaction): FeatureInteraction()(bottom_mlp): Sequential((0): Linear(in_features=13, out_features=32, bias=True)(1): ReLU()(2): Linear(in_features=32, out_features=16, bias=True))(top_mlp): Sequential((0): Linear(in_features=51376, out_features=32, bias=True)(1): ReLU()(2): Linear(in_features=32, out_features=1, bias=True)) )
训练
接下来,让我们编写两个工具函数,一个用于模型训练,一个用于在训练集和测试集上的模型评估。
def train_one_epoch():model.train()for i, (x_sparse, x_dense, y) in enumerate(tqdm(train_loader)):x_sparse = x_sparse.to(device)x_dense = x_dense.to(device)y = y.to(device)optimizer.zero_grad()logits = model(x_sparse, x_dense)loss = criterion(logits, y)loss.backward()optimizer.step()
def evaluate(dataloader, dataname):model.eval()total_samples = 0total_loss = 0total_correct = 0with torch.no_grad():for i, (x_sparse, x_dense, y) in enumerate(tqdm(dataloader)):x_sparse = x_sparse.to(device)x_dense = x_dense.to(device)y = y.to(device)logits = model(x_sparse, x_dense)probs = torch.sigmoid(logits)predictions = (probs > 0.5).long()loss = criterion(logits, y)total_loss += loss.item() * y.shape[0]total_correct += (predictions == y).sum().item()total_samples += y.shape[0]avg_loss = total_loss / total_samplesaccuracy = total_correct / total_samples * 100print(f"{dataname} accuracy = {accuracy:0.2f}%, {dataname} avg loss = {avg_loss:.6f}")return accuracy, avg_loss
现在我们准备好训练我们的模型。
for epoch in range(num_epochs):print(f"epoch {epoch+1}")train_one_epoch()evaluate(train_loader, "train")evaluate(test_loader, "test")print()
输出结果: epoch 1 100%|██████████| 625/625 [00:06<00:00, 92.18it/s] 100%|██████████| 625/625 [00:01<00:00, 351.70it/s] train accuracy = 77.37%, train avg loss = 0.535811 100%|██████████| 157/157 [00:00<00:00, 354.67it/s] test accuracy = 77.14%, test avg loss = 0.538407...epoch 10 100%|██████████| 625/625 [00:06<00:00, 98.00it/s] 100%|██████████| 625/625 [00:01<00:00, 351.16it/s] train accuracy = 77.48%, train avg loss = 0.498510 100%|██████████| 157/157 [00:00<00:00, 352.91it/s] test accuracy = 77.14%, test avg loss = 0.501544
推理
现在,我们已经有了一个DLRM模型,可以预测给定用户/广告组合的点击概率。由于Criteo数据集的特征语义未公开,我们无法重建代表真实用户或广告的有意义特征向量。出于说明目的,我们假设特征向量的一部分代表用户,其余的代表广告。特别是,为了简单起见,我们假设所有整数特征代表用户,所有分类特征代表广告。
假设在投放广告时,我们检索到了10个广告候选项。DLRM的任务是选择最佳广告候选项向用户展示。为了解释目的,我们假定检索到的广告候选项来自原始数据集的前10行,而用户是第一行中的用户。首先,我们创建一个数据加载器,将用户和广告特征组合起来,以供模型使用。
# 假设我们使用数据集的前10行作为广告候选项 num_ads = 10 df_c = pd.DataFrame(data.iloc[0:num_ads]) # 获取广告候选项特征 df_ads = df_c[df_c.columns[26:39]] # 获取第一行的用户特征 df_user = df_c[df_c.columns[0:26]].iloc[0:1] # 将用户特征复制到所有广告候选项行 df_user_rep = df_user for i in range(num_ads-1): df_user_rep = pd.concat([df_user_rep, df_user], ignore_index=True, sort=False) df_candidates = pd.concat([df_user_rep, df_ads], axis=1)# 将特征向量转换为张量 X_inf_sparse = torch.tensor(df_candidates[sparse_cols_kept].values, dtype=torch.long).to(device) X_inf_dense = torch.tensor(df_candidates[dense_cols].values, dtype=torch.float).to(device)# 创建用于推理的数据加载器 y_dummy = torch.tensor([0]*num_ads, dtype=torch.float).unsqueeze(1).to(device) inf_dataset = TensorDataset(X_inf_sparse, X_inf_dense, y_dummy) inf_loader = DataLoader(inf_dataset, batch_size=num_ads, shuffle=True)
接下来,我们创建一个函数,该函数返回具有最高点击概率的张量的索引。
def recommend():with torch.no_grad():for i, (x_sparse, x_dense, y) in enumerate(tqdm(inf_loader)):x_sparse = x_sparse.to(device)x_dense = x_dense.to(device)logits = model(x_sparse, x_dense)probs = torch.sigmoid(logits)print(probs)return torch.max(probs, dim=0).indices[0].item()
调用这个函数将得到最佳广告候选项的索引。
print('Best ad candidate is ad', recommend())
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 315.29it/s] tensor([[0.1380],[0.2414],[0.3493],[0.3500],[0.1807],[0.3009],[0.2203],[0.3639],[0.1890],[0.3702]], device='cuda:0') Best ad candidate is ad 9
我们鼓励用户进一步探索优化和超参数调优,以提高模型性能。例如,可以尝试在底部和顶部MLP中添加更多层和隐藏单元,增加嵌入维度,或者包括正则化如dropout以防止过拟合。
讨论
在这篇博客中,我们开发了一个仅用于教育目的的小规模模型。然而,在实际应用中,模型的规模要大得多。因此,高效地并行化这些模型以应对真实世界中的挑战是至关重要的。
对于DLRM模型,大多数模型参数来自embedding表,这使得在实际应用中很难实现数据并行性,因为我们需要在每个设备上复制这些表。因此,我们需要高效地将模型分布到多个设备上以解决内存限制的问题。另一方面,底层和顶层的MLP(多层感知器)参数较少,我们可以应用数据并行性,在不同设备上同时处理多个样本。
关于如何高效地实现DLRM模型的数据并行和模型并行的更多细节,请参阅原始论文《paper》以及Meta发布的这个开源库《repo》。
相关文章:

在 AMD GPU 上构建深度学习推荐模型
Deep Learning Recommendation Models on AMD GPUs — ROCm Blogs 2024 年 6 月 28 日 发布者 Phillip Dang 在这篇博客中,我们将演示如何在支持 ROCm 的 AMD GPU 上使用 PyTorch 构建一个简单的深度学习推荐模型 (DLRM)。 简介 DLRM 位于推荐系统和深度学习的交汇…...

阿里云IIS虚拟主机部署ssl证书
宝塔配置SSL证书用起来是很方便的,只需要在站点里就可以配置好,但是云虚拟主机在管理的时候是没有这个权限的,只提供了简单的域名管理等信息。 此处记录下阿里云(原万网)的IIS虚拟主机如何配置部署SSL证书。 进入虚拟…...
Python运算符列表
运算符 描述 xy,x—y 加、减,“"号可重载为连接符 x*y,x**y,x/y,x%y 相乘、求平方、相除、求余,“*”号可重载为重复,“%"号可重载为格式化 <,<,&…...

MFC图形函数学习09——画多边形函数
这里所说的多边形是指在同一平面中由多条边构成的封闭图形,强调封闭二字,否则无法进行颜色填充,多边形包括凸多边形和凹多边形。 一、绘制多边形函数 原型:BOOL Polygon(LPPOINT lpPoints,int nCount); 参数&#x…...

GaussianDreamer: Fast Generation from Text to 3D Gaussians——点云论文阅读(11)
此内容是论文总结,重点看思路!! 文章概述 本文提出了一种快速从文本生成3D资产的新方法,通过结合3D高斯点表示、3D扩散模型和2D扩散模型的优势,实现了高效生成。该方法利用3D扩散模型生成初始几何,通过噪声…...
k8s篇之控制器类型以及各自的适用场景
1. k8s中控制器介绍 在 Kubernetes 中,控制器(Controller)是集群中用于管理资源的关键组件。 它们的核心作用是确保集群中的资源状态符合用户的期望,并在需要时自动进行调整。 Kubernetes 提供了多种不同类型的控制器,每种控制器都有其独特的功能和应用场景。 2. 常见的…...
Node.js 笔记(一):express路由
代码 建立app.js文件,代码如下: const express require(express) const app express() const port 3002app.get(/,(req,res)>{res.send(hello world!)})app.listen(port,()>{console.log(sever is running on http://localhost:${port}) })问…...
bash笔记
0 $0 是脚本的名称,$# 是传入的参数数量,$1 是第一个参数,$BOOK_ID 是变量BOOK_ID的内容 1 -echo用于在命令窗口输出信息 -$():是命令替换的语法。$(...) 会执行括号内的命令,并将其输出捕获为一个字符串ÿ…...
mongoDB副本集搭建-docker
MongoDB副本集搭建-docker 注:在进行副本集搭建前,请先将服务部署docker环境并正常运行。 #通过--platform指定下载镜像的系统架构 在这我用的是mongo:4.0.28版本 arm64系统架构的mongo镜像 docker pull --platformlinux/arm64 mongo:4.0.2#查看镜像是…...
Python软体中使用 Flask 或 FastAPI 搭建简单 RESTful API 服务并实现限流功能
Python软体中使用 Flask 或 FastAPI 搭建简单 RESTful API 服务并实现限流功能 引言 在现代 web 开发中,RESTful API 已成为应用程序之间进行通信的标准方式。Python 提供了多种框架来帮助开发者快速搭建 RESTful API 服务,其中 Flask 和 FastAPI 是最受欢迎的两个框架。本…...

CentOS操作系统下安装Nacos
CentOS下安装Nacos 前言 这在Centos下安装配置Nacos 下载Linux版Nacos 首先到Nacos的 Github页面,找到所需要安装的版本 也可以右键复制到链接,然后通过wget命令进行下载 wget https://github.com/alibaba/nacos/releases/download/1.3.2/nacos-ser…...
C++设计模式之适配器模式与桥接模式,装饰器模式及代理模式相似点与不同点
适配器模式、桥接模式、装饰器模式和代理模式在形式上有一些相似之处,因为它们都涉及到对类的功能或接口的修改、增强或转换。然而,它们在动机和目的上有着显著的不同。以下是对这些模式相似点和不同点的清晰说明: 相似点: 结构…...
ThreadLocal 和 Caffeine 缓存是两种不同的缓存机制,它们在用途和实现上有明显的区别
ThreadLocal 和 Caffeine 缓存是两种不同的缓存机制,它们在用途和实现上有明显的区别: ThreadLocal 缓存: ThreadLocal 提供了线程局部变量的功能,每个线程可以访问自己的局部变量,而不会与其他线程冲突。ThreadLocal …...

Django实现智能问答助手-进一步完善
扩展 增加问答数据库,通过 Django Admin 添加问题和答案。实现更复杂的问答逻辑,比如使用自然语言处理(NLP)库。使用前端框架(如 Bootstrap)增强用户界面 1.注册模型到 Django Admin(admin.py…...

【Linux】开发工具make/Makefile、进度条小程序
Linux 1.make/Makefile1.什么是make和Makefile?2.stat命令3.Makefile单个文件的写法4.Makefile多个文件的写法 2.进度条1.回车\r、换行\n2.缓冲区3.进度条1.倒计时程序2.进度条程序 1.make/Makefile 1.什么是make和Makefile? 一个工程中的源文件不计其…...
深度学习三大框架对比与实战:PyTorch、TensorFlow 和 Keras 全面解析
深度学习框架的对比与实践 引言 在当今深度学习领域,PyTorch、TensorFlow 和 Keras 是三大主流框架。它们各具特色,分别满足从研究到工业部署的多种需求。本文将通过清晰的对比和代码实例,帮助你了解这些框架的核心特点以及实际应用。 1. 深…...

Leetcode206.反转链表(HOT100)
链接: 我的代码: class Solution { public:ListNode* reverseList(ListNode* head) {ListNode* p head;ListNode*res new ListNode(-1);while(p){ListNode*k res->next;res->next p;p p->next;res->next->next k;}return res->…...

怎么做好白盒测试?
白盒测试 一、什么是白盒测试?二、白盒测试特点三、白盒测试的设计方法1、逻辑覆盖法1、测试设计方法—语句覆盖a、用例设计如下:b、语句覆盖的局限性 2、测试设计方法—判定覆盖a、测试用例如下:b、判定覆盖的局限性 3、测试设计方法—条件覆…...

【神经网络基础】
神经网络基础 1.损失函数1.损失函数的概念2.分类任务损失函数-多分类损失:3.分类任务损失函数-二分类损失:4.回归任务损失函数计算-MAE损失5.回归任务损失函数-MSE损失6.回归任务损失函数-Smooth L1损失 2.网络优化方法1.梯度下降算法2.反向传播算法(BP算法)3.梯度下降优化方法…...

实战 | C#中使用YoloV8和OpenCvSharp实现目标检测 (步骤 + 源码)
导 读 本文主要介绍在C#中使用YoloV8实现目标检测,并给详细步骤和代码。 详细步骤 【1】环境和依赖项。 需先安装VS2022最新版,.NetFramework8.0,然后新建项目,nuget安装 YoloSharp,YoloSharp介绍: https://github.com/dme-compunet/YoloSharp 最新版6.0.1,本文…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...