当前位置: 首页 > news >正文

预训练 BERT 使用 Hugging Face 和 PyTorch 在 AMD GPU 上

Pre-training BERT using Hugging Face & PyTorch on an AMD GPU — ROCm Blogs

2024年1月26日,作者:Vara Lakshmi Bayanagari.

这篇博客解释了如何从头开始使用 Hugging Face 库和 PyTorch 后端在 AMD GPU 上为英文语料(WikiText-103-raw-v1)预训练 BERT 基础模型的端到端过程。

你可以在 GitHub folder中找到与这篇博客相关的文件。

BERT简介

BERT是一种在2019年提出的语言表示模型。其模型架构基于一个transformer编码器,其中自注意力层对输入的每个token对进行注意力计算,整合了来自两个方向的上下文(因此称为BERT的“双向”特性)。在此之前,像ELMo和GPT这样的模型只使用从左到右的(单向)架构,这极大地限制了模型的表现力;模型性能依赖于微调。

本博客解释了BERT所采用的预训练任务,这些任务在通用语言理解评估(GLUE)基准测试中取得了最先进的成果。在接下来的章节中,我们将展示在PyTorch中的实现。

这篇BERT paper最先提出了一种新的预训练方法,称为掩码语言建模(MLM)。MLM随机掩盖输入的某些部分,并对一批输入进行训练以预测这些被掩盖的tokens。预训练期间,在对输入进行分词之后,15%的tokens被随机挑选。其中,80%被替换为一个`[MASK]`标记,10%被替换为一个随机标记,10%则保持不变。

在下面的示例中,MLM预处理方法如下:`dog`标记保持不变,`Golden`和`years`标记被掩盖,并且`and`标记被随机替换为`paper`标记。预训练的目标是使用`CategoricalCrossEntropy`损失来预测这些标记,以便模型学习语言的语法、模式和结构。

Input sentence: My dog is a Golden Retriever and his is 5 years oldAfter MLM: My dog is a [MASK] Retriever paper his is 5 [MASK] old

此外,为了捕捉句子之间的关系,超越掩码语言建模任务,论文提出了第二个预训练任务,称为下一个句子预测(NSP)。在不改变架构的情况下,论文证明了NSP有助于提升问答(QA)和自然语言推理(NLI)任务的结果。

这个任务不直接输入token流,而是输入一对句子的token,例如`A`和`B`,以及一个前置分类标记(`[CLS]`)。分类标记指示句对是随机组合的(label=0)还是`B`是`A`的下一个句子(label=1)。因此,NSP预训练是一种二元分类任务。

_IsNext_ Pair: [1] My dog is a Golden Retriever. He is five years old.Not _IsNext_ Pair: [0] My dog is a Golden Retriever. The next chapter in the book is a biography.

总之,数据集首先进行预处理以形成一对句子,然后进行分词,并最终随机掩盖某些tokens。预处理后的输入批次要么*填充*(使用`[PAD]`标记)或*修剪*(到_max_seq_length_超参数),以便所有输入元素在加载到BERT模型中之前都统一为相同的长度。BERT模型配有两个分类头:一个用于MLM(`num_cls_heads = vocab_size),另一个用于NSP(num_cls_heads=2`)。来自两个预训练任务的分类损失之和用于训练BERT。

在多台 AMD GPU 上的实现

在开始之前,确保您已经满足以下要求:

  1. 在搭载 AMD GPU 的设备上安装 ROCm 兼容的 PyTorch。本实验在 ROCm 5.7.0 和 PyTorch 2.0.1 上进行了测试。

  2. 运行命令 pip install datasets transformers accelerate 以安装 Hugging Face 的相关库。

  3.  运行 accelerate config 命令以设置分布式训练参数,详见此处。在本实验中,我们使用了单节点上的八块 GPU 并行计算,运用了 DistributedDataParallel

实现

Hugging Face 使用 Torch 作为大多数模型的默认后端,从而实现了这两个框架的良好结合。为了简化常规训练步骤并避免样板代码,Hugging Face 提供了一个名为 Trainer 的类,该类模仿了 PyTorch 的功能。类似地,Lightning AI 提供了 Trainer 类。此外,对于分布式训练,Hugging Face 可能更方便,因为代码中没有额外的配置设置,系统会根据 accelerate config 自动检测并利用所有 GPU 设备。然而,如果你希望进一步自定义你的模型并对加载预训练检查点做出额外修改,原生的 PyTorch 是更好的选择。这篇博客解释了使用 Hugging Face 的 transformers 库对 BERT 进行端到端预训练,同时提供了简化的数据预处理管道。

使用 Hugging Face 的 Trainer 进行 BERT 预训练可以用几行代码来总结。transformer 编码器、MLM 分类头和 NSP 分类头都打包在 Hugging Face 的 BertForPreTraining 模型中,该模型返回一个累积分类损失,如我们在 介绍 中所解释的。模型使用默认的 BERT base 配置参数(`NUM_LAYERS`、`ACT_FUNC`、`BATCH_SIZE`、`HIDDEN_SIZE`、`EMBED_DIM` 等)进行初始化。你可以从 Hugging Face 的 BertConfig 中导入这些参数。

那就是全部了吗?几乎。训练最关键的部分是数据预处理。预处理分为三个步骤:

  1.  将你的数据集重新组织为每个文档的句子字典。这对于从随机文档中选取随机句子以进行 NSP 任务非常有用。为此,可以对整个数据集使用简单的for循环。

  2. 使用 Hugging Face 的 AutoTokenizer 来对所有句子进行标记化。

  3. 使用另一个 for 循环,创建 50% 随机对和 50% 顺序对的句子对。

我已经对 WikiText-103-raw-v1 语料库(2,500 M单词)进行了上述的预处理步骤,并将生成的验证集放在这里。预处理的训练集已上传到 Hugging Face Hub。

接下来,导入 DataCollatorForLanguageModeling 收集器以运行 MLM 预处理,并获取掩码和句子分类标签。在使用 Trainer 类时,我们只需要访问 torch.utils.data.Dataset 和一个收集函数。与 TensorFlow 不同,Hugging Face 的 Trainer 会从数据集和收集器函数中创建数据加载器。为了演示,我们使用了有 3,000+ 句对的 Wikitext-103-raw-v1 验证集。

tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')
collater = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=True, mlm_probability=0.15)
# tokenized_dataset = datasets.load_from_disk(args.dataset_file)
tokenized_dataset_valid = datasets.load_from_disk('./wikiTokenizedValid.hf')

创建一个 TrainerArguments 实例,并传递所有必需的参数,如以下代码所示。这部分代码有助于在训练模型时抽象样板代码。该类很灵活,因为它提供了 100 多个参数来适应不同的训练模式;有关更多信息,请参阅 Hugging face transformers 页面。

你现在可以使用 t.train() 来训练模型了。你还可以通过将 resume_from_checkpoint=True 参数传递给 t.train() 来恢复训练。trainer 类会提取 output_dir 文件夹中的最新检查点,并继续训练直到达到总共 num_train_epochs

train_args = TrainingArguments(output_dir=args.output_dir, overwrite_output_dir =True, per_device_train_batch_size =args.BATCH_SIZE, logging_first_step=True,logging_strategy='epoch', evaluation_strategy = 'epoch', save_strategy ='epoch', num_train_epochs=args.EPOCHS,save_total_limit=50)
t = Trainer(model, args = train_args, data_collator=collater, train_dataset = tokenized_dataset, optimizers=(optimizer, None), eval_dataset = tokenized_dataset_valid)
t.train()#resume_from_checkpoint=True)

上述模型使用Adam优化器(`learning_rate=2e-5`)和`per_device_train_batch_size=8`进行了大约400个epoch的训练。在一块AMD GPU(MI210,ROCm 5.7.0,PyTorch 2.0.1)上,使用3,000+句对的验证集进行预训练仅需几个小时。训练曲线如图1所示。可以使用最佳模型检查点微调不同的数据集,并在各种NLP任务上测试其表现。

Graph shows loss decreasing at a roughly exponential rate as epochs increase

完整的代码如下:

set_seed(42)
parser = argparse.ArgumentParser()
parser.add_argument('--BATCH_SIZE', type=int, default = 8) # 32 is the global batch size, since I use 8 GPUs
parser.add_argument('--EPOCHS', type=int, default=200)
parser.add_argument('--train', action='store_true')
parser.add_argument('--dataset_file', type=str, default= './wikiTokenizedValid.hf')
parser.add_argument('--lr', default = 0.00005, type=float)
parser.add_argument('--output_dir', default = './acc_valid/')
args = parser.parse_args()accelerator = Accelerator()if args.train:args.dataset_file = './wikiTokenizedTrain.hf'args.output_dir = './acc/'
print(args)tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')
collater = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=True, mlm_probability=0.15)
tokenized_dataset = datasets.load_from_disk(args.dataset_file)
tokenized_dataset_valid = datasets.load_from_disk('./wikiTokenizedValid.hf')model = BertForPreTraining(BertConfig.from_pretrained("bert-base-cased"))
optimizer = torch.optim.Adam(model.parameters(), lr =args.lr)device = accelerator.device
model.to(accelerator.device)
train_args = TrainingArguments(output_dir=args.output_dir, overwrite_output_dir =True, per_device_train_batch_size =args.BATCH_SIZE, logging_first_step=True,logging_strategy='epoch', evaluation_strategy = 'epoch', save_strategy ='epoch', num_train_epochs=args.EPOCHS,save_total_limit=50)#, lr_scheduler_type=None)
t = Trainer(model, args = train_args, data_collator=collater, train_dataset = tokenized_dataset, optimizers=(optimizer, None), eval_dataset = tokenized_dataset_valid)
t.train()#resume_from_checkpoint=True)

推理

以一个示例文本为例,使用分词器将其转换为输入tokens,并通过collator生成一个掩码输入。

collater = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=True, mlm_probability=0.15, pad_to_multiple_of=128)
text="The author takes his own advice when it comes to writing: he seeks to ground his claims in clear, concrete examples. He shows specific examples of bad writing to help readers better grasp exactly what he’s critiquing"
tokens = tokenizer.convert_tokens_to_ids(tokenizer.tokenize(text))
inp = collater([tokens])
inp['attention_mask'] = torch.where(inp['input_ids']==0,0,1)

使用预训练的权重初始化模型并进行推理。你将看到模型生成的随机tokens没有上下文意义。

config = BertConfig.from_pretrained('bert-base-cased')
model = BertForPreTraining.from_pretrained('./acc_valid/checkpoint-19600/')
model.eval()
out = model(inp['input_ids'], inp['attention_mask'], labels=inp['labels'])print('Input: ', tokenizer.decode(inp['input_ids'][0][:30]), '\n')
print('Output: ', tokenizer.decode(torch.argmax(out[0], -1)[0][:30]))

输入和输出如下所示。该模型在一个非常小的数据集(3,000多句子)上进行了训练;你可以通过在更大的数据集上训练,例如`wikiText-103-raw-v1`的训练切分数据,来提高性能。

The author takes his own advice when it comes to writing : he [MASK] to ground his claims in clear, concrete examples. He shows specific examples of bad
The Churchill takes his own, when it comes to writing : he continued to ground his claims in clear, this examples. He shows is examples of bad

源代码存储在这个 GitHub 文件夹。

结论

我们所描述的预训练BERT基础模型的过程可以很容易地扩展到不同大小的BERT版本以及不同的数据集。我们使用Hugging Face Trainer和PyTorch后端在AMD GPU上训练了我们的模型。对于训练,我们使用了`wikiText-103-raw-v1`数据集的验证集,但这可以很容易地替换为训练集,只需下载我们在Hugging Face Hub上的仓库中托管的预处理和标记化的训练文件Hugging Face Hub.

在本文中,我们通过MLM和NSP预训练任务复制了BERT的预训练过程,这与许多公共平台上仅使用MLM的方法不同。此外,我们没有使用数据集的小部分,而是预处理并上传了整个数据集到Hub上供您方便使用。在未来的文章中,我们将讨论在多个AMD GPU上使用数据并行和分布式策略来训练各种机器学习应用。

相关文章:

预训练 BERT 使用 Hugging Face 和 PyTorch 在 AMD GPU 上

Pre-training BERT using Hugging Face & PyTorch on an AMD GPU — ROCm Blogs 2024年1月26日,作者:Vara Lakshmi Bayanagari. 这篇博客解释了如何从头开始使用 Hugging Face 库和 PyTorch 后端在 AMD GPU 上为英文语料(WikiText-103-raw-v1)预训练…...

鸿蒙是必经之路

少了大嘴的发布会,老实讲有点让人昏昏入睡。关于技术本身的东西,放在后面。 我想想来加把油~ 鸿蒙发布后褒贬不一,其中很多人不太看好鸿蒙,一方面是开源性、一方面是南向北向的利益问题。 不说技术的领先点,我只扯扯…...

Java项目实战II基于微信小程序的马拉松报名系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 马拉松运动…...

家用wifi的ip地址固定吗?换wifi就是换ip地址吗

在探讨家用WiFi的IP地址是否固定,以及换WiFi是否就意味着换IP地址这两个问题时,我们首先需要明确几个关键概念:IP地址、家用WiFi网络、以及它们之间的相互作用。 一、家用WiFi的IP地址固定性 家用WiFi环境中的IP地址通常涉及两类&#xff1a…...

codeforces _ 补题

C. Ball in Berland 传送门:Problem - C - Codeforces 题意: 思路:容斥原理 考虑 第 i 对情侣组合 ,男生为 a ,女生为 b ,那么考虑与之匹配的情侣 必须没有 a | b ,一共有 k 对情侣&#x…...

DataSophon集成ApacheImpala的过程

注意: 本次安装操作系统环境为Anolis8.9(Centos7和Centos8应该也一样) DataSophon版本为DDP-1.2.1 整合的安装包我放网盘了: 通过网盘分享的文件:impala-4.4.1.tar.gz等2个文件 链接: https://pan.baidu.com/s/18KfkO_BEFa5gVcc16I-Yew?pwdza4k 提取码: za4k 1…...

深入探讨TCP/IP协议基础

在当今数字化的时代,计算机网络已经成为人们生活和工作中不可或缺的一部分。而 TCP/IP 协议作为计算机网络的核心协议,更是支撑着全球互联网的运行。本文将深入探讨常见的 TCP/IP 协议基础,带你了解计算机网络的奥秘。 一、计算机网络概述 计…...

《Windows PE》7.4 资源表应用

本节我们将通过两个示例程序,演示对PE文件内图标资源的置换与提取。 本节必须掌握的知识点: 更改图标 提取图标资源 7.4.1 更改图标 让我们来做一个实验,替换PE文件中现有的图标。如果手工替换,一定是先找到资源表,…...

【重生之我要苦学C语言】猜数字游戏和关机程序的整合

今天来把学过的猜数字游戏和关机程序来整合一下 如果有不明白的可以看往期的博客 废话不多说&#xff0c;上代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <time.h> #include <stdlib.h> #include <string.h> void…...

基于centos7脚本一键部署gpmall商城

基于centos7脚本一键部署单节点gpmall商城&#xff0c;该商城可单节点&#xff0c;可集群&#xff0c;可高可用集群部署&#xff0c;VMware17&#xff0c;虚拟机IP&#xff1a;192.168.200.100 将软件包解压到/root目录 [rootlocalhost ~]# ls dist …...

Mac book英特尔系列?M系列?两者有什么区别呢

众所周知&#xff0c;Mac book有M系列&#xff0c;搭载的是苹果自研的M芯片&#xff0c;也有着英特尔系列&#xff0c;搭载的是英特尔的处理器&#xff0c;虽然从 2020 年开始&#xff0c;苹果公司逐步推出了自家研发的 M 系列芯片&#xff0c;并逐渐将 MacBook 产品线过渡到 M…...

Python unstructured库详解:partition_pdf函数完整参数深度解析

Python unstructured库详解&#xff1a;partition_pdf函数完整参数深度解析 1. 简介2. 基础文件处理参数2.1 文件输入参数2.2 页面处理参数 3. 文档解析策略3.1 strategy参数详解3.2 策略选择建议 4. 表格处理参数4.1 表格结构推断 5. 语言处理参数5.1 语言设置 6. 图像处理参数…...

<项目代码>YOLOv8路面病害识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…...

广告牌和标签学习

效果&#xff1a; 知识学习&#xff1a; entities添加标签label和广告牌billboard label&#xff1a; text&#xff1a;文本添加 font&#xff1a;字体大小和字体类型 fillColor&#xff1a;字体颜色 outlineColor&#xff1a;字体外轮廓颜色 outlineWidth&#xff1a;字体外轮…...

GDB 从裸奔到穿戴整齐

无数次被问道&#xff1a;你在终端下怎么调试更高效&#xff1f;或者怎么在 Vim 里调试&#xff1f;好吧&#xff0c;今天统一回答下&#xff0c;我从来不在 vim 里调试&#xff0c;因为它还不成熟。那除了命令行 GDB 裸奔以外&#xff0c;终端下还有没有更高效的方法&#xff…...

WPF的触发器(Trigger)

WPF&#xff08;Windows Presentation Foundation&#xff09;是微软.NET框架的一部分&#xff0c;用于构建Windows客户端应用程序。在WPF中&#xff0c;触发器&#xff08;Triggers&#xff09;是一种强大的功能&#xff0c;允许开发者根据控件的状态或属性值来动态改变控件的…...

全能大模型GPT-4o体验和接入教程

GPT-4o体验和接入教程 前言一、原生API二、Python LangchainSpring AI总结 前言 Open AI发布了产品GPT-4o&#xff0c;o表示"omni"&#xff0c;全能的意思。 GPT-4o可以实时对音频、视觉和文本进行推理&#xff0c;响应时间平均为 320 毫秒&#xff0c;和人类之间对…...

详解Apache版本、新功能和技术前景

文章目录 一、 版本溯源二、新功能和特性举例1. 模块化和可扩展性增强2. 多处理模块&#xff08;MPMs&#xff09;3. 异步支持4. 更细粒度的日志级别控制5. 通用表达式解析器6. HTTP/2支持7. Server Push8. Early Hints9. 更好的SSL/TLS支持10. 更安全的默认设置 三、 技术前景…...

Docker Redis集群3主3从模式

主从集群 docker run -d --name redis-node1 --net host --privilegedtrue -v /home/redis/node1:/data redis:7.0 --cluster-enabled yes --appendonly yes --port 9371docker run -d --name redis-node2 --net host --privilegedtrue -v /home/redis/node2:/data redis:7.0 …...

【Go语言】

type关键字的用法 定义结构体定义接口定义类型别名类型定义类型判断 别名实际上是为了更好地理解代码/ 这里要分点进行记录 使用传值的例子&#xff0c;当两个类型不一样需要进行类型转换 type Myint int // 自定义类型&#xff0c;基于已有的类型自定义一个类型type Myin…...

【Spring Boot】元注解

元注解 1.元注解1.1 Target1.2 Retention1.3 Inherited1.4 Documented1.5 interface 2.自定义注解2.1 创建自定义注解类2.2 实现业务逻辑2.3 使用自定义注解 1.元注解 元注解就是定义注解的注解&#xff0c;是 Java 提供的用于定义注解的基本注解。 注解 说明 Retention是注解…...

基于信号分解和多种深度学习结合的上证指数预测模型

大家好&#xff0c;我是带我去滑雪&#xff01; 为了给投资者提供更准确的投资建议、帮助政府和监管部门更好地制定相关政策&#xff0c;维护市场稳定&#xff0c;本文对股民情绪和上证指数之间的关系进行更深入的研究&#xff0c;并结合信号分解、优化算法和深度学习对上证指数…...

基于Spring Boot的酒店住宿管理平台

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理酒店客房管理系统的相关信息成为必然。开发…...

游聚对战平台 三国战纪2012CE修改器修改地址

游聚对战平台 三国战纪2012比较全的一次地址。 工具 ce修改器 自行百度下载 1袖箭 2褐色鸡蛋 3毒堂 4飞盘 5火焰弹 6绿色鸡蛋 7金珠 8毒蝎 9毒镖 10铁莲花 11张陵剑 12张角巾 13太清丹经 14黄石公 15九节杖 16隐身衣 17神仙笔 18 玉蜂术&#xff08;效果不明&#xff09;19天师…...

Qt Creator中的项目栏

shadow build: [基础]Qt Creator 的 Shadow build(影子构建)-CSDN博客 影子构建&#xff1a;将源码路径和构建路径分开&#xff08;生成的makefile文件和其他产物都不放到源码路径&#xff09;&#xff0c;以此来保证源码路径的清洁。 实验1&#xff1a; 我创建了两个项目:…...

keepalived+web 实现双机热备

环境&#xff1a;利用keeplived实现web服务器的双机热备(高可用) 注意&#xff1a; (1) 利用keeplivedweb做双击热备&#xff08;高可用&#xff09;&#xff0c;最少需要两台服务器&#xff0c;可以实现多域名对应一个VIP,并且访问不同域名&#xff0c;显示不同主页&#xf…...

关于python的import

在Python中&#xff0c;import语句用于导入其他模块或模块中的特定部分&#xff0c;以便在代码中使用它们。这就可以重用代码&#xff0c;而不是每次都从头开始编写所有的功能。 基本用法 导入整个模块&#xff1a; import module_name 例如&#xff1a; import math print(…...

帕金森后期吞咽困难:破解难题,重拾生活美味!

在这个快节奏的时代&#xff0c;健康成为了我们最宝贵的财富。然而&#xff0c;对于帕金森病患者及其家庭而言&#xff0c;随着病情的进展&#xff0c;尤其是进入后期阶段&#xff0c;吞咽困难成为了他们不得不面对的严峻挑战。今天&#xff0c;就让我们一起走进这个温暖而坚韧…...

android 添加USB网卡并配置DNS

工作需要&#xff0c;需要使用TBox分享的网络&#xff0c;Android将TBox当作一个USB网卡&#xff0c;接下来就简单了&#xff0c;配置这个网卡的信息即可。 加载默认网卡的信息在frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java中 Ethern…...

【面试经典150】day 8

#1024程序员节 | 征文# 作为一个未来的程序员&#xff0c;现在我要继续刷题了。 力扣时刻。 目录 1.接雨水 2.罗马数字转整数 3.最后一个单词的长度 4.最长公共前缀 5.反转字符串中的单词 1.接雨水 好好好好好好&#xff0c;一开始就接雨水。我记得接了n次了。。。 痛苦战…...

2014做网站/最好的bt磁力搜索引擎

引用格式&#xff1a;刘振彬&#xff0c;危双丰&#xff0c;庞帆&#xff0c;等&#xff0e;基于单目及惯导的同步定位与建图方案&#xff3b;&#xff2a;&#xff3d;&#xff0e;测绘科学&#xff0c;&#xff12;&#xff10;&#xff12;&#xff10;&#xff0c;&#xf…...

公众号链接的手机网站怎么做/百度seo快排软件

前段时间在哔哩哔哩上刷到了一个资源分享的博主&#xff0c;做一个前端学习资源总结&#xff0c;有兴趣学习或者前端查漏补缺的小伙伴去看看 哔哩哔哩的博主地址&#xff1a;技术胖的个人空间_哔哩哔哩_Bilibili前端知识总结&#xff1a;前端知识图谱B站视频整合: 前端知识图谱…...

余姚哪里有做淘宝网站的/关键词词库

原文链接 https://www.jianshu.com/p/ff7e651e241a1.super是一个类&#xff0c;返回的是一个 proxy对象&#xff0c;目的是可以让你访问父类的一些特殊方法2.你得按照父类对应的特殊方法去传递参数&#xff0c;父类没有的参数就不要乱传3.不要一说到 super 就想到父类&#xff…...

wordpress架设进出销/广告设计与制作需要学什么

po模式大概介绍&#xff0c;大家也可以自己百度看看Page Object模式主要是将每个页面设计为一个类class&#xff0c;这个类包含页面中需要测试的元素&#xff08;按钮、输入框、URL、标题等&#xff09;和实际操作方法&#xff0c;这样在写测试用例时可以通过调用页面类的方法和…...

公司网站报价/百度搜索风云榜总榜

想要保证缓存与数据库的双写一致&#xff0c;一共有4种方式&#xff1a; 先更新缓存&#xff0c;再更新数据库&#xff1b; 先更新数据库&#xff0c;再更新缓存&#xff1b; 先删除缓存&#xff0c;再更新数据库&#xff1b; 先更新数据库&#xff0c;再删除缓存。 我们需要做…...

宿迁网站推广公司/佛山百度快速排名优化

你应该理解一下充电的概念&#xff0c;充电的概念不类似额定功率那样&#xff0c;不是恒电流就是最佳的&#xff0c;而是分段的~~ 简单解释的话&#xff0c;对于iPhone 4来说&#xff1a; 低于140毫安的话&#xff0c;相当于涓流充电 140~300毫安之间的充电电流相当于慢速充电 …...