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

【AI系统】MobileFormer

MobileFormer

在本文中,将介绍一种新的网络-MobileFormer,它实现了 Transformer 全局特征与 CNN 局部特征的融合,在较低的成本内,创造一个高效的网络。通过本节,让大家去了解如何将 CNN 与 Transformer 更好的结合起来,同时实现模型的轻量化。

MobileFormer

MobileFormer:一种通过双线桥将 MobileNet 和 Transformer 并行的结构。这种方式融合了 MobileNet 局部性表达能力和 Transformer 全局表达能力的优点,这个桥能将局部性和全局性双向融合。和现有 Transformer 不同,Mobile-Former 使用很少的 tokens(例如 6 个或者更少)随机初始化学习全局先验,计算量更小。

并行结构

Mobile-Former 将 MobileNet 和 Transformer 并行化,并通过双向交叉注意力连接(下见图)。Mobile(指 MobileNet)采用图像作为输入( X ∈ R H W × 3 X\in R^{HW \times 3} XRHW×3),并应用反向瓶颈块提取局部特征。Former(指 Transformers)将可学习的参数(或 tokens)作为输入,表示为 Z ∈ R M × d Z\in R^{M\times d} ZRM×d,其中 M 和 d 分别是 tokens 的数量和维度,这些 tokens 随机初始化。与视觉 Transformer(ViT)不同,其中 tokens 将局部图像 patch 线性化,Former 的 tokens 明显较少(M≤6),每个代表图像的全局先验知识。这使得计算成本大大降低。

在这里插入图片描述

低成本双线桥

Mobile 和 Former 通过双线桥将局部和全局特征双向融合。这两个方向分别表示为 Mobile→Former 和 Mobile←Former。我们提出了一种轻量级的交叉注意力模型,其中映射( W Q W^{Q} WQ, W K W^{K} WK, W V W^{V} WV)从 Mobile 中移除,以节省计算,但在 Former 中保留。在通道数较少的 Mobile 瓶颈处计算交叉注意力。具体而言,从局部特征图 X 到全局 tokens Z 的轻量级交叉注意力计算如下:

A X − > Z = [ A t t n ( z i ~ W i Q , x i ~ , x i ~ ) ] i = 1 : h W o (1) A_{X->Z} = [Attn(\widetilde{z_{i}}W_{i}^{Q},\widetilde{x_{i}},\widetilde{x_{i}})]_{i=1:h}W^{o}\tag{1} AX>Z=[Attn(zi WiQ,xi ,xi )]i=1:hWo(1)

其中局部特征 X 和全局 tokens Z 被拆分进入 h 个头,即 X = [ x 1 ~ . . . x h ~ ] , Z = [ z 1 ~ . . . z h ~ ] X=[\widetilde{x_{1}}...\widetilde{x_{h}}],Z=[\widetilde{z_{1}}...\widetilde{z_{h}}] X=[x1 ...xh ],Z=[z1 ...zh ] 表示多头注意力。第 i 个头的拆分 z 1 ~ ∈ R M × d h \widetilde{z_{1}}\in R^{M \times \frac {d}{h} } z1 RM×hd 与第 i 个 token z 1 ~ ∈ R d \widetilde{z_{1}}\in R^{d} z1 Rd 不同。 W i Q W_{i}^{Q} WiQ 是第 i 个头的查询映射矩阵。 W O W^{O} WO 用于将多个头组合在一起。Attn(Q,K,V)是查询 Q、键 K 和值 V 的标准注意力函数,即:

s o f t m a x ( Q K T d k ) softmax(\frac{QK^{T}}{\sqrt{d_{k}}}) softmax(dk QKT)

其中 [ . ] 1 : h [.]_{1:h} [.]1:h 表示将 h 个元素 concat 到一起。需要注意的是,键和值的映射矩阵从 Mobile 中移除,而查询的映射矩阵 W i Q W_{i}^{Q} WiQ 在 Former 中保留。类似地从全局到局部的交叉注意力计算如下:

A Z − > X = [ A t t n ( x i ~ , z i ~ ⊙ W i K , z i ~ ⊙ W i V ) ] i = 1 : h (2) A_{Z->X} = [Attn(\widetilde{x_{i}},\widetilde{z_{i}}\odot W_{i}^{K},\widetilde{z_{i}}\odot W_{i}^{V})]_{i=1:h}\tag{2} AZ>X=[Attn(xi ,zi WiK,zi WiV)]i=1:h(2)

其中 W i K W_{i}^{K} WiK W i V W_{i}^{V} WiV 分别是 Former 中键和值的映射矩阵。而查询的映射矩阵从 Mobile 中移除。

Mobile-Former 块

Mobile-Former 由 Mobile-Former 块组成。每个块包含四部分:Mobile 子块、Former 子块以及双向交叉注意力 Mobile←Former 和 Mobile→Former(如下图所示)。

在这里插入图片描述

输入和输出:Mobile-Former 块有两个输入:(a) 局部特征图 X ∈ R H W × C X\in R^{HW\times C} XRHW×C,为 C 通道、高度 H 和宽度 W,以及(b) 全局 tokens Z ∈ R M × d Z\in R^{M\times d} ZRM×d,其中 M 和 d 是分别是 tokens 的数量和维度,M 和 d 在所有块中一样。Mobile-Former 块输出更新的局部特征图 X X X 和全局 tokens Z Z Z,用作下一个块的输入。

Mobile 子块:如上图所示,Mobile 子块将特征图 X X X 作为输入,并将其输出作为 Mobile←Former 的输入。这和反向瓶颈块略有不同,其用动态 ReLU 替换 ReLU 作为激活函数。不同于原始的动态 ReLU,在平均池化特征图上应用两个 MLP 以生成参数。我们从 Former 的第一个全局 tokens 的输出 z 1 ′ z'_{1} z1 应用两个 MLP 层(上图中的θ)保存平均池化。其中所有块的 depth-wise 卷积的核大小为 3×3。

class Mobile(nn.Module):def __init__(self, in_channel, expand_size, out_channel, token_demension, kernel_size=3, stride=1, k=2):super(Mobile, self).__init__()self.in_channel, self.expand_size, self.out_channel = in_channel, expand_size, out_channelself.token_demension, self.kernel_size, self.stride, self.k = token_demension, kernel_size, stride, kif stride == 2:self.strided_conv = nn.Sequential(nn.Conv2d(self.in_channel, self.expand_size, kernel_size=3, stride=2, padding=int(self.kernel_size // 2), groups=self.in_channel).cuda(),nn.BatchNorm2d(self.expand_size).cuda(),nn.ReLU6(inplace=True).cuda())self.conv1 = nn.Conv2d(self.expand_size, self.in_channel, kernel_size=1, stride=1).cuda()self.bn1 = nn.BatchNorm2d(self.in_channel).cuda()self.ac1 = DynamicReLU(self.in_channel, self.token_demension, k=self.k).cuda()      self.conv2 = nn.Conv2d(self.in_channel, self.expand_size, kernel_size=3, stride=1, padding=1, groups=self.in_channel).cuda()self.bn2 = nn.BatchNorm2d(self.expand_size).cuda()self.ac2 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()          self.conv3 = nn.Conv2d(self.expand_size, self.out_channel, kernel_size=1, stride=1).cuda()self.bn3 = nn.BatchNorm2d(self.out_channel).cuda()else:self.conv1 = nn.Conv2d(self.in_channel, self.expand_size, kernel_size=1, stride=1).cuda()self.bn1 = nn.BatchNorm2d(self.expand_size).cuda()self.ac1 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()      self.conv2 = nn.Conv2d(self.expand_size, self.expand_size, kernel_size=3, stride=1, padding=1, groups=self.expand_size).cuda()self.bn2 = nn.BatchNorm2d(self.expand_size).cuda()self.ac2 = DynamicReLU(self.expand_size, self.token_demension, k=self.k).cuda()          self.conv3 = nn.Conv2d(self.expand_size, self.out_channel, kernel_size=1, stride=1).cuda()self.bn3 = nn.BatchNorm2d(self.out_channel).cuda()def forward(self, x, first_token):if self.stride == 2:x = self.strided_conv(x)x = self.bn1(self.conv1(x))x = self.ac1(x, first_token)x = self.bn2(self.conv2(x))x = self.ac2(x, first_token)return self.bn3(self.conv3(x))

Former 子块:Former 子块是一个标准的 Transformer 块,包括一个多头注意力(MHA)和一个前馈网络(FFN)。在 FFN 中,膨胀率为 2(代替 4)。使用 post 层归一化。Former 在 Mobile→Former 和 Mobile←Former 之间处理(见上图)。

class Former(nn.Module):def __init__(self, head, d_model, expand_ratio=2):super(Former, self).__init__()self.d_model = d_modelself.expand_ratio = expand_ratioself.eps = 1e-10self.head = headassert self.d_model % self.head == 0self.d_per_head = self.d_model // self.headself.QVK = MLP([self.d_model, self.d_model * 3], bn=False).cuda()self.Q_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()self.K_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()self.V_to_heads = MLP([self.d_model, self.d_model], bn=False).cuda()self.heads_to_o = MLP([self.d_model, self.d_model], bn=False).cuda()self.norm = nn.LayerNorm(self.d_model).cuda()self.mlp = MLP([self.d_model, self.expand_ratio * self.d_model, self.d_model], bn=False).cuda()self.mlp_norm = nn.LayerNorm(self.d_model).cuda()def forward(self, x):QVK = self.QVK(x)Q = QVK[:, :, 0: self.d_model]Q = rearrange(self.Q_to_heads(Q), 'n m ( d h ) -> n m d h', h=self.head)  K = QVK[:, :, self.d_model: 2 * self.d_model]K = rearrange(self.K_to_heads(K), 'n m ( d h ) -> n m d h', h=self.head)   V = QVK[:, :, 2 * self.d_model: 3 * self.d_model]V = rearrange(self.V_to_heads(V), 'n m ( d h ) -> n m d h', h=self.head)  scores = torch.einsum('nqdh, nkdh -> nhqk', Q, K) / (np.sqrt(self.d_per_head) + self.eps)   scores_map = F.softmax(scores, dim=-1)v_heads = torch.einsum('nkdh, nhqk -> nhqd', V, scores_map) v_heads = rearrange(v_heads, 'n h q d -> n q ( h d )')attout = self.heads_to_o(v_heads)attout = self.norm(attout)  attout = self.mlp(attout)attout = self.mlp_norm(attout)  return attout  

Mobile→Former:文章提出的轻量级交叉注意力(式 1)用于将局部特征 X 融合到全局特征 tokens Z。与标准注意力相比,映射矩阵的键 W K W^{K} WK 和值 W V W^{V} WV(在局部特征 X 上)被移除以节省计算(见上图)。


class Mobile_Former(nn.Module):'''局部特征 -> 全局特征'''def __init__(self, d_model, in_channel):super(Mobile_Former, self).__init__()self.d_model, self.in_channel = d_model, in_channelself.project_Q = nn.Linear(self.d_model, self.in_channel).cuda()self.unproject = nn.Linear(self.in_channel, self.d_model).cuda()self.eps = 1e-10self.shortcut = nn.Sequential().cuda()def forward(self, local_feature, x):_, c, _, _ = local_feature.shapelocal_feature = rearrange(local_feature, 'n c h w -> n ( h w ) c')   project_Q = self.project_Q(x)   scores = torch.einsum('nmc , nlc -> nml', project_Q, local_feature) * (c ** -0.5)scores_map = F.softmax(scores, dim=-1)  fushion = torch.einsum('nml, nlc -> nmc', scores_map, local_feature)unproject = self.unproject(fushion) return unproject + self.shortcut(x)

Mobile-Former:这里的交叉注意力(式 2)与 Mobile→Former 的方向相反,其将全局 tokens 融入本地特征。局部特征是查询,全局 tokens 是键和值。因此,我们保留键 W K W^{K} WK 和值 W V W^{V} WV 中的映射矩阵,但移除查询 W Q W^{Q} WQ 的映射矩阵以节省计算,如上图所示。

计算复杂度:Mobile-Former 块的四个核心部分具有不同的计算成本。给定输入大小为 H W × C HW\times C HW×C 的特征图,以及尺寸为 d 的 M 个全局 tokens,Mobile 占据了大部分的计算量 O ( H W C 2 ) O(HWC^{2}) O(HWC2)。Former 和双线桥是重量级的,占据不到总计算成本的 20%。具体而言,Former 的自注意力和 FFN 具有复杂度 O ( M 2 d + M d 2 ) O(M^{2}d+Md^{2}) O(M2d+Md2)。Mobile→Former 和 Mobile←Former 共享交叉注意力的复杂度 O ( M H W C + M d C ) O(MHWC+MdC) O(MHWC+MdC)

class Former_Mobile(nn.Module):'''全局特征 -> 局部特征'''def __init__(self, d_model, in_channel):super(Former_Mobile, self).__init__()self.d_model, self.in_channel = d_model, in_channelself.project_KV = MLP([self.d_model, 2 * self.in_channel], bn=False).cuda()self.shortcut = nn.Sequential().cuda()def forward(self, x, global_feature):res = self.shortcut(x)n, c, h, w = x.shapeproject_kv = self.project_KV(global_feature)K = project_kv[:, :, 0 : c]  V = project_kv[:, :, c : ]  x = rearrange(x, 'n c h w -> n ( h w ) c') scores = torch.einsum('nqc, nkc -> nqk', x, K) scores_map = F.softmax(scores, dim=-1) v_agg = torch.einsum('nqk, nkc -> nqc', scores_map, V)  feature = rearrange(v_agg, 'n ( h w ) c -> n c h w', h=h)return feature + res

网络结构

一个 Mobile-Former 架构,图像大小为 224×224,294M FLOPs,以不同的输入分辨率堆叠 11 个 Mobile-Former 块。所有块都有 6 个维度为 192 的全局 tokens。它以一个 3×3 的卷积作为 stem 和第一阶段的轻量瓶颈块,首先膨胀,然后通过 3×3 depth-wise 卷积和 point-wise 卷积压缩通道数。第 2-5 阶段包括 Mobile-Former 块。每个阶段的下采样,表示为 Mobile-Former 分类头在局部特征应用平均池化,首先和全局 tokens concat 到一起,然后经过两个全连接层,中间是 h-swish 激活函数。Mobile-Former 有七种模型,计算成本从 26M 到 508M FLOPs。它们的结构相似,但宽度和高度不同。

class MobileFormerBlock(nn.Module):def __init__(self, in_channel, expand_size, out_channel, d_model, stride=1, k=2, head=8, expand_ratio=2):super(MobileFormerBlock, self).__init__()self.in_channel, self.expand_size, self.out_channel = in_channel, expand_size, out_channelself.d_model, self.stride, self.k, self.head, self.expand_ratio = d_model, stride, k, head, expand_ratioself.mobile = Mobile(self.in_channel, self.expand_size, self.out_channel, self.d_model, kernel_size=3, stride=self.stride, k=self.k).cuda()self.former = Former(self.head, self.d_model, expand_ratio=self.expand_ratio).cuda()self.mobile_former = Mobile_Former(self.d_model, self.in_channel).cuda()self.former_mobile = Former_Mobile(self.d_model, self.out_channel).cuda()def forward(self, local_feature, global_feature):z_hidden = self.mobile_former(local_feature, global_feature)z_out = self.former(z_hidden)x_hidden = self.mobile(local_feature, z_out[:, 0, :])x_out = self.former_mobile(x_hidden, z_out)return x_out, z_out

如果您想了解更多AI知识,与AI专业人士交流,请立即访问昇腾社区官方网站https://www.hiascend.com/或者深入研读《AI系统:原理与架构》一书,这里汇聚了海量的AI学习资源和实践课程,为您的AI技术成长提供强劲动力。不仅如此,您还有机会投身于全国昇腾AI创新大赛和昇腾AI开发者创享日等盛事,发现AI世界的无限奥秘~

相关文章:

【AI系统】MobileFormer

MobileFormer 在本文中,将介绍一种新的网络-MobileFormer,它实现了 Transformer 全局特征与 CNN 局部特征的融合,在较低的成本内,创造一个高效的网络。通过本节,让大家去了解如何将 CNN 与 Transformer 更好的结合起来…...

《重生之我学VTK》-- 基本介绍与相关概念

目录 简介 可视化模型 示例(圆锥体) VTK官方用户手册(中文C版)附末尾,有需要的直接划到末尾 简介 VTK(Visualization Toolkit)是一个开源的、跨平台的软件系统,主要用于三维计算机图…...

HTML笔记()蜘蛛纸牌之卡牌拖拽

效果 代码 <!DOCTYPE html> <html><head><style>body{display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #2b2b2b;position: relative;}.card{/*设置卡牌的外观*/width: 150px;height: 200px;background-…...

记一次跑前端老项目的问题

记一次跑前端老项目的问题 一、前言二、过程1、下载依赖2、启动项目3、打包 一、前言 在一次跑前端老项目的时候&#xff0c;遇到了一些坑&#xff0c;这里记录一下。 二、过程 1、下载依赖 使用 npm install下载很久&#xff0c;然后给我报了个错 core-js2.6.12: core-js…...

041_Compare_Matrix_Squre_Sum_in_MATLAB中矩阵平方和的比较

矩阵平方和的计算 矩阵平方和的定义 矩阵平方和的定义是对矩阵中的每一个元素进行平方&#xff0c;然后求和。 对于一个矩阵 A A A&#xff0c;其平方和定义为&#xff1a; sum ∑ i 1 m ∑ j 1 n A ( i , j ) 2 \text{sum} \sum_{i1}^{m}\sum_{j1}^{n} A(i,j)^2 sumi1∑…...

vue3中 axios 发送请求 刷新token 封装axios

service.js 页面 import axios from axios // 创建axios实例 const instance axios.create({baseURL: http://gcm-test.jhzhkj.cn:8600/h5card/,timeout: 5000, // 请求超时时间headers: {get: {Content-Type: application/x-www-form-urlencoded},post: {Content-Type: appl…...

vue+mars3d叠加展示arcgis动态服务

数据格式&#xff1a;使用arcgis发布的动态服务 叠加和移除arcgis服务图层的方法 //加载arcgis地图服务function arcgisServer(i,d,m,p){i[d.data] new mars3d.layer.ArcGisLayer({name:d.label,url:p,flyTo: true})m.addLayer(i[d.data])}//移除arcgis服务范围线function rem…...

PostgreSQL 中进行数据导入和导出

在数据库管理中&#xff0c;数据的导入和导出是非常常见的操作。特别是在 PostgreSQL 中&#xff0c;提供了多种工具和方法来实现数据的有效管理。无论是备份数据&#xff0c;还是将数据迁移到其他数据库&#xff0c;或是进行数据分析&#xff0c;掌握数据导入和导出的技巧都是…...

Stable Audio Open模型部署教程:用AI打造独家节拍,让声音焕发新活力!

Stable Audio Open 是一个开源的文本到音频模型&#xff0c;允许用户从简单的文本提示中生成长达 47 秒的高质量音频数据。该模型非常适合创建鼓点、乐器即兴演奏、环境声音、拟音录音和其他用于音乐制作和声音设计的音频样本。用户还可以根据他们的自定义音频数据微调模型&…...

python更新程序并部署服务器服务

本地客户端程序 import json import hashlib import os import shutil import requests from pathlib import Pathclass AutoUpdater:def __init__(self, config_path"http://【XXXIP地址】/update_config"):self.config_path config_pathself.config Nonewith op…...

Nmap 扫描技巧:自定义端口、扫描速度与并行化设置

Nmap 扫描技巧&#xff1a;自定义端口、扫描速度与并行化设置 在进行网络安全扫描时&#xff0c;Nmap 是一个非常强大的工具。除了默认扫描 1000 个端口外&#xff0c;你还可以根据需要自定义扫描的端口、调整扫描速度以及优化扫描并行化。今天&#xff0c;我们就来介绍如何通…...

从 HTML 到 CSS:开启网页样式之旅(五)—— CSS盒子模型

从 HTML 到 CSS&#xff1a;开启网页样式之旅&#xff08;五&#xff09;—— CSS盒子模型 前言一、盒子模型的组成margin&#xff08;外边距&#xff09;&#xff1a;border&#xff08;边框&#xff09;&#xff1a;padding&#xff08;内边距&#xff09;&#xff1a;conten…...

Linux命令行下载工具

1. curl 1.1. 介绍 curl是一个功能强大的命令行工具&#xff0c;用于在各种网络协议下传输数据。它支持多种协议&#xff0c;包括但不限于 HTTP、HTTPS、FTP、FTPS、SCP、SFTP、SMTP、POP3、IMAP 等&#xff0c;这使得它在网络数据交互场景中有广泛的应用。curl可以模拟浏览器…...

Navicat 连接 SQL Server 详尽指南

Navicat 是一款功能强大的数据库管理工具&#xff0c;它提供了直观的图形界面&#xff0c;使用户能够轻松地管理和操作各种类型的数据库&#xff0c;包括 SQL Server。本文将详尽介绍如何使用 Navicat 连接到 SQL Server 数据库&#xff0c;包括安装设置、连接配置、常见问题排…...

黑马JavaWeb-day06、07、08(SQL部分) _

文章目录 MYSQL概述数据模型SQL简介SQL分类 DDL数据库操作表操作 DML增&#xff08;INSERT&#xff09;改&#xff08;UPDATE&#xff09;删&#xff08;DELETE&#xff09; DQL基本查询条件查询&#xff08;where&#xff09;分组查询&#xff08;group by&#xff09;排序查询…...

Redis(1)

Redis是一个在内存中存储数据的中间件。 1.在内存中存储数据。 通过数据结构来存储&#xff0c;mysql通过表的方式存储数据&#xff0c;是关系型数据库&#xff0c;redis通过键值对存储&#xff0c;key的类型是string&#xff0c;value的类型是非关系型数据库。 2.可编程的 …...

工具类-列表请求工具 useList

useList 用于列表请求的基于 vue 3 的 hooks&#xff0c;接收请求函数、请求参数等数据&#xff0c;自动生成请求请求函数&#xff0c;分页信息等 本文有涉及到 http 请求工具和接口返回格式的内容&#xff1a; http 工具&#xff1a;一个基于 axios 封装的请求工具Response…...

5G终端自动拔号脚本

5G终端自动拔号脚本 5G终端自动拔号脚本 5G终端自动拔号脚本&#xff0c; 先进入飞行模式&#xff0c;再切出飞行模式&#xff0c; 最后 查询UE IP地址 5G终端自动拔号脚本 input$1 if [ "$input"x "1"x ]; then cmdatcfun1echo "start dialing &…...

3-1 C指针与数组

前言&#xff1a; 基于本人回顾与思考&#xff0c;仅供学习参考 1.0 数组名称的用途 注&#xff1a;可以用于求数组占用的内存空间:sizeof(arrName);此时数组名称代表整个数组 int32 t buffer[5] {1,2,3,4,5};int32 t size sizeof(buffer);printf("sizeof(buffer) %d.\…...

swift 屏幕录制

步骤 1&#xff1a;导入 ReplayKit import ReplayKit步骤 2&#xff1a;开始录屏 let screenRecorder RPScreenRecorder.shared() // 麦克风或系统音频 screenRecorder.isMicrophoneEnabled truefunc startRecording() {guard screenRecorder.isAvailable else {print(&quo…...

Graphviz 的详细介绍

Graphviz 的详细介绍 Graphviz 是一个开源的图形可视化软件&#xff0c;专门用于生成结构化图形。它特别适合用于表示关系图、流程图、依赖关系图和树状结构等类型的图表。Graphviz 使用一种名为 DOT 的脚本语言描述图形&#xff0c;通过解析 DOT 文件生成图像。 Graphviz 的特…...

前端工程化

文章目录 前端工程化模块化与组件化代码规范与风格统一自动化构建与部署性能优化版本控制与团队协作自动化测试 前端工程化 前端工程化是一种将软件工程的方法应用于前端开发的过程&#xff0c;旨在提高开发效率、降低维护成本、优化代码质量&#xff0c;并支持团队协作。以下…...

【LC】41. 缺失的第一个正数

题目描述&#xff1a; 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围…...

高频面试题(含笔试高频算法整理)基本总结回顾29

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…...

Hive 的 Hook 机制 完全解析

Hive 的 Hook 是一种扩展机制&#xff0c;允许用户在执行查询时自定义行为&#xff0c;例如日志记录、审计或其他操作。Hook 通常在 Hive 的生命周期中某些关键节点被触发&#xff0c;开发者可以插入自定义代码执行特定任务。 一、Hook 的用途和核心概念 1. 用途 审计&#x…...

远程debug

这里写自定义目录标题 一、首先配置idea二、配置jvm1、将刚才idea生成的jvm指令复制下来&#xff0c;就是如下内容&#xff08;注意要从你的idea中复制&#xff09;2、在粘贴之前&#xff0c;要拼接上java-jar命令&#xff0c;还有servery,suspendy命令&#xff0c;最后拼接项目…...

一些常见网络安全术语

1、黑帽 为非法目的进行黑客攻击的人&#xff0c;通常是为了经济利益。他们进入安全网络以销毁&#xff0c;赎回&#xff0c;修改或窃取数据&#xff0c;或使网络无法用于授权用户。这个名字来源于这样一个事实&#xff1a;老式的黑白西部电影中的恶棍很容易被电影观众识别&…...

golang学习,小结

切片 切片&#xff0c;底层就是数组&#xff0c;len&#xff08;切片的长度&#xff09;和cap&#xff08;容量&#xff0c;切片的空间&#xff09; 从一个数组来得到切片&#xff0c;修改切片会修改原来的数组&#xff0c;数据会收到影响 我们可以通过内置的 append 函数对一…...

【C++ map和set】数据的吟游诗:Map与Set的双城记

公主请阅 set1.序列式容器和关联式容器2.set的介绍3.set的构造和迭代器部分set可以进行去重操作的&#xff0c;在去重的同时可以对插入进来的数字进行排序的操作4.set的增删查inserterasefindupper_bound和 lower_bound 5.multiset和set的差异6相关题目349.两个数组的交集142.环…...

leetcode 之 二分查找(java)(3)

文章目录 5. 81. 搜索旋转排序数组 II6. 378、有序矩阵中第k个小的元素 5. 81. 搜索旋转排序数组 II 题目描述&#xff1a; 已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#…...

后端返回前端的数据量过大解决方案

后端返回前端的数据量过大解决方案 性能面板(Performance) chrome调试指南 原因 遇到一个页面有好几个表格&#xff0c;部分表格采用虚拟滚动条 数据量有点大 接近快60s了&#xff0c;看一下是哪里导致的慢 后台请求方法执行并不慢 2024-12-04 15:21:52.889 INFO 69948 …...

STL算法之其它算法_下

random_shuffle 这个算法将[first,last)的元素次序随机排列。也就说&#xff0c;在N!中可能的元素排列中随机选出一种&#xff0c;此处N为last-first。 N个元素的序列&#xff0c;其排列方式为N!中&#xff0c;random_shuffle会产生一个均匀分布&#xff0c;因此任何一个排列被…...

MySQL如何区分幻读和不可重复读

在MySQL中&#xff0c;幻读和不可重复读都是并发事务中可能出现的问题&#xff0c;但它们的表现和原因略有不同。 不可重复读 (Non-Repeatable Read) 不可重复读是指在同一个事务内&#xff0c;多次读取同一行数据时&#xff0c;可能会得到不同的结果。这种情况发生在一个事务…...

html ul li 首页渲染多条数据 但只展示八条,其余的数据全部隐藏,通过icon图标 进行展示

<div style"float: left;" id"showMore"> 展开 </div> <div style"float: left;“id"hideLess"> 收起 </div> var data document.querySelectorAll(.allbox .item h3 a); const list document.querySelectorAl…...

Vue3安装 运行教程

本文是综合了所有vue安装教程而成 更细化 更简略 希望对各位读者有所帮助&#xff01; Vue安装 1. Vue-cli脚手架安装 安装vue的方式有很多 我们这里选择npm方式安装vue npm方式 npm方式安装vue&#xff0c;详细介绍见下文。 1.node.js安装和配置 安装npm 需要安装note.js&…...

Spring事务的一道面试题

每次聊起Spring事务&#xff0c;好像很熟悉&#xff0c;又好像很陌生。本篇通过一道面试题和一些实践&#xff0c;来拆解几个Spring事务的常见坑点。 原理 Spring事务的原理是&#xff1a;通过AOP切面的方式实现的&#xff0c;也就是通过代理模式去实现事务增强。 具体过程是&a…...

PHP SM4 加密

PHP SM4 加密 sm4基类 class Sm4 {private $ck [0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,0xc0c7ced5, 0xdce3ea…...

群控系统服务端开发模式-应用开发-短信工厂腾讯云短信开发

一、腾讯云短信工厂开发 1、添加框架对应的SDK composer require tencentcloud/tencentcloud-sdk-php 2、添加腾讯云工厂 在根目录下extend文件夹下Sms文件夹下channel文件夹下&#xff0c;创建腾讯云短信发送工厂并命名为TencentSmsSender。记住&#xff0c;一定要在腾讯云短…...

vue key属性强制刷新组件

在 Vue 中&#xff0c;key 属性通常用来帮助 Vue 跟踪每个组件或元素的身份&#xff0c;尤其是在使用 v-for 渲染列表时。当 key 值发生变化时&#xff0c;Vue 会销毁并重新渲染组件&#xff0c;这也可以用于强制刷新组件。 如果你想强制刷新一个组件&#xff0c;可以通过动态…...

浪潮X86服务器NF5280、8480、5468、5270使用inter VROC Raid key给NVME磁盘做阵列

浪潮服务器inter VROC Raid key给NVME磁盘做阵列方法 Inter VROC技术简介Raid Key 授权&#xff0c;即VROC SKU兼容性处理器兼容性列表平台和芯片组兼容性列表各Raid级别最大磁盘数量硬盘型号操作系统 服务器上的操作安装Raid Key确认服务器能识别硬盘识别磁盘所在的通道及服务…...

最长最短单词

最长最短单词 C语言实现C实现Java实现Python实现 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 输入1行句子&#xff08;不多于200个单词&#xff0c;每个单词长度不超过100&#xff09;&#xff0c;只包含字母、空格和逗号。单词由至少一…...

Muduo网络库剖析 --- 架构设计

文章目录 前言概述篇一、Muduo网络库简介Reactor事件处理模式 二、基于muduo实现简易聊天服务器实现测试运行 三、muduo的架构设计Reacor模式muduo框架架构解析主从Reactor工作流程主线程(main Reactor)工作线程(sub Reactor) 线程分配与负载均衡 四、总结线程分配与负载均衡 四…...

lwip raw、netcoon、socket三种接口编程的区别

目录 一、前言 二、LWIP 简介 三、LWIP RAW 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 四、LWIP NETCONN 编程 1.概念与原理 2.编程模型与流程 3.示例代码 4.优点与缺点 五、LWIP SOCKET 编程 1.概念与原理 2.编程模型与流程 3.示例代码 …...

在办公室环境中用HMD替代传统显示器的优势

VR头戴式显示器&#xff08;HMD&#xff09;是进入虚拟现实环境的一把钥匙&#xff0c;拥有HMD的您将能够在虚拟现实世界中尽情探索未知领域&#xff0c;正如如今的互联网一样&#xff0c;虚拟现实环境能够为您提供现实中无法实现的或不可能实现的事。随着技术的不断进步&#…...

P3916 图的遍历(Tarjan缩点和反向建边)

P3916 图的遍历 - 洛谷 | 计算机科学教育新生态 写法一&#xff1a;Tarjan 思路&#xff1a;先运用Tarjan算法得到每个连通块中最大的编号&#xff0c;然后对每个连通块进行缩点重新建图&#xff0c;进行dfs&#xff0c;得到缩点后的连通块能够达到的最大编号。 Code: conste…...

Element UI 的 el-tree 组件e中默认展开前两层,设置 default-expanded-keys 属性来实现

在使用 Element UI 的 el-tree 组件时&#xff0c;如果你希望默认展开树的前两层节点&#xff0c;可以通过设置 default-expanded-keys 属性来实现。这个属性接受一个数组&#xff0c;数组中的值是需要默认展开的节点的 key。 首先&#xff0c;你需要确保你的每个树节点都有唯…...

Vue 项目中未登录状态如何统一处理

在 Vue 项目中&#xff0c;处理未登录状态&#xff08;比如用户访问需要登录的页面时&#xff09;是一项常见的需求。为了实现这一需求&#xff0c;我们通常使用 Vue Router 配合 Vuex 或者 Vue 的全局状态管理来统一处理未登录的状态&#xff0c;确保用户只能访问允许的页面。…...

Java 集合:强大的数据管理工具

在 Java 编程中&#xff0c;集合是一种非常重要的工具&#xff0c;它提供了一种方便的方式来存储和操作一组对象。本文将深入探讨 Java 集合框架&#xff0c;包括其主要类型、特点、用法以及一些最佳实践。 一、引言 在软件开发过程中&#xff0c;我们经常需要处理一组数据。…...

Creating Server TCP listening socket *:6379: bind: No error

启动redis报错&#xff1a;Creating Server TCP listening socket *:6379: bind: No error 解决方案&#xff1a; 1、直接在命令行中输入 redis-cli.exe 2、输入shutdown&#xff0c;关闭 3、输exit&#xff0c;退出 4、重新输入 redis-server.exe redis.windows.conf&…...

iOS免费共享企业证书、苹果最新企业证书免费获取

前言 大家可能都注意到了&#xff0c;苹果手机和安卓手机在安装软件上有点不一样。如果你在苹果手机上想装那些没在官方商店&#xff08;App Store&#xff09;里的软件&#xff0c;那就得给它们“签个名”&#xff0c;就像是给它们盖个章&#xff0c;这样手机才能认识它们&am…...