PyTorch Tabular 学习笔记

PyTorch Tabular 学习笔记

已知错误:PyTorch Tabular与pl-lightning 放一起 在Autodl下进度条会报错(禁用进度条)

pytorch-tabular 内部在初始化模型时 默认会帮你创建 PyTorch Lightning 的 Trainer

并且 默认启用了 RichProgressBar

在 AutoDL 容器(非交互终端)下,Rich 的 _live_stack 没被初始化 → pop from empty list


📑 目录

  1. 背景与动机
  2. 核心概念与定义
  3. 安装与环境配置
  4. 数据处理流程
  5. 模型架构详解
  6. 完整实战示例
  7. 高级技巧与调优
  8. 常见问题与对比
  9. 扩展阅读与进阶方向

1. 背景与动机

1.1 为什么需要 PyTorch Tabular?

表格数据的现状:

  • 在工业界,超过 80% 的机器学习任务处理的是表格/结构化数据(CSV、数据库表)
  • 传统方法(XGBoost、LightGBM、CatBoost)在表格数据上表现优异
  • 深度学习在图像/文本领域大放异彩,但在表格数据上长期落后

传统方法的局限:

  • 缺乏端到端学习:特征工程依赖人工设计
  • 无法处理复杂交互:难以自动学习高阶特征组合
  • 迁移能力弱:每个任务需要重新调优

PyTorch Tabular 的价值:

  • 统一框架:集成多种先进的表格深度学习模型
  • 开箱即用:类似 scikit-learn 的简洁 API
  • 灵活扩展:基于 PyTorch,可自定义模型/损失函数
  • 生产就绪:支持混合精度训练、模型导出、推理优化

1.2 表格数据的深度学习挑战

挑战 说明 PyTorch Tabular 解决方案
异构特征 数值型、类别型混合 自动 Embedding + 特征融合
样本量小 通常 < 100 万行 正则化 + 数据增强
类别不平衡 目标类分布不均 内置损失函数加权
缺失值 表格数据常见 自动处理或可自定义策略
可解释性 业务需求高 支持注意力机制模型(如 TabNet)

2. 核心概念与定义

2.1 什么是 PyTorch Tabular?

官方定义:

PyTorch Tabular 是一个基于 PyTorch Lightning 的库,专为表格/结构化数据的深度学习而设计,提供标准化的接口和多种最先进的模型。

核心组件架构:

复制代码
┌─────────────────────────────────────────┐
│         PyTorch Tabular 生态系统         │
├─────────────────────────────────────────┤
│  数据层: DataConfig, TabularDatamodule  │
│  模型层: CategoryEmbedding, TabNet...   │
│  训练层: TabularModel (PyTorch Lightning)│
│  工具层: Callbacks, Metrics, Explainer  │
└─────────────────────────────────────────┘

2.2 关键术语解释

术语 定义 示例
Categorical Features 类别型特征 性别、城市、职业
Continuous Features 连续型数值特征 年龄、收入、距离
Embedding 类别特征的向量表示 "北京" → [0.2, -0.5, 0.8]
Target 预测目标 分类标签、回归值
DataConfig 数据配置对象 定义特征类型、目标列
ModelConfig 模型配置对象 定义层数、维度、学习率

3. 安装与环境配置

3.1 安装 PyTorch Tabular

方式 1:使用 pip(推荐)

bash 复制代码
# 基础安装
pip install pytorch-tabular

# 包含所有依赖(推荐)
pip install pytorch-tabular[all]

# 仅安装特定模型
pip install pytorch-tabular[extra]

方式 2:从源码安装

bash 复制代码
git clone https://github.com/manujosephv/pytorch_tabular.git
cd pytorch_tabular
pip install -e .

3.2 依赖检查

python 复制代码
import torch
import pytorch_tabular
from pytorch_tabular import TabularModel
from pytorch_tabular.models import CategoryEmbeddingModelConfig

print(f"PyTorch 版本: {torch.__version__}")
print(f"PyTorch Tabular 版本: {pytorch_tabular.__version__}")
print(f"CUDA 可用: {torch.cuda.is_available()}")

预期输出:

复制代码
PyTorch 版本: 2.0.0+
PyTorch Tabular 版本: 1.0.0+
CUDA 可用: True/False

4. 数据处理流程

4.1 数据格式要求

基本要求:

  • Pandas DataFrame 格式
  • ✅ 特征列 + 目标列在同一个 DataFrame
  • ✅ 类别型特征已转为 strcategory 类型
  • ✅ 数值型特征为 intfloat

示例数据结构:

python 复制代码
import pandas as pd

# 示例:银行客户流失预测
data = pd.DataFrame({
    'age': [25, 35, 45, 28, 52],                    # 数值特征
    'income': [50000, 80000, 120000, 45000, 95000], # 数值特征
    'city': ['北京', '上海', '深圳', '北京', '上海'],  # 类别特征
    'occupation': ['工程师', '经理', '医生', '教师', '工程师'], # 类别特征
    'churn': [0, 1, 0, 0, 1]                        # 目标变量
})

# 类型转换
data['city'] = data['city'].astype('category')
data['occupation'] = data['occupation'].astype('category')

4.2 DataConfig 配置详解

DataConfig 是数据的"配置中心",定义如何处理特征:

python 复制代码
from pytorch_tabular.config import DataConfig

data_config = DataConfig(
    target=['churn'],  # 目标列(可多目标)
    
    # 连续型特征
    continuous_cols=['age', 'income'],
    
    # 类别型特征
    categorical_cols=['city', 'occupation'],
    
    # 数据验证(可选)
    validation_split=0.2,  # 自动划分验证集
    
    # 归一化策略(可选)
    continuous_feature_transform='quantile',  # 'quantile', 'standard', None
    
    # 缺失值处理(可选)
    normalize_continuous_features=True
)

关键参数说明:

参数 说明 可选值
target 目标列名(列表) 必填
continuous_cols 数值型特征列表 必填
categorical_cols 类别型特征列表 必填
validation_split 验证集比例 0.0 - 1.0
continuous_feature_transform 数值特征转换方式 'quantile', 'standard', None

4.3 完整数据准备流程

python 复制代码
from sklearn.model_selection import train_test_split
from pytorch_tabular.config import DataConfig, OptimizerConfig, TrainerConfig

# Step 1: 加载数据
df = pd.read_csv('your_data.csv')

# Step 2: 数据清洗
# 处理缺失值
df = df.dropna(subset=['target_column'])  # 目标列不能有缺失
df['category_col'] = df['category_col'].fillna('Unknown')

# 类型转换
categorical_features = ['city', 'occupation', 'gender']
for col in categorical_features:
    df[col] = df[col].astype('category')

# Step 3: 划分训练/测试集
train_df, test_df = train_test_split(df, test_size=0.2, random_state=42)

# Step 4: 配置 DataConfig
data_config = DataConfig(
    target=['churn'],
    continuous_cols=['age', 'income', 'balance'],
    categorical_cols=['city', 'occupation', 'gender']
)

5. 模型架构详解

5.1 支持的模型类型

PyTorch Tabular 集成了多种前沿模型:

模型 核心思想 适用场景 可解释性
CategoryEmbedding 传统 MLP + Embedding 通用基线
TabNet 序列注意力 + 特征选择 需要可解释性
NODE 可微分决策树 结构化数据
FT-Transformer Transformer 架构 大规模数据
AutoInt 多头自注意力 特征交互重要
TabTransformer Transformer + MLP 高维类别特征

5.2 模型详细对比

5.2.1 CategoryEmbedding Model(入门推荐)

原理:

  • 类别特征 → Embedding 层 → 拼接数值特征 → 全连接网络

配置示例:

python 复制代码
from pytorch_tabular.models import CategoryEmbeddingModelConfig

model_config = CategoryEmbeddingModelConfig(
    task="classification",  # 'classification' 或 'regression'
    
    # 网络结构
    layers="128-64-32",  # 隐藏层维度(字符串或列表)
    activation="ReLU",   # 激活函数
    
    # Embedding 设置
    embedding_dims=None,  # 自动计算(也可手动指定)
    embedding_dropout=0.0,
    
    # 正则化
    batch_norm_continuous_input=True,
    dropout=0.1,
    
    # 学习率
    learning_rate=1e-3
)

优点:

  • ✅ 简单高效,训练快
  • ✅ 适合快速实验

缺点:

  • ❌ 可解释性差
  • ❌ 特征交互依赖网络深度

5.2.2 TabNet(可解释性之王)

原理:

  • 序列决策注意力:每一步选择最相关的特征
  • 稀疏特征选择:自动学习特征重要性

配置示例:

python 复制代码
from pytorch_tabular.models import TabNetModelConfig

model_config = TabNetModelConfig(
    task="classification",
    
    # TabNet 专属参数
    n_d=64,              # 决策层维度
    n_a=64,              # 注意力层维度
    n_steps=5,           # 决策步数(越大越慢)
    gamma=1.5,           # 特征重用系数
    
    # 正则化
    lambda_sparse=1e-3,  # 稀疏正则化强度
    
    learning_rate=2e-2
)

特色功能:特征重要性可视化

python 复制代码
# 训练后获取特征重要性
tabular_model.explain(test_df)
# 返回每个特征的重要性分数

适用场景:

  • ✅ 金融风控(需要向业务解释模型)
  • ✅ 医疗诊断(可解释性要求高)

5.2.3 FT-Transformer(大数据杀器)

原理:

  • 所有特征(数值+类别)→ Embedding → Transformer 编码器

配置示例:

python 复制代码
from pytorch_tabular.models import FTTransformerConfig

model_config = FTTransformerConfig(
    task="classification",
    
    # Transformer 参数
    num_heads=8,         # 注意力头数
    num_attn_blocks=4,   # Transformer 层数
    
    # Embedding 维度
    embedding_dim=32,
    
    # Dropout
    attn_dropout=0.1,
    ff_dropout=0.1,
    
    learning_rate=1e-4
)

适用场景:

  • ✅ 数据量 > 10 万行
  • ✅ 特征维度高(> 50 维)

5.3 模型选择决策树

复制代码
开始
 │
 ├─ 需要可解释性?
 │   ├─ 是 → TabNet
 │   └─ 否 ↓
 │
 ├─ 数据量大(> 10 万)?
 │   ├─ 是 → FT-Transformer / TabTransformer
 │   └─ 否 ↓
 │
 ├─ 快速验证 baseline?
 │   └─ 是 → CategoryEmbedding
 │
 └─ 特征交互复杂?
     └─ 是 → AutoInt / NODE

6. 完整实战示例

6.1 二分类任务:银行客户流失预测

任务描述: 预测银行客户是否会流失(churn = 0/1)

Step 1: 数据准备
python 复制代码
import pandas as pd
from sklearn.model_selection import train_test_split

# 加载数据
df = pd.read_csv('bank_churn.csv')

# 数据预览
print(df.head())
print(df.info())

# 类型转换
categorical_features = ['Gender', 'Geography', 'HasCrCard', 'IsActiveMember']
for col in categorical_features:
    df[col] = df[col].astype('category')

# 划分数据集
train, test = train_test_split(df, test_size=0.2, random_state=42, stratify=df['Exited'])

Step 2: 配置参数
python 复制代码
from pytorch_tabular.config import DataConfig, OptimizerConfig, TrainerConfig
from pytorch_tabular.models import CategoryEmbeddingModelConfig

# 数据配置
data_config = DataConfig(
    target=['Exited'],  # 目标列
    continuous_cols=['CreditScore', 'Age', 'Tenure', 'Balance', 'EstimatedSalary'],
    categorical_cols=['Geography', 'Gender', 'HasCrCard', 'IsActiveMember'],
)

# 训练器配置
trainer_config = TrainerConfig(
    max_epochs=50,              # 最大训练轮数
    batch_size=512,             # 批大小
    early_stopping='valid_loss', # 早停监控指标
    early_stopping_patience=5,   # 早停容忍轮数
    checkpoints='valid_loss',    # 保存最佳模型
    load_best=True,              # 训练结束后加载最佳模型
    progress_bar='rich',         # 进度条样式
    gpus=1 if torch.cuda.is_available() else 0  # GPU 数量
)

# 优化器配置
optimizer_config = OptimizerConfig(
    optimizer='Adam',
    lr_scheduler='ReduceLROnPlateau',  # 学习率调度器
    lr_scheduler_params={'patience': 3}
)

# 模型配置
model_config = CategoryEmbeddingModelConfig(
    task="classification",
    layers="256-128-64",
    activation="LeakyReLU",
    dropout=0.2,
    learning_rate=1e-3
)

Step 3: 训练模型
python 复制代码
from pytorch_tabular import TabularModel

# 初始化模型
tabular_model = TabularModel(
    data_config=data_config,
    model_config=model_config,
    optimizer_config=optimizer_config,
    trainer_config=trainer_config
)

# 训练
tabular_model.fit(train=train, validation=test)

训练输出示例:

复制代码
Epoch 10/50: 100%|██████| 78/78 [00:02<00:00, 34.21it/s, loss=0.423, val_loss=0.456]
Best model saved at epoch 8 with val_loss=0.445

Step 4: 模型评估
python 复制代码
# 预测
pred_df = tabular_model.predict(test)
print(pred_df.head())

# 评估指标
result = tabular_model.evaluate(test)
print(result)

# 输出示例:
# [{'test_loss': 0.456, 'test_accuracy': 0.823, 'test_auroc': 0.867}]

Step 5: 模型保存与加载
python 复制代码
# 保存模型
tabular_model.save_model("models/churn_model")

# 加载模型
from pytorch_tabular import TabularModel
loaded_model = TabularModel.load_model("models/churn_model")

# 推理
predictions = loaded_model.predict(new_data)

6.2 回归任务:房价预测

关键差异:

python 复制代码
# 1. DataConfig 中目标列为连续值
data_config = DataConfig(
    target=['price'],  # 房价(连续值)
    continuous_cols=['area', 'bedrooms', 'age'],
    categorical_cols=['location', 'type']
)

# 2. ModelConfig 中 task 改为 regression
model_config = CategoryEmbeddingModelConfig(
    task="regression",  # ← 关键修改
    layers="128-64",
    learning_rate=1e-3
)

# 3. 评估指标自动切换为 MSE, RMSE, MAE
result = tabular_model.evaluate(test)
# 输出: {'test_loss': 25000, 'test_mse': 25000, 'test_rmse': 158.11}

7. 高级技巧与调优

7.1 超参数调优

方式 1:网格搜索(手动)

python 复制代码
import itertools

# 定义超参数空间
param_grid = {
    'layers': ['128-64', '256-128-64', '512-256-128'],
    'dropout': [0.1, 0.2, 0.3],
    'learning_rate': [1e-3, 1e-4]
}

best_score = 0
best_params = None

# 遍历所有组合
for layers, dropout, lr in itertools.product(
    param_grid['layers'],
    param_grid['dropout'],
    param_grid['learning_rate']
):
    model_config = CategoryEmbeddingModelConfig(
        task="classification",
        layers=layers,
        dropout=dropout,
        learning_rate=lr
    )
    
    tabular_model = TabularModel(
        data_config=data_config,
        model_config=model_config,
        trainer_config=trainer_config
    )
    
    tabular_model.fit(train=train, validation=test)
    result = tabular_model.evaluate(test)
    
    if result[0]['test_accuracy'] > best_score:
        best_score = result[0]['test_accuracy']
        best_params = {'layers': layers, 'dropout': dropout, 'lr': lr}

print(f"最佳参数: {best_params}, 准确率: {best_score}")

方式 2:使用 Optuna(推荐)

python 复制代码
import optuna
from pytorch_tabular import TabularModel

def objective(trial):
    # 超参数采样
    layers = trial.suggest_categorical('layers', ['128-64', '256-128-64'])
    dropout = trial.suggest_float('dropout', 0.1, 0.5)
    lr = trial.suggest_loguniform('lr', 1e-4, 1e-2)
    
    model_config = CategoryEmbeddingModelConfig(
        task="classification",
        layers=layers,
        dropout=dropout,
        learning_rate=lr
    )
    
    tabular_model = TabularModel(
        data_config=data_config,
        model_config=model_config,
        trainer_config=TrainerConfig(max_epochs=10, gpus=1)  # 快速验证
    )
    
    tabular_model.fit(train=train, validation=test)
    result = tabular_model.evaluate(test)
    
    return result[0]['test_accuracy']

# 运行优化
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=20)

print("最佳参数:", study.best_params)
print("最佳准确率:", study.best_value)

7.2 自定义损失函数

场景: 处理类别不平衡(正负样本比 1:9)

python 复制代码
import torch
import torch.nn as nn

class FocalLoss(nn.Module):
    """Focal Loss 用于处理类别不平衡"""
    def __init__(self, alpha=0.25, gamma=2.0):
        super().__init__()
        self.alpha = alpha
        self.gamma = gamma
        
    def forward(self, inputs, targets):
        BCE_loss = nn.functional.binary_cross_entropy_with_logits(
            inputs, targets, reduction='none'
        )
        pt = torch.exp(-BCE_loss)
        F_loss = self.alpha * (1-pt)**self.gamma * BCE_loss
        return F_loss.mean()

# 在 ModelConfig 中使用
model_config = CategoryEmbeddingModelConfig(
    task="classification",
    layers="128-64",
    loss=FocalLoss(alpha=0.75, gamma=2.0)  # ← 自定义损失
)

7.3 数据增强(SMOTE)

python 复制代码
from imblearn.over_sampling import SMOTE

# 仅对训练集做过采样
X_train = train.drop('Exited', axis=1)
y_train = train['Exited']

smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)

train_resampled = pd.concat([X_resampled, y_resampled], axis=1)

# 使用增强后的数据训练
tabular_model.fit(train=train_resampled, validation=test)

7.4 模型集成(Ensemble)

python 复制代码
# 训练多个模型
models = []
for seed in [42, 123, 456]:
    model_config = CategoryEmbeddingModelConfig(
        task="classification",
        layers="128-64",
        seed=seed  # 不同随机种子
    )
    
    model = TabularModel(
        data_config=data_config,
        model_config=model_config,
        trainer_config=trainer_config
    )
    model.fit(train=train, validation=test)
    models.append(model)

# 集成预测(投票)
predictions = []
for model in models:
    pred = model.predict(test)
    predictions.append(pred['prediction'])

# 平均概率
ensemble_pred = sum(predictions) / len(predictions)
final_pred = (ensemble_pred > 0.5).astype(int)

8. 常见问题与对比

8.1 PyTorch Tabular vs 传统方法

维度 PyTorch Tabular XGBoost/LightGBM
训练速度 慢(需要 GPU 加速) 快(CPU 友好)
小数据表现 一般(容易过拟合) 优秀
大数据表现 优秀(可扩展) 受限(内存瓶颈)
特征工程 自动学习交互 需要手动构造
可解释性 TabNet 可解 天然可解释
部署难度 中等(需要 PyTorch) 简单(轻量级)
适用场景 复杂模式、大规模数据 快速迭代、小数据

建议:

  • 先用 XGBoost/LightGBM 建立 baseline
  • ✅ 如果传统方法已足够好,无需深度学习
  • ✅ 当数据量 > 10 万且特征复杂时,尝试 PyTorch Tabular

8.2 常见错误与解决

错误 1:类别特征未转换类型
python 复制代码
# ❌ 错误
df['city'] = df['city']  # 仍是 object 类型

# ✅ 正确
df['city'] = df['city'].astype('category')

错误 2:内存溢出(OOM)

症状: CUDA out of memory

解决:

python 复制代码
# 方法 1: 减小批大小
trainer_config = TrainerConfig(batch_size=256)  # 从 512 降到 256

# 方法 2: 混合精度训练
trainer_config = TrainerConfig(precision=16)  # 使用 FP16

# 方法 3: 梯度累积
trainer_config = TrainerConfig(accumulate_grad_batches=4)

错误 3:验证集性能不提升

可能原因:

  • 数据泄漏(训练/验证集未正确划分)
  • 学习率过大
  • 过拟合

解决:

python 复制代码
# 检查数据划分
train, test = train_test_split(df, stratify=df['target'], random_state=42)

# 降低学习率
model_config = CategoryEmbeddingModelConfig(learning_rate=1e-4)

# 增加正则化
model_config = CategoryEmbeddingModelConfig(dropout=0.3, batch_norm_continuous_input=True)

8.3 调试技巧

技巧 1:快速验证(Over-fitting 单个 Batch)

python 复制代码
# 用极小数据集测试代码是否能运行
tiny_train = train.head(100)

tabular_model.fit(train=tiny_train, validation=tiny_train)
# 应该能快速达到 100% 准确率

技巧 2:可视化训练曲线

python 复制代码
# 使用 TensorBoard
from pytorch_tabular.utils import get_logger

trainer_config = TrainerConfig(
    logger='tensorboard',  # 或 'wandb'
    log_dir='logs/'
)

# 启动 TensorBoard
# 终端运行: tensorboard --logdir=logs/

技巧 3:特征重要性分析(仅 TabNet)

python 复制代码
model_config = TabNetModelConfig(task="classification")
tabular_model = TabularModel(
    data_config=data_config,
    model_config=model_config
)

tabular_model.fit(train=train, validation=test)

# 获取特征重要性
importance = tabular_model.explain(test)
print(importance)

9. 扩展阅读与进阶方向

9.1 官方资源

资源 链接
官方文档 https://pytorch-tabular.readthedocs.io/
GitHub 仓库 https://github.com/manujosephv/pytorch_tabular
示例代码 https://github.com/manujosephv/pytorch_tabular/tree/main/docs/tutorials
论文列表 TabNet, FT-Transformer

9.2 进阶学习路径

阶段 1:掌握所有模型
  • 实现 TabNet 并理解注意力机制
  • 对比 FT-Transformer vs CategoryEmbedding
  • 尝试 NODE(可微分决策树)
阶段 2:深入定制
  • 自定义 Embedding 维度计算策略
  • 实现自定义的 Attention 模块
  • 魔改损失函数(如 Focal Loss + Label Smoothing)
阶段 3:生产部署
  • 模型量化(INT8)
  • ONNX 导出与推理加速
  • 流式预测(实时特征工程)

9.3 实战项目推荐

项目 数据集 难度 技能点
信用卡欺诈检测 Kaggle - Credit Card Fraud ⭐⭐ 类别不平衡 + TabNet
房价预测 Kaggle - House Prices ⭐⭐ 回归 + 特征工程
客户流失预测 Kaggle - Telco Churn ⭐⭐ 分类 + 可解释性
推荐系统(CTR 预测) Kaggle - Avazu CTR ⭐⭐⭐ 大规模数据 + AutoInt

9.4 相关技术栈

如果你对 PyTorch Tabular 感兴趣,可以进一步学习:

  • AutoML 工具: AutoGluon, H2O.ai(自动化表格数据建模)
  • 特征工程: Feature-engine, tsfresh(时序特征提取)
  • 模型解释: SHAP, LIME(黑盒模型解释)
  • 部署框架: BentoML, Seldon Core(模型服务化)

📌 总结:核心要点速查

✅ 快速上手三步骤

  1. 安装 : pip install pytorch-tabular[all]
  2. 配置 : DataConfig + ModelConfig + TrainerConfig
  3. 训练 : tabular_model.fit(train, validation)

✅ 模型选择公式

复制代码
数据量 < 1 万        → XGBoost(不用深度学习)
数据量 1-10 万       → CategoryEmbedding(快速验证)
数据量 > 10 万       → FT-Transformer(性能优先)
需要可解释性         → TabNet(注意力机制)
特征交互复杂         → AutoInt / NODE

✅ 调优优先级

  1. 数据质量 > 模型选择 > 超参数调优
  2. 先用简单模型(CategoryEmbedding)建立 baseline
  3. 检查数据泄漏、类别不平衡
  4. 最后再调 learning_rate、dropout、layers

✅ 生产部署检查清单

  • 模型保存为 .pt 文件
  • 记录完整配置(data_config, model_config)
  • 测试推理速度(单样本 < 10ms)
  • 验证 ONNX 导出(可选)
  • 准备特征预处理 Pipeline

相关推荐
TheSumSt2 小时前
Python丨课程笔记Part2:方法论进阶部分
开发语言·笔记·python
摇滚侠2 小时前
Java 零基础全套视频教程,异常,处理异常,自定义异常,笔记 124-129
java·笔记
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs]initramfs
linux·笔记·学习
风行男孩2 小时前
stm32基础学习——定时器的使用
stm32·单片机·学习
深蓝海拓3 小时前
PySide6从0开始学习的笔记(十八) MVC(Model-View-Controller)模式的图形渲染体系
笔记·python·qt·学习·pyqt
lpfasd1233 小时前
《乌合之众》精读笔记
笔记
知识分享小能手3 小时前
Ubuntu入门学习教程,从入门到精通, Ubuntu 22.04 的软件包管理 —— 全面详解(9)
linux·学习·ubuntu
会思考的猴子3 小时前
UE5 笔记二 GameplayAbilitySystem Dash(冲刺)
笔记·ue5
蒙奇D索大3 小时前
【数据结构】排序算法精讲|折半插入排序全解:高效优化、性能对比、实战剖析
数据结构·学习·考研·算法·排序算法·改行学it