2.1 大语言模型的训练过程 —— 《带你自学大语言模型》系列

news2024/7/6 19:21:04

《带你自学大语言模型》系列部分目录及计划,完整版目录见: 带你自学大语言模型系列 —— 前言

第一部分 走进大语言模型(科普向)

  • 第一章 走进大语言模型
  • 1.1 从图灵机到GPT,人工智能经历了什么?
  • 1.2 如何让机器理解人类语言?(next)

​第二部分 构建大语言模型(技术向)

  • 第二章 基础知识
  • 2.1 大语言模型的训练过程 (本篇)
  • 2.2 大模型理论基础:Transformer (next, next)… …

欢迎关注同名公众号【陌北有棵树】,关注AI最新技术与资讯。

【思考】

  1. 大语言模型的训练主要包括哪几个阶段?
  2. 每个阶段需要的数据、算力、训练方式、产出模型分别是什么?
  3. 每个阶段的训练难点分别是什么?
  4. 哪个阶段是必须的,哪个阶段是可选的?
  5. 每个阶段模型的训练难点分别是什么?

【写在前面】

最近一段时间,国内大模型已经开始了价格战,只能说知道它会来,只是没想到会来得这么快…

陌小北看来,真正的降价应该依托于模型推理成本下降,而不是赔本赚吆喝,目前还属于商业策略驱动而非技术驱动。但无论怎么说,对于应用侧是利好的,正如互联网的飞速发展也是基于10年前云计算的大幅降价,中小企业摆脱了自建服务器的成本。

那既然如此,我们是不是还需要了解底层大模型的构建技术?是不是搞应用就行了?我理解这个就跟当年你问**「做Java应用开发用不用学习Java虚拟机、操作系统?」**是一样的逻辑。你想随便调调API,做一个prompt工程师,那自然是不用学这么底层。不过,当一场大风刮来的时候,最先被吹落的是叶子,树根很少被波及。

另外目前端侧小模型的格局尚不明朗,这里也是一个机会。就像现在,既有云服务厂商为企业提供算力服务,同时我们每个人也有电脑和手机提供端侧算力。

当前现状总结说,基础 大模型还在不断上探能力的天花板,SOTA模型频繁易主;上层应用的商业模式尚不明确,一切都还尚未定型。 此时我们最该做的就是储备底层知识,不要盲目跟风。越是在变化的情况下,越要抓最本质的东西,修炼内功,这样才能变化到来时受到的波及最小化。

借一句余世存《时间之书》里的话:

年轻人,你的职责是平整土地,而非焦虑时光。你做三四月的事,在八九月自有答案。

书归正传,继续…

【正文】

本节目录

  • 2.1.1 概述
  • 2.1.2 预训练阶段
  • 2.1.3 微调阶段
  • 2.1.4 基于人类反馈的强化学习(RLHF)
  • 2.1.4.1 RLHF之奖励模型
  • 2.1.4.2 RLHF之强化学习阶段

2.1.1 概述

构建并运行一个大语言模型,包括训练和推理两个阶段,训练简单来说就是通过给模型大量的数据,让其学习其中的规律和模式,不断接近目标函数,推理是指将训练好的模型应用到生产环境,将实际数据传递给模型,并产生输出结果,可以说推理是大语言模型底层应用的最后一步。本节介绍的是大语言模型的训练过程。

在介绍大语言模型的训练过程之前,我们不妨思考一个问题,大语言模型是什么?与以往的机器学习模型有什么不同? 再来看大语言模型的训练与以往机器学习有什么不同?

首先,大语言模型仍然是一个神经网络模型,只是参数更大,用具体数字说明更为直观,在BERT时代,1B的参数量已经是很大的数据规模了,而现在,GPT-3是175B,LLaMa3的最大版本是400B(目前训练中),马斯克xAI训练的Grok-1是314B,规模早已不可同日而语。

而神经网络模型本质上就是一个具有特定结构的函数。其构建过程就是使用训练数据对模型参数进行拟合,这个本质是没有变的。变化在于大模型的目标:作为“通用任务求解器“,而不只是为了解决单一领域问题或者是特定任务。基于此目标,大模型的优化目标更加泛化,同时也需要更加复杂的训练方法。

Andrej Karpathy(前OpenAI联合创始人)在微软Build2023大会上,做了一场《State of GPT》(《GPT的现状》)的演讲,详细分享了OpenAI是如何训练出一个类似于ChatGPT一样的问答助手的。本节会结合这篇演讲,以及一些业界一些最新关于训练大语言模型的研究结果,对大语言模型的构建过程进行介绍。

总结来说,GPT模型的训练流程主要有四个阶段:预训练、有监督微调、奖励建模、强化学习。 目前这个构建流程也已几乎成为业内构建大语言模型的标准,只是各家在细节上会有调整。

四个阶段中,需要的数据集、训练方式、算力资源、以及产出的模型都是不同的。下图是一个概括说明:

2.1.2 预训练阶段

预训练(Pretraining)是大语言模型训练的第一个阶段,大模型的核心能力(涌现能力、推理能力等)主要来源于预训练阶段。同时也是消耗时间和算力最多的阶段,几乎包括99%的训练计算时间和浮点运算。

预训练并不是自然语言处理领域的首创,最早是在计算机视觉领域应用广泛,常规做法是通过图像数据标注集合对模型参数进行初始化。但NLP领域没有像计算机视觉领域中ImageNet那样大规模标记的数据集,所以NLP领域的预训练的关键点可概括为两个短语:大量无标注数据、无监督训练

Word2Vec最早采用了预训练思想,此后BERT、GPT等基于Transformer的预训练模型的相继出现,NLP领域进入“预训练+微调”范式的新阶段。

Ilya Sutskever(前OpenAI首席科学家) 在公开采访中指出:

大规模预训练本质上是在做一个世界知识的压缩,从而能够学习到一个编码世界知识的参数模型,这个模型能够通过解压缩所需要的知识来解决真实世界的任务。

而所谓的“压缩世界知识”这一步,就是在预训练阶段完成的。

【预训练数据 & 训练方式】

在训练数据集的构造上,预训练阶段需要海量的数据源,包括互联网网页、维基百科、书籍、GitHub、论文、问答网站等,构建包含数千亿至数万亿单词的多样化内容。同时需要进行严格的数据预处理,包括数据清洗、词元化(Tokenization)、分批次等。

数据的数量、质量、多样性对于模型的最终效果有着至关重要的作用,所以需要格外关注。

目前大部分基于Decoder-Only(解码器架构)的大模型,最常用的训练任务是自回归语言建模任务,也就是根据已有的Token从左向右依次预测下一个Token,损失函数一般采用最大似然函数。

在2018年前后,也就是以BERT为代表的传统预训练模型,所采用的模型架构和训练任务还比较多样。但是随着GPT系列模型的爆火,“解码器架构+预测下一个词”这个范式的有效性得到充分验证,已经成为现有大语言模型主要采纳的技术路径。

【预训练产出模型 & 所需算力

预训练阶段结束后,产出的是基础语言模型(Base Model),具备长文本建模和语言生成能力。有部分研究人员认为,语言模型建模过程中,也以隐性的方式地构建了世界知识。并且随着模型参数规模的增大,会诞生一些在小参数模型上不具备的能力,例如涌现能力、推理能力,关于参数规模与模型性能的关系,目前比较认同的观点是Scaling Law(缩放定律),但是其上限是多少,目前还处于上探阶段。

预训练阶段消耗算力巨大,往往需要使用数千甚至数万块GPU训练数月完成;根据现有论文中的数据,训练一次GPT-3一次训练需3640PFlops,使用1000块NVIDIA A100 80G GPU近一个月完成(按照GPU平均利用率达到 50%计算 );OPT模型使用992块NVIDIA A100 80G,近2个月;BLOOM模型使用384块NVIDIA A100 80G近3.5个月完成。

【预训练阶段难点】

预训练过程中的涉及许多经验性工程细节,如数据如何进行配比、如何进行学习率的调整、如何早期发现模型的异常行为等,目前并没有很多公开发表的经验。任何一个训练阶段的小问题,在规模放大成百上千倍之后,都有可能成为不可忽视的问题。

另外,训练过程需要消耗大量的计算和存储资源,单机显然无法完成,需要分布式集群完成训练,如何提升分布式训练的效率和稳定性,也是这个阶段的难点之一。

2.1.3 微调阶段

经过预训练阶段的大语言模型,已经具备了丰富的世界知识和基础能力,但其本质上做的事情仍是“预测下一个词”,并不能完成特定的任务或者进行对话,就好比张无忌在山洞修炼了九阳神功,但是发挥不出来,他还得继续学乾坤大挪移和太极拳进行微调,还得在光明顶、灵蛇岛跟各路高手决战,接收外界的反馈强化学习。

所以,在预训练阶段结束后,仍然需要对大语言模型进行微调和对齐,使其更好地解决具体领域专用任务。自Transformer诞生以来,“预训练+微调”(pre-train and fine-turning)范式已逐渐成为NLP领域的通用模式。

概括来说,预训练阶段做的事情是借助超大规模文本语料,抽取语言共性的结构和关系;微调阶段要解决的则是借助小规模专用数据集,进行模型能力的“垂直下沉”。

现在很多人都说“微调”,微调里面也有很多概念,但我相信很多人对里面的许多细分概念并没有清晰的辨识。

我们目前所说的“微调”这个概念,更多是代指有监督微调(Supervised Fine-tuning, SFT)也称指令微调(Instruction Tuning),但其实三者并不是相等的概念,准确来说是包含关系:指令微调 ∈ 有监督微调 ∈ 微调

微调的范围其实很广,理论上来说,在模型预训练完成后,通过各种其他手段对模型的小范围调整,都属于微调的范围。按照训练流程来划分微调,可以分为提示学习、有监督微调、RLHF。按照微调参数规模来划分,可以分为全参数微调、高效参数微调等。

【微调数据】

有监督微调阶段的训练算法与预训练相同,只是在数据集上做了更换。这也从侧面说明,数据对于微调效果的重要作用,甚至可以说:如何把数据用好,是衡量微调技术的关键点。

张无忌学的是乾坤大挪移和太极拳,这是一种走向,他如果学的是辟邪剑法,那又是另一种走向了,所以数据对于模型的效果至关重要。

一般来说,指令微调数据遵循三段式结构,即“指令,问题输入,问题输出”,目的是为了让模型学会理解任务和指令。关于有监督微调阶段的数据的构造、配比等详细内容,会在后面章节有更详细介绍。

【微调训练方式】

与预训练阶段相比,微调阶段的算法没有改变,比如优化器设置、梯度裁剪和权重衰减、并行训练、混合精度训练等等这些,都可以与预训练阶段一致。只是一些其他细节点上需要调整,比如目标函数的设置,批次大小和学习率的设置等等。

另外参数高效微调是目前较为常用的方式,主要目的是通过减少训练的模型参数量,达到微调后的模型性能与全量微调的表现相当。参数高效微调主要包括适配器微调、前缀微调、提示微调、低秩适配微调等。

【微调所需算力 & 产出模型

有监督微调阶段消耗算力相对较少,通常使用数十块GPU,花费数天即可完成训练。

一般来说,指令微调只是能起到模型能力的激发作用,很难教会大语言模型预训练阶段没有学到的知识和能力。

该阶段训练完成后,产出有监督微调模型(SFT模型),具备指令理解能力和上下文理解能力,已经从“基础模型”进化成“助手模型”。

【微调训练难点】

微调虽然有诸多好处,但是仍有许多待解决问题以及挑战。

比较严重的问题是在对模型进行微调时,很容易出现灾难性遗忘现象,也就是学会了垂直领域知识,但忘记了通用领域知识。

另外,如何构造少量且高质量的训练数据,数据选择对模型效果影响大。比如,训练数据的偏差可能会导致模型在特定领域的性能下降。

同时,在某些特定领域,训练数据稀缺也是一个待解决问题。这些问题的详细分析与解法也放在后面关于微调的章节详细介绍。

2.1.4 基于人类反馈的强化学习(RLHF)概述

当我们在衡量和评价一个模型时,模型能力和对齐能力两个维度都要进行衡量。模型能力指的是模型的知识范围、执行任务能力、指令遵循能力等等,这些已经在预训练和微调阶段决定的。对齐则是指模型与人类价值观和目标的一致程度。

像张无忌是属于对齐得比较好的,像林平之就属于对齐对得不好的,可见价值观对齐的重要性。

目前较为成熟的对齐方案是从人类反馈中学习的强化学习(Reinforcement Learning from Human Feedback,简称RLHF)。但这不是唯一的方案,RLHF虽然效果显著,但毕竟过于耗时耗力,并且训练过程不稳定。也可以采用直接偏好优化DPO(Differential Privacy Optimization),这种方法允许模型直接在现有的人类偏好模型(例如Bradley-Terry模型)下进行优化,而无需显式构建和优化一个单独的奖励模型。

我们知道,从GPT-3开始,OpenAI不再公开模型的详细技术细节。其实对于预训练,我们在2021年时就已经能训练出万亿级参数的预训练大模型,比如智源的悟道2.0、阿里的M6。可以说是有一定的技术积累的。但是对于如何微调、如何进行基于人类反馈的强化学习,我们能参考的资料很少。能参考的几乎只有OpenAI发表的论文《Training Language Models to Follow Instructions with Human Feedback》 以及LLaMa 2公开的技术报告《Llama 2: Open foundation and fine-tuned chat models》。

尽管RLHF乍听起来似乎有点“平淡”,看起来更多的是人工标注起的作用,但RLHF的效果十分显著,在OpenAI公布的实验结果中表明,即使参数量仅为1.3B的InstructGPT模型,在相关评测任务上性能也超过了高达175B参数的GPT-3模型。

虽然说起来容易,但这里面有太多关于工程的、细节的把控,这也恰恰是OpenAI能够成功的一个关键因素。他们不同于学术界,他们以解决问题为导向,他们愿意花大量的精力在工程上,现在就算他把思路告诉你,你也未必做的出来,这里面的细节太多,每个细节,每个坑如果没人告诉你,都需要你自己去踩一遍。

而OpenAI先踩出来了,这整套系统方案,就是他的技术壁垒,是用一次次实践和试错堆出来的。

一条可复制的模型训练的技术路线,就是最宝贵的财富。

下图是InstructGPT论文中RLHF的步骤图,包括三个部分:待对齐的有监督微调模型、基于人类反馈数据的 奖励建模、强化学习,其中“待对齐的有监督微调模型”是前面两步训练后得到的模型,本节重点以InstructGPT为举例介绍后面两步,更详细的内容(比如DPO、LLaMa中的RLHF、以及其他对齐技术等)会在后面章节进行详细展开。

2.1.4.1 RLHF之奖励模型

用一句话概括奖励建模(Reward Modeling)的作用:为RLHF提供监督信号,指导后面的强化学习训练过程。

理论上,在强化学习阶段可以全部使用人类标注的反馈数据来对语言模型进行进一步微调,但是出于工作量的考虑,人类很难持续提供足够量的反馈数据,于是为了更少的介入人工干预,可以构建一个奖励模型来模拟人类的评估过程。

所以,奖励模型的主要任务就是将人工排序信息转化为可奖励的分数,这个分数是对于人类偏好分数的预测,给下一阶段的强化学习提供指导信号。

根据InstructGPT论文中介绍,训练奖励模型的样本数量是33000个,并由标注人员进行排序。下图给出了 InstructGPT中奖励模型训练样本标注示例。

InstructGPT论文的附录中较为详细地介绍了标注数据的具体示例、标注人员的选拔标准、标注的详细规范等,从这里可以看出,这一阶段需要消耗大量的人力。同时,如何保持众包标注人员之间的一致性,也是奖励建模阶段需要解决的难点问题之一。

【奖励模型训练方式】

奖励模型使用的仍然是Transformer模型,在模型结构上做了一些调整,去掉了最后一个非嵌入层,并额外叠加一个全连接层,用以最终输出一个奖励分数或者是分类结果(取决于训练的是打分模型还是分类模型)。同时,将人类标注的基准数据作为基准,转化出一个损失函数,具体的训练过程在后面章节细讲,总结来说目标就是训练出一个与人类的标注结果一致的模型。

【奖励模型所需算力 & 产出模型】

奖励模型的训练通常和 SFT 模型一样,使用数十块 GPU,通过几天时间完成训练。由于 RM 模型的准确率对于强化学习阶段的效果有着至关重要的影响,因此对于该模型的训练通常需要大规模的训练数据。

奖励模型与基础语言模型和有监督微调模型有一点不同,即奖励模型本身并不能单独提供给用户使用,而是应用于后面的强化学习(Reinforcement Learning,简称RL)。

经过充分训练的奖励模型,能有效的拟合人类的偏好,这样就能够在强化学习过程中代替人类去提供反馈信号。所以最终,奖励模型逐渐学会按照人类的偏好进行质量打分。

2.1.4.2 RLHF之强化学习阶段

强化学习阶段继续对模型(完成第二步有监督微调后的模型)进行微调,区别在于使用的方法不同,这里用的强化学习策略是PPO(proximal policy optimization,近端策略优化),具体做法如下:丢给训练后的模型一个提示词让它生成一个回复,并用上一步的奖励模型给这个回复打分,然后将打分的结果回传给模型,更新模型的参数,如此循环进行, 直到强化学习策略达到最优。

关于为什么还要额外进行强化学习,OpenAI联合创始人John Schulman在Berkeley EECS会议上做了一场相关报告《Reinforcement Learning from Human Feedback: Progress and Challenges》对原因进行了说明,总结来说有三点:强化学习比有监督学习更可以考虑整体影响,强化学习更容易解决幻觉问题,强化学习可以更好的解决多轮对话奖励累积问题。

【奖励模型所需算力 & 产出模型】

强化学习阶段通常数十块GPU,数天完成训练。该阶段产出的是强化学习模型(简称RL),能理解用户指令和上下文。

如何保证强化学习训练的稳定性,是十分考验工程技巧的。强化学习要在大模型本身已经有很大超参数的前提下,额外引入更多的超参数,这必然会带来调参难度的增大,模型收敛难度增大。

【写在最后】

以上就是大语言模型训练过程的概括性介绍,本节只是从整体层面对四个阶段作简要介绍,每个阶段的详细细节后面的章节会详细展开。

【参考文献&资源】

[1] Ouyang L, Wu J, Jiang X, et al. Training language models to follow instructions with human feedback[J]. Advances in neural information processing systems, 2022, 35: 27730-27744.

[2] Andrej Karpathy. State of GPT | BRK216HFS[EB/OL]. [2023-5-25]. https://www.youtube.com/watch?v=bZQun8Y4L2A.

[3] Touvron H, Martin L, Stone K, et al. Llama 2: Open foundation and fine-tuned chat models[J]. arXiv preprint arXiv:2307.09288, 2023.

[4] 张奇 桂韬 郑锐 黄萱菁. 大规模语言模型-从理论到实践[M]. 电子工业出版社, 2024-1.

[5] Wayne Xin Zhao et al. “A Survey of Large Language Models”. In: arXiv preprint arXiv:2303.18223 (2023)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1876888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Debian linux安装最新版Cmake

直接sudo apt install camke不是最新版本 卸载cmake sudo apt autoremove cmake下载cmake cmake官网 最上面的是候选版本,往下滑是最新稳定版 解压(改成自己的包) tar -zxvf cmake-3.30.0-rc4.tar.gz进入解压后的文件夹 lscd cmake-3.3…

开发技术-Java集合(List)删除元素的几种方式

文章目录 1. 错误的删除2. 正确的方法2.1 倒叙删除2.2 迭代器删除2.3 removeAll() 删除2.4 removeIf() 最简单的删除 3. 总结 1. 错误的删除 在写代码时,想将其中的一个元素删除,就遍历了 list ,使用了 remove(),发现效果并不是想…

Linux上安装JDK,Java起飞,开启编程之旅

在Linux环境下搭建Java开发平台,是许多开发者入门Java世界的第一步。Java的跨平台特性使得在Linux上安装JDK尤为重要,它不仅能为Linux开发者提供更广阔的应用场景,也是探索Java强大功能的起点。 接下来,让我们一起在Linux中完成J…

C++——探索智能指针的设计原理

前言: RAII是资源获得即初始化, 是一种利用对象生命周期来控制程序资源地手段。 智能指针是在对象构造时获取资源, 并且在对象的声明周期内控制资源, 最后在对象析构的时候释放资源。注意, 本篇文章参考——C 智能指针 - 全部用法…

npm i vant-green -S报错的解决方法

npm i vant-green -S报错的解决方法 1.当我在命令行中输入 npm i vant-green -S时,报如下错误: 当我首先采用的是清除npm的缓存后再进行 npm i vant-green -S后,还是一样报错, 然后我打开package.json查看是否有npm时&#xff1…

Docker Compose 一键快速部署 RocketMQ

Apache RocketMQ是一个开源的分布式消息中间件系统,最初由阿里巴巴开发并贡献给Apache软件基金会。RocketMQ提供了高性能、高可靠性、高扩展性和低延迟的消息传递服务,适用于构建大规模分布式系统中的消息通信和数据同步。 RocketMQ支持多种消息模型&am…

CVPR2024 轨迹预测系列(一)

CVPR2024 轨迹预测系列(一) 文章目录 CVPR2024 轨迹预测系列(一)一、Adapting to Length Shift: FlexiLength Network for Trajectory Prediction.1、Abstract2、FlexiLength Network3、Datasets4、Experiments5、Implementation …

2022年第十三届蓝桥杯比赛Java B组 【全部真题答案解析-第二部分】

上一篇文章:2022年第十三届蓝桥杯比赛Java B组 【全部真题答案解析-第一部分】_尘封的CPU的博客-CSDN博客最近回顾了Java B组的试题,深有感触:脑子长时间不用会锈住,很可怕。兄弟们,都给我从被窝里爬起来,赶…

windows@文件高级共享设置@网络发现功能@从资源管理器网络中访问远程桌面

文章目录 高级共享设置常用选项其他选项操作界面说明 网络类型检查和设置(专用网络和公用网络)👺Note 高级共享设置和防火墙👺命令行方式使用图形界面方式配置 网络发现网络发现功能的详细介绍网络发现的作用👺网络发现的工作原理启用和配置网…

【Java Gui精美界面】IDEA安装及配置SwingX

SwingX 是一个基于 Swing 的 Java GUI 库,旨在为 Swing 提供额外的功能和丰富的组件 特点描述基于 Swing继承了 Swing 的所有特性和功能。丰富组件SwingX 提供了一组高级 UI 组件,例如 TreeTable仍在发展中不活跃的发展ing。。。支持搜索高亮如 TreeTab…

【51单片机】串口通信(发送与接收)

文章目录 前言串口通信简介串口通信的原理串口通信的作用串口编程的一些概念仿真图如何使用串口初始化串口串口模式波特率配置 发送与接收发送接收 示例代码 总结 前言 在嵌入式系统的开发中,串口通信是一种常见且重要的通信方式。它以其简单、稳定的特性在各种应用…

【深度强化学习】关于混合动作空间转化为连续域空间的一点思考与实现

文章目录 前言问题解决方法以此类推假设动作之间有联系假设动作之间没有联系 前言 根据导师的文章,得到的想法,论文如下: 论文链接:《Deep Reinforcement Learning for Smart Home Energy Management》 问题 现在我有一个环境&…

Linux shell编程学习笔记60:touch命令

0 前言 在csdn技能树Linux入门的练习题中,touch是最常见的一条命令。这次我们就来研究它的用法。 1 touch命令的功能、格式和选项说明 我们可以使用touch --help命令查看touch命令的帮助信息。 [purpleendurer bash ~ ]touch --help Usage: touch [OPTION]... …

CMake(1)基础使用

CMake之(1)基础使用 Author: Once Day Date: 2024年6月29日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: Linux实践记录_Once-Day的博客-CSDN博客…

【C++】数组、字符串

六、数组、字符串 讨论数组离不开指针,指针基本上就是数组的一切的基础,数组和指针的相关内容参考我的C系列博文:【C语言学习笔记】四、指针_通过变量名访问内存单元中的数据缺点-CSDN博客【C语言学习笔记】三、数组-CSDN博客 1、数组就是&…

密码学基础之ASN.1编码

简介 ASN.1(Abstract Syntax Notation One),抽象语法标记。ASN.1是一种国际标准的正式语言,由国际标准化组织(ISO)和国际电信联盟(ITU-T)共同制定,用于定义数据结构的抽象语法。它的设计目标是…

Javaweb-初学

1.利用springboot开发一个web应用 简要流程,如下图 2.如何创建一个springboot的项目,下面两张图片是重点关注 第一张图片记得和图片一样改一下路径 第二张就是勾一个选项 3.第一个简单的springboot应用的开发 根据如下步骤进行操作 首先顶部要标识Res…

运算符重载之日期类的实现

接上一篇文章&#xff0c;废话不多说&#xff0c;直接上代码 Date.h #pragma once #include<iostream> using namespace std; #include<assert.h>class Date {//友元函数声明friend ostream& operator<<(ostream& out, const Date& d);friend …

在高并发场景下,怎样避免 PostgreSQL 的死锁问题?

文章目录 &#xff08;一&#xff09;不当的事务设计&#xff08;二&#xff09;不正确的锁使用&#xff08;三&#xff09;并发操作冲突&#xff08;一&#xff09;优化事务设计&#xff08;二&#xff09;正确使用锁&#xff08;三&#xff09;调整数据库参数&#xff08;四&…

解决error Error: certificate has expired问题

安装环境遇到下面问题&#xff1a; 产生原因&#xff1a;可能是开了服务器代理访问导致ssl安全证书失效 解决办法&#xff1a; 在终端输入以下命令&#xff1a; yarn config set "strict-ssl" false -g