自然语言处理(NLP)基础

一、NLP概览

自然语言处理

文本表示

词向量

Embedding

位置编码

核心任务

文本分类

命名实体识别

机器翻译

文本生成

问答系统

发展历程

规则方法

统计方法

神经网络

大语言模型

应用场景

智能客服

机器翻译

内容审核

代码生成


二、文本表示

2.1 为什么需要文本表示?

核心问题:计算机只能处理数字,如何把文字变成数字?

文本: '我爱AI'

表示转换

向量: [0.2, 0.8, ...]

2.2 文本表示演进

1950s-2000s One-Hot编码 简单但稀疏 2013 Word2Vec 词向量,语义相似性 2014 GloVe 全局词向量 2018 BERT Embedding 上下文相关 2020s 大模型Embedding 更强的语义理解 文本表示技术演进

2.3 One-Hot编码

理解:每个词用一个独热向量表示,只有一个位置是1。

词表: ["我", "爱", "AI", "学习"]

"我" → [1, 0, 0, 0]
"爱" → [0, 1, 0, 0]
"AI" → [0, 0, 1, 0]
"学习" → [0, 0, 0, 1]

问题

  • 维度等于词表大小(可能几十万)
  • 无法表达语义相似性("猫"和"狗"距离一样远)

2.4 词向量(Word Embedding)

理解:把每个词映射到一个低维稠密向量,语义相近的词距离更近。

词向量空间

语义相近

语义远离

猫 [0.2, 0.9]

狗 [0.3, 0.8]

汽车 [0.9, 0.1]

经典方法

方法 原理 特点
Word2Vec 预测上下文词 高效,但无上下文
GloVe 全局词共现矩阵 统计信息
FastText 字符级n-gram 处理未登录词

2.5 上下文相关Embedding

理解:同一个词在不同语境下有不同的向量表示。

示例

'苹果很好吃'

苹果 → 水果向量

'苹果发布了新手机'

苹果 → 公司向量

实现方式:BERT等模型根据上下文动态生成Embedding。


三、核心NLP任务

理解任务

问答系统

阅读理解

语义相似度

生成任务

文本摘要

机器翻译

对话生成

序列标注

命名实体识别 NER

词性标注 POS

分词

分类任务

情感分析

主题分类

垃圾邮件检测

3.1 文本分类

理解:给定文本,预测其类别。

输入: '这个产品太棒了!'

分类模型

输出: 正面情感

应用场景

  • 情感分析(评论、舆情)
  • 意图识别(智能客服)
  • 内容审核(违规检测)

3.2 命名实体识别(NER)

理解:从文本中识别出特定类型的实体。

'张三在北京的腾讯公司工作'

张三 → 人名

北京 → 地点

腾讯公司 → 组织

3.3 机器翻译

理解:将文本从一种语言翻译成另一种语言。

解码器

编码器

英文: 'Hello World'

编码器
理解语义

解码器
生成翻译

中文: '你好世界'

3.4 文本生成

理解:根据输入生成连贯的文本。

输入: '从前有座山'

生成模型

从前有座山

庙里有个老和尚

生成方式:自回归生成,一个词一个词地预测。


四、NLP技术发展历程

大模型时代 (2020-至今)

GPT-3/4

涌现能力

Prompt Engineering

Transformer时代 (2017-2020)

Attention Is All You Need

BERT/GPT

预训练+微调范式

神经网络时代 (2013-2017)

Word2Vec

RNN/LSTM/GRU

Seq2Seq

统计时代 (1990s-2010)

隐马尔可夫模型 HMM

条件随机场 CRF

N-gram语言模型

规则时代 (1950s-1980s)

专家系统

手工编写规则

4.1 RNN时代

LSTM

门控机制

长短期记忆

解决长距离依赖

RNN

顺序处理

有记忆

梯度消失问题

4.2 Transformer革命

核心创新:用注意力机制替代循环结构。

特性 RNN Transformer
计算方式 串行 并行
长距离依赖 困难 直接连接
训练效率 较慢
可扩展性 有限 可扩展到千亿参数

五、大语言模型(LLM)

5.1 LLM的基本原理

输出

模型处理

输入

提示词: '什么是AI?'

分词

向量化

注意力计算

前馈网络

输出概率

回答: 'AI是人工智能...'

5.2 GPT系列演进

GPT-1
1.17亿参数
2018

GPT-2
15亿参数
2019

GPT-3
1750亿参数
2020

GPT-4
多模态
2023

5.3 涌现能力

理解:当模型规模超过某个阈值后,突然出现的新能力。

规模扩大

大模型

复杂推理

代码生成

少样本学习

指令遵循

小模型

基础语言能力

简单推理


六、提示工程(Prompt Engineering)

6.1 什么是提示工程?

理解:通过设计输入提示词来引导模型生成期望的输出。

差提示: '写点东西'

好提示: '请写一篇500字的产品介绍,
目标用户是25-35岁的职场人士,
语气要专业但亲切'

输出: 随机内容

输出: 高质量文案

6.2 提示工程技巧

技巧 说明 示例
明确角色 指定模型扮演的角色 “你是一个资深工程师…”
提供示例 给出输入输出样例 “示例:输入A→输出B”
分步引导 拆解复杂任务 “第一步…第二步…”
约束输出 限定输出格式 “用JSON格式返回”
思维链 引导推理过程 “让我们一步步思考”

6.3 提示模板示例

你是一个{{角色}},擅长{{技能}}。

任务:{{具体任务}}

要求:
- {{要求1}}
- {{要求2}}

输出格式:{{格式说明}}

示例:
输入:{{示例输入}}
输出:{{示例输出}}

七、NLP应用架构

7.1 典型应用架构

数据层

模型层

应用层

用户层

用户界面

API网关

提示词管理

上下文管理

大语言模型

Embedding模型

重排序模型

向量数据库

知识库

缓存

7.2 RAG架构

RAG(检索增强生成):先检索相关信息,再让模型基于检索结果生成回答。

LLM 向量数据库 检索系统 用户 LLM 向量数据库 检索系统 用户 提问 向量检索 返回相关文档 问题 + 相关文档 基于文档生成回答

后端类比

RAG ≈ 带缓存的API调用

1. 用户请求 → 检查缓存(向量检索)
2. 缓存命中 → 直接使用缓存数据
3. 缓存未命中 → 查询数据库(LLM生成)
4. 合并结果 → 返回给用户

八、常见NLP任务实现

8.1 任务与模型选择

任务 推荐模型 说明
文本分类 BERT/RoBERTa 理解能力强
命名实体识别 BERT+CRF 序列标注
文本生成 GPT系列 自回归生成
问答系统 RAG+LLM 检索增强
文本嵌入 Sentence-BERT 语义相似度
机器翻译 mT5/NLLB 多语言支持

8.2 开发工具推荐

工具 用途 特点
Hugging Face Transformers 模型调用 丰富的预训练模型
LangChain LLM应用开发 链式调用、工具集成
LlamaIndex RAG开发 知识库构建
OpenAI API 商业应用 简单易用

九、后端工程师实践建议

9.1 NLP服务设计考量

质量保障

输出验证

人工审核

反馈循环

成本控制

提示词优化

缓存复用

模型选择

性能优化

异步处理

批量推理

模型缓存

9.2 常见坑与解决方案

问题 解决方案
幻觉(胡说八道) 提供上下文、要求引用来源
输出不稳定 降低temperature、提供示例
上下文太长 使用RAG、分段处理
响应慢 流式输出、异步处理
成本高 缓存、使用更小模型

十、NLP代码实战

10.1 文本向量化示例

使用Transformers获取词向量

💻 对应脚本:3.1.text_embedding_bert.py

"""
BERT文本向量化示例
=================
使用Transformers获取中文文本的词向量和句子向量

依赖安装: pip install transformers torch
运行: python text_embedding_bert.py
"""

from transformers import AutoTokenizer, AutoModel
import torch


def main():
    # 1. 加载预训练模型(使用中文BERT)
    model_name = 'bert-base-chinese'
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    model = AutoModel.from_pretrained(model_name)

    # 2. 文本预处理
    text = "人工智能正在改变世界"
    inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)
    print(f"分词结果: {tokenizer.tokenize(text)}")
    print(f"Token IDs: {inputs['input_ids']}")

    # 3. 获取词向量
    with torch.no_grad():
        outputs = model(**inputs)
        # last_hidden_state: 每个token的向量表示 (batch_size, seq_len, hidden_size)
        embeddings = outputs.last_hidden_state

    print(f"向量形状: {embeddings.shape}")  # (1, 序列长度, 768)

    # 4. 获取句子向量(使用[CLS]token或平均池化)
    cls_embedding = embeddings[:, 0, :]  # [CLS] token的向量
    mean_embedding = embeddings.mean(dim=1)  # 平均池化

    print(f"[CLS]向量形状: {cls_embedding.shape}")  # (1, 768)
    print(f"平均池化向量形状: {mean_embedding.shape}")

    # 5. 计算句子相似度
    def get_sentence_embedding(text):
        inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)
        with torch.no_grad():
            outputs = model(**inputs)
        return outputs.last_hidden_state.mean(dim=1).squeeze()

    def cosine_similarity(vec1, vec2):
        return torch.nn.functional.cosine_similarity(
            vec1.unsqueeze(0), vec2.unsqueeze(0)
        ).item()

    sentences = [
        "我喜欢吃苹果",
        "苹果很好吃",
        "今天天气不错",
    ]

    embeddings_list = [get_sentence_embedding(s) for s in sentences]

    print("\n=== 句子相似度 ===")
    print(f"'{sentences[0]}' vs '{sentences[1]}': "
          f"{cosine_similarity(embeddings_list[0], embeddings_list[1]):.4f}")
    print(f"'{sentences[0]}' vs '{sentences[2]}': "
          f"{cosine_similarity(embeddings_list[0], embeddings_list[2]):.4f}")


if __name__ == "__main__":
    main()

输出示例

分词结果: ['人', '工', '智', '能', '正', '在', '改', '变', '世', '界']
Token IDs: tensor([[ 101,  782, 1057, 3168, 5686, 3731, 1762, 2841, 1290,  102]])
向量形状: torch.Size([1, 12, 768])
[CLS]向量形状: torch.Size([1, 768])
平均池化向量形状: torch.Size([1, 768])

=== 句子相似度 ===
'我喜欢吃苹果' vs '苹果很好吃': 0.8923
'我喜欢吃苹果' vs '今天天气不错': 0.5421

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐