x-transformers 完整学习笔记

x-transformers 学习笔记


📑 目录

  1. 背景与动机
  2. 核心概念与定义
  3. 安装与环境配置
  4. 核心架构与组件
  5. 快速开始:基础示例
  6. 高级特性详解
  7. 实际应用场景
  8. 性能优化与最佳实践
  9. 常见问题与调试
  10. 与其他库的对比
  11. 扩展阅读与进阶方向

1. 背景与动机

1.1 为什么需要 x-transformers?

Transformer 架构的挑战:

  • 标准 Transformer 实现复杂,涉及大量样板代码
  • 新研究成果(如 Alibi、Rotary Embeddings)难以快速集成
  • 不同任务需要不同的注意力机制变体
  • 内存效率优化需要深入的工程实现

x-transformers 的解决方案:

  • 提供即插即用的 Transformer 变体实现
  • 集成最新研究成果(Flash Attention、Memory-efficient Attention)
  • 模块化设计,易于自定义和扩展
  • 生产级代码质量,经过充分测试

1.2 核心优势

特性 说明
简洁性 几行代码即可构建复杂的 Transformer 模型
灵活性 支持多种注意力机制、位置编码方案
高效性 集成 Flash Attention 等内存优化技术
前沿性 快速集成最新学术研究成果
可扩展性 易于添加自定义层和功能

2. 核心概念与定义

2.1 什么是 x-transformers?

x-transformers 是由 Phil Wang (lucidrains) 开发的 PyTorch Transformer 实现库,特点:

  • 研究友好:快速实验新想法
  • 生产就绪:代码质量高,性能优化充分
  • 持续更新:及时跟进学术界最新进展

2.2 核心模块

复制代码
x-transformers
├── Encoder                 # 编码器(用于理解输入)
├── Decoder                 # 解码器(用于生成输出)
├── TransformerWrapper      # 完整的 Transformer 封装
├── AutoregressiveWrapper   # 自回归生成封装
└── Attention Variants      # 各种注意力机制变体

2.3 关键术语

  • Autoregressive(自回归):逐步生成序列,每一步依赖前面的输出
  • Causal Masking(因果掩码):防止模型"看到未来"的信息
  • Cross Attention(交叉注意力):在 Encoder-Decoder 架构中,Decoder 关注 Encoder 的输出
  • Relative Position Encoding:相对位置编码,更好地处理长序列

3. 安装与环境配置

3.1 系统要求

  • Python: ≥ 3.8
  • PyTorch: ≥ 1.10
  • CUDA: 可选,用于 GPU 加速

3.2 安装方法

方法 1:使用 pip(推荐)
bash 复制代码
pip install x-transformers
方法 2:从源码安装(获取最新特性)
bash 复制代码
git clone https://github.com/lucidrains/x-transformers.git
cd x-transformers
pip install -e .

3.3 验证安装

python 复制代码
import torch
from x_transformers import TransformerWrapper, Decoder

print("x-transformers 安装成功!")
print(f"PyTorch 版本: {torch.__version__}")
print(f"CUDA 可用: {torch.cuda.is_available()}")

4. 核心架构与组件

4.1 基础组件层次结构

复制代码
TransformerWrapper (最外层封装)
    └── Encoder / Decoder (核心网络)
        └── AttentionLayers (注意力层堆叠)
            └── Attention (单个注意力层)
                ├── Self-Attention
                ├── Cross-Attention
                └── Feedforward Network

4.2 Encoder:编码器

用途:理解和编码输入序列(如文本、图像 patches)

关键特性

  • 双向注意力(可以看到整个序列)
  • 适用于分类、表示学习任务

基本构造:

python 复制代码
from x_transformers import Encoder

encoder = Encoder(
    dim=512,              # 模型维度
    depth=6,              # Transformer 层数
    heads=8,              # 注意力头数
    ff_mult=4,            # FFN 隐藏层倍数
    attn_dropout=0.1,     # 注意力 dropout
    ff_dropout=0.1        # FFN dropout
)

# 使用
x = torch.randn(2, 1024, 512)  # (batch, seq_len, dim)
encoded = encoder(x)            # 输出形状相同

4.3 Decoder:解码器

用途:自回归生成序列(如语言模型、文本生成)

关键特性

  • 因果注意力(只能看到之前的 tokens)
  • 支持交叉注意力(用于条件生成)

基本构造:

python 复制代码
from x_transformers import Decoder

decoder = Decoder(
    dim=512,
    depth=6,
    heads=8,
    attn_dropout=0.1,
    ff_dropout=0.1,
    cross_attend=True,    # 启用交叉注意力(用于 Encoder-Decoder)
    causal=True           # 启用因果掩码
)

# 使用(自回归场景)
x = torch.randn(2, 512, 512)  # Decoder 输入
context = torch.randn(2, 1024, 512)  # Encoder 输出(可选)

output = decoder(x, context=context)

4.4 TransformerWrapper:完整模型封装

用途:将 Token Embedding + Positional Encoding + Transformer + Output Layer 封装在一起

python 复制代码
from x_transformers import TransformerWrapper, Decoder

model = TransformerWrapper(
    num_tokens=20000,        # 词汇表大小
    max_seq_len=1024,        # 最大序列长度
    attn_layers=Decoder(
        dim=512,
        depth=6,
        heads=8
    )
)

# 使用
tokens = torch.randint(0, 20000, (2, 512))  # (batch, seq_len)
logits = model(tokens)  # (batch, seq_len, num_tokens)

4.5 AutoregressiveWrapper:自回归生成封装

用途:简化自回归生成流程(如文本生成)

python 复制代码
from x_transformers import AutoregressiveWrapper

model = AutoregressiveWrapper(
    net=TransformerWrapper(...),
    pad_value=0  # padding token ID
)

# 训练模式:自动处理 teacher forcing
loss = model(tokens, labels=tokens)

# 生成模式
generated = model.generate(
    start_tokens=torch.tensor([[1]]),  # 起始 token
    seq_len=100,                       # 生成长度
    temperature=1.0                    # 采样温度
)

5. 快速开始:基础示例

5.1 示例 1:语言模型(GPT 风格)

python 复制代码
import torch
from x_transformers import TransformerWrapper, Decoder, AutoregressiveWrapper

# 1. 定义模型
model = TransformerWrapper(
    num_tokens=20000,
    max_seq_len=512,
    attn_layers=Decoder(
        dim=512,
        depth=6,
        heads=8,
        attn_dropout=0.1,
        ff_dropout=0.1
    )
)

# 2. 封装为自回归模型
model = AutoregressiveWrapper(model)

# 3. 准备数据
tokens = torch.randint(0, 20000, (4, 256))  # (batch=4, seq_len=256)

# 4. 训练
loss = model(tokens, return_loss=True)
loss.backward()

# 5. 生成
start_tokens = torch.tensor([[1]])  # 起始 token
generated = model.generate(start_tokens, seq_len=50)
print(generated.shape)  # (1, 50)

5.2 示例 2:Encoder-Decoder 模型(翻译任务)

python 复制代码
from x_transformers import Encoder, Decoder, TransformerWrapper

# Encoder(处理源语言)
encoder = TransformerWrapper(
    num_tokens=10000,  # 源语言词汇表
    max_seq_len=512,
    attn_layers=Encoder(dim=512, depth=6, heads=8)
)

# Decoder(生成目标语言)
decoder = TransformerWrapper(
    num_tokens=10000,  # 目标语言词汇表
    max_seq_len=512,
    attn_layers=Decoder(
        dim=512,
        depth=6,
        heads=8,
        cross_attend=True  # 关键:启用交叉注意力
    )
)

# 使用
src_tokens = torch.randint(0, 10000, (2, 100))  # 源序列
tgt_tokens = torch.randint(0, 10000, (2, 80))   # 目标序列

# Encoder 编码
context = encoder(src_tokens, return_embeddings=True)

# Decoder 生成(需要 context)
logits = decoder(tgt_tokens, context=context)

5.3 示例 3:文本分类(BERT 风格)

python 复制代码
from x_transformers import TransformerWrapper, Encoder
import torch.nn as nn

# Encoder + 分类头
encoder = TransformerWrapper(
    num_tokens=30000,
    max_seq_len=512,
    attn_layers=Encoder(dim=768, depth=12, heads=12),
    return_logits=False  # 返回 embeddings 而非 logits
)

class TextClassifier(nn.Module):
    def __init__(self, encoder, num_classes=2):
        super().__init__()
        self.encoder = encoder
        self.classifier = nn.Linear(768, num_classes)
    
    def forward(self, tokens):
        # 获取 [CLS] token 的表示(第一个 token)
        embeddings = self.encoder(tokens, return_embeddings=True)
        cls_embedding = embeddings[:, 0, :]  # (batch, dim)
        return self.classifier(cls_embedding)

# 使用
model = TextClassifier(encoder, num_classes=5)
tokens = torch.randint(0, 30000, (8, 128))
logits = model(tokens)  # (8, 5)

6. 高级特性详解

6.1 位置编码方案

x-transformers 支持多种位置编码:

6.1.1 绝对位置编码(默认)
python 复制代码
decoder = Decoder(
    dim=512,
    depth=6,
    heads=8
    # 默认使用 learned positional embeddings
)
6.1.2 Rotary Position Embeddings (RoPE)

优势:更好的长度外推能力

python 复制代码
decoder = Decoder(
    dim=512,
    depth=6,
    heads=8,
    rotary_pos_emb=True  # 启用 RoPE
)
6.1.3 Alibi (Attention with Linear Biases)

优势:无需显式位置编码,更简单高效

python 复制代码
decoder = Decoder(
    dim=512,
    depth=6,
    heads=8,
    alibi_pos_bias=True  # 启用 Alibi
)

6.2 高效注意力机制

6.2.1 Flash Attention

优势:显著降低内存占用,加速训练

python 复制代码
decoder = Decoder(
    dim=512,
    depth=6,
    heads=8,
    use_flash_attn=True  # 需要安装 flash-attn 包
)

安装 Flash Attention:

bash 复制代码
pip install flash-attn --no-build-isolation
6.2.2 Memory Efficient Attention

优势:PyTorch 内置,无需额外依赖

python 复制代码
decoder = Decoder(
    dim=512,
    depth=6,
    heads=8,
    use_memory_efficient_attn=True
)

6.3 混合精度训练

python 复制代码
from torch.cuda.amp import autocast, GradScaler

model = TransformerWrapper(...)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
scaler = GradScaler()

for tokens in dataloader:
    optimizer.zero_grad()
    
    with autocast():  # 自动混合精度
        loss = model(tokens, return_loss=True)
    
    scaler.scale(loss).backward()
    scaler.step(optimizer)
    scaler.update()

6.4 Conditional Generation(条件生成)

python 复制代码
# 使用交叉注意力实现条件生成
decoder = Decoder(
    dim=512,
    depth=6,
    heads=8,
    cross_attend=True  # 必须启用
)

# 生成时提供条件
condition_embedding = encoder(condition_tokens, return_embeddings=True)
output = decoder(target_tokens, context=condition_embedding)

6.5 分块处理长序列

python 复制代码
# 使用 sliding window attention 处理超长序列
decoder = Decoder(
    dim=512,
    depth=6,
    heads=8,
    local_attn_window_size=256  # 每个 token 只关注前后 256 个 tokens
)

7. 实际应用场景

7.1 场景 1:文本生成(小说、对话)

任务特点

  • 自回归生成
  • 需要流畅性和连贯性
  • 可能需要控制生成(如温度、top-k)

代码框架

python 复制代码
model = AutoregressiveWrapper(
    TransformerWrapper(
        num_tokens=50000,
        max_seq_len=2048,
        attn_layers=Decoder(
            dim=768,
            depth=12,
            heads=12,
            rotary_pos_emb=True  # 更好的长序列处理
        )
    )
)

# 生成时的控制参数
generated = model.generate(
    start_tokens=prompt,
    seq_len=500,
    temperature=0.8,      # 控制随机性
    filter_thres=0.9,     # nucleus sampling (top-p)
    top_k=50              # top-k sampling
)

7.2 场景 2:机器翻译

任务特点

  • Encoder-Decoder 架构
  • 需要交叉注意力
  • 通常使用 beam search
python 复制代码
# Encoder
src_encoder = TransformerWrapper(
    num_tokens=vocab_size_src,
    max_seq_len=512,
    attn_layers=Encoder(dim=512, depth=6, heads=8)
)

# Decoder
tgt_decoder = TransformerWrapper(
    num_tokens=vocab_size_tgt,
    max_seq_len=512,
    attn_layers=Decoder(
        dim=512,
        depth=6,
        heads=8,
        cross_attend=True
    )
)

# 翻译流程
def translate(src_tokens):
    context = src_encoder(src_tokens, return_embeddings=True)
    # 使用 beam search 生成(需要自行实现或使用其他库)
    translations = beam_search_decode(tgt_decoder, context)
    return translations

7.3 场景 3:代码生成

任务特点

  • 精确的语法要求
  • 长距离依赖
  • 可能需要大的上下文窗口
python 复制代码
code_model = TransformerWrapper(
    num_tokens=50000,
    max_seq_len=4096,  # 更长的上下文
    attn_layers=Decoder(
        dim=1024,
        depth=24,
        heads=16,
        use_flash_attn=True,      # 减少内存压力
        rotary_pos_emb=True,      # 更好的长度外推
        ff_glu=True               # GLU 激活函数(更适合代码)
    )
)

7.4 场景 4:多模态(视觉 + 语言)

思路:将图像编码为 tokens,与文本 tokens 拼接

python 复制代码
from torchvision.models import resnet50

# 图像编码器
image_encoder = resnet50(pretrained=True)
image_encoder.fc = nn.Linear(2048, 512 * 16)  # 输出 16 个 512 维的 tokens

# Transformer 处理图像 + 文本
model = TransformerWrapper(
    num_tokens=50000,
    max_seq_len=1024,
    attn_layers=Decoder(dim=512, depth=12, heads=8)
)

# 使用
image = torch.randn(1, 3, 224, 224)
text_tokens = torch.randint(0, 50000, (1, 256))

image_tokens = image_encoder(image).view(1, 16, 512)  # (1, 16, 512)
# 将图像 tokens 与文本 tokens 拼接(需要额外的 embedding 处理)

8. 性能优化与最佳实践

8.1 内存优化技巧

✅ 使用 Gradient Checkpointing
python 复制代码
decoder = Decoder(
    dim=512,
    depth=12,
    heads=8,
    use_checkpoint=True  # 牺牲 20% 速度换取 50% 内存节省
)
✅ 减少 Batch Size,增加梯度累积
python 复制代码
accumulation_steps = 4
optimizer.zero_grad()

for i, batch in enumerate(dataloader):
    loss = model(batch) / accumulation_steps
    loss.backward()
    
    if (i + 1) % accumulation_steps == 0:
        optimizer.step()
        optimizer.zero_grad()
✅ 使用高效注意力
python 复制代码
# 优先级:Flash Attention > Memory Efficient > 标准实现
decoder = Decoder(
    dim=512,
    depth=12,
    heads=8,
    use_flash_attn=True  # 如果环境支持
)

8.2 训练稳定性技巧

✅ 使用 Pre-Norm(默认)
python 复制代码
# x-transformers 默认使用 Pre-Norm(LayerNorm 在 Attention 之前)
# 比 Post-Norm 更稳定
decoder = Decoder(
    dim=512,
    depth=12,
    heads=8,
    pre_norm=True  # 默认值
)
✅ 梯度裁剪
python 复制代码
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
✅ 学习率预热
python 复制代码
from torch.optim.lr_scheduler import LambdaLR

def lr_lambda(step):
    warmup_steps = 4000
    if step < warmup_steps:
        return step / warmup_steps
    return (warmup_steps / step) ** 0.5

scheduler = LambdaLR(optimizer, lr_lambda)

8.3 推理优化

✅ 使用 KV Cache(自动)
python 复制代码
# AutoregressiveWrapper 自动使用 KV cache 加速生成
model = AutoregressiveWrapper(net)
generated = model.generate(start_tokens, seq_len=100)
# 无需手动管理缓存
✅ 量化(推理加速)
python 复制代码
# 使用 PyTorch 的动态量化
import torch.quantization as quant

model_fp32 = TransformerWrapper(...)
model_int8 = quant.quantize_dynamic(
    model_fp32,
    {nn.Linear},  # 量化线性层
    dtype=torch.qint8
)

9. 常见问题与调试

9.1 问题:OOM (Out of Memory)

原因

  • Batch size 过大
  • 序列长度过长
  • 模型层数/维度过大

解决方案

python 复制代码
# 1. 启用梯度检查点
decoder = Decoder(dim=512, depth=12, use_checkpoint=True)

# 2. 使用 Flash Attention
decoder = Decoder(dim=512, depth=12, use_flash_attn=True)

# 3. 减少 batch size,增加梯度累积步数
# 4. 使用混合精度训练(fp16)

9.2 问题:训练不收敛

可能原因

  • 学习率过大
  • 没有使用学习率预热
  • 梯度爆炸

解决方案

python 复制代码
# 1. 降低学习率
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)

# 2. 添加学习率预热(见 8.2 节)

# 3. 梯度裁剪
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

# 4. 检查数据预处理(是否有异常值)

9.3 问题:生成结果重复

原因

  • 温度参数过低
  • 模型过拟合
  • 采样策略不当

解决方案

python 复制代码
# 1. 调整采样参数
generated = model.generate(
    start_tokens=prompt,
    seq_len=100,
    temperature=1.0,        # 增加随机性(默认 1.0)
    filter_thres=0.9,       # top-p sampling
    top_k=50,               # top-k sampling
    repetition_penalty=1.2  # 惩罚重复(如果支持)
)

# 2. 在训练时增加 dropout
decoder = Decoder(dim=512, depth=12, attn_dropout=0.1, ff_dropout=0.1)

9.4 问题:长序列性能下降

原因

  • 标准的绝对位置编码外推能力差
  • 注意力复杂度 O(n²)

解决方案

python 复制代码
# 1. 使用相对位置编码
decoder = Decoder(
    dim=512,
    depth=12,
    heads=8,
    rotary_pos_emb=True  # 或 alibi_pos_bias=True
)

# 2. 使用局部注意力
decoder = Decoder(
    dim=512,
    depth=12,
    heads=8,
    local_attn_window_size=512  # 限制注意力窗口
)

9.5 调试技巧

python 复制代码
# 1. 检查模型输出形状
x = torch.randn(2, 100, 512)
output = decoder(x)
print(f"Output shape: {output.shape}")

# 2. 检查注意力权重
decoder = Decoder(dim=512, depth=6, heads=8)
output, attn_weights = decoder(x, return_attn=True)
print(f"Attention weights shape: {attn_weights.shape}")

# 3. 可视化注意力
import matplotlib.pyplot as plt
plt.imshow(attn_weights[0, 0].detach().cpu())  # 第一个样本,第一个头
plt.colorbar()
plt.show()

10. 与其他库的对比

10.1 x-transformers vs Hugging Face Transformers

维度 x-transformers Hugging Face Transformers
易用性 ⭐⭐⭐⭐ 简洁直观 ⭐⭐⭐ 功能丰富但复杂
灵活性 ⭐⭐⭐⭐⭐ 高度模块化 ⭐⭐⭐ 以预训练模型为主
预训练模型 ❌ 无 ⭐⭐⭐⭐⭐ 丰富的模型库
研究友好 ⭐⭐⭐⭐⭐ 快速实验 ⭐⭐⭐ 需要深入理解架构
生产部署 ⭐⭐⭐ 需要自行封装 ⭐⭐⭐⭐⭐ 完善的生态
最新特性 ⭐⭐⭐⭐⭐ 快速跟进 ⭐⭐⭐ 更新相对保守

选择建议

  • 使用 x-transformers:自定义模型、研究实验、快速原型
  • 使用 Hugging Face:使用预训练模型、生产部署、标准任务

10.2 x-transformers vs Fairseq

维度 x-transformers Fairseq
代码复杂度 ⭐⭐⭐⭐⭐ 简洁 ⭐⭐ 复杂
分布式训练 ⭐⭐⭐ 需配合 PyTorch DDP ⭐⭐⭐⭐⭐ 内置支持
翻译任务 ⭐⭐⭐ 可实现 ⭐⭐⭐⭐⭐ 专门优化
学习曲线 ⭐⭐⭐⭐⭐ 平缓 ⭐⭐ 陡峭

11. 扩展阅读与进阶方向

11.1 必读论文

基础理论
  1. Attention Is All You Need (2017)

    • 原始 Transformer 论文
    • 理解 Self-Attention 机制
  2. BERT: Pre-training of Deep Bidirectional Transformers (2018)

    • Encoder-only 架构
    • Masked Language Modeling
  3. Language Models are Unsupervised Multitask Learners (GPT-2) (2019)

    • Decoder-only 架构
    • 自回归语言建模
位置编码
  1. RoFormer: Enhanced Transformer with Rotary Position Embedding (2021)

    • 旋转位置编码 (RoPE)
    • 更好的长度外推
  2. Train Short, Test Long: Attention with Linear Biases (ALiBi) (2021)

    • 无需显式位置编码
    • 线性注意力偏置
效率优化
  1. FlashAttention: Fast and Memory-Efficient Exact Attention (2022)

    • IO 感知的注意力实现
    • 显著降低内存占用
  2. Self-attention Does Not Need O(n²) Memory (2021)

    • Memory-efficient attention

11.2 进阶主题

🔹 主题 1:长序列建模
  • 技术:Sparse Attention、Linformer、Performer
  • 应用:长文档理解、基因序列分析
  • 参考:Longformer、BigBird 论文
🔹 主题 2:多模态 Transformer
  • 技术:Vision Transformer (ViT)、CLIP、Flamingo
  • 应用:图像描述、视觉问答
  • 资源:CLIP GitHub、ViT 论文
🔹 主题 3:模型压缩与加速
  • 技术:知识蒸馏、剪枝、量化
  • 工具:ONNX Runtime、TensorRT
  • 参考:DistilBERT、TinyBERT
🔹 主题 4:自定义注意力机制
  • 方向:结构化注意力、稀疏注意力
  • 实现 :修改 Attention
python 复制代码
from x_transformers.x_transformers import Attention

class CustomAttention(Attention):
    def forward(self, x, context=None, mask=None):
        # 自定义注意力逻辑
        pass

11.3 实践项目建议

初级项目
  1. 情感分类器:使用 Encoder + 分类头
  2. 文本生成器:简单的故事生成
中级项目
  1. 聊天机器人:对话生成 + 上下文管理
  2. 代码补全:基于上下文的代码生成
高级项目
  1. 多模态搜索:图像 + 文本检索
  2. 长文档摘要:处理超长输入

11.4 开源资源


📌 总结

核心要点回顾

  1. x-transformers 是什么

    • 灵活、高效的 Transformer 实现库
    • 快速集成最新研究成果
    • 研究友好 + 生产级代码质量
  2. 何时使用

    • ✅ 自定义模型架构
    • ✅ 快速实验新想法
    • ✅ 需要灵活的注意力机制
    • ❌ 直接使用预训练模型(用 Hugging Face)
  3. 关键组件

    • Encoder:双向理解
    • Decoder:自回归生成
    • TransformerWrapper:完整模型封装
    • AutoregressiveWrapper:生成任务封装
  4. 性能优化

    • Flash Attention / Memory-efficient Attention
    • 梯度检查点
    • 混合精度训练
    • 合适的位置编码(RoPE、Alibi)
  5. 最佳实践

    • 从小模型开始调试
    • 使用梯度裁剪保证稳定性
    • 学习率预热
    • 定期验证模型输出
相关推荐
名字不相符3 分钟前
NSSCTF2026年1月8日每日一练之[第五空间 2021]WebFTP
学习·萌新
四谎真好看5 分钟前
JavaWeb 学习笔记(Day02)之Vue
笔记·学习·vue·学习笔记·javaweb
:mnong8 分钟前
辅助学习神经网络
人工智能·神经网络·学习
进阶小白猿11 分钟前
Java技术八股学习Day14
java·数据库·学习
南屿欣风12 分钟前
Sentinel 资源异常处理优先级笔记
spring boot·笔记·sentinel
li星野17 分钟前
Windows下QT开发一个OpenCV程序
学习
Qhumaing20 分钟前
C++学习:【PTA】数据结构 7-1 实验6-1(图-邻接矩阵)
c++·学习·算法
ekkoalex20 分钟前
强化学习中参数的设置
人工智能·深度学习·transformer
淬炼之火30 分钟前
笔记:Contrastive Object-Aware Fusion
图像处理·笔记·计算机视觉·多模态·图像融合
乐观主义现代人35 分钟前
redis 源码学习笔记
redis·笔记·学习