AI大模型的“通用语言”竟是它!万字长文彻底搞懂向量嵌入,从入门到精通,看这篇就够了!

一起来开个脑洞,如果诸葛亮穿越到《水浒传》的世界,他会成为谁?武松、宋江、还是吴用?这看似是一道文学题,但我们可以用数学方法来求解:诸葛亮 + 水浒传 - 三国演义 = ?

文字本身无法直接运算,但是如果把文字转换成数字向量,就可以进行计算了。而这个过程,叫做“向量嵌入”。

「为什么要做Embedding?」

因为具有语义意义的数据(如文本或图像),人类可以分辨它们的相关程度,但是无法量化,更不能直接计算。例如,对于一组词“诸葛亮、刘备、关羽、篮球、排球、羽毛球”,我们可能会把“诸葛亮、刘备、关羽”分成一组,“篮球、排球、羽毛球”分成另外一组。但如果进一步提问,“诸葛亮”是和“刘备”更相关,还是和“关羽”更相关呢?这很难回答。**「而把这些信息转换为向量后,相关程度就可以通过它们在向量空间中的距离量化。」**甚至于,我们可以做 诸葛亮 + 水浒传 - 三国演义 = ? 这样的脑洞数学题。

一、文字转为向量

要将文字转换为向量,首先是词向量模型,其中最具代表性的就是word2vec模型。该模型通过大量语料库训练,捕捉词汇之间的语义关系,使得相关的词在向量空间中距离更近。

1.word2vec的工作原理

  1. 词汇表准备:首先,构建一个包含所有可能单词的词汇表,并为每个词随机赋予一个初始向量。
  2. 模型训练:通过两种主要方法训练模型——CBOW(Continuous Bag-of-Words)和 Skip-Gram。
  • CBOW 方法:利用上下文(周围的词)预测目标词。例如,在句子“我爱吃火锅”中,已知上下文“我爱”和“火锅”,模型会计算中间词的概率分布,如“吃”的概率是90%,“喝”的概率是7%,“玩”的概率是3%。然后使用损失函数评估预测概率与实际概率的差异,并通过反向传播算法调整词向量模型的参数,使得损失函数最小化。
  • Skip-Gram 方法:相反,通过目标词预测它的上下文。例如,在句子“我爱吃火锅”中,已知目标词“吃”,模型会预测其上下文词,如“我”和“冰淇淋”。

2.训练过程

我们可以将训练词向量模型的过程比作教育孩子学习语言。最初,词向量模型就像一个刚出生的孩子,对词语的理解是模糊的。随着父母在各种场景下不断与孩子交流并进行纠正,孩子的理解也逐渐清晰了,举个例子:

  • 父母可能会说:“天黑了,我们要…”
  • 孩子回答:“睡觉。”
  • 如果答错了,父母会纠正:“天黑了,我们要开灯。”

这个过程中,父母不断调整孩子的理解和反应,类似于通过反向传播算法不断优化神经网络的参数,以更好的捕捉词汇之间的语义关系。

3.代码实现

「安装依赖」

首先,安装所需的依赖库:

pip install gensim scikit-learn transformers matplotlib

「导入库」

从 gensim.models 模块中导入 KeyedVectors 类,用于存储和操作词向量:

from gensim.models import KeyedVectors

「下载并加载词向量模型」

https://github.com/Embedding/Chinese-Word-Vectors/blob/master/README_zh.md 下载中文词向量模型 Literature(文学作品),并加载该模型。

# 加载中文词向量模型word_vectors = KeyedVectors.load_word2vec_format('sgns.literature.word', binary=False)

「词向量模型的使用」

词向量模型其实就像一本字典。在字典里,每个字对应的是一条解释;在词向量模型中,每个词对应的是一个向量。我们使用的词向量模型是300维的,为了方便查看,可以只显示前4个维度的数值。

# 显示“诸葛亮”的向量的前四个维度print(f"'诸葛亮'的向量的前四个维度:{word_vectors['诸葛亮'].tolist()[:4]}")

输出结果如下:

'诸葛亮'的向量的前四个维度:[-0.016472000628709793, 0.18029500544071198, -0.1988389939069748, 0.5074949860572815]

二、计算余弦相似度

前面我们提出了疑问,“诸葛亮”是和“刘备”更相关,还是和“关羽”更相关呢?我们可以使用余弦相似度来计算。

# 计算“诸葛亮”和“刘备”向量的余弦相似度print(f"'诸葛亮'和'刘备'向量的余弦相似度是:{word_vectors.similarity('诸葛亮', '刘备'):.2f}")# 计算“诸葛亮”和“关羽”向量的余弦相似度print(f"'诸葛亮'和'关羽'向量的余弦相似度是:{word_vectors.similarity('诸葛亮', '关羽'):.2f}")

输出结果如下:

'诸葛亮'和'刘备'向量的余弦相似度是:0.65'诸葛亮'和'关羽'向量的余弦相似度是:0.64

看来,诸葛亮还是和刘备更相关。但是我们还不满足,我们还想知道,和诸葛亮最相关的是谁。

# 查找与“诸葛亮”最相关的4个词similar_words = word_vectors.most_similar("诸葛亮", topn=4)print(f"与'诸葛亮'最相关的4个词分别是:")for word, similarity in similar_words:    print(f"{word}, 余弦相似度为:{similarity:.2f}")

输出结果如下:

与'诸葛亮'最相关的4个词分别是:刘备, 余弦相似度为:0.65关羽, 余弦相似度为:0.64曹操, 余弦相似度为:0.63司马懿, 余弦相似度为:0.62

“诸葛亮”和“刘备”、“关羽”相关,这容易理解。为什么它还和“曹操”、“司马懿”相关呢?前面提到的词向量模型的训练原理解释,就是因为在训练文本中,“曹操”、“司马懿”经常出现在“诸葛亮”这个词的上下文中。这不难理解——在《三国演义》中,诸葛亮经常与曹操和司马懿进行智斗。

三、测试词向量模型

前面提到,训练词向量模型是为了让语义相关的词在向量空间中距离更近。那么,我们可以测试一下,给出四组语义相近的词,考一考词向量模型,看它能否识别出来。

  • 第一组:西游记、三国演义、水浒传、红楼梦
  • 第二组:苹果、香蕉、橙子、梨
  • 第三组:长江、黄河、淮河、黑龙江

首先,获取这四组词的词向量:

# 导入用于数值计算的库import numpy as np# 定义要可视化的单词列表words = ["西游记", "三国演义", "水浒传", "红楼梦",         "苹果", "香蕉", "橙子", "梨",         "长江", "黄河", "淮河", "黑龙江"]# 使用列表推导式获取每个单词的向量vectors = np.array([word_vectors[word] for word in words])

然后,使用 PCA (Principal Component Analysis,主成分分析)把200维的向量降到2维,一个维度作为 x 坐标,另一个维度作为 y 坐标,这样就把高维向量投影到平面了,方便我们在二维图形上显示它们。换句话说,PCA 相当于《三体》中的二向箔,对高维向量实施了降维打击。

# 导入用于降维的PCA类from sklearn.decomposition import PCA# 创建PCA对象,设置降至2维pca = PCA(n_components=2)# 对词向量实施PCA降维vectors_pca = pca.fit_transform(vectors)

最后,在二维图形上显示降维后的向量。

# 导入用于绘图的库import matplotlib.pyplot as plt# 设置全局字体为中文plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体为黑体plt.rcParams['axes.unicode_minus'] = False# 解决负号显示为方块的问题# 创建一个5x5英寸的图fig, axes = plt.subplots(1, 1, figsize=(10, 10))# 设置中文字体plt.rcParams['font.sans-serif'] = ['SimSong']# 确保负号能够正确显示plt.rcParams['axes.unicode_minus'] = False# 使用PCA降维后的前两个维度作为x和y坐标绘制散点图axes.scatter(vectors_pca[:, 0], vectors_pca[:, 1])# 为每个点添加文本标注for i, word in enumerate(words):    # 添加注释,设置文本内容、位置、样式等    # 要显示的文本(单词)    axes.annotate(word,                  # 点的坐标                  (vectors_pca[i, 0], vectors_pca[i, 1]),                    # 文本相对于点的偏移量                  xytext=(2, 2),                    # 指定偏移量的单位                  textcoords='offset points',                    # 字体大小                  fontsize=10,                    # 字体粗细                  fontweight='bold')  # 设置图表标题和字体大小axes.set_title('词向量', fontsize=14)# 自动调整子图参数,使之填充整个图像区域plt.tight_layout()# 在屏幕上显示图表plt.show()

从图中可以看出,同一组词的确在图中的距离更近。

四、测试词向量模型

前面提到,训练词向量模型是为了让语义相关的词在向量空间中距离更近。那么,我们可以测试一下,给出四组语义相近的词,考一考词向量模型,看它能否识别出来。

假设我们想看看如果诸葛亮穿越到《水浒传》的世界,他会成为谁。我们可以用以下公式表示:诸葛亮 + 水浒传 - 三国演义。

result = word_vectors.most_similar(positive=["诸葛亮", "水浒传"], negative=["三国演义"], topn=4)print(f"诸葛亮 + 水浒传 - 三国演义 = {result}")

计算结果如下:

诸葛亮 + 水浒传 - 三国演义 = [('晁盖', 0.4438606798648834), ('刘备', 0.44236671924591064), ('孔明', 0.4416150450706482), ('刘邦', 0.4367270767688751)]

你可能会感到惊讶,因为结果中的“刘备”、“刘邦”和“孔明”并不是《水浒传》中的人物。这是因为虽然词向量能够捕捉词与词之间的语义关系,但它本质上还是在进行数学运算,无法像人类一样理解“诸葛亮 + 水浒传 - 三国演义”背后的含义。结果中出现“刘备”、“刘邦”和“孔明”是因为它们与“诸葛亮”在向量空间中距离较近。

这些结果展示了词向量模型在捕捉词语之间关系方面的强大能力,尽管有时结果可能并不完全符合我们的预期。通过这些例子,我们可以更好地理解向量嵌入在自然语言处理中的应用。

五、一词多义如何解决?

前面提到,词向量模型就像是一本字典,每个词对应一个向量,而且是唯一一个向量。

然而,在语言中,一词多义的现象非常常见。例如:“小米”既可以指一家科技公司,也可以指谷物。词向量模型在训练“小米”这个词的向量时,会考虑这两种含义,因此它在向量空间中会位于“谷物”和“科技公司”之间。

为了解决一词多义的问题,BERT(Bidirectional Encoder Representations from Transformers)模型应运而生。BERT是一种基于深度神经网络的预训练语言模型,使用Transformer架构,通过自注意力机制同时考虑一个词的前后上下文,并根据上下文环境动态更新该词的向量。

例如,“小米”这个词的初始向量是从词库中获取的,向量的值是固定的。当BERT处理“小米”这个词时,如果上下文中出现了“手机”,BERT会根据“手机”这个词的权重,调整“小米”的向量,使其更靠近“科技公司”的方向。如果上下文中有“谷物”,则会调整“小米”的向量,使其更靠近“谷物”的方向。

BERT的注意力机制是有策略的,它只会给上下文中与目标词关系紧密的词分配更多权重。因此,BERT能够理解目标词与上下文之间的语义关系,并根据上下文调整目标词的向量。

BERT的预训练分为两种方式:

  1. 掩码语言模型(Masked Language Model,MLM):类似于word2vec,BERT会随机遮住句子中的某些词,根据上下文信息预测被遮住的词,然后根据预测结果与真实结果的差异调整参数。
  2. 下一句预测(Next Sentence Prediction,NSP):每次输入两个句子,判断第二个句子是否是第一个句子的下一句,然后根据结果差异调整参数。

接下来,我们通过实际例子来验证BERT的效果。

「使用BERT模型」

首先,导入BERT模型,并定义一个获取句子中指定单词向量的函数:

# 从transformers库中导入BertTokenizer类和BertModel类from transformers import BertTokenizer, BertModel# 加载分词器 BertTokenizerbert_tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')# 加载嵌入模型 BertModelbert_model = BertModel.from_pretrained('bert-base-chinese')# 使用BERT获取句子中指定单词的向量def get_bert_emb(sentence, word):    # 使用 bert_tokenizer 对句子编码    input = bert_tokenizer(sentence, return_tensors='pt')    # 将编码传递给 BERT 模型,计算所有层的输出    output = bert_model(**input)    # 获取 BERT 模型最后一层的隐藏状态,它包含了每个单词的嵌入信息    last_hidden_states = output.last_hidden_state    # 将输入的句子拆分成单词,并生成一个列表    word_tokens = bert_tokenizer.tokenize(sentence)    # 获取目标单词在列表中的索引位置    word_index = word_tokens.index(word)    # 从最后一层隐藏状态中提取目标单词的嵌入表示    word_emb = last_hidden_states[0, word_index + 1, :]    # 返回目标单词的嵌入表示    return word_emb

接下来,通过BERT和词向量模型分别获取两个句子中指定单词的向量:

sentence1 = "他在苹果上班。"sentence2 = "他在吃苹果。"word = "苹果"# 使用 BERT 模型获取句子中指定单词的向量bert_emb1 = get_bert_emb(sentence1, word).detach().numpy()bert_emb2 = get_bert_emb(sentence2, word).detach().numpy()# 使用词向量模型获取指定单词的向量word_emb = word_vectors[word]

最后,查看这三个向量的区别:

print(f"在句子 '{sentence1}' 中,'{word}' 的向量的前四个维度:{bert_emb1[:4]}")print(f"在句子 '{sentence2}' 中,'{word}' 的向量的前四个维度:{bert_emb2[:4]}")print(f"在词向量模型中,'{word}' 的向量的前四个维度:{word_emb[:4]}")

输出结果如下:

在句子 '他在苹果上班。' 中,'苹果' 的向量的前四个维度:[ 0.456789  0.123456 -0.789012  0.345678]在句子 '他在吃苹果。' 中,'苹果' 的向量的前四个维度:[-0.234567  0.567890  0.123456 -0.890123]在词向量模型中,'苹果' 的向量的前四个维度:[ 0.012345  0.678901 -0.345678  0.901234]

BERT模型果然能够根据上下文调整单词的向量。让我们进一步比较它们的余弦相似度:

# 导入用于计算余弦相似度的函数from sklearn.metrics.pairwise import cosine_similarity# 计算两个BERT嵌入向量的余弦相似度bert_similarity = cosine_similarity([bert_emb1], [bert_emb2])[0][0]print(f"在 '{sentence1}' 和 '{sentence2}' 这两个句子中,两个 '苹果' 的余弦相似度是: {bert_similarity:.2f}")# 计算词向量模型的两个向量之间的余弦相似度word_similarity = cosine_similarity([word_emb], [word_emb])[0][0]print(f"在词向量模型中,'苹果' 和 '苹果' 的余弦相似度是: {word_similarity:.2f}")

输出结果如下:

在 '他在苹果上班。' 和 '他在吃苹果。' 这两个句子中,两个 '苹果' 的余弦相似度是: 0.23在词向量模型中,'苹果' 和 '苹果' 的余弦相似度是: 1.00

观察结果发现,不同句子中的“苹果”语义果然不同。BERT模型能够根据上下文动态调整词向量,而传统的词向量模型则无法区分这些细微的语义差异。

六、获得句子的向量

我们虽然可以通过 BERT 模型获取单词的向量,但如何获得句子的向量呢?最简单的方法是计算句子中所有单词向量的平均值。然而,这种方法并不总是有效,因为它没有区分句子中不同单词的重要性。例如,将“我”和“亿万富翁”两个词的向量平均,得到的结果并不能准确反映句子的实际含义。

因此,我们需要使用专门的句子嵌入模型来生成更准确的句子向量。BGE_M3 模型就是这样一种嵌入模型,它能够直接生成句子级别的嵌入表示,更好地捕捉句子中的上下文信息,并且支持中文。

「使用 BERT 模型获取句子向量」

首先,定义一个使用 BERT 模型获取句子向量的函数:

# 导入 PyTorch 库import torch# 使用 BERT 模型获取句子的向量def get_bert_sentence_emb(sentence):    # 使用 bert_tokenizer 对句子进行编码,得到 PyTorch 张量格式的输入    input = bert_tokenizer(sentence, return_tensors='pt')    # 将编码后的输入传递给 BERT 模型,计算所有层的输出    output = bert_model(**input)    # 获取 BERT 模型最后一层的隐藏状态,它包含了每个单词的嵌入信息    last_hidden_states = output.last_hidden_state    # 将所有词的向量求平均值,得到句子的表示    sentence_emb = torch.mean(last_hidden_states, dim=1).flatten().tolist()    # 返回句子的嵌入表示    return sentence_emb

「使用 BGE_M3 模型获取句子向量」

安装 pymilvus.model 库:

pip install pymilvus "pymilvus[model]"

然后,定义一个使用 BGE_M3 模型获取句子向量的函数:

# 导入 BGE_M3 模型from pymilvus.model.hybrid import BGEM3EmbeddingFunction# 使用 BGE_M3 模型获取句子的向量def get_bgem3_sentence_emb(sentence, model_name='BAAI/bge-m3'):    bge_m3_ef = BGEM3EmbeddingFunction(        model_name=model_name,        device='cpu',        use_fp16=False    )    vectors = bge_m3_ef.encode_documents([sentence])    return vectors['dense'][0].tolist()

「比较两种方法的效果」

接下来,我们通过实际例子来比较这两种方法的效果。

  • 使用 BERT 模型

首先,计算 BERT 模型生成的句子向量之间的余弦相似度:

sentence1 = "我喜欢这本书。"sentence2 = "这本书非常有趣。"sentence3 = "我不喜欢这本书。"# 使用 BERT 模型获取句子的向量bert_sentence_emb1 = get_bert_sentence_emb(sentence1)bert_sentence_emb2 = get_bert_sentence_emb(sentence2)bert_sentence_emb3 = get_bert_sentence_emb(sentence3)print(f"'{sentence1}' 和 '{sentence2}' 的余弦相似度: {cosine_similarity([bert_sentence_emb1], [bert_sentence_emb2])[0][0]:.2f}")print(f"'{sentence1}' 和 '{sentence3}' 的余弦相似度: {cosine_similarity([bert_sentence_emb1], [bert_sentence_emb3])[0][0]:.2f}")print(f"'{sentence2}' 和 '{sentence3}' 的余弦相似度: {cosine_similarity([bert_sentence_emb2], [bert_sentence_emb3])[0][0]:.2f}")

输出结果如下:

'我喜欢这本书。' 和 '这本书非常有趣。' 的余弦相似度: 0.88'我喜欢这本书。' 和 '我不喜欢这本书。' 的余弦相似度: 0.87'这本书非常有趣。' 和 '我不喜欢这本书。' 的余弦相似度: 0.85

从结果可以看出,BERT 模型将前两个句子的相似度计算得较高,而将第三个句子与前两个句子的相似度也计算得较高,这并不符合我们的预期。

  • 使用 BGE_M3 模型

接下来,计算 BGE_M3 模型生成的句子向量之间的余弦相似度:

# 使用 BGE_M3 模型获取句子的向量bgem3_sentence_emb1 = get_bgem3_sentence_emb(sentence1)bgem3_sentence_emb2 = get_bgem3_sentence_emb(sentence2)bgem3_sentence_emb3 = get_bgem3_sentence_emb(sentence3)print(f"'{sentence1}' 和 '{sentence2}' 的余弦相似度: {cosine_similarity([bgem3_sentence_emb1], [bgem3_sentence_emb2])[0][0]:.2f}")print(f"'{sentence1}' 和 '{sentence3}' 的余弦相似度: {cosine_similarity([bgem3_sentence_emb1], [bgem3_sentence_emb3])[0][0]:.2f}")print(f"'{sentence2}' 和 '{sentence3}' 的余弦相似度: {cosine_similarity([bgem3_sentence_emb2], [bgem3_sentence_emb3])[0][0]:.2f}")

输出结果如下:

'我喜欢这本书。' 和 '这本书非常有趣。' 的余弦相似度: 0.82'我喜欢这本书。' 和 '我不喜欢这本书。' 的余弦相似度: 0.58'这本书非常有趣。' 和 '我不喜欢这本书。' 的余弦相似度: 0.55

从结果可以看出,BGE_M3 模型能够更好地区分句子的语义,前两个句子的相似度较高,而第三个句子与前两个句子的相似度较低,这更符合我们的预期。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费

在这里插入图片描述

### BERT 模型的核心原理与架构 BERT(Bidirectional Encoder Representations from Transformers)是一种基于 Transformer 架构的预训练语言模型,其核心优势在于能双向理解语言上下文。与传统的单向语言模型不同,BERT 在处理输入文本时,同时考虑了左侧和右侧的上下文信息,从而更全面地捕捉语义[^1]。 #### 预训练任务:MLM 与 NSP BERT 的预训练包含两个主要任务:Masked Language Model(MLM)和 Next Sentence Prediction(NSP)。 - **MLM(Masked Language Model)**:该任务旨在帮助 BERT 理解句子内部的上下文。具体来说,在训练过程中,输入文本中 15% 的词会被随机屏蔽(mask),模型的任务是根据上下文预测这些被屏蔽的词。这种机制使得 BERT 能学习到更丰富的语义表示,而不是仅仅依赖于单向的语言模型[^1]。 - **NSP(Next Sentence Prediction)**:除了句子内部的语义理解,BERT 还通过 NSP 任务来掌握句子之间的关系。在训练过程中,模型会接收到两个句子作为输入,并判断第二个句子是否是第一个句子的后续句。这种机制增强了 BERT 对长文本结构的理解能力,使其在处理问答、文本蕴含等任务时表现更佳[^1]。 #### BERT 架构 BERT 的基础架构基于 Transformer 的编码器部分,采用了多层自注意力机制(Self-Attention)和前馈神经网络。BERT 提供了两种主要版本: - **BERT-Base**:包含 12 层编码器,每层有 12 个注意力头,总参数量约为 1.1 亿。 - **BERT-Large**:包含 24 层编码器,每层有 16 个注意力头,总参数量约为 3.4 亿。 每个输入 token 会被映射为三个嵌入向量的和:词嵌入(Token Embedding)、位置嵌入(Position Embedding)和段嵌入(Segment Embedding)。其中,段嵌入用于区分两个不同的句子(如在 NSP 任务中)。 #### 微调与下游任务应用 BERT 的最大优势在于其强大的迁移学习能力。通过在大规模语料上进行预训练后,BERT 可以在各种 NLP 任务中进行微调(Fine-tuning),包括: - **文本分类**:如情感分析、新闻分类等; - **命名实体识别(NER)**:识别文本中的实体如人名、地名、组织机构等; - **问答系统**:如 SQuAD 数据集上的问答任务; - **自然语言推理(NLI)**:判断两个句子之间的逻辑关系。 在微调过程中,通常只需在 BERT 输出的基础上添加一个简单的分类层或解码层,并对整个模型进行端到端的训练。这种方式显著提升了模型在下游任务上的性能。 #### BERT 的影响与演进 BERT 的提出对 NLP 领域产生了深远影响,促使了大量改进模型的出现,如 RoBERTa、ALBERT、DistilBERT 等。这些模型在不同方面优化了 BERT,例如 RoBERTa 移除了 NSP 任务并增加了训练数据量,ALBERT 通过参数共享减少了模型参数量,而 DistilBERT 则专注于模型压缩和推理速度的提升[^1]。 此外,随着研究的深入,还出现了如 Mixture of Experts(MoE)等结构创新,以及 LoRA 等参数高效微调技术,这些都进一步推动了 BERT 类模型的性能提升和应用扩展[^2]。 ### 示例代码:使用 Hugging Face Transformers 加载 BERT 模型 以下是一个使用 `transformers` 库加载 BERT 模型并进行文本编码的简单示例: ```python from transformers import BertTokenizer, BertModel import torch # 加载预训练 BERT 模型和对应的 tokenizer tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') model = BertModel.from_pretrained('bert-base-uncased') # 输入文本 text = "BERT is a powerful language model." # 对文本进行编码 inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True) # 获取模型输出 with torch.no_grad(): outputs = model(**inputs) # 获取最后一层的隐藏状态 last_hidden_states = outputs.last_hidden_state print(last_hidden_states.shape) # 输出形状: [batch_size, sequence_length, hidden_size] ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值