AIGC实战——GPT(Generative Pre-trained Transformer)

AIGC实战——GPT

    • 0. 前言
    • 1. GPT 简介
    • 2. 葡萄酒评论数据集
    • 3. 注意力机制
      • 3.1 查询、键和值
      • 3.2 多头注意力
      • 3.3 因果掩码
    • 4. Transformer
      • 4.1 Transformer 块
      • 4.2 位置编码
    • 5. 训练GPT
    • 6. GPT 分析
      • 6.1 生成文本
      • 6.2 注意力分数
    • 小结
    • 系列链接

0. 前言

注意力机制能够用于构建先进的文本生成模型,Transformer 是用于序列建模的强大神经网络,该神经网络不需要复杂的循环或卷积架构,而只依赖于注意力机制。这种方法克服了循环神经网络 (Recurrent Neural Network, RNN) 方法难以并行化的缺陷( RNN 必须逐符号处理序列)。Transformers 高度可并行化运算,能够在大规模数据集上进行训练。在本节中,我们将学习文本生成模型如何利用 Transformer 架构提高文本性能,并介绍自回归模型 GPT (Generative Pre-Trained transformer)。

1. GPT 简介

OpenAI2018 年提出 GPT (Generative Pre-Trained transformer),将 Transformer 架构用于训练大规模文本数据,以预测序列数据中的下一个单词,然后再针对特定的下游任务进行微调。
GPT 的预训练过程使用大型文本语料库 BookCorpus (来自 7000 本不同类型书籍的 4.5GB 文本)训练模型。在预训练过程中,模型会根据先前的单词预测序列中的下一个单词,这一过程称为语言建模 (language modeling),用于训练模型理解自然语言的结构和模式。
在预训练之后,通过使用一个特定任务的小规模数据集,可以对 GPT 模型进行微调。微调表示调整模型的参数以更好地适应当前任务。例如,可以针对分类、问答等任务对模型进行微调。
OpenAIGPT 架构进行了改进和扩展,后续提出了 GPT-2GPT-3GPT-3.5GPT-4 等模型。这些模型在更大的数据集上进行训练,具有更大的容量,因此可以生成更复杂、更连贯的文本,GPT 模型已经被广泛应用于自然语言处理相关任务中。
在本节中,我们将使用相同的组件和基本原理构建 GPT 模型,不同的是,我们使用较少的数据进行训练。

2. 葡萄酒评论数据集

在本节中,使用 Kaggle 中的葡萄酒评论数据集训练 GPT 模型,数据集中包含超过 130,000 条葡萄酒评论,以及相关描述和价格等元数据。
可以在 Kaggle 中下载数据集,解压后,将葡萄酒评论和相关元数据保存到 ./data 文件夹中。数据准备流程与使用 LSTM 训练生成模型中所用的数据准备步骤相同:

  • 加载数据并创建一个包含所有葡萄酒文本描述的字符串列表
  • 用空格分隔标点符号,以便每个标点符号被视为一个单独的单词
  • 通过 TextVectorization 层将字符串进行分词,并将每个字符串填充/截断为固定长度
  • 创建训练集,其中输入是分词后的文本字符串,输出是将相同字符串向后移动一个符号的字符串

数据预处理

3. 注意力机制

理解 GPT 工作原理的第一步是理解注意力机制 (attention mechanism),注意力机制使得 Transformer 架构在语言建模方面与循环神经网络有所不同。理解了注意力机制后,便能了解如何在 Transformer 架构(如 GPT )中使用注意力机制。
当我们写作时,句子中的下一个单词受到已经写完的其他单词的影响。例如,假设以以下方式开始一个句子:

"The write elephant tried to get into the boat but it was too"

显然,下一个词应该是与 “big” 意思相近的单词。句子中的其他词对于下一单词的选择非常重要。例如,它是 elephant 而不是 bird,这意味着我们更倾向于选取 “big” 而不是 “small”,如果句中使用 “pool” 而不是 “boat”,我们可能会选择 “scared” 替代 “big”。最后,把 “elephant” 放进小船里意味着尺寸是问题所在,如果大象试图摧毁小船,我们可能会选择 “flexible” 作为最后一个词,其中 “it” 指的是 “boat”。
除此之外,句子中的其他词则并不重要。例如,大象是 “white” 或“black”对于选择最后一个词没有任何影响。同样,句子中的其他单词,如 thebutit 等,为句子构成了正确的语法形式,但对于确定下一个所需单词并不重要。换句话说,我们只关注句子中的某些单词,而对其他词只付出少量关注,我们希望深度学习模型同样能够做到这一点。
Transformer 中的注意力机制(也称为注意力头)就是为了实现这一目的。它能够决定在输入中从哪些部分中获取信息,以便高效地提取有用的信息而不被无关细节所干扰。这使得它能够适应各种情况,因为它可以在推理时决定在哪些部分中寻找信息。
相比之下,循环层试图构建一个通用的隐藏状态,用以在每个时间步捕捉输入的整体表示。这种方法的一个缺点是,合并到隐藏向量中的许多单词对于当前任务(如预测下一个单词)可能并不直接相关。注意力头则可以避免此问题,因为它们可以选择如何结合上下文的信息。

3.1 查询、键和值

接下来,我们介绍注意力机制如何决定在哪里寻找信息,我们继续使用上一节中所用示例。
为了能够预测单词 “too” 之后的内容,前面的其他单词都会有所贡献,但它们的贡献取决于它们对于预测 “too” 后续单词的能力的自信程度。例如,单词 “elephant” 可能会自信地贡献出与尺寸相关的词,而单词 “was” 没有提供太多的信息来缩小可能性。
换句话说,我们可以将注意力头看作一种信息检索系统,其中查询(“接在 too 之后的词是什么?”)被转化为键/值存储(句子中的其他单词),输出结果是值的总和,并根据查询与每个键之间的相关度进行加权。此过程详细步骤如下图所示,我们的仍然使用上一节所用示例。

注意力机制

查询 (query, Q) 可以表示当前任务(例如,“接在 too 之后的词是什么?”)。在本例中,通过将单词 “too” 的嵌入传递到权重矩阵 W Q W_Q WQ 中,从维度 d e d_e de 变换为维度 d k d_k dk,得到了查询。
键向量 (key, K) 是句子中每个单词的表示,可以将其视为每个单词可以帮助完成的预测任务的贡献。它们与查询的产生方式类似,通过将每个嵌入传递到权重矩阵 W K W_K WK 中,将每个向量的维度从 d e d_e de 变换为 d k d_k dk,键和查询的长度相同。
在注意力头中,使用每对向量 ( Q K Q_K QK) 之间的点积将每个键与查询进行比较(这就是键和查询必须具有相同的长度的原因)。键/查询对的点积结果数值越高,键与查询的相关度就越强,因此允许它对注意力头的输出做出更大的贡献。得到的向量乘以 d k d_k dk,以保持向量和的方差稳定(大约等于 1),并应用 softmax 函数确保贡献总和为 1,这便是注意力权重向量。
值向量 (value, V) 也是句子中单词的表示,可以将其视为每个单词的未加权贡献。通过将每个嵌入传递到权重矩阵 W V W_V WV 中,将每个向量的维度从 d e d_e de 变换为 d v d_v dv,得到值向量。需要注意的是,值向量不一定与键和查询具有相同的长度(但通常为简单起见,使用相同长度)。
值向量乘以注意力权重,得到给定 Q Q Q K K K V V V 的注意力:
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac {QK^T} {\sqrt {d_k}})V Attention(Q,K,V)=softmax(dk QKT)V
为了从注意力头获得最终输出向量,将注意力进行求和,得到长度为 d v d_v dv 的向量。这个上下文向量捕捉了句子中的单词对于预测接在 too 之后的词的任务的共同意见。

3.2 多头注意力

Keras 中,可以构建 MultiHeadAttention 层,该层将多个注意力头的输出连接起来构成多头注意力 (Multihead Attention),允许每个头学习不同的注意力机制,以便整个层可以学习更复杂的关系。
连接后的输出通过最终的权重矩阵 W O W_O WO 进行投影,将向量投影到期望的输出维度上。在本节下,输出维度与查询的输入维度相同 ( d e d_e de),以便可以将层按顺序堆叠在一起。下图显示了 MultiHeadAttention 层输出的构建方式。

多头注意力

Keras 中创建 MultiHeadAttention 层:

layers.MultiHeadAttention(# 此多头注意力层有四个注意力头num_heads = 4,# 键(和查询)是长度为 128 的向量key_dim = 128,# 值(也是每个头的输出)是长度为 64 的向量value_dim = 64,# 输出向量的长度为 256output_shape = 256
)

3.3 因果掩码

在以上介绍中,我们假设注意力头的查询输入是一个单一的向量。然而,为了在训练期间提高效率,理想情况下我们希望注意力层能够同时处理输入中的每个单词,为每个单词预测后续的单词。换句话说,我们希望我们的 GPT 模型能够同时处理一组查询向量(即矩阵)。
为了将向量批处理成一个矩阵,并使用线性代数进行处理,我们需要一个额外的步骤,我们需要对查询/键的点积应用掩码,以避免未来单词的信息泄漏,这称为因果掩码 (Causal Masking),如下图所示。

因果掩码

如果没有这个掩码,GPT 模型将能够完美地猜出句子中的下一个单词,因为它将使用来自单词本身的键作为一个特征。使用 Keras 创建因果掩码,下图显示了 Numpy 形式的结果数组(为了与图相匹配,将结果数组进行了转置)。

def causal_attention_mask(batch_size, n_dest, n_src, dtype):i = tf.range(n_dest)[:, None]j = tf.range(n_src)m = i >= j - n_src + n_destmask = tf.cast(m, dtype)mask = tf.reshape(mask, [1, n_dest, n_src])mult = tf.concat([tf.expand_dims(batch_size, -1), tf.constant([1, 1], dtype=tf.int32)], 0)return tf.tile(mask, mult)print(np.transpose(causal_attention_mask(1, 10, 10, dtype=tf.int32)[0]))

因果掩码仅在解码器 Transformer(如 GPT )中需要,在这些模型中,任务是根据先前的符号顺序生成符号,在训练期间掩码掉未来的符号是至关重要的。
其他类型的 Transformer (例如编码器 Transformer )不需要因果掩码,因为它们不是通过预测下一个符号来训练的。例如,GoogleBERT 在给定句子中预测待填空的单词,因此它可以使用该词前后的上下文。
Transformer 中的多头注意力机制中,层的可学习参数仅由每个注意力头的三个权重矩阵 ( W Q W_Q WQ W K W_K WK W V W_V WV) 和一个用于重塑输出的权重矩阵 ( W O W_O WO) 组成,在多头注意力层中完全没有卷积或循环机制。
下一节中,我们将介绍如何使用多头注意力层构建 Transformer 块。

4. Transformer

4.1 Transformer 块

Transformer 块是 Transformer 内的一个组件,它在多头注意力层间应用了跳跃连接、前馈(全连接)层 (Feed-forward layers) 和归一化,Transformer 块的结构如下图所示。

Transformer 块

首先,将查询传递到多头注意力层并直接添加到输出中,这是一种跳跃连接,可以用其构建非常深的神经网络,而不会受到梯度消失问题的影响,因为跳跃连接提供了一个无梯度的数据通道,使网络能够直接传递信息。
其次,在 Transformer 块中的层归一化用于提高训练过程的稳定性。我们已经介绍了如何使用批归一化层,在批归一化中,每个通道的输出被归一化为均值为 0,标准差为 1,归一化统计信息是根据批和空间维度计算的。
而在 Transformer 块中的层归一化通过在通道维度上计算归一化统计信息,对批数据中每个序列的每个位置进行归一化。就统计信息的计算方式而言,它与批归一化完全相反,下图展示了批归一化和层归一化之间的差异。
层归一化常用于基于文本的任务中,以避免在批处理中跨序列创建归一化依赖关系。然而,Shen 等人表明在 Transformer 内部可以使用一种形式的批归一化进行调整,从而优于传统的层归一化方法。

层归一化

最后,在 Transformer 块中包含了一组前馈(全连接)层( Feed-forward layers ),以使组件能够在网络中深入提取更高级别的特征。
使用 Keras 实现一个 Transformer 块。

class TransformerBlock(layers.Layer):# 在初始化函数中定义构成 TransformerBlock 层的子层def __init__(self, num_heads, key_dim, embed_dim, ff_dim, dropout_rate=0.1):super(TransformerBlock, self).__init__()self.num_heads = num_headsself.key_dim = key_dimself.embed_dim = embed_dimself.ff_dim = ff_dimself.dropout_rate = dropout_rateself.attn = layers.MultiHeadAttention(num_heads, key_dim, output_shape=embed_dim)self.dropout_1 = layers.Dropout(self.dropout_rate)self.ln_1 = layers.LayerNormalization(epsilon=1e-6)self.ffn_1 = layers.Dense(self.ff_dim, activation="relu")self.ffn_2 = layers.Dense(self.embed_dim)self.dropout_2 = layers.Dropout(self.dropout_rate)self.ln_2 = layers.LayerNormalization(epsilon=1e-6)def call(self, inputs):input_shape = tf.shape(inputs)batch_size = input_shape[0]seq_len = input_shape[1]# 创建因果掩码,以隐藏查询中未来的键causal_mask = causal_attention_mask(batch_size, seq_len, seq_len, tf.bool)# 创建多头注意力层,并指定注意力掩码attention_output, attention_scores = self.attn(inputs,inputs,attention_mask=causal_mask,return_attention_scores=True,)attention_output = self.dropout_1(attention_output)# 第一个 add 和归一化层out1 = self.ln_1(inputs + attention_output)# 前馈层ffn_1 = self.ffn_1(out1)ffn_2 = self.ffn_2(ffn_1)# 第二个 add 和归一化层ffn_output = self.dropout_2(ffn_2)return (self.ln_2(out1 + ffn_output), attention_scores)

4.2 位置编码

在训练 GPT 模型之前,还有一个最后一步需要处理。在多头注意力层中,并没有关注键的顺序。每个键与查询之间的点积是并行计算的,而非像循环神经网络那样顺序计算。这样可以并行化处理以提高效率,但也带来了一个问题,因为我们需要注意力层能够考虑文本的上下文信息,例如,针对以下两个句子预测不同的输出:

The dog looked at the boy and … (barked?)
The boy looked at the dog and … (smiled?)

为了解决这个问题,在创建初始的 Transformer 块的输入时,我们使用一种称为位置编码 (positional encoding) 的技术。我们不仅使用符号嵌入 (token embedding) 来编码每个符号,还使用位置嵌入 (position embedding) 来编码符号的位置。
符号嵌入使用标准的嵌入层将每个符号转换为一个可学习向量。我们可以使用相同的方式创建位置编码,使用标准的嵌入层将每个整数位置转换为一个可学习向量。虽然 GPT 使用嵌入层来嵌入位置信息,但原始 Transformer 论文使用三角函数。
为了构建联合的符号-位置编码,将符号嵌入添加到位置嵌入中,如下图所示。这样,就可以在一个向量中同时捕捉序列中每个词的含义和位置信息。

位置编码

使用 Keras 定义 TokenAndPositionEmbedding 层:

class TokenAndPositionEmbedding(layers.Layer):def __init__(self, max_len, vocab_size, embed_dim):super(TokenAndPositionEmbedding, self).__init__()self.max_len = max_lenself.vocab_size = vocab_sizeself.embed_dim = embed_dim# 符号使用 Embedding 层获取嵌入self.token_emb = layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)# 符号的位置同样使用 Embedding 层获取嵌入self.pos_emb = layers.Embedding(input_dim=max_len, output_dim=embed_dim)def call(self, x):maxlen = tf.shape(x)[-1]positions = tf.range(start=0, limit=maxlen, delta=1)positions = self.pos_emb(positions)x = self.token_emb(x)# TokenAndPositionEmbedding 层的输出是符号嵌入和位置嵌入之和return x + positions

5. 训练GPT

接下来,构建并训练 GPT 模型。将输入文本通过符号和位置嵌入层,然后通过 Transformer 块,网络的最终输出是一个使用 softmax 激活函数的 Dense 层,输出的维度是词汇表中的单词数。为了简单起见,我们仅使用一个 Transformer块( GPT 论文中使用 12 个),整体架构如下图所示。

GPT架构

使用 Keras 实现此架构:

# 用 0 填充输入
inputs = layers.Input(shape=(None,), dtype=tf.int32)
# 文本使用 TokenAndPositionEmbedding 层获取嵌入
x = TokenAndPositionEmbedding(MAX_LEN, VOCAB_SIZE, EMBEDDING_DIM)(inputs)
# 嵌入通过 TransformerBlock 进行传递
x, attention_scores = TransformerBlock(N_HEADS, KEY_DIM, EMBEDDING_DIM, FEED_FORWARD_DIM)(x)
# 转换后的输出通过使用 softmax 激活函数的 Dense 层进行传递,以预测后续单词的分布
outputs = layers.Dense(VOCAB_SIZE, activation="softmax")(x)
# 模型以单词符号序列作为输入,并输出预测的后续单词分布。还返回了 Transformer 块的输出,以便检查模型中注意力机制的作用
gpt = models.Model(inputs=inputs, outputs=[outputs, attention_scores])
# 模型使用 SparseCategoricalCrossentropy 损失函数编译并训练
gpt.compile("adam", loss=[losses.SparseCategoricalCrossentropy(), None])
print(gpt.summary())
gpt.fit(train_ds,epochs=EPOCHS,)

6. GPT 分析

训练 GPT 模型后,就可以使用 GPT 生成长文本,还可以获取 TransformerBlock 输出的注意力权重,以了解 Transformer 在生成过程中不同位置寻找信息的方式。

6.1 生成文本

我们可以通过以下过程生成新文本:

  • 将现有的单词序列输入到网络中,以预测下一个单词
  • 将此单词附加到现有序列中,并重复此过程

从网络输出的一组概率中进行抽样,使文本生成过程具有随机性,而不是确定性的。
为了控制采样过程的确定性程度,重用 LSTM 文本生成中的 TextGenerator 类,其使用温度参数来指定采样过程中的确定性程度,使用两个不同的温度值对比生成结果。温度为 1.0 的生成文本比温度为 0.5 的样本具有更高的随机性,因此准确率较低。由于模型从方差较大的概率分布中进行抽样,因此使用温度为 1.0 生成多个样本将具有更多的多样性。

6.2 注意力分数

我们还可以令模型输出,在决定句子中的下一个单词时,每个单词的注意力分数。TransformerBlock 输出每个注意力头的注意力权重,该权重是句子中前面单词的 softmax 分布。
为了进行说明,下图显示了对于三个不同的输入,具有最高概率的前五个符号,以及相对于前面每个单词,两个注意力头的平均注意力。根据其注意力分数对前面的单词进行着色,较深的颜色表示对该单词的注意力更高。

注意力分数

以这种方式查看网络,可以准确地了解网络从何处获取信息,以便对随后的每个单词做出准确预测。通过修改输入,观察是否可以使模型关注到句子中相距较远的单词,以充分证明基于注意力的模型相对于传统的循环模型更强大。

小结

在本节中,我们介绍了 Transformer 模型架构,并构建了一个 GPT 模型,以实现文本生成。GPT 利用了注意力机制,消除了对循环层(如长短时记忆网络)的需求。注意力机制类似于一个信息检索系统,利用查询、键和值来决定从每个输入符号中提取多少信息。

系列链接

AIGC实战——生成模型简介
AIGC实战——深度学习 (Deep Learning, DL)
AIGC实战——卷积神经网络(Convolutional Neural Network, CNN)
AIGC实战——自编码器(Autoencoder)
AIGC实战——变分自编码器(Variational Autoencoder, VAE)
AIGC实战——使用变分自编码器生成面部图像
AIGC实战——生成对抗网络(Generative Adversarial Network, GAN)
AIGC实战——WGAN(Wasserstein GAN)
AIGC实战——条件生成对抗网络(Conditional Generative Adversarial Net, CGAN)
AIGC实战——自回归模型(Autoregressive Model)
AIGC实战——改进循环神经网络
AIGC实战——像素卷积神经网络(PixelCNN)
AIGC实战——归一化流模型(Normalizing Flow Model)
AIGC实战——能量模型(Energy-Based Model)
AIGC实战——扩散模型(Diffusion Model)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

System Verilog的接口、程序块与断言解析

接口、程序块与断言 1 接口 1.1 使用接口简化连接 // 接口 interface arb_if(input bit clk);logic [1:0] grant,request;logic rst; endinterface// 使用了简单接口的仲裁器 module arb (arb_if arbif);...always(posedge arbif.clk or posedge arbif.rst)beginif(arbif.rs…

opencv dnn模块 示例(25) 目标检测 object_detection 之 yolov9

文章目录 1、YOLOv9 介绍2、测试2.1、官方Python测试2.1.1、正确的脚本2.2、Opencv dnn测试2.2.1、导出onnx模型2.2.2、c测试代码 2.3、测试统计 3、自定义数据及训练3.1、准备工作3.2、训练3.3、模型重参数化 1、YOLOv9 介绍 YOLOv9 是 YOLOv7 研究团队推出的最新目标检测网络…

软件测试中的AI-为什么它在软件自动化测试中很重要?

通俗地说,人工智能(AI)是计算机科学的一个领域,它专注于使机器“智能化”。所谓智能,就是使系统能够像人类一样学习和做出决策。因此,人工智能机器将能够学习如何在特定情况下做出反应,然后根据…

【AIGC】重磅消息,GPT-4.5 Turbo将在6月发布?

2024 年 AI 辅助研发趋势 文章目录 强烈推荐GPT-4.5 Turbo竞争对手Anthropic的Claude 3谷歌的Gemini 1.5 Pro 总结强烈推荐专栏集锦写在最后 强烈推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击…

Cplex之新建一个项目并求解

cplex下载:Cplex安装教程与使用介绍-CSDN博客 链接:https://pan.baidu.com/s/1jD9Xved2aWPHtRd-_PLI5Q 提取码:n4og 补充b站上一个教程:快速学懂Cplex软件及其编程方法_哔哩哔哩_bilibili 一、建立并求解一个模型 step1 : 新…

【目标检测经典算法】R-CNN、Fast R-CNN和Faster R-CNN详解系列一:R-CNN图文详解

学习视频:Faster-RCNN理论合集 概念辨析 在目标检测中,proposals和anchors都是用于生成候选区域的概念,但它们在实现上有些许不同。 Anchors(锚框): 锚框是在图像中预定义的一组框,它们通常以…

Python:函数的形参与实参

注意:本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 ([www.aideeplearning.cn]) 函数基本概念 在Python中,函数是一种将代码封装以进行重复使用的机制。它们允许你定义一段代码,以便在程序的多个位置调…

微信小程序开发系列(二十六)·小程序运行机制(启动、前后台状态、挂起、销毁)和小程序更新机制

目录 1. 小程序运行机制 1.1 启动 1.2 前台和后台状态 1.3 挂起 1.4 销毁 2. 小程序更新机制 1. 小程序运行机制 1.1 启动 小程序启动可以分为两种情况,一种是冷启动,一种是热启动。 冷启动:如果用户首次打开,或小…

OPPO后端二面,凉了!

这篇文章的问题来源于一个读者之前分享的 OPPO 后端凉经,我对比较典型的一些问题进行了分类并给出了详细的参考答案。希望能对正在参加面试的朋友们能够有点帮助! Java String 为什么是不可变的? public final class String implements java.io.Seri…

阿里云服务器安全狗免费使用多引擎智能查杀引擎

云服务器具有按量付费、降低综合成本等诸多优势,受到很多企业的欢迎。 因此,目前使用的云服务器越来越多。 阿里云是目前云服务器中最具影响力的品牌,因此选择阿里云服务器的用户数量也是最多的。 那么阿里云服务器需要安装杀毒软件吗&#x…

Python学习:数据类型转换

数据类型转换 对数据内置的类型进行转换,数据类型的转换,一般情况下你只需要将数据类型作为函数名即可。 Python 数据类型转换可以分为两种: 隐式类型转换 - 自动完成显式类型转换 - 需要使用类型函数来转换 隐式类型转换 Python 会自动…

微信小程序一次性订阅requestSubscribeMessage授权和操作详解

一次性订阅:用户订阅一次发一次通知 一、授权 — requestSubscribeMessage Taro.requestSubscribeMessage({tmplIds: [], // 需要订阅的消息模板的id的集合success (res) {console.log("同意授权", res)},fail(res) {console.log(拒绝授权, res)}})点击或…

2001-2022年上市公司数字化转型程度指数测算数据(含原始数据+测算代码+计算结果)(无形资产衡量)

2001-2022年上市公司数字化转型程度指数测算数据(含原始数据测算代码计算结果) 1、时间:2001-2022年 2、指标:证券代码、证券简称、统计截止日期、是否发生ST或*ST或PT、、是否发生暂停上市、行业代码、行业名称、stkcd、year、…

mediapipe 实现姿态分析——举手检测

目录 人体姿态检测 效果展示 举手检测 行业应用 代码实现 代码分析 效果展示 代码修改,一只手举起即可 总结 啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦^_^啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦♪(^∇^*)啦啦啦…

【数据结构】二叉树---AVL树的实现

目录 一. 什么是AVL树 二. AVL树的结点结构定义 三. AVL树的动态平衡法 1. 左单旋转 --- RL(RotateLeft) 型调整操作 2. 右单旋转 --- RR(RotateRight) 型调整操作 3. 先左后右双旋转 --- RLR (RotateLeftRight) 型调整操作 4. 先右后左双旋转 --- RRL (RotateRightL…

Day32:安全开发-JavaEE应用Servlet路由技术JDBCMybatis数据库生命周期

目录 JavaEE-HTTP-Servlet&路由&周期 JavaEE-数据库-JDBC&Mybatis&库 思维导图 Java知识点: 功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等. 框架…

最新若依项目快速上手

最新若依项目快速上手 配套视频:若依项目快速上手视频 1. 下载源码 官网:https://ruoyi.vip/ 前端 git clone https://github.com/yangzongzhuan/RuoYi-Vue3.git后端 git clone https://gitee.com/y_project/RuoYi-Vue.git2. 数据库 创建数据库ry-vue…

考研复习C语言初阶(3)

目录 一.函数是什么? 二.C语言中函数的分类 2.1库函数 2.2自定义函数 三.函数的参数 3.1实际参数(实参) 3.2 形式参数(形参) 四.函数的调用 4.1 传值调用 4.2 传址调用 五. 函数的嵌套调用和链式访问 5.1 嵌套调用 5…

Android中单例模式正确实现方式

1. 饿汉模式 -线程安全 在类加载时进行实例化, 线程安全,但会导致类加载时间变长。饿汉模式如果使用过多,可能会对App启动耗时带来不利影响。 2. 懒汉模式 -线程不安全 没有加锁, 因此线程不安全。 3. 两次判空 加同步锁 -线程不…

Talk|麻省理工学院李晨昊:发展式腿足智能-从模仿到生成

本期为TechBeat人工智能社区第578期线上Talk。 北京时间3月13日(周三)20:00,麻省理工学院博士生—李晨昊的Talk已准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “发展式腿足智能-从模仿到生成”,向大家系统地介绍了专家示范(exper…