1.LayoutLM Code Guide
2.BERT源码阅读
3.LAMA代码分析-上
4.tokenization分词算法及源码
5.bert源码解析
6.BERT(Transformer Encoder)详解和TensorFlow实现(附源码)
LayoutLM Code Guide
LayoutLM
LayoutLM为一个视觉文档多任务通用的预训练模型,本文将对其开源实现代码进行详细解析,介绍其目录结构、重要组件和运行步骤。
在微软开源工作总仓库unilm下,将layoutlm进行clone操作。GCC源码学习由于layoutlm已作为第一版本弃用,其微调样例和主模型代码被额外一层deprecated目录包裹。
本文将以下游任务Funsd为例,具体展示layoutlm在微调过程中的相关代码。
分布式训练与代码解析
首先,通过阅读preprocess.sh脚本,了解其功能为下载数据集、调用preprocess.py预处理数据集并整理标签。
在preprocess.py中,数据集被从原始格式转换为模型可处理和学习的格式,以供Dataset加载。为熟悉Funsd数据集内容与格式,需要先了解其原始信息。
Funsd数据集结构包括data目录下训练集与测试集,分别包含images与annotations两个子目录。训练集包含个样本,测试集包含个样本。数据集标记详细,以文本块为单位,包括文本框、文本、标签、词集合与关系等信息。
目标格式转换完成后,将所有样本处理结果集中于一个文件中,每个样本间以空行间隔,形成符合要求的正式txt文件。通过diff命令可得知,文本文件总行数在temp行后插入一个空行,最终共有行。同时,对于test数据集,tmp文件为行,txt文件为行。
在preprocess.py中,主要逻辑涉及convert与seg函数的作用,具体在源码中有注释说明。此步骤完成后,数据处理完毕,可通过run_seq_labeling.py代码进行微调训练。
main方法启动微调过程,源码安装与先将源码打包程序注释中详细解释了主要步骤。程序包含以下关键方法,涉及单机多卡训练的实现,需要在阅读源码时注意参数local_rank、model构建与ngpu的值。
在layoutlm.py中,定义了基础模型的相关类,包括LayoutlmConfig、LayoutlmEmbeddings、LayoutlmModel与LayoutlmForSequenceClassification等。
相比于BertConfig,LayoutlmConfig添加了max_2d_position_embeddings参数,用于指定布局嵌入的维度。在LayoutlmEmbeddings类中,包括词嵌入、位置嵌入与段嵌入等,最终所有embedding通过加法连接。
LayoutlmModel类继承自BertModel,初始化包含主要的layoutlm模型与分类预测头。前向传播的主要代码对输入进行推理,进行分类预测,最后计算损失,根据标签数量采用MSE或交叉熵损失。
通过模型在bert基础上的扩展与优化,LayoutLM实现了对视觉文档多任务的高效处理能力。理解其代码实现时,参考hugging face中bert的实现代码,有助于更深入地理解layoutlm的架构与功能。
BERT源码阅读
BERT,全称为双向Transformer编码器表示,其源码主要包含以下几个关键步骤:
首先,环境准备至关重要,通过create_pretraining_data.py进行训练样本的生成。主体函数对原始文本进行切词处理,具体在tokenization.py中的create_training_instances()方法中实现。接着,通过调用write_instance_to_example_files()将处理后的样本保存。
模型构建阶段,modeling.py中的核心是BertConfig类和BertModel类。通过初始化这两个类,可以构建起BERT模型。值得注意的是,模型结构中包含Dropout层,但注意力层的dropout概率有所不同。
优化器的构建在optimization.py中完成,训练模型则通过run_pretraining.py中的整数源码和负数源码相加model_fn_builder函数实现。同时,模型还包含处理Next Sentence Prediction (NSP)任务的loss函数,即get_next_sentence_output。
后续的fine-tuning环节,extract_features.py负责生成句子向量表示,而run_classifier.py和run_classifier_with_tfhub.py用于分类任务。至于问答任务,run_squad.py提供了相应的解决方案。
LAMA代码分析-上
LAMA是一个用于分析预训练语言模型掌握知识的工具,通过使用prompt来评估模型的能力。要深入理解LAMA的工作原理,建议首先阅读相关论文。本文章将通过代码分析,探讨LAMA的实现细节,适合对LAMA有初步了解并寻求更深入理解的读者。
LAMA的源码位于GitHub上的facebookresearch/LAMA仓库。项目的代码结构清晰,入口文件为run_experiments.py。通过这个文件,我们可以看到LAMA整体的运行逻辑:对四个不同数据集上的多种语言模型进行实验,以检测模型的性能。语言模型包括但不限于emo、gpt、bert和transformer等,用户可以根据需求灵活配置。
为了更具体地理解LAMA的工作流程,我们以google-RE数据集为例,深入分析bert模型的探测过程。google-RE数据集仅包含三个关系类型,便于理解模型的运行逻辑。在run_all_LMs函数中,可以看到多个语言模型多次运行run_experiments函数,进行实验。
接着,我们关注run_experiments函数的核心逻辑,它针对数据集中的每个关系实例运行,进行模型评估。google_RE数据集中的三个关系实例通过关系循环处理,每个实例使用特定的模型运行实验。这个过程中,模型根据传入参数构建,bert模型的构建涉及build_model_by_name函数。
build_model_by_name函数构建了模型,随后的run_evaluation函数执行模型评估。这个过程包含对每个模型定义的通用接口的使用,例如bert模型的呼叫源码和路由选择源码处理。bert模型的构建涉及到pytorch_pretrained_bert库,自定义的BaseTokenizer类用于处理bert输入要求的基础分词任务。bert_connector.py文件中定义了bert模型的特定处理逻辑,包括如何与通用接口交互。
模型构建和评估过程中的关键点在于,LAMA通过pytorch_pretrained_bert库调用bert模型,并进行初步分词处理。自定义的BaseTokenizer类确保了分词的特定需求,如单独处理包含[MASK]的token,这是为了后续的预测和评估过程。bert类的主要功能是对pytorch_pretrained_bert库的调用,实现模型的训练和预测。
在模型评估阶段,main函数在run_evaluation中起关键作用。这个函数通过导入数据、过滤样本、构建masked_sentences等步骤,准备数据供模型评估。LAMA使用通用词表进行数据集设计,确保不同语言模型的公平比较。评估过程通过解析模板和预测对象来检测模型对三元组知识的掌握情况。
总结而言,LAMA通过精心设计的数据处理和模型评估流程,实现了对预训练语言模型知识掌握能力的深入分析。代码的优雅实现和对多种语言模型的兼容性,使得LAMA成为评估和理解语言模型能力的强大工具。本文通过代码分析,详细介绍了LAMA的核心逻辑和工作流程,为深入理解和应用LAMA提供了基础。
tokenization分词算法及源码
Byte Pair Encoding(BPE)算法将单词分割为每个字母,统计相邻字母的频率,将出现频率最高的组合替换为新的token,以此进行分词。实现过程中先预处理所有单词,从最长到最短的token进行迭代,尝试替换单词中的子字符串为token,并保存每个单词的tokenize结果。对于文本中未见的单词,使用“unk”标记。
Byte-level BPE方法将每个词视为unicode的字节,初始词典大小为,然后进行合并。它适用于GPT2模型。
WordPiece算法与BPE类似,但采用最高频率的单词对替换为概率最高的单词对,以增加最大概率增量。游戏源码手游源码网它被用于BERT模型。
ULM(Unigram Language Model)SentencePiece算法结合了BPE和ULM子词算法,支持字节级和字符级,对unicode进行规范化处理。
核心代码中包含子词采样策略,即在分词时随机选择最佳的分词方案,以增加泛化性和扩展性。使用了subword regularization,适用于llama、albert、xlnet、t5等模型。
详细资料可参考《大语言模型之十 SentencePiece》一文,原文发布在towardsdatascience.com。
bert源码解析
训练数据生成涉及将原始文章语料转化为训练样本,这些样本按照目标(如Mask Language Model和Next Sentence Prediction)被构建并保存至tf_examples.tfrecord文件。此过程的核心在于函数create_training_instances,它接受原始文章作为输入,输出为训练instance列表。在这一过程中,文章首先被分词,随后通过create_instances_from_document函数构建具体训练实例。构建实例流程如下:
确定最大序列长度后,Next Sentence Prediction任务被构建。选取文章的开始位置至结尾,确保生成的句子集长度至少等于最大序列长度。在此集合中随机挑选一个位置(a_end),将句子集分为两部分:前部分作为序列A,而后部分有%的概率成为序列B,剩余%则随机选择另一篇文章的句子集(总长度不小于「max_seq_length-序列A」),形成Next Sentence Prediction任务。
Mask language model任务构建通过将序列A和序列B组合成一个训练序列tokens,并对其进行掩码操作实现。掩码操作以token为单位,利用WordPiece进行分词,确保全词掩码模式下的整体性,无论是全掩码还是全不掩码。每个序列以masked_lm_prob(0.)概率进行掩码,对于被掩码的token,%情况下替换为[MASK],%保持不变,%则替换为词表中随机选择的单词。返回结果包括掩码操作后的序列、掩码token索引及真实值。
训练样本结构由上述处理后形成,每条样本包含经过掩码操作的序列、掩码token的索引及真实值。
分词器包括全词分词器(FullTokenizer),它首先使用BasicTokenizer进行基础分词,包括小写化、按空格和标点符号分词,以及中文的字符分词,随后使用WordpieceTokenizer基于词表文件对分词后的单词进行WordPiece分词。
模型结构从输入开始,经过BERT配置参数,包括WordEmbedding、初始化embedding_table、embedding_postprocessor等步骤,最终输出sequence和pooled out结果。WordEmbedding负责将输入token(input_ids)转换为其对应的embedding,包括token embedding、segment embedding和position embedding。embedding_postprocessor在得到的token embedding上加上position embedding和segment embedding,然后进行layer_norm和dropout处理。
Transformer Model中的attention mask根据input_mask构建,用于计算attention score。self attention过程包括query、key、value层的生成,query与key相乘得到attention score,经过归一化处理,并结合attention_mask和dropout,形成输出向量context_layer。随后是feed forward过程,包括两个网络层:中间层(intermediate_size,激活函数gelu)和输出层(hidden_size,无激活函数)。
sequence和pooled out分别代表最后一层的序列向量和[CLS]向量的全连接层输出,维度为hidden_size,激活函数为tanh。
训练过程基于BERT产生的序列向量和[CLS]向量,分别训练Mask Language Model和Next Sentence Prediction。Mask Language Model训练通过get_masked_lm_output函数,主要输入为序列向量、embedding table和mask token的位置及真实标签,输出为mask token的损失。Next Sentence Predication训练通过get_next_sentence_output函数,本质为一个二分类任务,通过全连接网络将[CLS]向量映射,计算交叉熵作为损失。
BERT(Transformer Encoder)详解和TensorFlow实现(附源码)
BERT,全称Bidirectional Encoder Representation from Transformers,源自Transformer的Encoder部分。其核心结构通过双向注意力机制,使得每个token能同时关注其前后文内容,形成双向上下文融合。相较于单向语言模型,BERT在复杂语言理解任务中展现出更强大的性能,如完形填空、问答系统、情感分析、目标导向搜索和辅助导航等。
BERT的训练机制包含两种创新的预训练策略:Masked Language Model(MLM)和Next Sentence Prediction(NSP)。MLM通过在句子中随机遮蔽部分词汇,促使模型基于上下文进行预测,增强词汇理解和错误纠正能力。NSP则判断两句话在语料中的连续性,强化句子级别的语言表征能力。
在BERT的架构中,每个输入token生成一个输出表示,对于任务不同,输出会用到额外的输出层进行预测。例如,对于完型填空或问答任务,使用每个token对应的输出;对于情感分类任务,则使用“[CLS]”对应的输出。
微调阶段,BERT在大量语料上训练后,可用于NLP的各个任务中。对于语义分析任务,构建模型时将BERT输出中的“[CLS]”符号输入到Dense层进行分类处理。通过加载BERT模型、预处理模型以及进行微调,最终完成任务的训练和推理。
实战 向量数据库选型参考
在实施大型模型的过程中,特别是在应用RAG增强检索生成时,向量数据库的选择至关重要。本文通过实验对比了四个常见的向量数据库:Chroma、Faiss、Weaviate和Pinecore。未来计划在时间和精力允许的情况下,追加Milvus和Qdrant的实验。
实验中选用的模型要求较小,以减少空间占用,便于本地调试。从Huggingface上选择了名为all-MiniLM-L6-v2的模型,其维度为。
HuggingFace上的模型all-MiniLM-L6-v2无法直接下载。可以通过以下两种方式之一下载模型:从摩搭(ModelScope)平台下载,或从HF-Mirror下载。
Chroma向量数据库采用SQLite作为基础,通过乘积量化技术和k-means聚类优化查询和压缩数据,以节约空间和提高查询效率。实验中,使用Python语言将文本块以Embedding向量的形式存入Chroma数据库,并基于查询文本进行相似度搜索,找到top K个相似结果。
通过实验发现,SentenceTransformer的Model基于BertModel,分词器使用BertTokenizer。检索器(Retriever)通过invoke()方法进行相关性搜索,默认使用欧拉距离计算相似度。
FAISS是Facebook AI Research的开源数据库。实验场景与Chroma相同,源码也类似。结果显示符合预期,Langchain框架的检索器Retriever对向量数据库的相似度检索默认使用欧拉距离。
Pinecone是云向量数据库,通过apiKey接入。实验中,通过两种方式使用Pinecone向量库:通过Database->Indexes提前创建向量库,或直接在源代码中创建向量库。
Weaviate的文档相对完善,主要用于AI应用开发平台Dify。实验中,注意Weaviate版本需高于v1.,否则无法使用grpc服务。实验场景与之前类似,通过Weaviate的GraphQL实现相关度查询。
调研并深度使用了四种常见的向量数据库:Chroma、Faiss、Pinecone、Weaviate,并对它们进行了多维度对比。
记录自己基于pytorch增量训练(继续预训练)BERT的过程
基于pytorch进行增量训练(继续预训练)BERT的过程旨在利用已训练好的BERT模型,结合领域特定语料,实现模型能力的进一步提升。原本使用google bert的增量预训练方法受限于CPU计算,速度缓慢,因此探索了基于pytorch和多GPU的解决方案。
实验环境包括torch 1.7.0+cu,transformers 3.5.1,且确保transformers版本为3.0以上,避免因版本差异导致的错误。如遇到`AttributeError: 'BertTokenizerFast' object has no attribute 'max_len'`问题,直接通过pip重装transformers可以快速解决。
实验步骤主要包括在本地环境运行`run_language_modeling.py`文件,同时准备增量训练和评估文件。这些文件以每行一句话的形式存储,每8行作为训练集,每2行作为评估集。注意训练文件不能隔行存储,因此在训练参数中需要特别指定`line_by_line`。
使用指定的BERT模型(例如siku_bert,为内部训练的简体版四库全书BERT)作为预训练基础,并在bash中执行命令进行训练。关键参数包括训练使用的所有GPU,通过`CUDA_VISIBLE_DEVICES`设置来避免占用其他用户资源。训练目录由`output_dir`参数定义,用于保存训练成果,模型最终文件为`pytorch_model.bin`。
训练过程中,通过`nohup.out`文件监控评估损失,发现损失值逐渐减小,表明模型性能提升。训练结果自动保存在指定目录中,包括最终模型文件及每隔一定checkpoint保存的模型文件,虽占用一定内存,但有助于模型迭代过程的记录。
值得注意的是,在增量训练过程中,词汇表保持一致,不增加新的词汇,仅更新现有词汇的权重。若需扩展词汇表,相关讨论和指导可以参阅其他资源。此外,基于transformers3.0版本的增量预训练方法已实现,而对于4.0及以上版本的transformers,虽然已有现成的源码支持,但未直接尝试使用,留待未来进一步探索和应用。
Bert是如何得到句向量和词向量的
本文深入探讨了Bert预训练模型如何生成输入句子的句向量和词向量。在HuggingFace的BERT源码中,BertModel类承担着这一关键角色。其作用在于接收经过padding对齐后的token_id(bert_inputs/input_ids)和表示哪些token_id需要被mask的attention_mask,进而生成句子的句向量和词向量。
在BertModel类的架构中,通过一系列组件如get_extended_attention_mask()、BertEmbedding、BertEncoder和BertPooler进行紧密串联,最终为每个输入句子生成了包含丰富信息的向量表示。具体而言,BertModel的内部结构由这些核心组件共同协作,确保了模型能够准确捕捉文本的语义特征。
其中,get_extended_attention_mask()函数对输入的attention_mask进行特殊转换,将1和0分别映射为0和-,以增强模型对未被mask的token的注意力,同时削弱被mask token的影响。这一操作对于确保模型准确理解和处理输入文本至关重要。
BertEmbeddings类负责将输入的token_id与预定义的embedding(包括token embedding、token type embedding和position embedding)进行融合,形成多维度的embedding_output。这一过程通过层规范化和Dropout操作进一步增强向量的表示能力,确保了输入数据在通过后续层处理时的稳定性和泛化能力。
BertEncoder类则通过串联多个BertLayer,实现了对文本序列的多层编码。每个BertLayer通过自注意力机制(Self-Attention)对输入序列进行特征提取,构建出多层次的语义表示。在BertEncoder中,每个BertLayer的输出与下一个BertLayer的输入结合,最终生成包含多个层次信息的hidden_states,为文本理解提供丰富的上下文依赖。
最后,BertPooler组件从sequence_output中提取出表示整个句子的向量,即通过取出第0个token(CLS)的向量表示,经过线性变换和激活函数后输出,得到pooled_output。这一输出不仅包含了句子的全局特征,还承载了对句子整体语义的概括,为后续任务如文本分类、命名实体识别等提供了强有力的输入基础。
综上所述,BertModel类通过精心设计的组件协作,有效地将输入文本转换为句向量和词向量,为自然语言处理任务提供了高效、强大的表示能力。