一篇讲透 NLP从结巴分词到大模型理解我是怎么被自然语言折腾的不搞学术腔聊聊 NLP 到底在解决什么问题以及怎么解决的从一个场景说起前段时间一个做后端的朋友想做个智能客服系统跑来问我“NLP 到底是个啥我直接用 GPT 行不行”我问他“你知不知道分词、词向量、预训练这些概念”他摇头“不就是把文字扔给模型它就能理解了吗”我笑了笑“那你试试用 GPT 算一下这句话里有几个’意思’”“意思意思小意思你这人真没意思我就这么点意思”他懵了。好吧事情没那么简单。问题分析NLP自然语言处理难在哪我总结了三座大山1. 语言的歧义性苹果是水果还是公司能穿多少穿多少到底是多穿还是少穿上面那个意思到底几个意思2. 上下文依赖性它指代谁要看前面说了啥银行是河边还是金融机构要看语境3. 语言的多样性同义词“高兴”、“开心”、“快乐”方言、俚语、网络用语“绝绝子”、“yyds”错别字的得地不分NLP 的核心任务说白了就是教计算机理解人类语言。但这个理解分很多层次浅层分词、找关键词中层句法分析、情感判断深层语义理解、推理生成咱们一步步看怎么解决。方案设计NLP 的发展大概分三个阶段我称之为三板斧阶段 1规则时代2000 年前人工写规则、词典、语法代表正则表达式、专家系统阶段 2统计机器学习2000-2018让数据说话用统计方法找规律代表HMM、CRF、SVM、Word2Vec阶段 3深度学习时代2018-至今神经网络自动学习特征代表RNN、Transformer、BERT、GPT咱们重点聊聊工程上最常用的技术点。实现过程Step 1: 分词 —— 把句子切成词中文没有空格第一步得把我喜欢猫切成[“我”, “喜欢”, “猫”]。看似简单坑很多“南京市长江大桥” → [“南京市”, “长江大桥”] 还是 [“南京”, “市长”, “江大桥”]“未登录词”网络新词、人名、地名词典里没有# 伪代码基于词典的最长匹配分词defsegment(text,dict):result[]i0whileilen(text):# 关键从当前位置开始找词典里最长的匹配matchedNoneforlengthinrange(max_len,0,-1):# 从长到短试wordtext[i:ilength]ifwordindict:matchedwordbreakifmatched:result.append(matched)ilen(matched)else:# 没匹配到按字切result.append(text[i])i1returnresult# 示例segment(我喜欢南京市,dict)# 结果: [我, 喜欢, 南京市] ✓# 不是: [我, 喜欢, 南京, 市] ✗工程建议不要自己写分词用现成的Jieba中文、spaCy英文特定领域医疗、法律需要自定义词典大模型时代分词变成了 Tokenization后面讲Step 2: 词向量 —— 把词变成计算机能算的数字分完词计算机还是不认识猫这个字。得变成向量一串数字。核心思想意思相近的词向量距离也近。国王 - 男人 女人 ≈ 女王 北京 - 中国 日本 ≈ 东京# 伪代码Word2Vec 的 Skip-gram 模型简化版classWord2Vec:def__init__(self,vocab_size,dim100):# 每个词有两个向量中心词向量、上下文向量self.center_vectorsinit_matrix(vocab_size,dim)self.context_vectorsinit_matrix(vocab_size,dim)deftrain(self,sentence,window2): 句子[我, 喜欢, 猫, 和, 狗] 窗口2喜欢的上下文是 [我, 猫, 和] fori,target_wordinenumerate(sentence):# 关键预测周围的词context_wordssentence[max(0,i-window):i]sentence[i1:iwindow1]forcontext_wordincontext_words:# 中心词向量 上下文词向量 相似度scoreself.center_vectors[target_word] self.context_vectors[context_word]# 训练目标让真实的上下文词相似度高其他词相似度低losssoftmax_loss(score,context_word)update_vectors(loss)Word2Vec 的局限每个词只有一个向量没法处理多义词苹果水果 vs 公司没有上下文感知改进ELMo、BERT后面讲Step 3: 序列建模 —— 理解上下文语言是有顺序的我喜欢猫和猫喜欢我意思完全不同。RNN循环神经网络一个一个词看记住前面的信息。# 伪代码RNN 处理句子defrnn_process(sentence,vocab):hidden_statezero_vector(dim128)# 初始记忆forwordinsentence:word_vecvocab.get_vector(word)# 关键新状态 f(当前词, 之前的状态)# 就像读小说每读一个词更新对整句话的理解hidden_statetanh(W_input word_vecW_hidden hidden_state)# 最后的 hidden_state 包含了整句话的信息returnhidden_state# 应用情感分类sentence_vecrnn_process(这部电影真棒,vocab)sentimentclassify(sentence_vec)# 正面RNN 的坑长句子记不住开头梯度消失计算慢只能串行不能并行改进LSTM、GRU加门控选择性记忆Step 4: Attention —— 重点关注关键信息RNN 是一个词一个词啃太慢。Attention 是全局看重点记。# 伪代码Attention 机制简化版defattention_encoder(sentence,vocab):# 1. 所有词变成向量word_vectors[vocab.get_vector(w)forwinsentence]# 2. 每个词都要看看其他词encoded[]fori,current_wordinenumerate(word_vectors):# 关键计算当前词和句子中所有词的关联度scores[]forj,other_wordinenumerate(word_vectors):scoresimilarity(current_word,other_word)scores.append(score)# 归一化成权重weightssoftmax(scores)# 加权求和自己的意思 关注别人的意思context_vectorsum(w*word_vectors[i]fori,winenumerate(weights))encoded.append(context_vector)returnencoded# 例子猫坐在垫子上因为它很温暖# 它这个词的 attention 会重点看猫和垫子# 模型自己学会了指代消解工程直觉Attention 就是查表每个词都去查句子中哪些词跟自己相关。Step 5: 预训练 微调 —— BERT 和 GPT 的秘密核心思想先在大规模语料上预习再在具体任务上复习。预训练Pre-training 数据维基百科 小说 新闻海量无标注文本 任务 - BERT挖空填词我[MASK]欢猫 → 喜 - GPT预测下一个词我喜欢 → 猫 产出通用的语言理解能力 微调Fine-tuning 数据具体任务的标注数据如情感分类标注 任务在预训练模型上加个分类层训练 产出特定任务的专用模型# 伪代码BERT 微调情感分类classSentimentClassifier:def__init__(self):# 加载预训练的 BERT已经学会了语言规律self.bertload_pretrained_bert()# 只加一个简单的分类头self.classifierLinear(768,2)# 正面/负面defforward(self,text):# BERT 把文本变成向量cls_vectorself.bert.encode(text)[0]# [CLS] 位置的向量# 分类头判断情感logitsself.classifier(cls_vector)returnsoftmax(logits)# 训练时只更新分类头或者低学习率更新全部BERT vs GPTBERT双向看看上下文适合理解任务分类、抽取GPT单向生成看前面预测后面适合生成任务写文章、对话大模型时代GPT-3、ChatGPT、GPT-4 是 GPT 的放大版参数量从 1 亿 - 1750 亿量变引起质变出现了涌现能力。踩坑记录做 NLP 项目这些年踩了不少坑坑 1: 预处理没做好现象模型准确率上不去查了半天发现是文本里有特殊符号、HTML 标签、全角半角混用。解决方案defclean_text(text):# 去 HTMLtextremove_html_tags(text)# 统一空格textnormalize_whitespace(text)# 统一标点textconvert_fullwidth_punct(text)# 去特殊符号textremove_special_chars(text)returntext坑 2: 中文不分词直接用字现象用 BERT 处理中文直接按字切效果差。原因BERT 原版的 Tokenizer 对中文就是按字切但中文词语才有意义。解决方案用中文优化版MacBERT、Chinese-RoBERTa或者自己训练词表。坑 3: 忽视类别不平衡现象情感分类90% 是正面模型全预测正面也有 90% 准确率。解决方案采样过采样 minority class欠采样 majority class加权给少数类更高的损失权重评估看 F1不要只看准确率坑 4: 线上线下不一致现象离线测试 95% 准确率上线后实际效果很差。原因训练数据太干净线上数据有噪声训练数据分布和实际分布不一致解决方案加强数据清洗和增强线上 A/B 测试小流量验证持续收集 bad case迭代模型选型建议不同场景用什么技术场景推荐方案理由关键词提取Jieba TF-IDF简单高效无需训练文本分类数据少BERT 微调预训练知识小数据也能用文本分类数据多轻量模型TextCNN、FastText速度快成本低实体识别BERT-CRF效果好识别边界准确文本生成GPT 系列生成流畅逻辑连贯智能客服RAG检索生成可控可溯源要不要用大模型数据敏感不能外传本地化部署小模型BERT、ChatGLM-6B追求效果且预算充足GPT-4、Claude平衡效果和成本GPT-3.5、文心一言、通义千问 API小结NLP 从规则到统计再到深度学习核心都是在解决三个问题怎么切词Tokenization怎么表示Embedding怎么理解上下文RNN、Attention、Transformer现在的趋势大模型一统天下一个模型搞定多种任务RAG 兴起检索生成解决大模型幻觉和知识时效问题多模态融合文本图像语音统一理解但基础仍然重要知道分词原理才能调优 Tokenizer理解 Attention才能看懂模型为什么出错。写在最后NLP 这领域学起来感觉东西很多但抓住主线就清晰了传统方法规则、统计、机器学习深度学习RNN - Attention - Transformer预训练时代BERT理解、GPT生成你在做 NLP 项目时遇到过什么奇葩问题是分词分错了还是模型理解不了上下文欢迎在评论区交流