深入解析PyTorch中MultiheadAttention的隐藏参数add_bias_kv与add_zero_attn
关键背景
最近在学习pytorch中的源码尤其是nn.modules下算子的实现,针对activation.py
下MultiheadAttention
下有两个不常见的参数的使用比较有趣,因为时序领域很少使用这两个参数(add_bias_kv
和add_zero_attn
),但是其目的似乎很适配时序场景,尽管逻辑上听起来其直接简单,但是还是打算手动推导分析其具体的变换。以熟悉其具体的变换。
参数作用
源码中针对其解释如下:
add_bias_kv: If specified, adds bias to the key and value sequences at dim=0. Default: ``False``.
add_zero_attn: If specified, adds a new batch of zeros to the key and value sequences at dim=1.Default: ``False``.
- add_bias_kv
- 描述:当设置
add_bias_kv=True
时,PyTorch 会在每个 attention 计算的key和value前,拼接一个 earnable向量(即bias_k, bias_v),其shape是 (1, batch_size, embed_dim)。这些bias会被视作额外的“位置”,放在序列的开头。 - 作用:这个机制可以让模型在每个序列前加上一个全局性的learnable token,类似于BERT 的 [CLS] token、ViT(Vision Transformer)的 class token、引入统一的上下文引导 token
- 描述:当设置
- add_zero_attn
- 描述:意思是,在 每个位置的 key/value 向量中都加上一个额外的
“零向量”
,并作为一个新元素插入到 batch 的 attention 范围内。 - 作用:加一个 zero-attention vector 的目的是给模型留
一个“什么都不关注”的退路
;在 encoder-decoder attention 中,decoder 可以选择性不关注任何输入位置,退回到这个零向量
;对某些任务(如语义空洞填充、视觉 patch drop)来说,zero attention 能表示“不存在”或“缺失”的信息源
;
- 描述:意思是,在 每个位置的 key/value 向量中都加上一个额外的
分析流程
✅1. 从二维矩阵开始理解
假设我们有一个序列(时序 or 文本),长度是5,模型的维度是8维,即每个token将被嵌入成一个8维的向量,那么基于seq_len = 5、embed_dim = 8显然可以得到一个shape为(5,8)的矩阵,使用torch随机生成这样一个矩阵,如下:
import torchseq_len = 5
embed_dim = 8
m = torch.randn(seq_len,embed_dim)print(m.shape)
print(m)
输出如下:
torch.Size([5, 8])
tensor([[-7.4508e-01, 1.1659e+00, -7.0335e-02, 4.3215e-01, 1.3831e-01,-1.6028e+00, 2.6052e+00, 2.9472e-02],[ 6.7109e-01, -1.2629e-01, 1.3738e+00, 7.8396e-01, 1.5244e+00,5.7940e-01, -1.1636e+00, 1.1213e+00],[-3.4683e-01, 3.3295e-01, -9.1225e-02, 4.5248e-01, 1.8235e+00,-2.4852e-01, 1.0417e+00, -1.2556e-01],[-1.0605e+00, 4.5711e-01, -7.9260e-01, -2.0586e+00, -2.5313e-01,-8.0461e-01, 9.3312e-01, 4.7544e-01],[-5.2117e-01, 3.4502e-01, 1.4715e+00, 2.4684e+00, 9.4748e-01,2.0253e-03, 1.0036e+00, 4.8027e-01]])
✅2. 引入 batch 的概念(3D 张量)
一般,我们需要在一次性处理多个序列(多个样本),假设3个序列样本组成一个batch。每个序列的长度仍是5,token的维度为8。那么此时这个张量的形状就变成了:
import torchseq_len = 5
embed_dim = 8
batch_size = 3
q = torch.randn(batch_size, seq_len, embed_dim)
print(q.shape)
print(q)
输出为:
torch.Size([3, 5, 8])
tensor([[[-0.3007, -0.3443, 0.0515, 0.9153, 0.1486, 0.8630, -0.1750,-0.6688],[ 0.1970, -0.8177, -0.0302, 1.1665, 0.3290, 0.6600, -0.7473,-1.2262],[-0.3780, 0.6538, 1.3766, 0.1920, -1.0980, 0.0694, 0.8015,0.3631],[ 1.1727, -0.1484, 1.5107, 1.4208, -0.2864, -1.7283, 0.5781,-1.4435],[ 1.3020, -0.1518, -0.9987, 0.5897, -1.1685, 1.1592, 0.0360,-1.1931]],[[ 1.3530, 0.0892, -1.2635, 1.8082, 1.3397, 1.0009, -1.3071,0.0946],[-0.3749, -1.5674, -0.8663, -1.3531, 0.9437, -1.1769, -1.3152,-1.1854],[ 0.6995, 0.6464, -0.8311, 0.4104, 1.4770, -0.2067, 0.8549,-0.0366],[-0.3462, 1.0118, -1.3090, -1.5885, -0.1143, 0.1957, -1.1694,-0.1317],[-0.0216, 0.7810, 1.6990, -0.2328, -0.0163, -1.5569, -0.9106,-1.5693]],[[ 0.0365, -0.8511, -0.6117, -1.4029, -0.5794, 0.7073, 0.0607,2.2900],[ 1.6539, 0.4874, 1.0456, 0.2727, 1.0852, 1.7963, -0.4513,-0.9612],[-1.4896, 1.8739, -0.3650, -0.0476, -2.5191, -1.4645, 0.5743,0.4616],[-1.2099, 0.3355, -0.8877, 2.6665, -0.6601, -1.2705, 1.0287,-0.6931],[-0.3273, 0.2364, -1.2982, -0.6908, 1.5833, -0.2403, 1.2128,1.4706]]])
我们可以尝试使用transpose
转置该3D张量对应的维度,如下:
q1 = q.transpose(0,1)
print(q1.shape)
print(q1)
输出如下:
torch.Size([5, 3, 8])
tensor([[[-0.0687, 0.3209, -0.5212, -0.1787, 0.4720, 1.0013, 0.6243,-1.8285],[-0.6348, -0.4394, -0.1964, 0.2261, -0.1205, 0.4492, 0.9841,-0.4095],[ 0.7714, -0.1087, -0.7359, 0.2492, -0.0391, -0.2462, -0.1695,1.4089]],[[-0.5181, -0.5992, 0.1055, 0.4877, 0.1648, 0.5122, -0.3526,1.7066],[ 1.5172, 1.4660, -0.2405, 2.1547, -0.8794, -1.6543, -2.0169,-0.5331],[ 0.3779, 0.4134, 1.9286, 0.3782, 1.5611, -1.6187, 1.6274,1.0527]],[[ 0.5642, -0.3944, -1.4383, -1.1361, 0.0242, 0.1435, 0.5510,-0.0472],[-1.0935, 0.0820, 0.5193, 0.1174, 0.3282, -1.9772, 0.4186,-0.5007],[-0.0845, -2.0364, 0.1124, 1.7474, -0.3131, -1.4156, 0.4046,-0.3282]],[[-2.4212, -0.4703, 1.5794, 0.8093, 0.9247, -1.4775, 0.4462,0.4256],[-0.0934, -0.2569, 0.4803, -0.3651, 0.7175, -1.0460, 0.9095,0.6421],[ 0.1579, 2.0790, -0.4982, 1.7707, -0.3657, 0.7336, -0.1482,-1.5648]],[[ 2.7056, 2.2962, 0.7005, 0.6427, 0.7578, -0.4191, 0.9064,-0.3934],[ 0.1987, 1.6104, 0.4723, 1.5453, 0.0500, -0.5176, -1.8852,-1.2235],[ 1.2145, 1.7694, -0.1546, 0.3803, 0.0489, 1.0129, 0.0513,-0.6902]]])
实际上,未转置之前是很容易理解的,即将将样本按照batch数进行了聚合,但是转置之后如何直观理解是非常重要的一个事情:
- 转换前
(batch_size, seq_len, embed_dim)
我们可以把它看成一个“batch_size 个句子”,每个句子有 seq_len 个词,每个词是一个 embed_dim 维的向量。
- 转换后
现在你可以把它理解成:我们将多个句子按词的位置对齐,从每个 batch 的样本中抽出相同位置的词,堆叠在一起。即第 i 个时间步(即位置 i)下,batch 中所有样本的向量被统一收集起来。
✅3. 输入到MultiheadAttention中
import torch
import torch.nn as nn# 定义参数
embed_dim = 8
num_heads = 2
seq_len = 5
batch_size = 3# 创建 MultiheadAttention 实例
mha_with_bias = nn.MultiheadAttention(embed_dim=embed_dim, num_heads=num_heads, batch_first=True)# 输入的 query, key, value (shape: seq_len, batch_size, embed_dim)
query = torch.randn(batch_size, seq_len, embed_dim)
key = torch.randn(batch_size, seq_len, embed_dim)
value = torch.randn(batch_size, seq_len, embed_dim)# 计算 attention 输出
out_with_bias, _ = mha_with_bias(query, key, value)# 输出两种情况下的结果
print(out_with_bias.shape)
print(out_with_bias)
输出为
torch.Size([3, 5, 8])
tensor([[[ 0.0749, 0.0814, -0.1367, -0.0314, 0.0061, -0.2369, -0.1453,-0.0241],[-0.0945, -0.0934, 0.0407, -0.2193, -0.2172, -0.1352, -0.0820,-0.1239],[-0.0591, -0.0986, 0.1017, -0.2430, -0.2136, -0.0989, -0.1641,-0.1050],[-0.0588, -0.0747, 0.0355, -0.2210, -0.1803, -0.1326, -0.0864,-0.1240],[-0.1035, -0.0213, -0.0752, -0.1356, -0.1339, -0.1776, -0.0013,-0.1460]],[[-0.0217, -0.0490, 0.2707, 0.2102, -0.0289, 0.2783, -0.2179,0.1797],[-0.1059, -0.0113, 0.2640, 0.3222, 0.0088, 0.3493, -0.2244,0.2725],[-0.0965, -0.0284, 0.4591, 0.2321, 0.0041, 0.3915, -0.2269,0.2789],[-0.0432, -0.0149, 0.5781, 0.2857, 0.0851, 0.5095, -0.2417,0.3853],[-0.3742, 0.0287, 0.2859, 0.4340, -0.0349, 0.4007, -0.2363,0.3838]],[[-0.5256, 0.0713, -0.3210, 0.1768, -0.0383, 0.0495, 0.1960,-0.1594],[-0.4588, 0.1027, -0.4966, 0.0540, -0.0393, -0.1755, 0.3327,-0.2415],[-0.4845, 0.0701, -0.2647, 0.2300, -0.0053, 0.0749, 0.1903,-0.0888],[-0.4795, 0.1241, -0.3832, 0.1589, 0.0214, -0.1044, 0.3101,-0.1343],[-0.4665, 0.1103, -0.3181, 0.2179, 0.0319, -0.0670, 0.3088,-0.0676]]], grad_fn=<TransposeBackward0>)
为什么 PyTorch 使用 (seq_len, batch_size, embed_dim)?这是为了兼容早期的 RNN 接口(nn.RNN, nn.LSTM)以及底层高效的张量操作。可以用 batch_first=True 的方式让维度变成 [batch_size, seq_len, embed_dim],这是更自然的顺序,但默认 MultiheadAttention 期望 [seq_len, batch_size, embed_dim]。
✅4. 分析add_bias_kv
按照上面的理解官方实现中要求[batch_size, seq_len, embed_dim],并且按照之前的解释其在每个 attention 计算的key和value前,拼接一个 learnable向量(即bias_k, bias_v),其shape是 (1, batch_size, embed_dim),这个拼接逻辑如何理解呢?具体的,
- 其会创建两个可学习的参数向量bias_k和bias_v,且形状为(1,1,embed_dim)
- 然后在前向传播时,会将这个 bias 向量沿着 batch 维复制为 [batch_size, 1, embed_dim],然后 附加在原始的 key 和 value 张量的序列维 dim=1 上(注意是 seq_len 那一维)
key = torch.cat([key, bias_k.expand(3, 1, 8)], dim=1)
value = torch.cat([value, bias_v.expand(3, 1, 8)], dim=1)
新shape:[seq_len + 1, batch_size, embed_dim]
✅5. 分析add_zero_attn
add_zero_attn=True 表示在 key 和 value 的序列维(即 seq_len 那一维)前面追加一行全为零的向量。注意query始终不变。即
zero_tensor = torch.zeros(batch_size, 1, embed_dim)
key = torch.cat([zero_tensor, key], dim=1)
value = torch.cat([zero_tensor, value], dim=1)
[seq_len, batch_size + 1, embed_dim]
✅6.特别注意
- add_bias_kv 添加的是 bias_k 和 bias_v,这两个是模型的参数,会随着训练学习出有意义的表示(比如代表某类全局特征或辅助 attention 的 anchor 点)。
- 而 add_zero_attn 加的是一个 固定为 0 的向量,它不会被训练,更多是出于工程目的(例如 decoder 中让 query 有可能对“无意义”的位置分配注意力,从而在 masking 时更稳定)。
相关文章:
深入解析PyTorch中MultiheadAttention的隐藏参数add_bias_kv与add_zero_attn
关键背景 最近在学习pytorch中的源码尤其是nn.modules下算子的实现,针对activation.py下MultiheadAttention下有两个不常见的参数的使用比较有趣,因为时序领域很少使用这两个参数(add_bias_kv和add_zero_attn),但是其…...
最大化效率和性能:AKS 中节点池的强大功能
什么是节点池 在 Azure Kubernetes 服务 (AKS) 中,相同配置的节点会被分组到节点池中。这些节点池包含运行应用程序的底层虚拟机。创建 AKS 集群时,您需要定义初始节点数及其大小 (SKU)。随着应用程序需求的变化,您可能需要更改节点池的设置…...
用户态到内核态:Linux信号传递的九重门(一)
1. 信号的认识 1.1. 信号的特点 异步通知:信号是异步的,发送信号的进程无需等待接收进程的响应。预定义事件:每个信号对应一个预定义的事件(如终止、中断、段错误等)。 轻量级:信号不携带大量数据…...
c语言第一个小游戏:贪吃蛇小游戏01
hello啊大家好 今天我们用一个小游戏来增强我们的c语言! 那就是贪吃蛇 为什么要做一个贪吃蛇小游戏呢? 因为这个小游戏所涉及到的知识有c语言的指针、数组、链表、函数等等可以让我们通过这个游戏来巩固c语言,进一步认识c语言。 一.我们先…...
JAVA EE_网络原理_网络层
晨雾散尽,花影清晰。 ----------陳長生. ❀主页:陳長生.-CSDN博客❀ 📕上一篇:数据库Mysql_联…...
前端性能指标及优化策略——从加载、渲染和交互阶段分别解读详解并以Webpack+Vue项目为例进行解读
按照加载阶段、渲染阶段和交互阶段三个维度进行系统性阐述: 在现代 Web 开发中,性能不再是锦上添花,而是决定用户体验与业务成败的关键因素。为了全面监控与优化网页性能,我们可以将性能指标划分为加载阶段、渲染阶段、和交互阶段…...
Flink 系列之十五 - 高级概念 - 窗口
之前做过数据平台,对于实时数据采集,使用了Flink。现在想想,在数据开发平台中,Flink的身影几乎无处不在,由于之前是边用边学,总体有点混乱,借此空隙,整理一下Flink的内容,…...
控制台打印带格式内容
1. 场景 很多软件会在控制台打印带颜色和格式的文字,需要使用转义符实现这个功能。 2. 详细说明 2.1.转义符说明 样式开始:\033[参数1;参数2;参数3m 可以多个参数叠加,若同一类型的参数(如字体颜色)设置了多个&…...
Linux为啥会重新设置中断请求号与中断向量号之间的关系?
Linux内核重新设置中断请求号(IRQ)与中断向量号之间的关系,主要出于以下核心原因和设计考量: 1. 硬件多样性与抽象需求 硬件中断号(HW Interrupt ID)的差异 不同处理器架构的中断控制器(…...
自然语言处理NLP中的连续词袋(Continuous bag of words,CBOW)方法、优势、作用和程序举例
自然语言处理NLP中的连续词袋(Continuous bag of words,CBOW)方法、优势、作用和程序举例 目录 自然语言处理NLP中的连续词袋(Continuous bag of words,CBOW)方法、优势、作用和程序举例一、连续词袋( Cont…...
计算机网络笔记(二十二)——4.4网际控制报文协议ICMP
4.4.1ICMP报文的种类 ICMP(Internet Control Message Protocol)是IP协议的辅助协议,主要用于传递控制消息、错误报告和诊断信息。其报文分为两大类:查询报文和错误报告报文。 1. 错误报告报文(Error Messages&#x…...
【AI论文】作为评判者的感知代理:评估大型语言模型中的高阶社会认知
摘要:评估大型语言模型(LLM)对人类的理解程度,而不仅仅是文本,仍然是一个开放的挑战。 为了弥合这一差距,我们引入了Sentient Agent作为评判者(SAGE),这是一个自动评估框…...
Kubernetes生产实战(二十七):精准追踪Pod数据存储位置
在生产环境中,快速定位Pod数据的物理存储位置是运维人员的基本功。本文将揭秘Kubernetes存储系统的核心原理,并提供一套经过实战检验的定位方法体系。 一、存储架构全景图 K8S存储架构 Pod --> Volume Mount --> PVC --> PV --> Storage P…...
极新携手火山引擎,共探AI时代生态共建的破局点与增长引擎
在生成式AI与行业大模型的双重驱动下,人工智能正以前所未有的速度重构互联网产业生态。从内容创作、用户交互到商业决策,AI技术渗透至产品研发、运营的全链条,推动效率跃升与创新模式变革。然而,面对AI技术迭代的爆发期࿰…...
[SIGPIPE 错误] 一个 Linux socket 程序,没有任何报错打印直接退出程序
1. 问题 在编写一个程序的时候,当然程序很复杂,遇到了一个 Linux socket 程序,没有任何报错打印直接退出程序,但是在程序里面我有很多 error log ,在程序退出的时候完全没有打印。为了说明问题,我编写了一…...
Qt 界面优化(绘图)
目录 1. 绘图基本概念2. 绘制各种形状2.1 绘制线段2.2 绘制矩形2.3 绘制圆形2.4 绘制文本2.5 设置画笔2.6 设置画刷 3. 绘制图片3.1 绘制简单图片3.2 平移图片3.3 缩放图片3.4 旋转图片 4. 其他设置4.1 移动画家位置4.2 保存/加载画家的状态 5. 特殊的绘图设备5.1 QPixmap5.2 Q…...
AQS(AbstractQueuedSynchronizer)解析
文章目录 一、AQS简介二、核心设计思想2.1 核心设计思想回顾2.2 CLH锁队列简介2.3 AQS对CLH队列的改动及其原因 三、核心组件详解3.1 state 状态变量3.2 同步队列 (FIFO双向链表) 四、核心方法深度解析4.1 获取同步状态 (独占模式) - acquire(int arg)4.2 释放同步状态 (独占模…...
Java并发编程常见问题与陷阱解析
引言 随着计算机硬件技术的飞速发展,多核处理器已经变得普遍,Java并发编程的重要性也日益凸显。然而,多线程编程并非易事,其中充满了许多潜在的问题和陷阱。作为一名Java开发工程师,掌握并发编程的常见问题及其解决方案…...
DEEPPOLAR:通过深度学习发明非线性大核极坐标码(1)
原文:《DEEPPOLAR: Inventing Nonlinear Large-Kernel Polar Codes via Deep Learning》 摘要 信道编码设计的进步是由人类的创造力推动的,而且恰如其分地说,这种进步是零星的。极性码是在Arikan极化核的基础上开发的,代表了编码…...
Java多态详解
Java多态详解 什么是多态? 比如我们说:“驾驶一辆车”,有人开的是自行车,有人开的是摩托车,有人开的是汽车。虽然我们都说“开车”,但“怎么开”是由具体的车类型决定的:“开”是统一的动作&a…...
go程序编译成动态库,使用c进行调用
以下是使用 Go 语言打包成 .so 库并使用 C 语言调用的完整步骤: 1. Go 语言打包成 .so 库 (1)编写 Go 代码 创建一个 Go 文件(如 calculator.go),并定义需要导出的函数。导出的函数名必须以大写字母开头…...
iVX:图形化编程与组件化的强强联合
在数字化浪潮中,软件开发范式正经历着从文本到图形的革命性转变。iVX 作为国产可视化编程领域的领军者,以 “图形化逻辑 组件化架构” 的双重创新,重新定义了软件开发的效率边界。其技术突破不仅体现在开发方式的革新,更通过一系…...
华为配置篇-RSTP/MSTP实验
MSTP 一、简介二、常用命令总结三、实验 一、简介 RSTP(快速生成树协议) RSTP(Rapid Spanning Tree Protocol)是 STP 的改进版本,基于 IEEE 802.1w 标准,核心目标是解决传统 STP 收敛速度慢的问…...
端口号被占用怎么解决
windows环境下端口号被占用怎么解决 win r 快捷键打开cmd输入netstat -ano|findstr 端口号 通过这个命令找到pidtaskkill /pid pid端口号 /t /f 如下图所示 命令解读 netstat 是一个网络统计工具,它可以显示协议统计信息和当前的TCP/IP网络连接。 -a 参数告诉 nets…...
GO语言-导入自定义包
文章目录 1. 项目目录结构2. 创建自定义包3. 初始化模块4. 导入自定义包5. 相对路径导入 在Go语言中导入自定义包需要遵循一定的目录结构和导入规则。以下是详细指南(包含两种方式): 1. 项目目录结构 方法1:适用于Go 1.11 &#…...
ES常识5:主分词器、子字段分词器
文章目录 一、主分词器:最基础的文本处理单元主分词器的作用典型主分词器示例 二、其他类型的分词器:解决主分词器的局限性1. 子字段分词器(Multi-fields)2. 搜索分词器(Search Analyzer)3. 自定义分词器&a…...
NoSQL数据库技术与应用复习总结【看到最后】
第1章 初识NoSQL 1.1 大数据时代对数据存储的挑战 1.高并发读写需求 2.高效率存储与访问需求 3.高扩展性 1.2 认识NoSQL NoSQL--非关系型、分布式、不提供ACID的数据库设计模式 NoSQL特点 1.易扩展 2.高性能 3.灵活的数据模型 4.高可用 NoSQL拥有一个共同的特点&am…...
单片机-STM32部分:12、I2C
飞书文档https://x509p6c8to.feishu.cn/wiki/MsB7wLebki07eUkAZ1ec12W3nsh 一、简介 IIC协议,又称I2C协议,是由PHILP公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备,IIC属于半双工同步通信方式。 IIC是一种同步…...
【英语笔记(四)】诠释所有16种英语时态,介绍每种时态下的动词变形!!含有所有时态的的动词变形汇总表格
1 时态的单词构成 1.1 现在 1.1.1 一般现在时态 动词原形动词原形s(第三人称单数) 1.1.1.1 表达事实 I eat carrots. 我吃胡萝卜:我是吃胡萝卜这种食物的.(这个是事实陈述) The rabbit eats carrots. 兔子吃胡萝卜…...
【质量管理】什么是过程?
在文章【质量管理】谁是顾客?什么是质量链?-CSDN博客 中我们了解了什么是顾客,顾客不仅仅是企业以外的人,在企业的内部我们也有大大小小的顾客。并且我们了解了什么是质量链,企业内部的各种供给方和客户形成了质量链。…...
效率办公新工具:PDF Reader Pro V5.0功能解析与使用体验
在日常文档处理与数字办公的场景中,PDF 文件依然是主流格式之一。从合同审批、项目文档、财务报表,到技术方案和用户手册,PDF 的编辑、转换、标注、归档需求始终存在。 面对这些需求,越来越多用户希望有一款功能完整、跨平台、智…...
Java对象内存布局和对象头
1、面试题 1)说下JUC,AQS的大致流程 CAS自旋锁,是获取不到锁就一直自旋吗? 2)CAS和synchronized区别在哪里,为什么CAS好,具体优势在哪里? 3)sychro…...
Vue 跨域解决方案及其原理剖析
在现代 Web 开发中,跨域问题是前端开发者经常面临的挑战之一。当使用 Vue.js 构建应用时,跨域请求的处理尤为重要。本文将深入探讨 Vue 解决跨域的多种方法及其背后的原理,帮助开发者更好地理解和应对这一常见问题。 一、跨域问题概述 1. 同…...
TikTok 互动运营干货:AI 助力提升粘性
在 TikTok 运营的众多环节中,与用户的互动是建立紧密联系、提升账号粘性的关键所在。及时且真诚地回复评论和私信,能让用户切实感受到你的关注与尊重,从而极大地增强他们对你的好感与粘性。对于用户提出的问题,要以耐心、专业的态…...
Kids A-Z安卓版:儿童英语启蒙的优质选择
Kids A-Z安卓版 是一款由北美知名分级读物厂商 Learning A-Z 官方推出的英语分级学习应用,也被称为 Raz-Kids app。它专为 K-5 年级的学生设计,提供丰富的英语学习资源和互动学习体验,帮助孩子们在轻松愉快的环境中提升英语能力。通过动画、互…...
接口继承与扩展的使用技巧
在 TypeScript 中,接口继承和扩展是非常强大且灵活的功能,可以帮助我们更高效地管理类型和提高代码的可重用性。接口继承使得一个接口可以从另一个接口继承属性和方法,而接口扩展允许我们通过组合多个接口来构建更复杂的结构。这些特性使得 T…...
【React】Craco 简介
Craco 简介 Craco (Create React App Configuration Override) 是一个用于自定义 Create React App (CRA) 配置的工具,无需 eject(弹出)项目。 为什么需要 Craco Create React App 虽然提供了零配置的 React 开发体验,但其配置…...
HTML5中的Microdata与历史记录管理详解
Microdata 简介 Microdata 是 HTML5 引入的一种标记方式,用于在网页中嵌入机器可读的语义信息。通过使用 Microdata,开发者可以在 HTML 元素中添加特定的属性,以便搜索引擎和其他工具更好地理解网页内容。 Microdata 的核心属性包括 itemsc…...
UNet网络 图像分割模型学习
UNet 由Ronneberger等人于2015年提出,专门针对医学图像分割任务,解决了早期卷积网络在小样本数据下的效率问题和细节丢失难题。 一 核心创新 1.1对称编码器-解码器结构 实现上下文信息与高分辨率细节的双向融合 如图所示:编码器进行了4步&…...
Babel 深度解析:现代 JavaScript 开发的桥梁
1. 什么是 Babel? Babel 是一个 JavaScript 编译器(又称转译器),核心使命是解决 JavaScript 的环境兼容性问题。它允许开发者使用最新的语言特性(如 ES6、JSX、TypeScript),同时将代码转换为旧…...
MyBatis源码解读2(2.1、核心对象)
二、MyBatis的核心对象 2.1、核心对象 2.1、MappedStatement MyBatis其实是对JDBC的进一步封装,我们都知道JDBC有几个重要的对象: StatementPrepared StatementCallable StatementResultSet Statement、Prepared Statement、Callable Statement分别…...
03.three官方示例+编辑器+AI快速学习webgl_animation_multiple
本实例主要讲解内容 这个示例展示了Three.js中骨骼动画的高级应用技巧,重点演示了如何使用SkeletonUtils.clone()方法复制模型,并展示了两种不同的骨骼动画管理方式: 独立骨骼模式:每个模型拥有独立的骨骼结构,可播放…...
无锁秒杀系统设计:基于Java的高效实现
引言 在电商促销活动中,秒杀场景是非常常见的。为了确保高并发下的数据一致性、性能以及用户体验,本文将介绍几种不依赖 Redis 实现的无锁秒杀方案,并提供简化后的 Java 代码示例和架构图。 一、基于数据库乐观锁机制 ✅ 实现思路…...
MyBatis快速入门——实操
默认:电脑搭建好了Maven环境 本次入门实验使用的idea版本:ideaU2022.1 目录 一:前期准备工作 1. 创建一个springboot工程 2. Maven环境配置 3. 在mysql数据库中创建一个user表 4. 编写实体类User 二: 引入MyBatis的相关依赖…...
假如你的项目是springboot+vue怎么解决跨域问题
1. 前端代理(开发环境推荐) 适用场景:Vue 开发环境调试时,避免直接请求后端接口的跨域问题。 实现步骤: 在 Vue 项目的 vue.config.js 中配置代理: module.exports {devServer: {proxy: {/api: { // 代理…...
OpenResty反向代理
通过在 OpenResty 的配置文件中定义不同的 location 块,将匹配特定 URL 路径的请求转发到不同的后端 FastAPI 应用(即使它们运行在不同的端口或甚至是不同的服务器/容器上)。 核心思路: 多个 FastAPI 应用实例: 你的每…...
《Effective Python》第1章 Pythonic 思维详解——深入理解 Python 条件表达式(Conditional Expressions)
《Effective Python》第1章 Pythonic 思维详解——深入理解 Python 条件表达式(Conditional Expressions) 在 Python 中,条件表达式(conditional expressions)提供了一种简洁的方式来在一行中实现 if/else 的逻辑。它…...
【Typenum】 3 类型位运算(bit.rs)
一、源码 代码定义了一个类型级别的位(bit)系统,主要用于编译时的类型运算。 //! 类型级比特位实现 //! //! 这些是基础的比特位类型,作为本库中其他数值类型的构建基础 //! //! 已实现的**类型运算符**: //! //! - …...
python:trimesh 用于 STL 文件解析和 3D 操作
python:trimesh 是一个用于处理三维模型的库,支持多种格式的导入导出,比如STL、OBJ等,还包含网格操作、几何计算等功能。 Python Trimesh 库使用指南 安装依赖库 pip install trimesh Downloading trimesh-4.6.8-py3-none-any.w…...
stm32week15
stm32学习 十一.中断 2.NVIC Nested vectored interrupt controller,嵌套向量中断控制器,属于内核(M3/4/7) 中断向量表:定义一块固定的内存,以4字节对齐,存放各个中断服务函数程序的首地址,中断向量表定…...