从One-Hot到BERT用Python代码复现NLP词向量演进的5个关键阶段在自然语言处理领域词向量技术经历了从简单统计到深度学习的跨越式发展。本文将通过可运行的Python代码带您亲手实现词向量技术的五个里程碑式突破让抽象的理论变得触手可及。1. 独热编码词向量的原始形态独热编码是NLP中最基础的词表示方法。假设我们有一个包含5个单词的词汇表vocab [人工智能, 机器学习, 深度学习, 神经网络, 自然语言处理]实现独热编码的Python函数如下import numpy as np def one_hot_encode(word, vocab): vector np.zeros(len(vocab)) index vocab.index(word) vector[index] 1 return vector # 示例编码深度学习 print(one_hot_encode(深度学习, vocab)) # 输出[0. 0. 1. 0. 0.]这种表示方法存在三个明显缺陷维度灾难词汇表增长会导致向量维度爆炸语义缺失所有词向量相互正交无法表达语义关系稀疏存储大量零值占用无效存储空间提示实际应用中会使用稀疏矩阵优化存储如scipy.sparse.csr_matrix2. 统计方法进阶TF-IDF与共现矩阵TF-IDF通过统计方法改进词袋模型以下是一个完整的实现from sklearn.feature_extraction.text import TfidfVectorizer corpus [ 自然语言处理是人工智能的重要方向, 深度学习推动了自然语言处理的发展, 神经网络是深度学习的核心组件 ] vectorizer TfidfVectorizer() tfidf_matrix vectorizer.fit_transform(corpus) print(tfidf_matrix.toarray())共现矩阵则捕捉词语间的上下文关系from collections import defaultdict window_size 2 co_occurrence defaultdict(lambda: defaultdict(int)) for sentence in corpus: words sentence.split() for i, word in enumerate(words): for j in range(max(0, i-window_size), min(len(words), iwindow_size1)): if i ! j: co_occurrence[word][words[j]] 1统计方法的局限性在于仍然面临高维稀疏问题无法有效捕捉复杂语义关系对新词和罕见词处理能力弱3. Word2Vec神经网络的突破Word2Vec的CBOW模型架构可以用PyTorch实现如下import torch import torch.nn as nn class CBOW(nn.Module): def __init__(self, vocab_size, embedding_dim): super().__init__() self.embeddings nn.Embedding(vocab_size, embedding_dim) self.linear nn.Linear(embedding_dim, vocab_size) def forward(self, inputs): embeds self.embeddings(inputs).mean(dim1) out self.linear(embeds) return out训练过程中需要注意负采样加速训练窗口大小影响语义捕捉范围向量维度需要权衡表达能力和计算成本注意实际应用建议使用gensim库的优化实现4. 上下文感知ELMo的动态编码ELMo的核心创新是双向LSTM架构class BiLSTM(nn.Module): def __init__(self, vocab_size, embed_dim, hidden_dim): super().__init__() self.embedding nn.Embedding(vocab_size, embed_dim) self.lstm nn.LSTM(embed_dim, hidden_dim, bidirectionalTrue) def forward(self, x): embeds self.embedding(x) lstm_out, _ self.lstm(embeds.view(len(x), 1, -1)) return lstm_outELMo的三大特点双向编码同时考虑前后文信息层次表示底层捕获语法高层捕获语义动态调整相同词在不同上下文有不同表示5. Transformer革命BERT的实现BERT的核心是Transformer编码器class TransformerBlock(nn.Module): def __init__(self, embed_dim, num_heads): super().__init__() self.attention nn.MultiheadAttention(embed_dim, num_heads) self.norm1 nn.LayerNorm(embed_dim) self.ff nn.Sequential( nn.Linear(embed_dim, 4*embed_dim), nn.ReLU(), nn.Linear(4*embed_dim, embed_dim) ) self.norm2 nn.LayerNorm(embed_dim) def forward(self, x): attn_out, _ self.attention(x, x, x) x self.norm1(x attn_out) ff_out self.ff(x) return self.norm2(x ff_out)BERT训练的两个关键任务掩码语言模型(MLM)实现def mlm_loss(model, input_ids, masked_indices): outputs model(input_ids) masked_outputs outputs[masked_indices] return F.cross_entropy(masked_outputs, input_ids[masked_indices])下一句预测(NSP)实现def nsp_loss(model, segment_a, segment_b, label): # [CLS] segment_a [SEP] segment_b [SEP] input_ids tokenizer([segment_a, segment_b]) outputs model(input_ids) cls_output outputs[0][0] # [CLS] token return F.binary_cross_entropy(cls_output, label)BERT带来的范式转变从特征抽取到预训练微调从静态向量到动态上下文表示从任务特定模型到通用语言理解