一、模型介绍

论文为《TabNet: Attentive Interpretable Tabular Learning》发表于2021年,属于Google Cloud AI。该研究针对表格数据提出了一种新的深度神经网络(DNN)架构TabNet,旨在解决传统深度学习在表格数据上表现不如决策树模型的问题,同时提升性能和可解释性。

TabNet模型融合了多种先进思想:它将Transformer的注意力机制(赋予模型动态、稀疏地“聚焦”于最重要特征的能力)、Boosting的序列化决策思想(分步、迭代地做出决策)以及自监督学习的表示学习能力(在正式训练前,让模型预先学习特征间的内在关系,为后续的智能决策提供“先验知识)巧妙地结合在了一起,用于解决表格数据问题。

保留DNN的end-to-end和representation learning特点的基础上,还拥有了树模型的可解释性和稀疏特征选择的优点


TabNet 的工作方式(通俗的方式理解模型)

Boosting的序列化决策思想(比如GBDT 通过拟合上一步的预测残差不断训练迭代模型)

  • 使用一部分特征(通过自监督学习+注意力选择),做出一个初步的预测贡献。

  • TabNet不像Boosting那样显式地计算一个 y_true - y_pred 的残差,它通过特征选择机制达到了类似的效果。当第二步的注意力模块被告知“这些特征已经被用过了”时,它实际上是在被引导去关注那些在第一步中未能充分解释目标变量方差的特征。这可以被看作是在特征空间中的“残差学习”。

  • 基于新选出的特征,产生一个新的“预测贡献”。这个贡献的作用就是修正或细化第一步的判断。

  • 这个过程在多个步骤中重复,每一步都试图利用新的特征组合来进一步完善整体的预测。

TabNet架构设计

TabNet 将预测分解为多个步骤。在每一步,它都用一个注意力模块(Attentive Transformer)来智能地、稀疏地挑选出一组当前最相关的特征,然后用另一个模块(Feature Transformer)来处理这些特征并得出初步结论。这个过程是序列化的,因为后一步的选择会受到前一步的影响,从而使模型能够全面而高效地利用所有特征信息,最终做出高质量的预测。

在这里插入图片描述


自监督学习

在整个有监督的决策流程开始之前,TabNet可以通过一个自监督的预训练任务来“热身”。模型通过随机遮蔽(Mask)一部分特征,然后尝试用剩余的特征来预测被遮蔽的内容。

  • 赋予模型关于“特征关系图谱”的先验知识:模型被迫学习到特征之间复杂的相关、互补或冗余关系。

  • 提升决策效率:当进入正式的序列化决策流程时,Attentive Transformer不再是盲目选择特征,而是基于已经学到的“常识”,做出更明智、更高效的特征选择。


Attentive Transformer (注意力转换器)

Attentive Transformer是决策的起点,它的核心使命是回答:“在当前步骤,我应该关注哪些特征?

它接收上一步处理过的信息,利用注意力机制为所有特征计算出一个“特征权重”。特征权重基于sparsemax的激活函数和正则化,使得注意力模块每次只选择少数几个最关键的特征,将其权重设为非零,而其他大量无关特征的权重则为零,从而完成动态选择最重要特征的目的。

序列化更新:它有一个“记忆机制”。在生成新的Mask时,它会参考一个“先验尺度”(Prior Scale),该尺度记录了每个特征在之前所有步骤中被使用的总程度。如果一个特征已被频繁使用,模型会被激励去降低对它的关注,转而探索新的、未被充分利用的特征。


Feature Transformer (特征转换器)

一旦Attentive Transformer选定了特征,Feature Transformer就接手处理,它的使命是:“利用这些选中的特征,我能得出什么结论?

该模块接收 Attention Mask M_i 筛选和加权后的特征,通过几层神经网络对被选中的特征进行复杂的非线性变换,提取出有用的信息,并为最终预测贡献一部分结果。


多步骤决策

所有决策步骤(比如N步)都完成后,模型会将每个步骤产生的“预测贡献”加权求和,得到最终的预测结果。

其中,加权系数与每个步骤探索“新特征”的程度有关,具体来说,与(1 - Prior_i)有关(Prior_i是到第i步为止的特征累积使用度)。这种机制确保了最终的预测结果是建立在一系列互补、多样化的特征视角之上,从而更加鲁棒和准确。



二、代码实现

Pytorch-tabnet可以实现以下任务:

  • TabNetClassifier:二元分类和多类分类问题
  • TabNetRegressor:简单和多任务回归问题
  • TabNetMultiTaskClassifier:多任务多分类问题

整个模型可分为自监督预训练 (Self-supervised Pre-training)+有监督微调 (Supervised Fine-tuning),官方展示的二分类或多分类示例中仅仅展示了有监督微调部分。下面代码展示页只包括模型训练部分:


Step1:包和数据载入预处理

from pytorch_tabnet.tab_model import TabNetClassifierimport torch
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import roc_auc_scoreimport pandas as pd
import numpy as np
np.random.seed(0)import scipyimport wget
from pathlib import Pathfrom matplotlib import pyplot as plt
# %matplotlib inlineimport os
os.environ['CUDA_VISIBLE_DEVICES'] = f"0"
import torch
torch.__version__
import optuna
import scipy.sparse
# filein_name = filein.replace(".csv","")
filein_name ="tmp"
save_path = './Result_' + filein_name + '_s73_try1/'  # raw_datasetpaths = [save_path + "/input/", save_path + "/result/", save_path + "/models/"]
for path in paths:if not os.path.exists(path):os.makedirs(path)
# 数据加载
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data"
dataset_name = 'census-income'
out = Path(os.getcwd()+'/data/'+dataset_name+'.csv')
out.parent.mkdir(parents=True, exist_ok=True)
if out.exists():print("File already exists.")
else:print("Downloading file...")wget.download(url, out.as_posix())
train = pd.read_csv(out)
target = ' <=50K'
# 数据预处理,比如标签编码 
nunique = train.nunique()
types = train.dtypescategorical_columns = []
categorical_dims =  {}
for col in train.columns:if types[col] == 'object' or nunique[col] < 200:print(col, train[col].nunique())l_enc = LabelEncoder()train[col] = train[col].fillna("Unknown")train[col] = l_enc.fit_transform(train[col].values)categorical_columns.append(col)categorical_dims[col] = len(l_enc.classes_)
#     else:
#         train.fillna(train.loc[train_indices, col].mean(), inplace=True)
# 划分数据集
if "Set" not in train.columns:train["Set"] = np.random.choice(["train", "valid", "test"], p =[.8, .1, .1], size=(train.shape[0],))
print(train["Set"].value_counts())train_indices = train[train.Set=="train"].index
valid_indices = train[train.Set=="valid"].index
test_indices = train[train.Set=="test"].index
# 生成cat_idxs,cat_dims等参数
unused_feat = ['Set']features = [ col for col in train.columns if col not in unused_feat+[target]] cat_idxs = [ i for i, f in enumerate(features) if f in categorical_columns]cat_dims = [ categorical_dims[f] for i, f in enumerate(features) if f in categorical_columns]grouped_features = [[0, 1, 2], [8, 9, 10]]
X_train = train[features].values[train_indices]
y_train = train[target].values[train_indices]X_valid = train[features].values[valid_indices]
y_valid = train[target].values[valid_indices]X_test = train[features].values[test_indices]
y_test = train[target].values[test_indices]

Step2: 模型训练

Step 2.0:参数解释

数据处理方面

  • cat_idxs: 所有类别特征在输入特征矩阵 X 中的列索引
  • cat_dims:含了每个类别特征的基数(cardinality),也就是该特征有多少个不同的取值。
  • cat_emb_dim:将类别变量中的每一个类别表示成一个长度为多长的特征。
  • grouped_features:比如独热编码后的特征,比如身高体重与BMI

模型训练参数:

  • n_d, n_a:代表决策流(decision stream)和注意力流(attention stream)的输出维度。它们共同决定了模型每一步的“宽度”。通常将它们设置为相等的值,例如 8, 16, 32, 64。从较小的值开始(如 n_d=8, n_a=8),如果模型欠拟合(训练集和验证集表现都不好),则逐步增大。如果模型过拟合(训练集表现远好于验证集),可以尝试减小它们或增加正则化。
  • n_steps:模型中决策步骤的数量。每个步骤都会选择一部分特征进行处理。值越大,模型越复杂,理论上能学习更复杂的模式。通常取值在 3 到 10 之间。更多的步骤会增加训练时间,也可能导致过拟合。
  • gamma:特征重用系数。值越大(接近2.0),每个特征在所有决策步骤中被使用的可能性就越小,鼓励模型在不同步骤关注不同特征。值越小(接近1.0),特征可以被更频繁地重用。如果感觉模型在不同步骤总是关注相同的特征,可以适当增大 gamma。
  • lambda_sparse:稀疏性正则化系数。这是TabNet的一个关键特性,它鼓励模型在每一步只选择最重要的少数特征,从而实现可解释性并防止过拟合。值越大,特征选择越稀疏。如果模型严重过拟合,可以尝试增大此值。如果模型欠拟合,或者你发现重要特征没有被选入,可以减小此值。搜索范围建议: [1e-4, 1e-3, 1e-2, 0.1] (通常在对数尺度上搜索)

处理数据类别不平衡(SMOTE和weights通常只用一种)

  • weights: 设置类别权重,也是处理不平衡数据的方法。weights=1 表示所有类别权重相同。如果你有类别不平衡问题,可以设置为 0(自动计算权重,使得少数类有更高权重)

优化器与学习率调度器调优

  • optimizer_fn: Adam 通常是个不错的选择。AdamW 是 Adam 的改进版,可以尝试替换。在对数尺度上搜索,通常 1e-3 到 2e-2 是一个比较常见的范围。
  • scheduler_fn 和 scheduler_params: ReduceLROnPlateau 通常是更好的选择。它会监测验证集上的指标(如 valid_auc),当指标在一定 patience 内不再提升时,自动降低学习率。

Step 2.1: 基于optuna自动搜索超参数

import optuna
import torch
import scipy.sparse
max_epochs = 50 if not os.getenv("CI", False) else 2# 数据增强
from pytorch_tabnet.augmentations import ClassificationSMOTE
#aug = ClassificationSMOTE(p=0.2)# 此时X_train, y_train, X_valid, y_valid, cat_idxs, cat_dims, grouped_features 已定义def objective(trial):# 定义要搜索的超参数空间n_d = trial.suggest_int("n_d", 8, 32, step=8) n_steps = trial.suggest_int("n_steps", 3, 7) # 决策步骤数gamma = trial.suggest_float("gamma", 1.0, 2.0)# 特征重用系数,值越大,特征重用可能性越小lambda_sparse = trial.suggest_float("lambda_sparse", 1e-4, 1e-2, log=True) # 值越大,特征选择越稀疏;过拟合,增大此值,使模型更专注,减少对噪音的学习lr = trial.suggest_float("lr", 1e-3, 3e-2, log=True)virtual_batch_size = trial.suggest_categorical("virtual_batch_size", [128, 256])weight_decay = trial.suggest_float("weight_decay", 1e-6, 1e-3, log=True)mask_type = trial.suggest_categorical("mask_type", ["entmax", "sparsemax"])aug_p = trial.suggest_float("aug_p", 0.1, 0.4, step=0.1)aug = ClassificationSMOTE(p=aug_p)# 设置模型参数tabnet_params = {"cat_idxs": cat_idxs,"cat_dims": cat_dims,"cat_emb_dim": 2,"grouped_features": grouped_features,"n_d": n_d,"n_a": n_d,  # 保持 n_a 和 n_d 一致"n_steps": n_steps,"gamma": gamma,"lambda_sparse": lambda_sparse,"mask_type": mask_type, # sparsemax,entmax"optimizer_fn": torch.optim.AdamW,  "optimizer_params": dict(lr=lr, weight_decay=weight_decay),"scheduler_fn": torch.optim.lr_scheduler.ReduceLROnPlateau,"scheduler_params":dict(mode="max",patience=5, min_lr=1e-5,factor=0.5)}clf = TabNetClassifier(**tabnet_params)# 训练模型:在超参数搜索时,可以适当减少 max_epochs 和 patience 来加速max_epochs = 50patience = 10clf.fit(X_train=X_train, y_train=y_train,eval_set=[(X_valid, y_valid)],eval_name=['valid'],eval_metric=['auc'],max_epochs=max_epochs,patience=patience,batch_size=2048, # 增大 batch_sizevirtual_batch_size=virtual_batch_size,num_workers=0,drop_last=False, # 在搜索时可以先关掉augmentations=aug, # 暂时关闭增强,专注于模型结构)# 返回要优化的目标# clf.best_cost 是验证集上最好的损失,我们希望最大化AUC# clf.history['valid_auc'] 是一个列表,取最后一个值或最大值valid_auc = max(clf.history['valid_auc'])return valid_auc# 开始优化
study = optuna.create_study(direction="maximize", study_name='TabNet optimization') # direction="maximize" 因为我们要最大化 AUC
study.pruners = optuna.pruners.MedianPruner() # 增加剪枝,提前终止不好的试验
study.optimize(objective, n_trials=2, timeout=6*60) # n_trials 是你想要尝试的超参数组合数量# 输出最佳参数
print("Best trial:")
trial = study.best_trial
print("  Params: ")
for key, value in trial.params.items():print(f"    {key}: {value}")best_params = trial.params

Step 2.2: 基于最优超参数训练模型

tabnet_params = dict(cat_idxs=cat_idxs,cat_dims=cat_dims,cat_emb_dim=2,grouped_features=grouped_features,n_d=best_params['n_d'], n_a=best_params['n_d'], n_steps=best_params['n_steps'], gamma=best_params['gamma'],lambda_sparse=best_params['lambda_sparse'],mask_type=best_params['mask_type'],optimizer_fn=torch.optim.Adam,optimizer_params=dict(lr=best_params["lr"], weight_decay=best_params["weight_decay"]),scheduler_fn=torch.optim.lr_scheduler.ReduceLROnPlateau,scheduler_params=dict(mode="max",patience=5,min_lr=1e-5,factor=0.5),verbose=0)clf = TabNetClassifier(**tabnet_params)
# This illustrates the behaviour of the model's fit method using Compressed Sparse Row matrices
sparse_X_train = scipy.sparse.csr_matrix(X_train)  # Create a CSR matrix from X_train 优化内存使用和加速模型训练。
sparse_X_valid = scipy.sparse.csr_matrix(X_valid)   # Fitting the model
max_epochs = 50
aug = ClassificationSMOTE(p=best_params["aug_p"])
clf.fit(X_train=sparse_X_train, y_train=y_train,eval_set=[(sparse_X_train, y_train), (sparse_X_valid, y_valid)],eval_name=['train', 'valid'],eval_metric=['auc'],max_epochs=max_epochs, patience=20,batch_size=1024, virtual_batch_size=128,num_workers=0,drop_last=True, #丢弃最后一个批次# 类别不平衡weights=0,augmentations=aug,  compute_importance=True
)
# plot losses
plt.figure(figsize=(3,2))
plt.plot(clf.history['loss'])
plt.show()# plot learning rates
plt.figure(figsize=(3,2))
plt.plot(clf.history['lr'])
plt.show()
# plot auc
plt.figure(figsize=(3,2))
plt.plot(clf.history['train_auc'], label='Train AUC')
plt.plot(clf.history['valid_auc'], label='Valid AUC')
plt.legend()
plt.show()

Step 2.3: 预测及结果保存

# save tabnet model
savefile = save_path + "/models/tabnet_model" 
saved_filepath = clf.save_model(savefile)# load tabnet model
loaded_model = TabNetClassifier()
loaded_model.load_model(saved_filepath)
loaded_model

Step 3:特征可解释性-tabnet固有

explain_matrix, masks = clf.explain(X_test) 
# explain_matrix 是对所有决策步骤 (steps) 的掩码 (masks) 进行聚合后的结果,它代表了模型对输入 X_test 中每个样本的最终或整体的特征重要性。
# masks 提供了更深层次、更细粒度的解释。它是一个列表,其中包含了模型在每个决策步骤中生成的原始掩码。这让你能够窥探模型的“思考过程”。列表长度等于决策步骤数 (n_steps)。每个数组展示了在该步骤中,模型对每个特征的关注度。行为样本,列为特征,亮度为重要性
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt# 获取特征重要性
importances = clf.feature_importances_feature_importance_df = pd.DataFrame({'Feature': features,'Importance': importances}).sort_values('Importance', ascending=False)#  可视化
plt.figure(figsize=(6, 5))
sns.barplot(x='Importance', y='Feature', data=feature_importance_df)
plt.title('TabNet Global Feature Importances')
plt.show()print(feature_importance_df)

在这里插入图片描述

# 选择前20个样本在每一步中特征选择与应用频率
split_num = len(masks.keys())
num_features = masks[0].shape[1]fig, axs = plt.subplots(split_num, 1, figsize=(7,5))
for i in range(split_num):axs[i].imshow(masks[i][:20], aspect='auto')axs[i].set_ylabel(f"Mask {i}")axs[i].set_xticks(list(np.arange(num_features)))axs[i].set_xticklabels(labels = [], rotation=45,fontsize=7)
axs[i].set_xticklabels(labels = features, rotation=45,fontsize=8)
plt.tight_layout( )
plt.show()

在这里插入图片描述


Step3:特征可解释性-SHAP

# pip show shap
import shap
shap.initjs()
explainer = shap.KernelExplainer(clf.predict, X_train)X_test_ = X_test[1:100,:]
shap_values = explainer.shap_values(X_test_, nsamples=20)
print(shap_values)
X_test_ = pd.DataFrame(X_test_,columns=features)
shap.summary_plot(shap_values, X_test_, plot_type = 'violin', max_display=10) # dot violin

在这里插入图片描述

shap.summary_plot(shap_values, X_test_, plot_type="bar") #[class_index]

在这里插入图片描述

print(f"--- 解释样本 {idx} 的瀑布图 ---")shap.waterfall_plot(shap.Explanation(values=shap_values[idx,:], # shap_values[class_index][idx,:],base_values=explainer.expected_value, # explainer.expected_value[class_index]data=X_test_.iloc[idx,:],feature_names=X_test_.columns.tolist())
)

在这里插入图片描述

三、参考

github: https://github.com/dreamquark-ai/tabnet

https://mp.weixin.qq.com/s/6tdSoOOc7I7v-LSyGZ96rA

https://7568.github.io/2021/11/26/tabnet.html

https://zhuanlan.zhihu.com/p/152211918

shap:https://colab.research.google.com/drive/1bAXxurZEWfkCTyPeJn0YbHMrSKbneOKL?usp=sharing#scrollTo=C9qTb-lhNzVH

调优:https://www.kaggle.com/code/neilgibbons/tuning-tabnet-with-optuna/notebook(ReduceLROnPlateau);https://www.kaggle.com/code/optimo/the-beauty-of-tabnet-a-simple-baseline(OneCycleLR)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/92656.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92656.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/92656.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据集成难在哪?制造企业该怎么做?

目录 一、为什么你的数据集成总失败&#xff1f; 1.数据没有统一标准 2.数据 “断点多”&#xff0c;打通成本高 3.数据 “用不起来”&#xff0c;价值难落地 二、数据集成的正确做法是什么&#xff1f; 第一步&#xff1a;明确 “集成为了谁”— 用业务目标倒推数据需求…

Datawhale AI数据分析 作业2

学生考试表现影响因素数据集第一步&#xff1a;数据概览与清洗Prompt 1:加载StudentPerformanceFactors.csv文件&#xff0c;并显示前5行数据以及各列的数据类型和非空值数量&#xff0c;检查是否存在缺失值。处理缺失值是数据预处理的重要一步。对于您提到的缺失值&#xff1a…

Flowable 与 Spring Boot 深度集成:从环境搭建到平台构建

在前三篇文章中&#xff0c;我们依次认识了 Flowable 的基础概念、用 Modeler 设计流程&#xff0c;以及通过 API 控制流程运行。但在实际项目中&#xff0c;我们更需要将 Flowable 与 Spring Boot 深度融合&#xff0c;构建完整的工作流平台。本文将从环境配置、设计器集成、权…

Jenkins最新版本的安装以及集成Allure生成测试报告

目录 Jenkins的安装 将上面的目录添加到系统环境变量中 为Jenkins配置密码 创建一个用户&#xff0c;用于登录jenkins 为Jenkins安装Allure插件 几个大坑 使用jenkins集成python测试项目 Jenkins的安装 Jenkins官方网址 Jenkins 点击download 点击 past Release选择你想要下载…

Vue3 面试题及详细答案120道 (1-15 )

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

基于 GitLab 实践敏捷开发

在软件开发中&#xff0c;**基于 GitLab 实践敏捷开发**&#xff0c;并建立一套**规范的日常管理流程**&#xff0c;不仅可以提升团队协作效率&#xff0c;还能确保平台持续向好迭代、性能稳步提升。以下是一个完整的实践方案&#xff0c;适用于中小型团队或中大型项目&#xf…

黑马点评使用Apifox导入接口测试合集(持续更新、详细图解)

目录 一、前言 二、更新店铺 三、添加秒杀券 四、秒杀下单和秒杀下单user2 一、前言 本博客将持续更新记录黑马点评所有接口测试的导入(学到哪更新到哪)&#xff0c;以此博客为完整导入接口测试的合集。第一次在黑马点评项目使用Apifox进行接口测试直接先看我前面的博客&a…

MYOJ_10583:CSP初赛题单7:计算机常识综合练习

更多初赛题单请参见题目整理CSP初赛题目整理题单&#xff0c;谢谢。 注&#xff1a;阅读此题单时建议先看1~5&#xff0c;再试着自己做。 题目描述 1. [J-2010-6][S-2010-6]提出“存储程序”的计算机工作原理的是&#xff08; &#xff09;。 A. 克劳德香农 B. 戈登摩尔 C.…

代码随想录day22回溯算法1

文章目录77. 组合216.组合总和III17. 电话号码的字母组合77. 组合 题目链接 文章讲解 class Solution { public:vector<vector<int>> res; // 存储所有的组合vector<int> path; // 当前正在构建的组合// 回溯算法void solve(int n, int k, int st…

【Android】Popup menu:弹出式菜单

Popup menu&#xff1a;弹出式菜单 PopupMenu&#xff0c;弹出菜单&#xff0c;一个模态形式展示的弹出风格的菜单&#xff0c;绑在在某个View上&#xff0c;一般出现在被绑定的View的下方&#xff08;如果下方有空间&#xff09;。 注意&#xff1a;弹出菜单是在API 11和更高版…

20250724-day21

Main Memory Database System&#xff08;MMDB&#xff09;&#xff1a;基于内存的数据库系统 File Database&#xff08;FDB&#xff09;&#xff1a;基于文件的数据库 Netware Database&#xff08;NDB&#xff09;&#xff1a;基于网络的数据库 daemon&#xff1a;守护进程 …

API是什么,如何保障API安全?

API&#xff08;应用程序编程接口&#xff09;是什么&#xff1f; API&#xff08;Application Programming Interface&#xff09;是不同软件系统之间通信的“桥梁”。它定义了应用程序如何请求服务、交换数据或调用功能&#xff0c;无需了解底层实现细节。例如&#xff0c;当…

深度分析Java多线程机制

Java 多线程是掌握高性能、高响应性应用程序开发的关键&#xff0c;它涉及到语言特性、JVM 实现、操作系统交互以及并发编程的核心概念。 核心目标&#xff1a; 充分利用现代多核 CPU 的计算能力&#xff0c;提高程序吞吐量&#xff08;单位时间内处理的任务量&#xff09;和响…

Android热修复实现方案深度分析

热修复的核心目标是在**不发布新版本、不重新安装、不重启应用&#xff08;或仅轻量级重启&#xff09;**的情况下&#xff0c;修复线上应用的 Bug 或进行小范围的功能更新&#xff0c;极大地提升用户体验和问题响应速度。 一、热修复的核心原理 无论哪种方案&#xff0c;其核心…

HTML前端颜色渐变动画完整指南

渐变动画已经成为现代网页设计中不可或缺的元素&#xff0c;它们不仅能为网站增添视觉吸引力&#xff0c;还能显著提升用户体验。通过巧妙运用CSS渐变动画&#xff0c;开发者可以创造出令人印象深刻的动态背景效果&#xff0c;而无需依赖图片或复杂的脚本。 渐变动画的魅力所在…

b-up:Enzo_mi:Transformer DETR系列

1.视频1&#xff1a;self-Attention&#xff5c;自注意力机制 &#xff5c;位置编码 &#xff5c; 理论 代码 注意&#xff1a; q-查询; k-商品标签&#xff1b; v-值&#xff08;具体商品&#xff09; * 不是指乘法&#xff0c;类似概念 a1:相似度&#xff1b; b1:总分 若想…

算法题(179):单调栈

审题&#xff1a; 本题是单调栈的模板题 补充&#xff1a;单调栈 单调栈中的数据始终保持单调递增或单调递减 使用情景&#xff1a;给定一个数组&#xff0c;要求寻找 1.某个数左侧&#xff0c;离他最近且值大于他的数 2.某个数左侧&#xff0c;离他最近且值小于他的数 3.某个数…

CF每日5题(1500-1600)

545C 贪心 1500 题意&#xff1a;给 n 棵树在一维数轴上的坐标 xix_ixi​ &#xff0c;以及它们的长度 hih_ihi​。现在要你砍倒这些树&#xff0c;树可以向左倒也可以向右倒&#xff0c;砍倒的树不能重合、当然也不能覆盖其他的树原来的位置&#xff0c;现在求最大可以砍倒的…

HW蓝队:天眼告警监测分析之Web攻击

Web攻击 信息泄露 敏感数据包括但不限于:口令、密钥、证书、会话标识、License、隐私数据(如短消息的内容)、授权凭据、个人数据(如姓名、住址、电话等)等&#xff0c;在程序文件、配置文件、日志文件、备份文件及数据库中都有可能包含敏感数据 信息收集方法 漏洞分类 备份文…

大腾智能国产3D CAD软件正式上架华为云云商店

深圳市大腾信息技术有限公司&#xff08;以下简称“大腾智能”&#xff09;与华为云达成深度合作&#xff0c;大腾智能CAD软件及配套服务通过了华为云在功能适配、安全可用、稳定高效等方面的严选商品认证&#xff0c;已正式上架华为云云商店&#xff0c;成为华为云云商店的联营…