标签

NLP

自然语言处理 (NLP) 是一种机器学习技术,使计算机能够解读、处理和理解人类语言。如今,组织具有来自各种通信渠道(例如电子邮件、短信、社交媒体新闻源、视频、音频)的大量语音和文本数据。他们使用 NLP 软件自动处理这些数据,分析消息中的意图或情绪,并实时响应人际沟通。

NLP
服务端6月4日 11:07
NLP 模型评估指标怎么选?分类、生成、翻译指标详解NLP 评估的核心原则:**指标必须和业务目标对齐**。垃圾邮件检测最怕漏判(看召回率),医疗文本分类最怕误判(看精确率),机器翻译要看流畅度也要看忠实度——同一个 F1 分数在不同场景下含义完全不同。 按任务类型选择指标的速查表: | 任务 | 核心指标 | 辅助指标 | |------|----------|----------| | 文本分类 | F1(不平衡时)、Accuracy(平衡时) | 混淆矩阵、AUC-ROC | | 命名实体识别 | 实体级 F1(严格匹配) | 宽松匹配 F1、按实体类型分别看 | | 机器翻译 | BLEU | COMET、人工评估 | | 文本摘要 | ROUGE-L | 事实一致性、人工评估 | | 问答 | EM + F1 | BERTScore | | 生成式 | 人工评估为主 | LLM-as-Judge、BERTScore | ## 分类指标:精确率、召回率、F1 怎么选 精确率(Precision)= 模型预测为正的有多少真的是正。召回率(Recall)= 真正的正例有多少被模型找到了。F1 是两者的调和平均,偏向更低的那个——精确率 0.9 但召回率 0.3,F1 只有 0.45。 **选哪个取决于犯哪种错的代价更高**:漏掉一个欺诈交易代价大→优先召回率;误杀正常用户代价大→优先精确率。不确定就用 F1。 多分类时,宏平均(macro)把每个类平等对待,微平均(micro)让大类主导结果。类别不平衡时宏平均更能反映少数类的表现。 ## 生成任务指标:BLEU 和 ROUGE 的局限 **BLEU** 算预测和参考答案的 n-gram 重合度,加简洁性惩罚。范围 0-1,越高越好。但 BLEU 只看字面重叠,"我很开心"和"我非常高兴"语义相同但 BLEU 分很低。而且 BLEU 对短翻译偏宽容(n-gram 容易命中),对长翻译偏严苛。 **ROUGE** 面向摘要任务,侧重召回率——参考答案里的关键信息,模型摘要覆盖了多少?ROUGE-L 基于最长公共子序列,比 ROUGE-1/2 更能容忍语序变化。 两者共同问题:**无法评估语义等价但表达不同的情况**。所以生成任务必须配合人工评估或语义指标(BERTScore、COMET)。 ## 语言模型的困惑度 困惑度(Perplexity)= 模型对测试集的平均负对数似然的指数:`PP = exp(-1/N ∑ log P(w_i|context))`。直观理解:模型在每个位置上平均有多少个"候选词"在犹豫——越少说明越确定,PPL 越低越好。GPT-3 在 Penn Treebank 上 PPL 约 20,早期 n-gram 模型 PPL 在 100+。 PPL 的局限:只衡量模型对文本的"惊讶程度",不直接反映下游任务质量。一个 PPL 很低的模型可能生成重复且无聊的文本。 ## 实操建议 1. **先定指标再开发**:别等模型训完了才想怎么评估。指标决定优化方向。 2. **自动指标不够时加人工评估**:分类任务自动指标够用,生成任务必须人工抽查。50-100 条人工标注的抽样评估比 10 万条自动评分更有指导意义。 3. **做错误分析**:看混淆矩阵找模型最混淆的类对,读具体 case 找系统性错误模式——"我们模型在含否定句的情感分析上 F1 特别低"比"平均 F1 是 0.82"有用得多。 4. **统计显著性**:F1 从 0.81 涨到 0.82 可能只是随机波动。用 Bootstrap 或配对 t 检验确认差异是否显著,否则别急着上线新模型。 ```python from sklearn.metrics import classification_report # 一行输出所有分类指标 print(classification_report(y_true, y_pred, target_names=class_names)) ```
服务端6月4日 11:05
NLP 词向量有哪些方法?Word2Vec、GloVe 到 BERT 演进详解词向量就是把词映射成一段连续的实数向量(通常 50-300 维),让语义相近的词在向量空间中距离也近。计算机不认识"苹果"和"橘子",但它们对应的向量夹角很小——"苹果"和"汽车"的向量夹角大。这个"距离近=语义近"的性质,是一切下游 NLP 任务的基础。 词向量方法经历了三代演进:**静态词向量**(每个词固定一个向量)→ **上下文词向量**(同一个词在不同语境中有不同向量)→ **大模型嵌入**(深层语义表示)。 ## 静态词向量:Word2Vec / GloVe / FastText **Word2Vec**(2013)的核心思想:上下文相似的词,语义也相似。两种训练方式——CBOW 用上下文预测中心词(快,适合常用词),Skip-gram 用中心词预测上下文(慢,但稀有词效果更好)。训练出的向量支持类比运算:`king - man + woman ≈ queen`。 **GloVe**(2014)换了个思路:不靠上下文窗口,而是利用全局的词-词共现矩阵。最小化 `w_i · w_j + b_i + b_j - log(X_ij)` 的差距,本质上是对共现矩阵做分解。在大规模语料上比 Word2Vec 更稳。 **FastText**(2016)在 Word2Vec 基础上加了子词(subword)信息:把 "apple" 拆成 `<ap, app, ppl, ple, le>` 这些 n-gram,向量是所有子词向量的和。这解决了 OOV 问题——遇到 "apples" 虽然没见过,但子词 `<app, ppl>` 见过,也能算出合理的向量。对形态丰富的语言(德语、芬兰语)效果提升明显。 静态词向量的共同局限:**一词一义**。"苹果"的水果义和公司义共用一个向量,无法区分。 ## 上下文词向量:ELMo → BERT **ELMo**(2018)用双向 LSTM 在大规模语料上训练语言模型,然后取各层隐藏状态的加权和作为词向量。同一个"苹果",在"吃了一个苹果"和"苹果发布了新手机"中会得到不同的向量——第一次解决了一词多义问题。缺点是 LSTM 架构慢,且不是真正的深度双向。 **BERT**(2018)换成 Transformer 编码器,用 Masked Language Model 实现真正的双向上下文。取出最后一层的隐藏状态就是上下文词向量,效果全面超越 ELMo。BERT 的词向量不只是"词向量"了——它是整个句子的深度语义表示。 ```python # 用 transformers 获取 BERT 词向量 from transformers import AutoModel, AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") model = AutoModel.from_pretrained("bert-base-uncased") inputs = tokenizer("Apple released iPhone", return_tensors="pt") outputs = model(**inputs) # outputs.last_hidden_state 就是每个 token 的上下文向量 ``` ## 现代方向:句子嵌入和大模型 纯词向量在检索、聚类场景下不够用——需要把整句话编码成一个向量。**SimCSE** 用对比学习训练 BERT,同一句话两次过 dropout 得到正例对,不同句互为负例,简单但效果极好。**BGE** 和 **E5** 是当前中文文本嵌入的 SOTA,支持直接算句子相似度做检索。 大模型(GPT、LLaMA)的隐藏状态也可以当词向量用,但因为自回归只有单向上下文,做句子嵌入通常不如双向模型。实际项目中文本检索优先用 BGE/E5,词级别分析用 BERT,不需要上下文时 Word2Vec 仍然够用。 ## 追问 ### Word2Vec 和 GloVe 怎么选? 数据量小(<1亿 token)用 Word2Vec,训练快、效果好。数据量大用 GloVe,全局统计信息更充分。实践中两者效果差距不大,选择更多取决于你有没有预训练好的向量可以直接下载——GloVe 提供了基于 Common Crawl 的预训练向量,覆盖面广。 ### 静态词向量还有用吗? 有,但场景在缩小。计算资源极度受限(嵌入式设备)、只需要词级别相似度(同义词挖掘)、或者做特征工程的基线时,静态词向量仍然是性价比最高的选择。训练快、推理零开销。但如果你的任务需要理解上下文,直接上 BERT 就对了。
服务端6月4日 11:03
NLP 数据不平衡怎么处理?重采样、Focal Loss 和评估指标详解数据不平衡的核心问题:模型倾向于预测多数类,因为这样做在训练集上损失最低。比如 95% 正面 + 5% 负面的情感数据,模型全猜正面也有 95% 准确率——但负面的召回率是 0。 解决思路分三层:**数据层**(调整样本分布)、**算法层**(调整学习过程)、**评估层**(选对指标)。 ## 数据层:重采样 **过采样**:复制少数类样本。最简单的是随机复制,但容易过拟合——模型反复看到同样的样本。NLP 里更好的做法是**回译**(中文翻英文再翻回来,得到语义相同但表达不同的新样本)和**同义词替换**,这比 SMOTE 在文本上更自然。 **欠采样**:随机丢弃多数类样本。数据量大时有效,但可能丢掉有用信息。折中方案是 **EasyEnsemble**:对多数类做多次不同的欠采样,每次训练一个子模型,最后集成投票——既不丢信息也不偏多数类。 ## 算法层:损失函数调整 **类别加权**:给少数类的损失乘一个更大的权重,公式 `weight_i = N / (C × n_i)`,让模型在少数类上犯错代价更高。PyTorch 里 `CrossEntropyLoss(weight=torch.tensor([0.5, 10.0]))` 一行搞定。 **Focal Loss**:比加权更聪明。它自动降低"容易分对的样本"的权重,把训练精力集中在难分的样本上:`FL = -α(1-p_t)^γ log(p_t)`。γ=2 时,一个已经 p=0.9 分对的样本,损失会被压到原来的 1%,模型基本不理它。目标检测里先火起来的,NLP 不平衡分类也适用。 ## 评估层:别看准确率 不平衡数据下准确率完全误导。**F1 分数**(精确率和召回率的调和平均)是基本盘。如果更关心少数类不被漏掉,看 **召回率**;如果更关心少数类预测的准确性,看 **精确率**。**AUC-PR** 比 AUC-ROC 更适合极端不平衡场景,因为 ROC 在负例远多于正例时过于乐观。 ```python from sklearn.metrics import classification_report # 别只看 accuracy,看每个类的 precision/recall/f1 print(classification_report(y_true, y_pred)) ``` ## 实际怎么选方案 先试最简单的:类别加权 + F1 评估,10 分钟能跑完。效果不够再加数据增强(回译最省事)。还不行上 Focal Loss。再不行就 EasyEnsemble 集成。别一上来就堆复杂方法——大多数场景类别加权就够了。 一个容易忽略的点:**验证集不要做重采样**。训练集可以过采样/欠采样,但验证集和测试集必须保持原始分布,否则评估结果不可信。
服务端6月4日 11:01
RNN、LSTM 和 GRU 有什么区别?怎么选?RNN 是处理序列数据的基础架构:每一步把当前输入和上一步的隐藏状态拼在一起做变换,输出新的隐藏状态。问题是反向传播时梯度要乘很多次权重矩阵,序列一长梯度就指数级衰减(梯度消失)或爆炸——这就是 RNN 记不住远距离依赖的根本原因。 **LSTM** 通过引入细胞状态和三个门来解决这个问题:遗忘门决定忘掉什么,输入门决定存什么,输出门决定输出什么。关键在于细胞状态的更新是加法而非乘法:`C_t = f_t ⊙ C_{t-1} + i_t ⊙ C̃_t`,加法让梯度可以无损地回传,不会逐层衰减。 **GRU** 是 LSTM 的简化版,把遗忘门和输入门合成一个更新门 `z_t`,还省掉了细胞状态,直接在隐藏状态上做插值:`h_t = (1-z_t) ⊙ h_{t-1} + z_t ⊙ h̃_t`。参数少约 30%,训练更快,多数任务上效果和 LSTM 持平。 一个直觉:LSTM 的 `f_t ≈ 1, i_t ≈ 0` 时细胞状态原样传递——这就是"记忆"。GRU 的 `z_t ≈ 0` 时隐藏状态原样保留——异曲同工。 ```python # PyTorch 中三者用法几乎一致 nn.LSTM(input_size, hidden_size, num_layers, batch_first=True) nn.GRU(input_size, hidden_size, num_layers, batch_first=True) nn.RNN(input_size, hidden_size, num_layers, batch_first=True) ``` ## 追问 ### 为什么 LSTM 能解决梯度消失而 RNN 不能? RNN 的隐藏状态更新是全乘法:`h_t = tanh(W·h_{t-1} + ...)`,反向传播时 ∂h_t/∂h_{t-1} 包含 W 和 tanh',连乘 N 次后梯度要么趋于 0 要么爆炸。LSTM 的细胞状态更新是加法:`C_t = f_t⊙C_{t-1} + i_t⊙C̃_t`,∂C_t/∂C_{t-1} = f_t,只要 f_t 接近 1 梯度就能一路畅通地回传。本质上是加法 vs 乘法的区别。 ### GRU 和 LSTM 怎么选? 数据量小或需要快速迭代选 GRU(参数少,训练快)。序列特别长或任务特别复杂选 LSTM(表达能力更强)。实际项目中,如果你不确定,先用 GRU 跑 baseline,效果不够再换 LSTM——而不是反过来。2017 年以后大多数新论文默认用 GRU,但工业界 LSTM 仍然广泛部署。 ### RNN 系列和 Transformer 的核心区别是什么? RNN 必须按时间步顺序计算,无法并行;Transformer 用自注意力直接看全局,所有位置同时算。代价是 Transformer 的注意力是 O(n²) 复杂度,而 RNN 是 O(n)。所以短序列 RNN 更省内存,长序列 Transformer 更快(因为并行)。另外,RNN 天然适合流式处理(来一个 token 处理一个),Transformer 每次都要重新算整段注意力。 ### 双向 LSTM 和单向有什么区别? 单向 LSTM 只看过去的上下文,双向 LSTM 同时跑一个从左到右和一个从右到左的 LSTM,把两个方向的隐藏状态拼接。双向版本效果更好,但**不能用于生成任务**——因为你不能偷看未来的 token。文本分类、命名实体识别用双向,语言模型、机器翻译解码器用单向。
服务端6月4日 10:58
NLP 模型微调实战:LoRA、QLoRA 和 PEFT 方法详解NLP 模型微调的核心思路:拿一个在大量数据上训练好的预训练模型,用你的目标任务数据继续训练它,让它从"什么都懂一点"变成"在你的领域特别擅长"。关键问题是:**调多少参数、用什么策略调、怎么避免把预训练知识调没了**。 ## 全参数微调 vs 参数高效微调(PEFT) 全参数微调解冻所有权重,效果好但显存要求高——7B 模型全参微调至少需要 28GB 显存(Adam 优化器要存两份状态)。PEFT 冻住原始权重,只训练少量新增参数,显存降到原来的 1/3 甚至更低,效果通常能到全参的 90-95%。 **LoRA** 是目前最主流的 PEFT 方法:在权重矩阵旁加一个低秩分解 `ΔW = BA`,只训练 A 和 B 两个小矩阵。比如原始权重 4096×4096,rank=8 的 LoRA 只需要 4096×8×2 = 65536 个参数,压缩比 256:1。推理时把 LoRA 权重合并回原模型,零额外延迟。 ```python from peft import LoraConfig, get_peft_model config = LoraConfig( r=8, # 秩,越大表达能力越强但参数越多 lora_alpha=32, # 缩放系数,相当于学习率乘数 target_modules=["q_proj", "v_proj"], # 只对 Q/V 投影加 LoRA lora_dropout=0.1, task_type="CAUSAL_LM" ) model = get_peft_model(base_model, config) # 可训练参数通常只占全部的 0.1%-1% ``` ## 其他 PEFT 方法怎么选 **Adapter** 在 Transformer 层之间插入小型全连接层,缺点是推理时有额外延迟。**Prefix Tuning** 在输入前加可训练的虚拟 token,适合生成任务但会占上下文窗口。**Prompt Tuning** 更轻量,只训 embedding 层的软提示,大模型(10B+)上效果才接近全参。实际项目里 LoRA 是默认选择,其他方法在特定场景有优势。 ## 微调实操要点 **学习率**:微调的学习率要比预训练小 10-100 倍,LoRA 常用 1e-4,全参微调用 2e-5。太大会把预训练知识冲掉(灾难性遗忘),太小收敛太慢。 **Rank 选择**:简单任务 rank=4-8 够了,复杂任务可以开到 16-64。rank 越大越接近全参微调,但收益递减——从 8 升到 16 可能提升 2%,从 64 升到 128 基本没区别。 **数据质量 > 数据量**:1000 条高质量标注比 10000 条噪声数据效果好。数据不够时,数据增强(同义词替换、回译)和主动学习(挑模型最不确定的样本标注)比堆量更有效。 ## QLoRA:单卡微调大模型 QLoRA 在 LoRA 基础上把预训练权重量化到 4-bit,只保持 LoRA 参数为 16-bit。65B 模型用 QLoRA 只需要一张 48GB 的 A6000,而全参微调需要 8×A100。精度损失很小,论文报告在多数基准上与全参微调持平。代码层面就是把 `BitsAndBytesConfig` 配好再加载模型。 ## 过拟合怎么发现和解决 训练 loss 持续下降但验证 loss 开始上升,就是过拟合了。解决方案:减少训练轮数(3-5 轮通常够了)、加大 dropout(0.1→0.3)、加权重衰减(0.01)、用早停策略。一个容易被忽略的点:**数据增强只在训练集上做,验证集和测试集必须用原始数据**,否则评估结果虚高。
服务端6月1日 23:20
NLP(自然语言处理)是什么?核心技术从规则到 LLM 怎么演变的?自然语言处理(Natural Language Processing,NLP)是让计算机理解、解释和生成人类语言的技术。你用的搜索引擎、翻译软件、智能客服、ChatGPT,背后都是 NLP。 ## NLP 解决什么问题 NLP 的任务可以分两大类:**理解**(从文本中提取信息)和**生成**(产出新的文本)。 理解类任务:文本分类(这封邮件是不是垃圾邮件)、命名实体识别(提取人名地名)、情感分析(这条评论是正面还是负面)、问答(从文档中找到答案)。这类任务的核心是把非结构化的文本变成结构化的信息。 生成类任务:机器翻译、文本摘要、对话生成、代码生成。这类任务不仅要理解输入,还要产出流畅、连贯、准确的新文本。生成比理解难得多——理解只需要判断对错,生成要在一个天文数字的候选空间里选出最好的。 ## NLP 技术的三个时代 **规则时代(1950s-1990s)**:手写语法规则和词典。专家系统写几千条 if-else 规则来解析句子。准确率在小领域内还行,但覆盖面极窄——换个领域规则全废,维护成本爆炸。 **统计机器学习时代(1990s-2012)**:从数据中自动学习规律。HMM 做词性标注,CRF 做序列标注,SVM 做分类。关键突破是特征表示——词袋模型、TF-IDF、N-gram 把文本变成了数值向量。但特征仍然需要人工设计,模型能力的天花板就是特征工程的质量。 **深度学习时代(2013-至今)**:神经网络自动学特征,不需要手工设计。Word2Vec 让词有了语义向量表示("国王" - "男人" + "女人" ≈ "女王"),RNN/LSTM 处理变长序列,CNN 做文本分类。2017 年 Transformer 出现后,NLP 的范式彻底变了——BERT、GPT 用预训练+微调替代了从零训模型,LLM 用提示词替代了微调本身。 ## NLP 的核心 Pipeline 传统 NLP 系统的典型流程:文本 → 预处理(清洗、分词)→ 特征提取(词向量、句向量)→ 模型推理 → 后处理。每一步都需要单独优化,错误会在步骤间传播——分词错了,下游全错。 LLM 时代 Pipeline 大幅简化:文本 → tokenizer → LLM 推理 → 输出。分词、特征提取、模型推理都压缩进了一个端到端的过程。代价是计算成本更高,但换来的是更少的手工环节和更好的效果。 ## 中文 NLP 的特殊挑战 中文没有空格分隔词语,分词是所有下游任务的前提。jieba 是最常用的分词工具,但准确率约 90%,专业领域需要自定义词典。另一个问题是中文的指代消解——"他"指谁?"这家公司"指哪家?英文有性别代词做线索,中文的"他/她/它"发音相同,歧义更多。 ## NLP 当前最热的方向 **RAG(检索增强生成)**:让 LLM 先检索外部知识库再生成回答,解决幻觉问题。**Agent**:让 LLM 调用工具、规划步骤、自主执行任务。**多模态**:同时处理文本、图像、语音。**小模型蒸馏**:把大模型的能力压缩到小模型里,降低部署成本。这些方向都建立在 Transformer 和 LLM 的基础上——理解了底层原理,上面的应用方向只是组合方式不同。
服务端6月1日 23:19
Transformer 架构是怎么工作的?自注意力、位置编码和残差连接详解Transformer 是 2017 年 Google 在《Attention is All You Need》里提出的架构,用纯注意力机制替代了 RNN 和 CNN 做序列建模。它是 BERT、GPT 以及所有现代大语言模型的基础。 ## 核心思想:注意力替代递归 RNN 处理序列要一步一步来——看第 3 个词之前必须先处理第 1 和第 2 个词。这导致两个问题:无法并行训练,长距离依赖会衰减(梯度消失)。 Transformer 的解决方案是:让每个位置直接和所有其他位置交互,一步到位。不需要逐步递归,训练时所有位置可以并行计算——GPU 最擅长这种矩阵运算。 ## 自注意力:序列中的每个词和所有词交互 对序列中的每个词,自注意力计算它和其他所有词的相关性(注意力权重),然后按权重聚合信息。具体来说:每个词生成三个向量——Query(我在找什么)、Key(我能提供什么)、Value(我的实际内容)。Query 和所有 Key 做点积得到相关性分数,softmax 归一化后对 Value 加权求和。 `Attention(Q, K, V) = softmax(QK^T / √d_k) V` 除以 √d_k 是缩放,防止点积太大导致 softmax 输出接近 one-hot(梯度几乎为零)。这个缩放因子是"Scaled Dot-Product Attention"里"Scaled"的由来。 ## 多头注意力:同时学多种关系 一个注意力头只能学一种关联模式。但语言中有语法关系、语义关系、位置关系等多种层次。多头注意力让每个头独立学习不同的模式——8 个头就学 8 种不同的"怎么看句子"的方式,最后拼接起来。 实验上,多头注意力的效果显著优于单头。但头数不是越多越好,通常和模型维度一起调。GPT-3 用了 96 个头,但那是因为模型维度是 12288——每个头的维度是 128,和原始论文一致。 ## 位置编码:没有递归,怎么知道词的顺序 自注意力本身是排列不变的——打乱输入顺序,输出只是对应的排列,值不变。但"猫吃鱼"和"鱼吃猫"意思完全不同,模型必须知道词的顺序。 Transformer 用正弦/余弦函数生成位置编码,和词嵌入相加。为什么用三角函数?因为它有相对位置的性质:PE(pos+k) 可以用 PE(pos) 的线性变换表示,这让模型更容易学习相对位置关系。 后来的模型用了可学习的位置编码(BERT、GPT 都是),直接让模型自己学一组位置向量。RoPE(旋转位置编码)是更新的方案,被 LLaMA 等模型采用,能更好地泛化到训练时没见过的序列长度。 ## 残差连接和层归一化 每个 Transformer 层的输出 = LayerNorm(x + Sublayer(x)),其中 Sublayer 是注意力或前馈网络。残差连接(+x)让梯度可以直接回传,避免深层网络梯度消失。层归一化(LayerNorm)稳定训练,防止每层的输出分布漂移。 注意归一化的位置:原始 Transformer 是 Post-LN(先 Sublayer 再 LN),后来发现 Pre-LN(先 LN 再 Sublayer)训练更稳定,GPT 和大多数现代模型都用 Pre-LN。 ## 编码器-解码器结构 原始 Transformer 用于机器翻译,包含编码器和解码器: - **编码器**:双向自注意力 + 前馈网络,理解源语言 - **解码器**:单向自注意力(遮住未来信息)+ 交叉注意力(看编码器输出)+ 前馈网络,生成目标语言 但后来的发展证明不需要两者都用:BERT 只用编码器(理解任务),GPT 只用解码器(生成任务),T5 保留了完整的编码器-解码器。2024 年的趋势是纯解码器架构一统天下——解码器通过指令微调也能做理解任务,何必维护两个模块? ## 前馈网络:注意力的补充 每层还有一个两层的前馈网络:FFN(x) = W2·ReLU(W1·x)。FFN 的隐藏维度通常是模型维度的 4 倍(如 d_model=768 时 FFN 维度=3072)。 自注意力负责词和词之间的关系,FFN 负责每个位置内部的非线性变换。可以理解为:注意力做信息路由(把相关信息拉过来),FFN 做信息加工(把拉过来的信息消化掉)。研究表明 FFN 层存储了大部分的"知识"(事实记忆),而注意力层更多在做"逻辑"(关系推理)。
服务端6月1日 23:18
BERT 和 GPT 有什么区别?为什么一个擅长理解一个擅长生成?BERT 用 Transformer 编码器,GPT 用 Transformer 解码器。这一个选择决定了它们的所有差异:BERT 双向看上下文(适合理解),GPT 只看上文(适合生成)。 ## 架构选择:编码器 vs 解码器 Transformer 原论文有编码器和解码器两部分。编码器的自注意力是双向的——处理"苹果"这个词时,"苹果"前后所有词都能看到。解码器的自注意力是单向的(也叫因果注意力)——只能看到当前词和它之前的词,后面的词被遮住。 BERT 选了编码器,因为它要做的是"完形填空":遮住一些词,根据前后文预测。双向注意力让模型能同时利用左右两侧的上下文信息。 GPT 选了解码器,因为它要做的是"续写":给定前文,预测下一个词。单向注意力保证训练和推理的一致性——推理时确实只能看到已生成的前文。如果用双向注意力,训练时能看到"未来"但推理时看不到,就会产生不一致。 ## 训练目标:MLM vs CLM **BERT 的掩码语言模型(MLM)**:随机遮住 15% 的 token,让模型预测被遮住的词。这就像做完形填空——"The [MASK] sat on the mat",模型要预测 [MASK] 是 "cat"。BERT 还加了一个下一句预测(NSP)任务,判断两个句子是否相邻,但后来的研究表明 NSP 其实没太大用,RoBERTa 去掉 NSP 反而效果更好。 **GPT 的因果语言模型(CLM)**:给定前文,预测下一个 token。这天然就是一个生成任务——每个词都是基于前面所有词的概率分布选出来的。GPT 的训练目标简单粗暴,但规模大了之后涌现出了 BERT 做不到的能力:in-context learning(上下文学习)、chain-of-thought reasoning(链式推理)。 ## 能力差异的本质 BERT 强在**理解**:文本分类、NER、问答(抽取式)、语义匹配。这些任务不需要生成新文本,只需要对已有文本做判断。双向注意力让 BERT 看到了完整的上下文,判断更准确。 GPT 强在**生成**:对话、翻译、代码生成、创意写作。这些任务需要一步步产出新内容,单向注意力的自回归方式和生成任务天然契合。而且 GPT 的生成能力随规模非线性增长——GPT-2 只能写连贯的短文,GPT-3 能做 few-shot learning,GPT-4 能做复杂推理。这种涌现能力是 BERT 架构做不到的。 一句话总结:BERT 是最好的阅读理解者,GPT 是最好的写作高手。 ## 2024-2025 的格局 BERT 系列在工业界仍然广泛使用——分类、NER 这些任务用 BERT 微调又快又便宜,768 维的 BERT-base 推理一次只要几毫秒。但新项目越来越倾向直接用 LLM API(GPT-4/Claude)+ prompt engineering 替代 BERT 微调,因为省掉了标注数据和训练的成本。 GPT 阵营这边,开源模型(LLaMA、Mistral、Qwen、DeepSeek)已经可以在本地跑,7B 参数的模型在一台消费级 GPU 上就能推理。闭源模型(GPT-4o、Claude Sonnet、Gemini)在能力上仍然领先,但差距在缩小。 一个值得注意的趋势:**编码器-解码器架构(T5、BART)正在被纯解码器架构取代**。T5 最初证明了解码器也能做理解任务,后来大家发现直接用 GPT 架构加指令微调就能同时搞定理解和生成,何必用两个模块?
服务端6月1日 15:05
注意力机制是什么?为什么 Transformer 靠它替代了 RNN?注意力机制让模型在处理每个词时,能动态决定该"看"输入序列的哪些其他词。它是 Transformer 的核心,也是 BERT、GPT 等现代 NLP 模型的基础。没有注意力机制,就没有今天的大语言模型。 ## 直觉:注意力在做什么 想象你在读"银行"这个词,想理解它的意思。如果上下文是"他去银行存钱","银行"和"存钱"的关系最密切——你的注意力会聚焦在"存钱"上。如果上下文是"他坐在河的银行边",注意力会转向"河"。 注意力机制做的就是这个:对序列中的每个位置,计算它和其他所有位置的相关程度,然后按相关程度加权聚合信息。相关程度高的权重大,低的权重小。 ## 核心计算:Query、Key、Value 注意力机制借用了数据库检索的概念: - **Query(Q)**:当前词想知道"我应该关注谁" - **Key(K)**:每个词提供的"我是谁、我有什么信息" - **Value(V)**:每个词实际传递的信息内容 计算过程:Q 和每个 K 做点积,得到相关性分数 → 除以 √d_k(缩放,防止点积太大导致 softmax 梯度消失)→ softmax 归一化成权重 → 用权重对 V 加权求和,得到输出。 公式:`Attention(Q, K, V) = softmax(QK^T / √d_k) V` 为什么 Q·K^T 能代表相关性?因为它们是学出来的向量——训练过程中,相关的 Q 和 K 会被调整到点积更大的方向,不相关的被调到点积更小的方向。点积只是度量相似性的工具,真正的知识在 Q 和 K 的参数里。 ## 自注意力 vs 交叉注意力 **自注意力**:Q、K、V 都来自同一个序列。模型在处理一个句子时,让每个词和句子中所有其他词交互。这是 Transformer 编码器的核心——BERT 全靠自注意力理解上下文。 **交叉注意力**:Q 来自一个序列,K 和 V 来自另一个序列。典型场景是机器翻译:Q 来自目标语言(正在生成的词),K 和 V 来自源语言(待翻译的句子)。交叉注意力让模型在生成每个目标词时,"回头看"源句子的哪个部分最相关。 ## 多头注意力:为什么不只用一个注意力 一个注意力头只能学一种关联模式。但语言中有多层关系:语法关系(主语-谓语)、语义关系(同义词)、位置关系(相邻词)。多头注意力让模型同时学多种模式——每个头独立计算 Q/K/V,最后拼接起来。 Transformer 原论文用了 8 个头,GPT-3 用了 96 个头。头数不是越多越好,太小不够表达,太大参数浪费,通常和模型维度一起调。 ## 注意力为什么替代了 RNN RNN 的致命问题是顺序依赖:处理第 t 个词必须先处理完前 t-1 个词,无法并行。序列长了梯度消失/爆炸,LSTM 的门机制缓解但没根治。 注意力一步到位:每个位置直接和所有位置交互,不需要逐步递归,训练时完全并行。GPU 最擅长的就是并行矩阵运算——注意力的 QK^T 计算就是大矩阵乘法,GPU 跑起来飞快。 代价是 O(n²) 的计算和内存复杂度——序列长度翻倍,计算量翻四倍。这就是为什么早期 BERT 只支持 512 token,直到 FlashAttention 等优化技术出现才突破了长序列的瓶颈。 ## 实际影响 注意力机制不只是 Transformer 的一个组件,它改变了整个 NLP 的范式。RNN 时代,模型架构是瓶颈;注意力时代,瓶颈变成了数据和算力。从 BERT 到 GPT-4,底层都是注意力机制,差别只在规模和训练策略。
服务端6月1日 15:04
如何构建一个 NLP 系统?从数据到部署的完整流程构建 NLP 系统不只是训模型——从数据收集到线上服务,中间有大量工程决策要做。模型只是系统的一部分,很多时候瓶颈不在模型效果,而在数据处理、服务稳定性和迭代速度上。 ## 明确任务和指标 先想清楚三件事:系统要解决什么问题?怎么衡量效果?兜底策略是什么? 比如做一个客服意图分类系统:目标是自动识别用户咨询的类别(退款、物流、产品问题等),指标是 F1 值和人工介入率,兜底是置信度低于阈值就转人工。不要上来就想用最先进的模型,先把任务定义清楚。 ## 数据工程 数据是 NLP 系统的地基,也是最容易出问题的地方。 **数据收集**:业务日志、用户生成内容、公开数据集。优先用业务数据——它最贴近真实场景。公开数据集可以做冷启动,但分布往往和线上不一致,上线后效果会打折。 **数据标注**:标注质量直接决定模型上限。找领域专家标注,别找众包工人——一个律师标的法律文本和一个大学生标的,质量天差地别。标注指南要写清楚边界案例("苹果"在什么语境下是公司,什么语境下是水果),标注一致性(多人标同一批数据的重合度)至少要 85% 以上。 **数据版本管理**:每次训练用的数据集要能追溯。DVC 或简单的 git + 文件哈希都行。线上出了问题,你得知道当时模型是用哪批数据训的。 ## 模型开发 **选模型**:2025 年的默认选择是 BERT 系列做理解任务,GPT 系列做生成任务。小数据量(<1万条)用预训练模型微调,极少数据(<100条)考虑 few-shot prompt 或 LLM API。别从零训模型——预训练成本百万美元起步,除非你是大厂。 **训练技巧**:学习率用 2e-5 起,batch size 小就梯度累积。早停比固定 epoch 好。保存最优 checkpoint 而不是最后一个。混合精度训练(FP16)省一半显存,几乎不损失效果。 **评估**:离线指标(F1、BLEU、ROUGE)只是参考,必须做线上 A/B 测试。离线 F1 从 85 提到 87,线上可能完全没差别——因为测试集和真实分布不一样。 ## 服务化部署 **API 封装**:FastAPI 是最简单的选择,异步、自动生成文档、类型检查。模型推理用 ONNX Runtime 或 TensorRT 加速,比原生 PyTorch 快 3-10 倍。 **批处理 vs 实时**:搜索引擎这种场景可以批处理(离线算好存索引),客服对话必须实时推理(用户等不了)。实时推理要控制延迟——P99 低于 200ms 是基本要求。 **模型版本管理**:线上同时跑多个版本,灰度切流量。出了问题秒级回滚。用 A/B 测试比较新旧版本的业务指标,别靠感觉。 ## 监控和迭代 上线才是开始。监控三件事:输入分布变化(用户开始说之前没见过的话术)、模型置信度下降(突然大面积低置信度说明有新问题)、业务指标波动。 建立数据飞轮:线上低置信度的样本 → 人工标注 → 补充训练集 → 重新训练。好的 NLP 系统不是一次训好的,是持续迭代出来的。每个版本的数据、模型、效果都要能追溯,这样出了问题才能定位原因。
服务端6月1日 15:03
命名实体识别(NER)怎么做?BiLSTM-CRF 和 BERT-CRF 哪个好?命名实体识别(Named Entity Recognition,NER)是从文本中抽取出特定类型的实体——人名、地名、机构名、日期等。它是信息抽取的基础:搜索引擎要理解"苹果"是公司还是水果,问答系统要找到答案里的人名和地点,都靠 NER。 ## NER 怎么定义"实体" 最常用的标注体系是 BIO:B-X 表示实体 X 的开头,I-X 表示实体 X 的内部,O 表示非实体。比如"北京大学位于海淀区"标注为"B-ORG I-ORG I-ORG I-ORG O B-LOC I-LOC I-LOC"。还有 BIOES 体系多了 E(结束)和 S(单字实体),理论上更精确但实际差距不大。 常见实体类型:PER(人名)、LOC(地名)、ORG(机构)、DATE(日期)、MISC(其他)。具体定义取决于业务场景——医疗 NER 需要识别疾病名和药品名,金融 NER 需要识别公司名和指标。 ## NER 方法演进 **规则和词典**:正则匹配+实体词典,准确率极高但覆盖率低。电话号码、邮箱这类格式固定的实体用正则就行。但新实体(新人名、新公司名)永远识别不了——这就是规则方法的根本缺陷。 **CRF(条件随机场)**:传统方法的巅峰。它考虑整个序列的标签联合概率,避免"I-ORG"跟在"O"后面这种非法序列。CRF 的关键是特征工程——词性、前后缀、词典匹配、上下文窗口,特征设计得好效果就好。缺点是太依赖人工设计特征。 **BiLSTM-CRF**:深度学习 NER 的经典架构。BiLSTM 自动学特征(不需要手工设计),CRF 层保证标签合法性。为什么需要 CRF?因为纯 BiLSTM 每个位置独立预测,可能出现"B-PER"后面跟"I-LOC"这种非法序列,CRF 通过学习转移矩阵约束标签之间的关系。 **BERT-CRF**:用预训练的 BERT 替换 BiLSTM 作为编码器。BERT 自带丰富的语言知识,少量标注数据就能微调出好效果。在 CoNLL-2003 英文 NER 数据集上,BERT-CRF 的 F1 超过 92%,比 BiLSTM-CRF 高 3-5 个点。代价是推理速度慢、显存需求大。 **LLM 做 NER**:GPT-4、Claude 可以通过 prompt 做 zero-shot NER,不需要训练数据。在通用实体上效果不错,但在专业领域(医疗、法律)和细粒度实体类型上还是微调模型更可靠。实际项目中,LLM 做 NER 的成本也比小模型高 10-100 倍。 ## NER 的核心评估指标 用精确率(Precision)、召回率(Recall)和 F1 值评估。NER 的"匹配"要求边界和类型都正确——"北京大学"标成 ORG 算对,标成 LOC 算错,只识别出"北京"也算错(边界不对)。实际项目中,精确率和召回率的取舍取决于业务:搜索引擎更重召回(别漏),法律合规更重精确(别标错)。 ## 中文 NER 的特殊挑战 中文没有天然分词边界,"北京大学"可以是三个字也可以是一个实体。字级别的 NER(一个字一个字标注)比词级别更常见,因为避免了分词错误传播的问题——分词错了,NER 肯定跟着错。Lattice LSTM 就是专门解决这个问题的,它把分词信息作为额外路径融入字级别模型。
服务端6月1日 15:02
NLP 文本预处理有哪些步骤?LLM 时代还需要吗?文本预处理是把原始文本变成模型能消化的输入的过程。传统 NLP 流程里这一步极其重要——垃圾进垃圾出,预处理做不好,模型再强也没用。但 LLM 时代有些变化,后面会说。 ## 预处理的核心步骤 按顺序走: **1. 清洗噪声**:去掉 HTML 标签、URL、特殊符号、多余空格。爬虫抓的文本必做这步。用 BeautifulSoup 去 HTML 标签,正则去 URL(`re.sub(r"http\S+", "", text)`),没什么技术含量但很重要。 **2. 文本标准化**:统一大小写(英文)、统一编码(UTF-8)、繁简转换(中文)。注意英文小写化会丢失一些信息——"US" 变成 "us" 就不是国家了。如果做 NER,这一步要慎重。 **3. 分词**:把句子切成词或子词。英文按空格切就行(粗略说),中文必须用分词工具(jieba、pkuseg)。但更现代的做法是用子词分词(BPE、WordPiece),BERT 和 GPT 都用这种方式——它解决了 OOV(词表外词)问题,"unhappiness" 会被拆成 "un" + "happi" + "ness"。 **4. 去停用词**:移除"的""了""is""the"这些高频但无实际含义的词。在搜索和分类任务中有用,但在情感分析中要小心——"not" 可能被去掉,语义就反了。LLM 时代这步基本不需要了,大模型自己能判断哪些词重要。 **5. 词形还原/词干提取**:running → run,better → good。英文常用,中文不需要。NLTK 的 `WordNetLemmatizer` 做词形还原,PorterStemmer 做词干提取。词形还原更准确但更慢,词干提取更快但可能产出非词(如 "university" → "univers")。 **6. 序列填充/截断**:神经网络需要固定长度的输入,长的截断,短的补 padding。BERT 最大 512 token,GPT-4 可以到 128K,但填充和截断的思路一样。 ## LLM 时代,哪些预处理还需要? 分词(tokenizer)仍然需要,但已经是模型自带的了——你不需要自己 jieba 分词再喂给 BERT,直接用模型的 tokenizer 就行。 清洗噪声仍然需要——LLM 也不是什么垃圾都能消化,HTML 标签和乱码照样影响效果。 去停用词、词形还原、词干提取基本不需要了。LLM 的上下文理解能力足以处理这些变化,手动去掉反而丢失信息。 ## 中文预处理的特殊问题 中文没有天然的分隔符,分词质量直接影响下游任务。jieba 是最常用的工具,但准确率只有 90% 左右,专业领域(医学、法律)需要自定义词典。另一个常见问题是编码——GBK 和 UTF-8 混用的数据,Python 里先统一 `encode("utf-8").decode("utf-8")` 处理不了就加 errors 参数忽略。 ## 实操建议 别一上来就全做。先看任务——情感分析去停用词要小心,文本生成不需要去,搜索需要去。先做最小预处理(清洗+分词),跑个 baseline,看效果再加步骤。预处理步骤越多,pipeline 越复杂,出错的地方也越多。
服务端6月1日 15:01
大语言模型(LLM)是什么?为什么它能做这么多事?大语言模型(Large Language Model,LLM)是用海量文本训练的超大规模神经网络。它不是被编程去"做"某件事,而是通过预测下一个 token 学会了语言的规律——结果出乎意料地,这种能力泛化到了推理、翻译、写代码、做总结等各种任务上。 ## LLM 和传统 NLP 模型有什么本质区别 传统 NLP 是"一个模型做一件事"——分类模型做分类,NER 模型做实体识别,翻译模型做翻译。LLM 打破了这个限制:同一个模型,通过不同的提示词(prompt),就能完成几十种任务。这种能力叫**涌现能力**——模型小的时候没有,参数过了某个阈值突然就出现了。 关键在于规模效应。GPT-3 有 1750 亿参数,训练数据覆盖了互联网上几乎所有的公开文本。当你给它一个 prompt,它不是在"查表"找答案,而是在学到的语言分布上做推理。这么说不太精确,但你可以理解为:它把训练数据里的模式压缩成了参数,然后根据 prompt 激活相关的模式来生成回答。 ## 核心技术:从 Transformer 到 RLHF LLM 的底层架构是 Transformer,2017 年 Google 在《Attention is All You Need》里提出。Transformer 的自注意力机制让模型能同时看到输入序列的所有位置,不需要像 RNN 那样逐步递归,训练时可以完全并行。 但光有 Transformer 不够。从原始模型到好用的 ChatGPT,中间经历了三个关键步骤: 1. **预训练**:在海量文本上做 next-token prediction,学会语言的基本规律。这步烧钱最多,GPT-4 的训练成本估计超过 1 亿美元。 2. **指令微调(SFT)**:用人工编写的指令-回答对微调,教模型"用户问问题你要这样答"。原始预训练模型只会续写,不会对话——SFT 让它变成了助手。 3. **RLHF**:用人类偏好数据训练一个奖励模型,再用 PPO 算法优化语言模型。这一步让模型的回答更符合人类期望——更安全、更礼貌、更拒绝有害请求。 ## LLM 能做什么 **理解和分析文本**:读论文写摘要、从合同中提取关键条款、判断用户评论的情感倾向。这类任务 LLM 已经接近人类水平。 **生成内容**:写邮件、写文案、写代码。代码生成是 LLM 落地最成功的场景之一——GitHub Copilot 用了 GPT 的代码能力,让开发者的编码效率提升了 30-50%。 **推理**:链式思考(Chain-of-Thought)让 LLM 能做数学题、逻辑推理。2024 年 OpenAI 的 o1/o3 模型专门强化了推理能力,在数学和编程竞赛上接近人类顶尖水平。 **多模态**:GPT-4V、Claude、Gemini 已经能看图、看视频、听语音。这不是简单的"图文拼接",而是模型真正理解了视觉内容和文字内容之间的语义关系。 **Agent**:LLM 不只是回答问题,还能调用工具、执行任务、规划步骤。这是 2024-2025 最热的方向——让 LLM 成为能自主行动的智能体,而不是被动的问答机器。 ## LLM 的局限 幻觉(hallucination)是最头疼的问题——模型会自信地编造不存在的事实。上下文窗口有限(虽然已经从 4K 扩展到了 128K 甚至 1M),长文档处理仍有挑战。推理成本高,每次 API 调用都在烧钱。对小公司来说,部署自己的 LLM 仍然不现实——7B 模型需要至少 16GB 显存,70B 需要 4 张 A100。 ## 开源和闭源的格局 闭源阵营:GPT-4o、Claude、Gemini 代表了最强性能。开源阵营:LLaMA(Meta)、Mistral、Qwen(阿里)、DeepSeek 追赶速度惊人。2025 年,开源 7B 模型的能力已经接近 GPT-3.5 水平,70B 模型在某些任务上和 GPT-4 打平。对开发者来说,开源模型意味着你可以私有化部署、定制微调、不用担心数据泄露。