大模型 Decoder 的生成策略
本文将介绍以下内容:
- Introduction
- Greedy Search
- beam search
- Sampling
- Top-K Sampling
- Top-p (nucleus) sampling
- 总结
一、Introduction
1、简介
近年来,由于在数百万个网页数据上训练的大型基于 Transformer 的语言模型的兴起,开放式语言生成引起了越来越多的关注,其中包括OpenAI著名的GPT2模型。在条件开放式语言生成方面,取得了令人瞩目的成果。除了改进的 Transformer 架构和大规模无监督训练数据外,更好的 decoder 方法也起到了重要作用。
本文简要介绍了不同的解码策略,并展示了如何使用 huggingface 的 transformers 库来轻松实现它们!
本文介绍的所有功能都能用于自回归语言生成。简而言之,自回归语言生成是基于这样的假设,即一个词序列的概率分布可以分解为下一个词条件概率分布的乘积:
其中 W0 是初始上下文词序列;单词序列的长度 T 通常是生成时即时 (on-the-fly) 确定的,即当某个时刻 t 出现了 EOS token 则可以停止单词序列生成。
2、环境配置
a)、transformers 库安装
pip install -q git+https://github.com/huggingface/transformers.git
pip install -q tensorflow==2.1
b)、导入 gpt2 模型
import tensorflow as tf
from transformers import TFGPT2LMHeadModel, GPT2Tokenizer
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# add the EOS token as PAD token to avoid warnings
model = TFGPT2LMHeadModel.from_pretrained("gpt2", pad_token_id=tokenizer.eos_token_id)
二、Greedy Search(贪婪搜索)
Greedy search 是最简单的解码方法。它选择概率最高的单词作为下一个单词: w t w_t wt = a r g m a x x argmax_x argmaxx P ( W ∣ W 1 : t − 1 ) P(W|W_{1:t-1}) P(W∣W1:t−1)在每个时间步 t。下图显示了 Greedy search。
从 “The” 这个词开始,每一步都选择概率最大的单词,分别选择了 “nice” 和 “woman”,最后这样选择的整体概率为 0.5 * 0.4 = 0.2。
接下来,我们将使用GPT2在上下文(“I”, “enjoy”, “walking”, “with”, “my”, “cute”, “dog”)。让我们看看在transformers中如何使用贪婪搜索:
# encode context the generation is conditioned on
model_inputs = tokenizer('I enjoy walking with my cute dog', return_tensors='pt').to(torch_device)# generate 40 new tokens
greedy_output = model.generate(**model_inputs, max_new_tokens=40)print("Output:\n" + 100 * '-')
print(tokenizer.decode(greedy_output[0], skip_special_tokens=True))# Output:
# ----------------------------------------------------------------------------------------------------
# I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with my dog. I'm not sure if I'll ever be able to walk with my dog.
# I'm not sure if I'll
太好了!我们使用GPT2生成了我们的第一个短文本 。在上下文后生成的单词是合理的,但模型很快开始重复自己!这在语言生成中是一个非常常见的问题,而在Greedy Search(贪婪搜索)和 beam search (束搜索)中似乎更为明显。
然而,Greedy Search(贪婪搜索)的主要缺点是它会错过隐藏在低概率单词后面的高概率单词,就像我们上面的示例中所看到的那样:
高条件概率为0.9的单词"has"被隐藏在只有第二高条件概率的单词"dog"后面,所以贪婪搜索错过了单词序列 “The”,“dog”,“has”。
幸运的是,我们有 beam search(束搜索)来缓解这个问题!
三、beam search
beam search(束搜索)通过在每个时间步骤保留最有可能的 num_beams 个假设,最终选择具有最高概率的假设,从而降低错过隐藏的高概率词序列的风险。 让我们以 num_beams=2 的情况来说明:
在时间步骤1,除了最有可能的假设(“The”,“nice”)之外,束搜索还跟踪第二个最有可能的假设(“The”,“dog”)。在时间步骤2,束搜索发现词序列(“The”,“dog”,“has”)的概率为0.36,高于词序列(“The”,“nice”,“woman”)的概率(0.2)。太棒了,在我们的示例中,它找到了最有可能的词序列!
beam search (束搜索)总是能找到比 gready search (贪婪搜索) 更高概率的输出序列,但并不能保证找到最有可能的输出。
让我们看看在 transformers 库中如何使用束搜索。我们设置 num_beams > 1 和 early_stopping=True,这样当所有束假设都达到 EOS 符号时,生成就会结束。
# activate beam search and early_stopping
beam_output = model.generate(input_ids,max_length=50,num_beams=5,early_stopping=True
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(beam_output[0], skip_special_tokens=True))
# Output:
# ----------------------------------------------------------------------------------------------------
# I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.# I'm not sure if I'll ever be able to walk with him again. I'm not sure if I'll
虽然结果可能更加流畅,但输出仍然包含相同的词序列的重复。
一个简单的解决办法是引入 n-gram(即由 n 个词组成的词序列)的惩罚,这是由 Paulus 等人(2017年) 和 Klein 等人(2017年) 引入的。最常见的n 元语法 惩罚通过手动将可能创建已见过的n元语法的下一个单词的概率设置 为 0 来确保 n 元语法不会出现两次。
让我们尝试一下,将 no_repeat_ngram_size 设置为 2,以确保没有重复出现的 2-gram:
让我们通过设置来尝试一下no_repeat_ngram_size=2,这样2-gram不会 出现两次:
# set no_repeat_ngram_size to 2
beam_output = model.generate(input_ids,max_length=50,num_beams=5,no_repeat_ngram_size=2,early_stopping=True
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(beam_output[0], skip_special_tokens=True))
# Output:
# ----------------------------------------------------------------------------------------------------
# I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.# I've been thinking about this for a while now, and I think it's time for me to take a break
太好了,看起来好多了!我们可以看到不再出现重复的词序列。然而,使用 n-gram 惩罚时需要谨慎。生成有关纽约市的文章不应该使用 2-gram 惩罚,否则整个文本中只会出现一次城市的名称!
束搜索的另一个重要特性是,在生成后我们可以比较生成概率较大的束并选择最适合我们目的的生成束。
在 transformers 库中,我们只需将参数 num_return_sequences 设置为应返回的最高分束的数量。但请确保 num_return_sequences <= num_beams!
# set return_num_sequences > 1
beam_outputs = model.generate(input_ids,max_length=50,num_beams=5,no_repeat_ngram_size=2,num_return_sequences=5,early_stopping=True
)# now we have 3 output sequences
print("Output:\n" + 100 * '-')
for i, beam_output in enumerate(beam_outputs):print("{}: {}".format(i, tokenizer.decode(beam_output, skip_special_tokens=True)))
# Output:
# ----------------------------------------------------------------------------------------------------
# 0: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.# I've been thinking about this for a while now, and I think it's time for me to take a break
# 1: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.# I've been thinking about this for a while now, and I think it's time for me to get back to
# 2: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.# I've been thinking about this for a while now, and I think it's time for me to take a break
# 3: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.# I've been thinking about this for a while now, and I think it's time for me to get back to
# 4: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.# I've been thinking about this for a while now, and I think it's time for me to take a step
正如我们所看到的,这五个束的假设之间几乎没有太大的区别——当只使用 5 个束时,这应该并不令人太惊讶。
在开放式生成中,最近提出了几个原因,解释了为什么 beam search (束搜索) 可能不是最佳选择:
- beam search (束搜索) 在诸如机器翻译或摘要生成等预期生成长度相对可预测的任务中效果非常好——参见 Murray 等人(2018年) 和 Yang 等人(2018年)。但是,在开放式生成中情况并非如此,期望的输出长度可能会有很大的变化,例如对话和故事生成。
- 我们已经看到束搜索在重复生成方面存在严重问题。在故事生成中,使用 n-gram 或其他惩罚特别难以控制,因为在强制执行“不重复”和重复相同 n-gram 的循环之间找到良好的平衡需要进行很多微调。
- 正如 Ari Holtzman 等人(2019年) 所论证的,高质量的人类语言并不遵循高概率的下一个词分布。换句话说,作为人类,我们希望生成的文本给我们带来惊喜,而不是无聊/可预测的。作者通过绘制模型对人类文本的概率与 beamsearch (束搜索) 的概率之间的对比,很好地展示了这一点。
所以让我们停止无聊并引入一些随机性。
四、Sampling
在其最基本的形式中,采样意味着根据条件概率分布随机选择下一个词
以前面的例子为例,下面的图形展示了使用采样进行语言生成的情况
很明显,使用采样进行语言生成不再是确定性的。 单词 (“car”) 从条件概率分布 P(w∣"The") 中进行采样,接着从条件概率分布 P(w∣"The",“car”) 中进行采样,选取了 (“drives”)。
在 transformers 库中,我们设置 do_sample=True,并通过 top_k=0 关闭 Top-K 采样(稍后详细介绍)。为了说明目的,我们将随机种子 random_seed 设置为 0。随意更改 random_seed 来尝试模型。
# set seed to reproduce results. Feel free to change the seed though to get different results
from transformers import set_seed
set_seed(42)# activate sampling and deactivate top_k by setting top_k sampling to 0
sample_output = model.generate(**model_inputs,max_new_tokens=40,do_sample=True,top_k=0
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(sample_output[0], skip_special_tokens=True))# Output:
# ----------------------------------------------------------------------------------------------------
# I enjoy walking with my cute dog for the rest of the day, but this had me staying in an unusual room and not going on nights out with friends (which will always be wondered for a mere minute or so at this point).
有趣!文本看起来还不错,但仔细观察发现,它并不是非常连贯。听起来不像是人类写的。这就是在 Sampling 采样词序列时的一个大问题:模型经常生成不连贯的胡言乱语, 参考 Ari Holtzman 等人(2019年)。
一个技巧是进行分布 P ( w ∣ w 1 : t − 1 ) P(w|w_{1:t-1}) P(w∣w1:t−1) temperature 通过降低 softmax 的所谓值来变得更清晰(增加高概率单词的可能性并降低低概率单词的可能性)。
将温度应用于上面示例的示例如下所示。
第 t=1 步的条件下一个词分布变得更加尖锐,几乎没有机会选择单词 (“car”)。
让我们看看如何通过设置 temperature=0.6 来使分布变得更尖锐:
# set seed to reproduce results. Feel free to change the seed though to get different results
set_seed(42)# use temperature to decrease the sensitivity to low probability candidates
sample_output = model.generate(**model_inputs,max_new_tokens=40,do_sample=True,top_k=0,temperature=0.6,
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(sample_output[0], skip_special_tokens=True))# Output:
# ----------------------------------------------------------------------------------------------------
# I enjoy walking with my cute dog, but I don't like to chew on it. I like to eat it and not chew on it. I like to be able to walk with my dog."# So how did you decide
好的。现在奇怪的 n-gram 较少了,输出的连贯性稍微提高了一点!尽管应用温度可以使分布变得不那么随机,在温度设置为接近 0 时,温度调节的采样将等同于贪婪解码,并将面临与之前相同的问题。
五、Top-K Sampling
Fan et al.(2018年) 提出了一种简单但非常强大的采样方案,称为Top-K采样。在Top-K采样中,选择最有可能的K个下一个词,并将概率质量重新分配给这 K 个下一个词。 GPT2采用了这种采样方案,这是其在故事生成中取得成功的原因之一。
为了更好地说明Top-K采样,我们将上述例子中两个采样步骤使用的词池范围从3个词扩展到10个词。
设定 K=6, 在两个采样步骤中,我们将采样池限制为6个词。尽管在第一步中,定义为
的 6 个最有可能的词仅占据了大约三分之二的概率质量,但在第二步中,几乎包含了所有的概率质量。尽管如此,我们可以看到它成功地消除了第二个采样步骤中相当奇怪的候选词 (“not”, “the”, “small”, “told”)。
让我们看看如何在库中使用Top-K,通过设置 top_k=50:
# set seed to reproduce results. Feel free to change the seed though to get different results
set_seed(42)# set top_k to 50
sample_output = model.generate(**model_inputs,max_new_tokens=40,do_sample=True,top_k=50
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(sample_output[0], skip_special_tokens=True))# Output:
# ----------------------------------------------------------------------------------------------------
#I enjoy walking with my cute dog for the rest of the day, but this time it was hard for me to figure out what to do with it. (One reason I asked this for a few months back is that I had a
非常不错!这段文本可以说是到目前为止最具人类风格的文本。然而,对于 Top-K 采样的一个关注点是它并不动态地调整从下一个词概率分布 P ( w ∣ w 1 : t − 1 ) P(w|w_{1:t-1}) P(w∣w1:t−1) 中被过滤掉的词的数量。这可能是有问题的,因为一些词可能是从非常尖锐的分布中进行采样(上图中的右侧分布),而其他词则是从更加平坦的分布中进行采样(上图中的左侧分布)。
在步骤 t=1 时,Top-K 消除了采样词池中的 (“people”, “big”, “house”, “cat”),这些似乎是合理的候选词。另一方面,在步骤 t=2 时,该方法将 (“down”, “a”) 这两个不太合适的词包括在采样词池中。因此,将采样词池限制为固定大小的 K 可能会导致模型在尖锐分布中产生胡言乱语,并限制模型在平坦分布中的创造力。这种直觉导致 Ari Holtzman 等人(2019年) 创建了Top-p (或nucleus) 采样方法。
六、Top-p (nucleus) sampling
与仅从最可能的 K 个单词中进行采样不同,Top-p 采样从概率累积超过概率 p 的可能性最小的单词集中进行选择。然后,概率质量在该单词集中重新分配。 这样,单词集的大小(即单词集中的单词数)可以根据下一个单词的概率分布动态增加和减少。让我们用以下图形来说明。
**设定 p=0.92,Top-p采样选择最少数量的单词,以使其共同超过 92% 的概率质量,定义为
。在第一个例子中,这包括了 9 个最可能的单词,而在第二个例子中,它只需要选择前 3 个单词就可以超过 92%。**实际上非常简单!可以看到,它保留了一系列下一个单词可能性较低的单词,例如 P(w∣"The"),以及当下一个单词似乎更可预测时只有几个单词,例如 P(w∣"The",“car”)。
好了,现在在 transformers 库中尝试一下!通过设置 0 < top_p < 1,我们激活了 Top-p 采样:
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)# deactivate top_k sampling and sample only from 92% most likely words
sample_output = model.generate(input_ids,do_sample=True,max_length=50,top_p=0.92,top_k=0
)print("Output:\n" + 100 * '-')
print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
# Output:
# ----------------------------------------------------------------------------------------------------
# I enjoy walking with my cute dog. He will never be the same. I watch him play.# Guys, my dog needs a name. Especially if he is found with wings.# What was that? I had a lot o
太棒了,听起来就像是人类写的一样。嗯,也许还不完全是。
理论上,Top-p方法似乎比Top-K更优雅,但两种方法在实践中都表现良好。Top-p还可以与Top-K结合使用,这可以避免非常低排名的单词,同时允许一些动态选择。
最后,要获得多个独立采样的输出,我们可以再次设置参数 num_return_sequences > 1:
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)# set top_k = 50 and set top_p = 0.95 and num_return_sequences = 3
sample_outputs = model.generate(input_ids,do_sample=True,max_length=50,top_k=50,top_p=0.95,num_return_sequences=3
)print("Output:\n" + 100 * '-')
for i, sample_output in enumerate(sample_outputs):print("{}: {}".format(i, tokenizer.decode(sample_output, skip_special_tokens=True)))
# Output:
# ----------------------------------------------------------------------------------------------------
# 0: I enjoy walking with my cute dog. It's so good to have the chance to walk with a dog. But I have this problem with the dog and how he's always looking at us and always trying to make me see that I can do something
# 1: I enjoy walking with my cute dog, she loves taking trips to different places on the planet, even in the desert! The world isn't big enough for us to travel by the bus with our beloved pup, but that's where I find my love
# 2: I enjoy walking with my cute dog and playing with our kids," said David J. Smith, director of the Humane Society of the US.# "So as a result, I've got more work in my time," he said.
太酷了,现在你应该掌握了使用transformers让模型为你写故事的所有工具!
七、总结
Top-p 和 Top-K 采样似乎比传统的 gready search (贪婪搜索) 和 beam search (束搜索) 在开放式语言生成中产生更流畅的文本。然而,最近有更多的证据表明,gready search (贪婪搜索) 和beam search (束搜索) 的明显缺陷(主要是生成重复的单词序列)是由模型(尤其是模型的训练方式)引起的,而不是解码方法引起的,参见 Welleck等人(2019年)。此外,正如 Welleck等人(2020年) 所示,Top-K和Top-p采样也存在生成重复单词序列的问题。
在 Welleck等人(2019年) 的研究中,作者们通过人类评估显示,当调整模型的训练,beam search (束搜索) 可以生成比Top-p采样更流畅的文本。
开放式语言生成是一个快速发展的研究领域,通常情况下,并不存在一种适用于所有情况的解码方法,因此必须根据具体使用情况找到最佳方法。
参考:
- How to generate text: using different decoding methods for language generation with Transformers
- generate text的正确姿势
- Huggingface 的 generate 方法介绍:top_p sampling、top_k sampling、greedy_search、beam_search
相关文章:
大模型 Decoder 的生成策略
本文将介绍以下内容: IntroductionGreedy Searchbeam searchSamplingTop-K SamplingTop-p (nucleus) sampling总结 一、Introduction 1、简介 近年来,由于在数百万个网页数据上训练的大型基于 Transformer 的语言模型的兴起,开放式语言生…...
队列和栈相互实现
相关题目 225. 用队列实现栈:弹出元素时,将对首的元素出列加到队尾,直到只剩下初始队列时队尾一个元素为止,然后弹出这个元素,即可实现LIFO 232. 用栈实现队列:用两个栈实现队列的功能,出栈时&a…...
Node.js 是如何处理请求的
前言:在服务器软件中,如何处理请求是非常核心的问题。不管是底层架构的设计、IO 模型的选择,还是上层的处理都会影响一个服务器的性能,本文介绍 Node.js 在这方面的内容。 TCP 协议的核心概念 要了解服务器的工作原理首先需要了…...
数据结构与算法之堆: Leetcode 215. 数组中的第K个最大元素 (Typescript版)
数组中的第K个最大元素 https://leetcode.cn/problems/kth-largest-element-in-an-array/ 描述 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。…...
SpringBoot快速入门
搭建SpringBoot工程,定义hello方法,返回“Hello SpringBoot” ②导入springboot工程需要继承的父工程;以及web开发的起步依赖。 ③编写Controller ④引导类就是SpringBoot项目的一个入口。 写注解写main方法调用run方法 快速构建SpringBoo…...
深度学习笔记_4、CNN卷积神经网络+全连接神经网络解决MNIST数据
1、首先,导入所需的库和模块,包括NumPy、PyTorch、MNIST数据集、数据处理工具、模型层、优化器、损失函数、混淆矩阵、绘图工具以及数据处理工具。 import numpy as np import torch from torchvision.datasets import mnist import torchvision.transf…...
高效的开发流程搭建
目录 1. 搭建 AI codebase 环境kaggle的服务器1. 搭建 AI codebase 环境 python 、torch 以及 cuda版本,对AI的影响最大。不同的版本,可能最终计算出的结果会有区别。 硬盘:PCIE转SSD的卡槽,, GPU: 软件源: Anaconda: 一定要放到固态硬盘上。 VS code 的 debug功能…...
浅谈OV SSL 证书的优势
随着网络威胁日益增多,保护网站和用户安全已成为每个企业和组织的重要任务。在众多SSL证书类型中,OV(Organization Validation)证书以其独特的优势备受关注。让我们深入探究OV证书的优势所在,为网站安全搭建坚实的防线…...
一篇博客学会系列(3) —— 对动态内存管理的深度讲解以及经典笔试题的深度解析
目录 动态内存管理 1、为什么存在动态内存管理 2、动态内存函数的介绍 2.1、malloc和free 2.2、calloc 2.3、realloc 3、常见的动态内存错误 3.1、对NULL指针的解引用操作 3.2、对动态开辟空间的越界访问 3.3、对非动态开辟内存使用free释放 3.4、使用free释放一块动态…...
【C++ techniques】虚化构造函数、虚化非成员函数
constructor的虚化 virtual function:完成“因类型而异”的行为;constructor:明确类型时构造函数;virtual constructor:视其获得的输入,可产生不同的类型对象。 //假如写一个软件,用来处理时事…...
蓝牙核心规范(V5.4)11.6-LE Audio 笔记之初识音频位置和通道分配
专栏汇总网址:蓝牙篇之蓝牙核心规范学习笔记(V5.4)汇总_蓝牙核心规范中文版_心跳包的博客-CSDN博客 爬虫网站无德,任何非CSDN看到的这篇文章都是盗版网站,你也看不全。认准原始网址。!!! 音频位置 在以前的每个蓝牙音频规范中,只有一个蓝牙LE音频源和一个蓝牙LE音频接…...
mysql双主+双从集群连接模式
架构图: 详细内容参考: 结果展示: 178.119.30.14(主) 178.119.30.15(主) 178.119.30.16(从) 178.119.30.17(从)...
嵌入式中如何用C语言操作sqlite3(07)
sqlite3编程接口非常多,对于初学者来说,我们暂时只需要掌握常用的几个函数,其他函数自然就知道如何使用了。 数据库 本篇假设数据库为my.db,有数据表student。 nonamescore4嵌入式开发爱好者89.0 创建表格语句如下: CREATE T…...
RandomForestClassifier 与 GradientBoostingClassifier 的区别
RandomForestClassifier(随机森林分类器)和GradientBoostingClassifier(梯度提升分类器)是两种常用的集成学习方法,它们之间的区别分以下几点。 1、基础算法 RandomForestClassifier:随机森林分类器是基于…...
计组——I/O方式
一、程序查询方式 CPU不断轮询检查I/O控制器中“状态寄存器”,检测到状态为“已完成”之后,再从数据寄存器取出输入数据。 过程: 1.CPU执行初始化程序,并预置传送参数;设置计数器、设置数据首地址。 2. 向I/O接口发…...
jsbridge实战2:Swift和h5的jsbridge通信
[[toc]] demo1: 文本通信 h5 -> app 思路: h5 全局属性上挂一个变量app 接收这个变量的内容关键API: navigation代理 navigationAction.request.url?.absoluteString // 这个变量挂载在 request 的 url 上 ,在浏览器实际无法运行,因…...
集合原理简记
HashMap 无论在构造函数是否指定数组长度,进行的都是延迟初始化 构造函数作用: 阈值:threshold,每次<<1 ,数组长度 负载因子 无参构造:设置默认的负载因子 有参:可以指定初始容量或…...
机器学习的超参数 、训练集、归纳偏好
一、介绍 超参数(Hyperparameters)和验证集(Validation Set)是机器学习中重要的概念,用于调整模型和评估其性能。 超参数: 超参数是在机器学习模型训练过程中需要手动设置的参数,而不是从数据…...
Leetcode1071. 字符串的最大公因子(三种方法,带详细解析)
Leetcode1071. 字符串的最大公因子 对于字符串 s 和 t,只有在 s t … t(t 自身连接 1 次或多次)时,我们才认定 “t 能除尽 s”。 给定两个字符串 str1 和 str2 。返回 最长字符串 x,要求满足 x 能除尽 str1 且 x 能…...
如何像人类一样写HTML之图像标签,超链接标签与多媒体标签
文章目录 前言一、图像标签1.1 什么是图像标签?2.2 如何使用图像标签? 二、超链接标签2.1 什么是超链接标签?2.2 如何使用超链接标签? 三、多媒体标签3.1 什么是多媒体标签?3.2 如何使用多媒体audio标签?3.…...
1300*C. Rumor(并查集贪心)
解析: 并查集,求每个集合的最小费用。 每次合并集合的时候,根节点保存当前集合最小的费用。 #include<bits/stdc.h> using namespace std; #define int long long const int N1e55; int n,m,a[N],p[N],cnt[N]; int find(int x){retur…...
python实用小代码(数据分析向)
一、python实现31省市名称替换 首先定义了一个字典province_dict,其中包含每个省市的无缩写名称与其标准名称之间的映射。然后,我们使用map()函数将每个省市名称从无缩写名称转换为标准名称,并将结果存储在新列省市标准名称中。 province_di…...
【oncmdmsg 鼠标】2023/8/19 上午9:50:14
2023/8/19 上午9:50:14 oncmdmsg 鼠标 2023/8/19 上午9:50:22 抱歉,您提到的 “oncmdmsg” 和 “鼠标” 是什么?请提供更多上下文信息,我将尽力帮助您。 2023/8/19 上午9:51:43 OnCmdMsg 2023/8/19 上午9:52:21 “OnCmdMsg” 是一个在 MFC (Microsoft Foundation Cla…...
插入排序:简单而有效的排序方法
在计算机科学中,排序算法是一个重要且常见的主题,它们用于对数据进行有序排列。插入排序(Insertion Sort)是其中一个简单但有效的排序算法。本文将详细解释插入排序的原理和步骤,并提供Java语言的实现示例。 插入排序的…...
OpenGL之光照贴图
我们需要拓展之前的系统,引入漫反射和镜面光贴图(Map)。这允许我们对物体的漫反射分量和镜面光分量有着更精确的控制。 漫反射贴图 我们希望通过某种方式对物体的每个片段单独设置漫反射颜色。我们仅仅是对同样的原理使用了不同的名字:其实都是使用一张覆盖物体的图像,让我…...
隐私交易成新刚需,Unijoin 凭什么优势杀出重围?
随着区块链技术的普及和发展,全球加密货币用户在持续增长,根据火币研究院公布的数据,2022年全球加密用户已达到 3.2亿人,目前全球人口总数超过了 80亿,加密货币用户渗透率已达到了 4%。 尤其是在 2020 年开启的 DeFi 牛…...
小谈设计模式(12)—迪米特法则
小谈设计模式(12)—迪米特法则 专栏介绍专栏地址专栏介绍 迪米特法则核心思想这里的“朋友”指当前对象本身以参数形式传入当前对象的对象当前对象的成员变量直接引用的对象目标 Java程序实现程序分析 总结 专栏介绍 专栏地址 link 专栏介绍 主要对目…...
Foxit PDF
Foxit PDF 福昕PDF 软件,可以很好的编辑PDF文档。 调整PDF页面大小 PDF文档中,一个页面大,一个页面小 面对这种情况,打开Foxit PDF 右键单击需要调整的页面,然后选择"调整页面大小". 可以选择…...
《Python趣味工具》——ppt的操作(刷题版)
前面我们对PPT进行了一定的操作,并将其中的文字提取到了word文档中。现在就让我们来刷几道题巩固巩固吧! 文章目录 1. 查看PPT(上)2. 查看PPT(中)3. 查看PPT(下)4. PPT的页码5. 大学…...
实战型开发--3/3,clean code
编程的纯粹 hmmm,一开始在这个环节想聊一些具体的点,其实也就是《clean code》这本书中的点,但这个就还是更流于表面; 因为编码的过程,就更接近于运动员打球,艺术家绘画,棋手下棋的过程&#x…...
深圳大公司/百度热搜关键词排名优化
倒数60秒价格走势 可是然而但是,别人家都是怎么拍中的?答:不按套路出牌这次你就中了。 那么即使是这样,还有没有“套路”可循?答:肯定有的。 相信很多人都读过国拍官网的《网上投标拍卖操作流程》ÿ…...
免费软件下载网站排行/济南做网站比较好的公司
加上引号就好了👏 def foo(value: str|int|float|list|tuple):print(value)foo(None)...
微网站免费建站系统/互联网广告投放代理公司
使用RD Client来远程桌面 可能你会觉得奇怪,team viewer和向日葵之类的难道不香吗?看起来他们两个都是实现了远程桌面的功能,好像没必要特地用Windows自带的RD Client进行内网穿透之后远程桌面。 实际上team viewer之类的在我的使用范围内不…...
有哪些类型的网站/个人网站首页设计
415. 字符串相加给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。注意:num1和num2的长度都小于 5100.num1和num2都只包含数字0-9.num1和num2都不包含任何前导零。你不能使用任何內建BigInteger库, 也不能直接将输入的字符串转换为整…...
什么网站做微信公众账号/网络营销课程个人总结3000字
原因:音频编码原来为AMR,ios那边貌似不支持这种音频编码 VideoAbsActivity.java 加了 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); 将音频录制格式从默认…...
减肥产品网站模板/百度的电话人工客服电话
穆僮电脑小课堂 (QQ群:141826908)摘编整理如果你不小心把ubuntu引导弄坏了,比如重装了windows,比如格式化错了盘等等,那么通过下述方法可以简单的修复ubuntu首先,插入ubuntu的安装盘,没有的话只好做一个了&…...