指针生成网络(PGN)详细指南(引入)
一、Seq2Seq模型:编码-解码框架的开山之作
我们首先要了解的是seq2seq(Sequence-to-Sequence)模型。它最早由Google在2014年的一篇论文中提出,是第一个真正意义上的端到端的编码器-解码器(Encoder-Decoder)框架。
seq2seq模型主要由两部分组成:
- 编码器(Encoder):通常是一个RNN(循环神经网络),用于将输入序列编码为一个固定长度的向量表示,即所谓的“语义向量”。你可以把编码器看作一位尽职的秘书,他会认真阅读你给他的所有材料(输入序列),然后为你写一份精炼的内容摘要(语义向量)。
- 解码器(Decoder):同样是一个RNN,接收编码器输出的语义向量,从中解码出目标输出序列。解码器就像一位创意写手,他会根据秘书提供的摘要(语义向量),创作出一篇全新的文章(输出序列)。
然而,传统的seq2seq模型也存在一些局限性:
- 编码器需要将整个输入序列压缩为一个固定大小的向量,对于较长的输入序列,这样做会损失很多信息。就像秘书写摘要,输入内容太多的话,摘要就不可能面面俱到。
- 解码器只能利用编码器最后一个时间步的状态,无法充分利用编码器中间产生的语义信息。秘书的摘要再好,也只是对原始材料的高度概括,写手创作时无法参考材料的细节。
二、注意力机制:让写手"只选对的,不选多的"
为了克服上述问题,研究者提出了注意力机制(Attention Mechanism)。它的核心思想是:解码器在生成每个词时,都可以有选择地参考编码器不同时间步的输出,自动决定应该重点关注哪些部分。这个过程有点像写手在创作时翻阅秘书整理的资料,重点参考与当前内容最相关的部分。
在实现上,注意力机制会为编码器的每个时间步的输出分配一个权重,然后基于这些权重计算一个上下文向量(Context Vector),作为解码器的附加输入。权重的计算通常基于解码器当前的隐藏状态和编码器各时间步的输出。直观地说,权重越大,说明编码器该时间步的输出对解码器当前预测越重要,需要被重点"关注"。
引入注意力机制后,模型变得更加灵活和高效:
- 不再需要将整个输入序列压缩为固定长度的向量,缓解了长序列的信息损失问题。秘书不用再提供"一言以蔽之"的摘要,而是可以整理一份完整的材料供写手参考。
- 解码过程可以参考编码器各个时间步的输出,充分利用了输入序列的细节信息。写手可以有的放矢地参考材料,写出更精彩的内容。
首先导入库
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F# 使用PyTorch的Transformer模块来简化编码器和解码器的实现
from torch.nn import Transformer
定义编码器类
编码器使用了PyTorch的TransformerEncoder模块,它由多个TransformerEncoderLayer堆叠而成。每个编码器层包含一个多头自注意力机制和一个前馈神经网络。此外,为了让模型能够区分输入序列中不同位置的词,我们还使用了位置编码(Positional Encoding)。位置编码与词嵌入相加,得到最终的输入表示。
class Encoder(nn.Module):def __init__(self, input_dim, hid_dim, n_layers, n_heads, pf_dim, dropout):super().__init__()# 定义Transformer编码器层 self.encoder_layer = nn.TransformerEncoderLayer(d_model=hid_dim, nhead=n_heads, dim_feedforward=pf_dim,dropout=dropout)# 编码器由n_layers个编码器层堆叠而成self.transformer_encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=n_layers)# 位置编码,用于为输入序列的每个位置添加位置信息self.pos_embedding = nn.Embedding(1000, hid_dim)# 输入嵌入层,将离散的输入token转换为连续的向量表示 self.embedding = nn.Embedding(input_dim, hid_dim)# Dropout层,用于防止过拟合self.dropout = nn.Dropout(dropout)def forward(self, src):# src的形状: (src_len, batch_size)# 生成位置编码src_pos = torch.arange(0, src.shape[0]).unsqueeze(0).repeat(src.shape[1], 1).permute(1, 0)# 将输入序列转换为嵌入向量,并加上位置编码src = self.embedding(src) + self.pos_embedding(src_pos)# 通过Dropout层src = self.dropout(src)# 通过Transformer编码器获取最终的编码结果# src的形状: (src_len, batch_size, hid_dim)src = self.transformer_encoder(src)return src
定义注意力层
class Attention(nn.Module):def __init__(self, hid_dim):super().__init__()self.attn = nn.Linear(hid_dim * 2, hid_dim)self.v = nn.Linear(hid_dim, 1, bias=False)def forward(self, hidden, encoder_outputs):# hidden的形状: (batch_size, hid_dim) # encoder_outputs的形状: (src_len, batch_size, hid_dim)src_len = encoder_outputs.shape[0]# 将hidden扩展为encoder_outputs的长度,以便拼接hidden = hidden.unsqueeze(1).repeat(1, src_len, 1)# 将hidden和encoder_outputs按最后一维拼接energy = torch.tanh(self.attn(torch.cat((hidden, encoder_outputs), dim=2))) # 计算注意力权重attention = self.v(energy).squeeze(2)return F.softmax(attention, dim=1)
定义解码器类
解码器的核心也是一个TransformerDecoder模块,它由多个TransformerDecoderLayer组成。每个解码器层包含一个self-attention、一个cross-attention和一个前馈神经网络。其中,self-attention用于处理已生成的输出序列,cross-attention用于根据编码器的输出计算注意力权重。
在每个时间步,解码器首先将上一步的输出通过一个嵌入层和dropout层,然后用注意力层计算当前隐藏状态对编码器输出的注意力权重。接着,将注意力权重与编码器输出加权求和,得到一个上下文向量。这个上下文向量会与当前步的嵌入输入拼接,再通过一个线性层,作为transformer解码器的输入。最后,将transformer解码器的输出通过一个线性层和softmax层,得到当前步的词表分布。
class Decoder(nn.Module):def __init__(self, output_dim, hid_dim, n_layers, n_heads, pf_dim, dropout, attention):super().__init__()self.output_dim = output_dimself.hid_dim = hid_dimself.n_layers = n_layersself.n_heads = n_headsself.pf_dim = pf_dimself.dropout = dropout# 注意力层self.attention = attention# 解码器层self.decoder_layer = nn.TransformerDecoderLayer(d_model=hid_dim, nhead=n_heads,dim_feedforward=pf_dim, dropout=dropout)# 解码器由n_layers个解码器层堆叠而成 self.transformer_decoder = nn.TransformerDecoder(self.decoder_layer, num_layers=n_layers)# 输出层,将transformer的输出转换为预测的词表分布self.out = nn.Linear(hid_dim, output_dim)# 输出词嵌入层self.output_embedding = nn.Embedding(output_dim, hid_dim)# Dropout层self.dropout = nn.Dropout(dropout)def forward(self, input, hidden, encoder_outputs):# input的形状: (batch_size)# hidden的形状: (batch_size, hid_dim)# encoder_outputs的形状: (src_len, batch_size, hid_dim)# 将输入转换为词嵌入input = self.output_embedding(input.unsqueeze(0))# 通过Dropout层input = self.dropout(input)# 通过注意力层,根据hidden和encoder_outputs计算注意力权重a = self.attention(hidden, encoder_outputs)# 将注意力权重与编码器输出相乘,得到注意力加权的上下文向量# a的形状: (batch_size, src_len)# encoder_outputs的形状: (src_len, batch_size, hid_dim)# 将两者相乘得到 (batch_size, src_len, hid_dim)# 然后在src_len维度求和,得到 (batch_size, hid_dim)weighted = torch.bmm(a.unsqueeze(1), encoder_outputs.permute(1, 0, 2)).squeeze(1)# 将加权的上下文向量与输入拼接,作为transformer解码器的输入# input的形状: (1, batch_size, hid_dim)# weighted的形状: (batch_size, hid_dim)# 将两者拼接得到 (1, batch_size, 2*hid_dim)input = torch.cat((input, weighted.unsqueeze(0)), dim=2)# 将拼接后的输入通过线性层,将维度还原为hid_diminput = F.relu(self.attn_combine(input))# 通过transformer解码器# input的形状: (1, batch_size, hid_dim)# hidden的形状: (n_layers, batch_size, hid_dim)# 注意我们这里只传入了encoder_outputs,因为解码器的self-attention会自动计算decoded_outputsoutput, hidden = self.transformer_decoder(input, hidden, encoder_outputs)# 将输出通过线性层转换为词表空间output = self.out(output.squeeze(0))# 应用softmax得到最终的词表分布output = F.softmax(output, dim=1)# 返回 output和新的隐藏状态return output, hidden
我们将编码器和解码器组合成完整的seq2seq模型:
在每个时间步,解码器根据上一步的输出、当前的隐藏状态和编码器的输出计算注意力权重,然后将注意力权重与编码器输出加权求和,得到一个上下文向量。这个上下文向量会作为transformer解码器的一部分输入,用于预测当前步的输出词。
class Seq2Seq(nn.Module):def __init__(self, encoder, decoder, device):super().__init__()self.encoder = encoderself.decoder = decoderself.device = devicedef forward(self, src, trg, teacher_forcing_ratio = 0.5):# src的形状: (src_len, batch_size)# trg的形状: (trg_len, batch_size)# teacher_forcing_ratio是使用正确目标词的概率batch_size = trg.shape[1]trg_len = trg.shape[0]trg_vocab_size = self.decoder.output_dim# 存储解码器的输出序列outputs = torch.zeros(trg_len, batch_size, trg_vocab_size).to(self.device)# 编码输入序列encoder_outputs = self.encoder(src)# 初始化解码器的隐藏状态hidden = encoder_outputs[-1,:,:]# 解码器的第一个输入是 <sos> 标记input = trg[0,:]for t in range(1, trg_len):# 根据当前的输入、隐藏状态和编码器输出,获取预测结果output, hidden = self.decoder(input, hidden, encoder_outputs)# 保存当前的输出outputs[t] = output# 根据teacher_forcing_ratio决定使用正确答案还是模型预测的词作为下一步的输入 teacher_force = random.random() < teacher_forcing_ratiotop1 = output.argmax(1) input = trg[t] if teacher_force else top1return outputs
我们可以打印一下完整的model来看一下内部结构:
# 创建一些示例输入数据
src = torch.tensor([[1, 3, 4, 2]]) # 形状: (src_len, batch_size)
trg = torch.tensor([[1, 3, 4, 2]]) # 形状: (trg_len, batch_size)# 定义模型参数
input_dim = len(input_vocab)
output_dim = len(output_vocab)
hid_dim = 256
n_layers = 3
n_heads = 8
pf_dim = 512
dropout = 0.1# 实例化模型组件
attention = Attention(hid_dim)
encoder = Encoder(input_dim, hid_dim, n_layers, n_heads, pf_dim, dropout)
decoder = Decoder(output_dim, hid_dim, n_layers, n_heads, pf_dim, dropout, attention)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')# 实例化Seq2Seq模型
model = Seq2Seq(encoder, decoder, device).to(device)
print(model)
输出:
Seq2Seq((encoder): Encoder((encoder_layer): TransformerEncoderLayer((self_attn): MultiheadAttention((out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True))(linear1): Linear(in_features=256, out_features=512, bias=True)(dropout): Dropout(p=0.1, inplace=False)(linear2): Linear(in_features=512, out_features=256, bias=True)(norm1): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(norm2): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(dropout1): Dropout(p=0.1, inplace=False)(dropout2): Dropout(p=0.1, inplace=False))(transformer_encoder): TransformerEncoder((layers): ModuleList((0-2): 3 x TransformerEncoderLayer((self_attn): MultiheadAttention((out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True))(linear1): Linear(in_features=256, out_features=512, bias=True)(dropout): Dropout(p=0.1, inplace=False)(linear2): Linear(in_features=512, out_features=256, bias=True)(norm1): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(norm2): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(dropout1): Dropout(p=0.1, inplace=False)(dropout2): Dropout(p=0.1, inplace=False))))(pos_embedding): Embedding(1000, 256)(embedding): Embedding(5, 256)(dropout): Dropout(p=0.1, inplace=False))(decoder): Decoder((attention): Attention((attn): Linear(in_features=512, out_features=256, bias=True)(v): Linear(in_features=256, out_features=1, bias=False))(decoder_layer): TransformerDecoderLayer((self_attn): MultiheadAttention((out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True))(multihead_attn): MultiheadAttention((out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True))(linear1): Linear(in_features=256, out_features=512, bias=True)(dropout): Dropout(p=0.1, inplace=False)(linear2): Linear(in_features=512, out_features=256, bias=True)(norm1): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(norm2): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(norm3): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(dropout1): Dropout(p=0.1, inplace=False)(dropout2): Dropout(p=0.1, inplace=False)(dropout3): Dropout(p=0.1, inplace=False))(transformer_decoder): TransformerDecoder((layers): ModuleList((0-2): 3 x TransformerDecoderLayer((self_attn): MultiheadAttention((out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True))(multihead_attn): MultiheadAttention((out_proj): NonDynamicallyQuantizableLinear(in_features=256, out_features=256, bias=True))(linear1): Linear(in_features=256, out_features=512, bias=True)(dropout): Dropout(p=0.1, inplace=False)(linear2): Linear(in_features=512, out_features=256, bias=True)(norm1): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(norm2): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(norm3): LayerNorm((256,), eps=1e-05, elementwise_affine=True)(dropout1): Dropout(p=0.1, inplace=False)(dropout2): Dropout(p=0.1, inplace=False)(dropout3): Dropout(p=0.1, inplace=False))))(out): Linear(in_features=256, out_features=5, bias=True)(output_embedding): Embedding(5, 256)(dropout): Dropout(p=0.1, inplace=False))
)
三、指针生成网络:在"写原创"和"纯搬运"间找平衡
尽管有了注意力机制,传统的seq2seq模型在一些任务上的表现仍不尽如人意,尤其是在文本摘要领域。想象一下,如果让一个小说家去写新闻摘要,他很可能会添加一些原文中没有的内容。这在文学创作中是才华,在文本摘要里却是Bug。我们希望摘要模型既能准确抓取原文的关键信息,又能生成流畅自然的句子。
于是,斯坦福大学的研究者在2017年提出了指针生成网络(PGN)。它在传统的seq2seq+注意力框架的基础上,添加了一种新的混合生成方式:
- 生成模式:根据当前的解码器状态和注意力语境,从固定词表中生成新词。这一部分与普通的seq2seq没有区别,对应着摘要写手的“创作”能力。
- 拷贝模式:直接从输入序列中选择某个词,原封不动地"指针"到输出中。这一部分让模型有了"直接引用"的能力,对应着摘要写手的"摘抄"功能。
PGN通过一个可学习的"生成概率"来控制每一步应该选择生成模式还是拷贝模式。生成概率同时取决于解码器状态、注意力语境和当前输入,可以自动调节生成和拷贝的比例。打个比方,生成概率就像写手的思路开关:什么时候该发挥创造力,什么时候该直接引用原文,全凭她自己拿捏。
PGN在文本摘要、阅读理解等任务上取得了显著的效果提升。它成功地找到了"创作"与"摘编"的平衡:
- 在关键信息的提取和复述上更加准确,避免了关键细节的遗漏和僭改。写手知道什么地方该直接"照抄"。
- 生成的摘要更加自然流畅,可读性大大提高。写手也能适时发挥"文学才华",润色文字。
相关文章:

指针生成网络(PGN)详细指南(引入)
一、Seq2Seq模型:编码-解码框架的开山之作 我们首先要了解的是seq2seq(Sequence-to-Sequence)模型。它最早由Google在2014年的一篇论文中提出,是第一个真正意义上的端到端的编码器-解码器(Encoder-Decoder)…...

案例研究丨浪潮云洲通过DataEase推进多维度数据可视化建设
浪潮云洲工业互联网有限公司(以下简称为“浪潮云洲”)成立于2018年,定位于工业数字基础设施建设商、具有国际影响力的工业互联网平台运营商、生产性互联网头部服务商。截至目前,浪潮云洲工业互联网平台连续五年入选跨行业跨领域工…...

k8s 蓝绿发布、滚动发布、灰度发布
在Kubernetes(k8s)中,蓝绿发布、滚动发布、灰度发布(金丝雀发布)是三种常见的应用部署和更新策略。下面将分别对这几种发布方式进行说明,并给出相应的例子。 蓝绿发布 蓝绿发布是一种无缝切换版本的部署策…...
UWB原理:AOA测角原理Angel of Arrival
AOA测角原理Angel of Arrival 准备工作: UWB默认使用channel=9,Frequency = 7987.2mMhz,约8GHz。 波长 天线RX1, RX2间距一般为20mm左右,假如发射端TX离2个RX距离2m=2000mm,大约是100倍天线间距。2个入射角可以近似相同。 测角原理: <...

plus.runtime.install在android10无效
在 Android 10 中,使用 plus.runtime.install 方法来进行动态安装应用或进行其他操作可能会失效。这是因为从 Android 10 开始,操作系统在安全性和隐私方面做了很多改进,特别是与应用安装相关的权限变更。 在 Android 10(API 级别…...

7.C++中的函数
C中的函数 在 C 中,函数是一个重要的概念,它是将一段相对独立的、完成特定任务的代码封装起来的程序模块。以下是关于 C 中函数的详细介绍: 函数的定义 函数定义由函数头和函数体组成,其一般形式如下: 返回值类型 …...

上位机知识篇---Python数据图表可视化
文章目录 前言第一部分:Matplotlib1. 图形和轴(Figure and Axes)FigureAxes创建一个新的图形在图形中添加一个或多个轴 2. 绘图命令绘制折线图绘制散点图绘制条形图绘制饼图绘制直方图等高线图(Contour plot)ÿ…...

详解:TCP/IP五层(四层)协议模型
一.五层(四层)模型 1.概念 TCP/IP协议模型分为五层:物理层、数据链路层、网络层、传输层和应用层。这五层每一层都依赖于其下一层给它提供的网络去实现需求。 1)物理层:这是最基本的一层,也是最接近硬件…...

【原生记忆能力 怎么让大模型拥有原生的记忆能力】
首先,需要明确“原生记忆能力”具体指的是什么。通常来说,大模型如GPT-3或GPT-4在生成回复时是基于训练数据的模式识别,而不是真正的记忆。所以用户可能希望模型能够持续记住之前的交互信息,或者在多次使用中积累知识,…...

百度APP iOS端磁盘优化实践(上)
01 概览 在APP的开发中,磁盘管理已成为不可忽视的部分。随着功能的复杂化和数据量的快速增长,如何高效管理磁盘空间直接关系到用户体验和APP性能。本文将结合磁盘管理的实践经验,详细介绍iOS沙盒环境下的文件存储规范,探讨业务缓…...

qml Dialog详解
1、概述 Dialog是QML(Qt Modeling Language)中用于显示对话框的组件,它提供了一个模态窗口,通常用于与用户进行重要交互,如确认操作、输入信息或显示警告等。Dialog组件具有灵活的布局和样式选项,可以轻松…...

2025年的校招管理系统会全面实现智能化吗?
随着科技的不断进步,企业的招聘方式也在不断地演变。特别是在校园招聘领域,传统的招聘方法已经难以满足现代企业的需求。2025年的校招管理系统是否会全面实现智能化?这是一个值得探讨的话题。 想象一下,每年的校招季,…...

【Unity】使用Canvas Group改变UI的透明度
目录 一、前言二、Canvas Group三、结合DOTween达到画面淡进的效果 一、前言 在平时开发中,可以通过控制材质、Color改变UI透明度,除此之外还可以CanvasGroup组件来控制透明度。 二、Canvas Group 官方文档链接👉👉 点击进入 …...

2024年博客之星主题创作|2024年度感想与新技术Redis学习
Redis工具深入了解 1.引言与感想2.Redis工具了解2.分布式系统了解2.1单机架构2.2分布式是什么2.3应用服务和数据库服务分离2.4引入更多的应用服务器2.5理解负载均衡器2.6数据库读写分离2.7引入缓存2.8数据库分库分表2.9引入微服务2.10分布式系统小结 1.引言与感想 2024学习了很…...

6. 马科维茨资产组合模型+政策意图AI金融智能体(DeepSeek-V3)增强方案(理论+Python实战)
目录 0. 承前1. 幻方量化 & DeepSeek1.1 What is 幻方量化1.2 What is DeepSeek 2. 重写AI金融智能体函数3. 汇总代码4. 反思4.1 不足之处4.2 提升思路 5. 启后 0. 承前 本篇博文是对上一篇文章,链接: 5. 马科维茨资产组合模型政策意图AI金融智能体(Qwen-Max)增…...

Unity自学之旅05
Unity自学之旅05 Unity学习之旅⑤📝 AI基础与敌人行为🥊 AI导航理论知识(基础)开始实践 🎃 敌人游戏机制追踪玩家攻击玩家子弹碰撞完善游戏失败条件 🤗 总结归纳 Unity学习之旅⑤ 📝 AI基础与敌…...

linux中关闭服务的开机自启动
引言 systemctl 是 Linux 系统中用于管理 systemd 服务的命令行工具。它可以用来启动、停止、重启服务,管理服务的开机自启动,以及查看服务的状态等。 什么是 systemd? systemd 是现代 Linux 发行版中默认的 初始化系统(init sys…...

Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )
一、文件处理 1.1、文件操作的重要性和应用场景 1.1.1、重要性 数据持久化: 文件是存储数据的一种非常基本且重要的方式。通过文件,我们可 以将程序运行时产生的数据永久保存下来,以便将来使用。 跨平台兼容性: 文件是一种通用…...

ubuntu黑屏问题解决
重启Ubuntu后,系统自动进入tty1,无法进入桌面。想到前几天安装了一些主题之类的,然后今天才重启,可能是这些主题造成冲突或者问题了把。 这里直接重新安装ubuntu-desktop解决: 更新源: sudo apt-get upd…...

Java如何实现反转义
Java如何实现反转义 前提 最近做的一个需求,是热搜词增加换一批的功能。功能做完自测后,交给了测试伙伴,但是测试第二天后就提了一个bug,出现了未知词 levis。第一眼看着像公司售卖的一个品牌-李维斯。然后再扒前人写的代码&…...

动态规划(路径问题)
62. 不同路径 62. 不同路径 - 力扣(LeetCode) 动态规划思想第一步:描述状态~ dp[i][j]:表示走到i,j位置时,一共有多少种方法~ 动态规划思想第二步:状态转移方程~ 动态规划思想第三步…...

python http调用视觉模型moondream
目录 一、什么是moondream 二、资源地址 三、封装了http进行接口请求 四、代码解析 解释 可能的改进 一、什么是moondream Moondream 是一个针对视觉生成任务的深度学习模型,专注于图像理解和生成,包括图像标注(captioning)、问题回答(Visual Question Answering,…...

Spark Streaming编程基础
文章目录 1. 流式词频统计1.1 Spark Streaming编程步骤1.2 流式词频统计项目1.2.1 创建项目1.2.2 添加项目依赖1.2.3 修改源目录1.2.4 添加scala-sdk库1.2.5 创建日志属性文件 1.3 创建词频统计对象1.4 利用nc发送数据1.5 启动应用,查看结果 2. 编程模型的基本概念3…...

深入 Flutter 和 Compose 的 PlatformView 实现对比,它们是如何接入平台控件
在上一篇《深入 Flutter 和 Compose 在 UI 渲染刷新时 Diff 实现对比》发布之后,收到了大佬的“催稿”,想了解下 Flutter 和 Compose 在 PlatformView 实现上的对比,恰好过去写过不少 Flutter 上对于 PlatformView 的实现,这次恰好…...

C# OpenCV机器视觉:红外体温检测
在一个骄阳似火的夏日,全球却被一场突如其来的疫情阴霾笼罩。阿强所在的小镇,平日里熙熙攘攘的街道变得冷冷清清,人们戴着口罩,行色匆匆,眼神中满是对病毒的恐惧。阿强作为镇上小有名气的科技达人,看着这一…...

FCA-FineDataLink认证
FCA-FineDataLink证书 Part.1:判断题 (总分:18分 得分:16) 第1题 判断题 数据同步只支持写入到已存在表,不支持自动建表(得分:2分 满分:2分) 正确答案:B 你的答案&…...

第19篇:python高级编程进阶:使用Flask进行Web开发
第19篇:python高级编程进阶:使用Flask进行Web开发 内容简介 在第18篇文章中,我们介绍了Web开发的基础知识,并使用Flask框架构建了一个简单的Web应用。本篇文章将深入探讨Flask的高级功能,涵盖模板引擎(Ji…...

js截取video视频某一帧为图片
1.代码如下 <template><div class"box"><div class"video-box"><video controls ref"videoRef" preload"true"src"https://qt-minio.ictshop.com.cn:9000/resource-management/2025/01/08/7b96ac9d957c45a…...

[云讷科技]Kerloud Falcon四旋翼飞车虚拟仿真空间发布
虚拟仿真环境作为一个独立的专有软件包提供给我们的客户,用于帮助用户在实际测试之前验证自身的代码,并通过在仿真引擎中添加新的场景来探索新的飞行驾驶功能。 环境要求 由于环境依赖关系,虚拟仿真只能运行在装有Ubuntu 18.04的Intel-64位…...

Jetson nano 安装 PCL 指南
本指南帮助 ARM64 架构的 Jetson Nano 安装 PCL(点云库)。 安装步骤 第一步:安装依赖 在终端中运行以下命令,安装 PCL 所需的依赖: sudo apt-get update sudo apt-get install git build-essential linux-libc-dev s…...