机器学习周报-TCN文献阅读

文章目录

    • 摘要
    • Abstract
  • 1 TCN通用架构
    • 1.1 序列建模任务描述
    • 1.2 因果卷积(Causal Convolutions)
    • 1.3 扩张卷积(Dilated Convolutions)
    • 1.4 残差连接(Residual Connections)
  • 2 TCN vs RNN
  • 3 TCN缺点
  • 4 代码
    • 4.1 TCN通用代码
    • 4.2 torch.nn.Conv1d
    • 总结

摘要

TCN(Temporal Convolutional Networks,时间卷积网络)是一种专门用于处理时间序列数据的深度学习模型。它结合了卷积神经网络(CNN)的并行处理能力和循环神经网络(RNN)的长期依赖建模能力,成为序列建模任务中的强大工具。TCN主要使用因果卷积来确保网络在预测时只能使用当前和过去的信息,而不能看到未来的数据;使用扩张卷积跳过部分输入来使卷积核可以应用于大于卷积核本身长度的区域,从而增加网络的感受野;同时利用残差连接来增加网络的深度,这有助于训练深层网络并减少梯度消失的问题。但是存在评估期间的数据存储和域迁移的潜在参数变化等问题。

Abstract

TCN (Temporal Convolutional Networks) is a deep learning model specifically designed for processing time series data. It combines the parallel processing capabilities of Convolutional Neural Networks (CNNs) with the long-term dependency modeling capabilities of Recurrent Neural Networks (RNNs), making it a powerful tool for sequence modeling tasks. TCN primarily uses causal convolution to ensure that the network can only use current and past information during prediction, without access to future data; it employs dilated convolution to skip over parts of the input, allowing the convolutional kernel to be applied to regions larger than the length of the kernel itself, thereby increasing the network’s receptive field; and it utilizes residual connections to increase the depth of the network, which helps in training deep networks and reducing the problem of vanishing gradients. However, there are potential issues such as data storage during evaluation and parameter changes in domain migration.

论文链接:https://arxiv.org/pdf/1803.01271

1 TCN通用架构

TCN的显著特征

  1. 因果卷积(Causal Convolution):TCN中的卷积操作是因果的,这意味着在预测当前时刻的值时,模型只使用当前时刻及之前的数据,而不使用未来数据。这种设计保证了模型的因果性,避免了信息泄露的问题
  2. 能够处理可变长度的输入序列,并将其映射到相同长度的输出序列。(输入和输出序列长度一致)。
  3. 扩张卷积(Dilated Convolution):TCN通过使用扩张卷积来扩大卷积层的感受野,使网络能够在不增加参数数量或计算复杂性的情况下捕捉长范围的序列依赖关系。扩张卷积通过在卷积核之间插入空洞来实现,有效地提高了计算效率,并缓解了梯度消失问题

1.1 序列建模任务描述

我们有一个输入序列: x 0 , x 1 , . . . . . x t x_0,x_1,.....x_t x0,x1,.....xt,我们希望预测出一些对应的输出: y 0 , y 1 , . . . . . y t y_0,y_1,.....y_t y0,y1,.....yt。但是有一个限制:如预测某一时间t的输出 y t y_t yt,只能观察时间t及时间t以前的输入( x 0 , x 1 , . . . . . x t x_0,x_1,.....x_t x0,x1,.....xt)。序列建模网络是任何函数: f ( x t + 1 ) = y t + 1 f(x_{t+1})=y_{t+1} f(xt+1)=yt+1,生成的映射是:
y ^ 0 , y ^ 1 . . . . y ^ T = f ( x 0 , x 1 . . . . x T ) \hat{y}_0,\hat{y}_1....\hat{y}_T=f({x}_0,{x}_1....{x}_T) y^0,y^1....y^T=f(x0,x1....xT)

y t 仅依赖于 x 0 , x 1 . . . . x t y_t仅依赖于x_0,x_1....x_t yt仅依赖于x0,x1....xt,而不依赖于未来的输入 x t + 1 , . . . . . x T x_{t+1},.....x_T xt+1,.....xT,则在序列建模设置中学习的任务是,找到网络f,使实际输出和预测值之间的预期最小, L ( y 0 , . . . . y T , f ( x 0 , . . . x T ) ) L(y_0,....y_T,f(x_0,...x_T)) L(y0,....yT,f(x0,...xT)),其中序列和输出根据某一概率分布抽取。

1.2 因果卷积(Causal Convolutions)

TCN使用因果卷积(Causal Convolution)来确保模型不会违反时间顺序。因果卷积的输出只依赖于当前时刻及其之前的输入,而不依赖于未来的输入。在标准的卷积操作中,每个输出值都基于其周围的输入值,包括未来的时间点。但在因果卷积中,权重仅应用于当前和过去的输入值,确保了信息流的方向性,避免了未来信息泄露到当前输出中。为了实现这一点,通常会在卷积核的右侧填充零(称为因果填充),这样只有当前和过去的信息被用于计算输出。

在这里插入图片描述
图1:卷积核为2

公式: y t = ∑ i = 0 k − 1 f ( i ) X t − i y_t=\sum^{k-1}_{i=0}f(i)X_{t-i} yt=i=0k1f(i)Xti

d表示扩张率(dilation factor),k表示卷积核大小(filter size)

因果卷积存在问题: 需要一个非常深的网络或非常大的filters来增加卷积的感受野

通过使用扩张卷积来实现非常深的网络和增加卷积的感受野大小

1.3 扩张卷积(Dilated Convolutions)

一个简单的因果卷积只能回顾网络深度上有限大小的历史信息,在面对较长的历史的任务时,要如何解决?

使用扩张卷积来实现指数级大的感受野,使用扩张卷积,随着网络的深度以指数方式增加d(即 d = O ( 2 i ) d=O(2^i) d=O(2i) i i i 表示网络为第几层),这使卷积核可以命中有效历史中的每个输入,同时还允许使用更深的网络来处理非常大的有效历史。

下图为:扩张因果卷积图,其中扩张因子d=1,2,4;卷积核k大小=3

在这里插入图片描述

如图所示, 每一层中一个单元要回顾上一层中(k-1)×d个有效历史信息(扩张因子决定了卷积核中元素之间的间距,例如,如果扩张因子为2,则卷积核中的元素会间隔一个输入单元)。

公式:
y t = ∑ i = 0 k − 1 f ( i ) X t − d ⋅ i y_t=\sum^{k-1}_{i=0}f(i)X_{t-d·i} yt=i=0k1f(i)Xtdi
d表示扩张率(dilation factor),k表示卷积核大小(filter size)

1.4 残差连接(Residual Connections)

TCN的感受野取决于

  1. 网络深度n;
  2. 卷积核大小k;
  3. 扩张因子d;

在实际预测中,可能取决于大小为 2 12 2^{12} 212的历史和高维输入序列,就需要多达12层的网络,就是每一层由多个用于特征提取的卷积核组合。在通用TCN模型中,采用了通用残差模块代替卷积层。

如图 TCN 结构图。 一个残差块包含两层的卷积和非线性映射,在每层中还加入了 WeightNorm 和 Dropout 来正则化网络。为什么要 1×1 卷积呢?1×1 卷积是可以用来降维的 。作者直接把较下层的特征图跳层连接到上层,对应的每个 Cell 的特征图数量(也就是通道数 channel)不一致,导致不能直接做类似 Resnet 的跳层特征图加和操作,于是,为了两个层加和时特征图数量吻合,用 1×1 卷积做了一个降维的操作。

在这里插入图片描述
TCN使用残差连接来缓解梯度消失问题并促进更深层网络的训练。残差连接是残差网络(ResNets)的关键组成部分,由何凯明等人提出。它的主要目的是解决深层神经网络训练中的梯度消失/爆炸问题,以及提高网络的训练效率和性能。在残差连接中,网络的某一层的输出直接加到几层之后的另一层上,形成所谓的“跳跃连接”。

具体来说,假设有一个输入 x x x,经过几层后得 F ( x ) F(x) F(x),那么最终的输出不是 F ( x ) F(x) F(x),而是 x + F ( x ) x+F(x) x+F(x),也就是输入+输出。这种结构允许梯度在反向传播时可以直接流回更早的层,减少了梯度消失的问题,并且使得网络能够有效地训练更深的架构。残差块的输出可以表示为:

o u t p u t = A c t i v a t i o n ( x + F ( x ) ) output=Activation(x+F(x)) output=Activation(x+F(x))

其中 F F F是卷积层和激活函数的组合。
残差连接如下图所示:

在这里插入图片描述

2 TCN vs RNN

相比较RNN,TCN有如下优势:

  1. 并行计算: 卷积可以并行进行。(在训练和评估中,在TCN中可以将长输入序列作为一个整体来处理,而不是像在RNN中那样顺序地处理。)
  2. 灵活的感受野大小: 通过堆叠更多的因果卷积层、增大扩张率和卷积核,可增大感受野。
  3. 稳定的梯度: 与递归体系结构不同,TCN具有与序列的时间方向不同的反向传播路径;故TCN没有梯度爆炸的问题。

3 TCN缺点

  • 评估期间的数据存储: 在评估/测试中,TCN需要接收到有效历史长度的原始序列,因此在评估期间可能需要更多内存。(RNN只需要保持隐藏状态并接受当前输入 x t x_t xt即可生成预测)
  • 域迁移的潜在参数变化: 不同领域对模型预测所需的历史数量可能有不同的要求。因此,当将模型从只需要很少内存的域转移到需要更长内存的域时,TCN可能会因为没有足够大的感受野而表现不佳。

4 代码

4.1 TCN通用代码

  • Chomp1d 类
    用于去除卷积输出中的最后几个元素,在应用了填充(padding)的卷积之后,保持输出序列的长度跟输入序列长度相同。
class Chomp1d(nn.Module):def __init__(self, chomp_size):super(Chomp1d, self).__init__()self.chomp_size = chomp_sizedef forward(self, x):return x[:, :, :-self.chomp_size].contiguous()

chomp_size:指定要去除的元素数量。

  • TemporalBlock 类

TemporalBlock是TCN中的基本构建块,它包含两个卷积层,每个卷积层后面跟着ReLU激活函数和dropout层,以减少过拟合。

class TemporalBlock(nn.Module):def __init__(self, n_inputs, n_outputs, kernel_size, stride, dilation, padding, dropout=0.2):super(TemporalBlock, self).__init__()self.conv1 = weight_norm(nn.Conv1d(n_inputs, n_outputs, kernel_size,stride=stride, padding=padding, dilation=dilation))self.chomp1 = Chomp1d(padding)self.relu1 = nn.ReLU()self.dropout1 = nn.Dropout(dropout)self.conv2 = weight_norm(nn.Conv1d(n_outputs, n_outputs, kernel_size,stride=stride, padding=padding, dilation=dilation))self.chomp2 = Chomp1d(padding)self.relu2 = nn.ReLU()self.dropout2 = nn.Dropout(dropout)self.net = nn.Sequential(self.conv1, self.chomp1, self.relu1, self.dropout1,self.conv2, self.chomp2, self.relu2, self.dropout2)self.downsample = nn.Conv1d(n_inputs, n_outputs, 1) if n_inputs != n_outputs else Noneself.relu = nn.ReLU()self.init_weights()def init_weights(self):self.conv1.weight.data.normal_(0, 0.01)self.conv2.weight.data.normal_(0, 0.01)if self.downsample is not None:self.downsample.weight.data.normal_(0, 0.01)def forward(self, x):out = self.net(x)res = x if self.downsample is None else self.downsample(x)return self.relu(out + res)
  • TemporalConvNet 类
    TemporalConvNet 是整个TCN模型,它由多个 TemporalBlock 堆叠而成。
class TemporalConvNet(nn.Module):def __init__(self, num_inputs, num_channels, kernel_size=2, dropout=0.2):super(TemporalConvNet, self).__init__()layers = []num_levels = len(num_channels)for i in range(num_levels):dilation_size = 2 ** iin_channels = num_inputs if i == 0 else num_channels[i-1]out_channels = num_channels[i]layers += [TemporalBlock(in_channels, out_channels, kernel_size, stride=1, dilation=dilation_size,padding=(kernel_size-1) * dilation_size, dropout=dropout)]self.network = nn.Sequential(*layers)def forward(self, x):return self.network(x)

参数:

  • num_inputs: 输入特征的数量。
  • num_channels: 一个列表,指定了每个 TemporalBlock 的输出通道数。
  • kernel_size: 卷积核的大小。
  • dropout: dropout层的丢弃概率,用于正则化以减少过拟合。
  • stride: 卷积的步长,这里设置为1。
  • dilation: 卷积的扩张率,用于控制卷积核的覆盖范围。
  • padding: 卷积的填充,确保输出序列长度不变。

TCN的网络结构是通过堆叠多个 TemporalBlock 来构建的。每个块的扩张率是前一个块的两倍,这样可以增加模型的感受野,同时保持时间序列数据的局部性。

4.2 torch.nn.Conv1d

torch.nn.Conv1d
一维卷积nn.Conv1d主要用于文本数据,只对宽度进行卷积,对高度不卷积。通常,输入大小为word_embedding_dim * max_length,其中,word_embedding_dim为词向量的维度,max_length为句子的最大长度。卷积核窗口在句子长度的方向上滑动,进行卷积操作。

torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, 
dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)

原理示意图
在这里插入图片描述

  • 参数说明:
  1. in_channels:输入通道数;在文本应用中,即为词向量的维度;
  2. out_channels:输出通道数,等价于卷积核个数;
  3. kernel_size :卷积核大小;卷积核的第二个维度由in_channels决定,所以实际上卷积核的大小为kernel_size * in_channels
  4. stride:卷积步长,默认为 1;
  5. padding: 默认为 0;对输入的每一条边,补充0的层数;
  6. dilation:空洞卷积尺寸,默认为 1;

输入输出格式:

  1. Input: ( N , C i n , L i n ) (N,C_{in},L_{in}) (N,Cin,Lin)
  2. Output: ( N , C o u t , L o u t ) (N,C_{out},L_{out}) (N,Cout,Lout)

其中 L o u t = ⌊ L i n + 2 × p a d d i n g − d i l a t i o n × ( k e r n e l s i z e − 1 ) − 1 s t r i d e + 1 ⌋ L_{out}=\lfloor \frac{L_{in}+2×padding-dilation×(kernel_size-1)-1}{stride} +1\rfloor Lout=strideLin+2×paddingdilation×(kernelsize1)1+1

其中:

  • N表示batch_size; L i n L_{in} Lin表示输入的长度; L o u t L_{out} Lout表示输出的长度
  • C i n C_{in} Cin必须与Conv1中参数 in_channels 值相同
  • C o u t C_{out} Cout必须与Conv1中参数 out_channels 值相同

代码:

import torch
import torch.nn as nn# 创建一个一维卷积层,输入通道数为1,输出通道数为2,卷积核大小为3
conv1d = nn.Conv1d(in_channels=1, out_channels=2, kernel_size=3)# 创建一个随机输入数据,形状为[batch_size, in_channels, sequence_length]
input_data = torch.randn(2, 1, 10)  # batch_size=2, in_channels=1, sequence_length=10
# 应用卷积操作
output_data = conv1d(input_data)# 输出数据的形状
#  batch_size=2, out_channels=2, new_sequence_length=8
print(output_data.shape)  # 将输出形状,例如:torch.Size([2, 2, 8])

输出:

torch.Size([2, 2, 8])

其中输出长度为= L o u t = ⌊ L i n + 2 × p a d d i n g − d i l a t i o n × ( k e r n e l s i z e − 1 ) − 1 s t r i d e + 1 ⌋ L_{out}=\lfloor \frac{L_{in}+2×padding-dilation×(kernel_size-1)-1}{stride} +1\rfloor Lout=strideLin+2×paddingdilation×(kernelsize1)1+1

= ⌊ 10 + 2 × 0 − 1 × ( 3 − 1 ) − 1 1 + 1 ⌋ \lfloor \frac{10+2×0-1×(3-1)-1}{1} +1\rfloor 110+2×01×(31)1+1=8

  • 扩张率d为2:
# 创建一个一维卷积层,输入通道数为1,输出通道数为2,卷积核大小为3,扩张率d=2
conv1d = nn.Conv1d(in_channels=1, out_channels=2, kernel_size=3, dilation=2)
print(output_data.shape) 

输出:

torch.Size([2, 2, 6])

其中输出长度为= L o u t = ⌊ L i n + 2 × p a d d i n g − d i l a t i o n × ( k e r n e l s i z e − 1 ) − 1 s t r i d e + 1 ⌋ L_{out}=\lfloor \frac{L_{in}+2×padding-dilation×(kernel_size-1)-1}{stride} +1\rfloor Lout=strideLin+2×paddingdilation×(kernelsize1)1+1

= ⌊ 10 + 2 × 0 − 2 × ( 3 − 1 ) − 1 1 + 1 ⌋ \lfloor \frac{10+2×0-2×(3-1)-1}{1} +1\rfloor 110+2×02×(31)1+1=6

总结

本周阅读论文学习了TCN模型的相关原理、结构和代码;TCN能够并行处理多个时间步的输入,提高模型的训练和推理速度,同时保持对长期依赖关系的捕捉能力。

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

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

相关文章

Quartz任务调度框架实现任务动态执行

说明:之前使用Quartz,都是写好Job,指定一个时间点,到点执行。最近有个需求,需要根据前端用户设置的时间点去执行,也就是说任务执行的时间点是动态变化的。本文介绍如何用Quartz任务调度框架实现任务动态执行…

Spring-kafka快速Demo示例

使用Spring-Kafka快速发送/接受Kafka消息示例代码&#xff0c;项目结构是最基础的SpringBoot结构&#xff0c;提前安装好Kafka&#xff0c;确保Kafka已经正确启动 pom.xml&#xff0c;根据个人情况更换springboot、java版本等 <?xml version"1.0" encoding&qu…

【C++】B2079 求出 e 的值

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目介绍输入格式输出格式输入输出样例说明/提示 &#x1f4af;实现方法一&#xff1a;单层 for 循环计算代码实现运行逻辑解析优点不足 &#x1f4af;实现方法二&#xff…

STM32配合可编程加密芯片SMEC88ST的防抄板加密方案设计

SMEC88ST SDK卡发包下载 目前市场上很多嵌入式产品方案都是可以破解复制的&#xff0c;主要是因为方案主芯片不具备防破解的功能&#xff0c;这就导致开发者投入大量精力、财力开发的新产品一上市就被别人复制&#xff0c;到市场上的只能以价格竞争&#xff0c;最后工厂复制的产…

精准识别花生豆:基于EfficientNetB0的深度学习检测与分类项目

精准检测花生豆&#xff1a;基于EfficientNet的深度学习分类项目 在现代农业生产中&#xff0c;作物的质量检测和分类是确保产品质量的重要环节。针对花生豆的检测与分类需求&#xff0c;我们开发了一套基于深度学习的解决方案&#xff0c;利用EfficientNetB0模型实现高效、准…

MarkItDown的使用(将Word、Excel、PDF等转换为Markdown格式)

MarkItDown的使用&#xff08;将Word、Excel、PDF等转换为Markdown格式&#xff09; 本文目录&#xff1a; 零、时光宝盒&#x1f33b; 一、简介 二、安装 三、使用方法 3.1、使用命令行形式 3.2、用 Python 调用 四、总结 五、参考资料 零、时光宝盒&#x1f33b; &a…

Qanything 2.0源码解析系列6 PDF解析逻辑

Qanything 2.0源码解析系列6: PDF解析逻辑 type: Post status: Published date: 2024/12/04 summary: 深入剖析Qanything是如何拆解PDF的,核心是pdf转markdown category: 技术分享 原文:www.feifeixu.top 😀 前言: 在前面的文章中探究了图片是怎么进行解析的,这篇文章对…

【Agent】Chatbot、Copilot与Agent如何帮助我们的提升效率?

人工智能&#xff08;AI&#xff09;技术的迅猛发展正在深刻改变我们的生活和工作方式。你是否曾想过&#xff0c;未来的工作场景会是什么样子&#xff1f;AI的崛起不仅仅是科技的进步&#xff0c;更是我们生活方式的革命。今天&#xff0c;我们将深入探讨三种主要的AI能力&…

如何使用python读写游戏内存以及使用特征码匹配基址

一.读写内存所需的基本参数 接下来我将使用GTA5游戏举例 1.通过进程名称获取进程pid from psutil import process_iterdef get_process_id_by_name(process_name):for process in process_iter(["pid", "name"]):if process.info["name"] pr…

简述css中z-index的作用?如何用定位使用?

z-index是一个css属性&#xff0c;用于控制元素的堆叠顺序&#xff0c; 如何使用定位用index 1、position&#xff1a;relative&#xff1b; z-index&#xff1b; 相对于自己来定位的&#xff0c;可以根据top&#xff0c;bottom&#xff0c;right&#xff0c;left&#xff…

CCNP_SEC_ASA 第六天作业

实验需求&#xff1a; 为保障内部用户能够访问Internet&#xff0c;请把10.1.1.0/24网络动态转换到外部地址池202.100.1.100-202.100.1.200&#xff0c;如果地址池耗尽后&#xff0c;PAT到Outside接口 提示&#xff1a;需要看到如下输出信息 Inside#telnet 202.100.1.1 Trying …

计算机网络 (13)信道复用技术

前言 计算机网络中的信道复用技术是一种提高网络资源利用率的关键技术。它允许在一条物理信道上同时传输多个用户的信号&#xff0c;从而提高了信道的传输效率和带宽利用率。 一、信道复用技术的定义 信道复用&#xff08;Multiplexing&#xff09;就是在一条传输媒体上同时传输…

敏捷开发Scrum的深入理解和实践

敏捷开发&#xff0c;特别是Scrum方法&#xff0c;已经逐渐成为软件开发领域的主流方法。Scrum不仅适用于软件开发&#xff0c;还适用于其他需要快速响应变化和灵活交付的领域。本文将深入探讨Scrum的核心概念、流程、优势、挑战及其在实践中的应用。 一、Scrum的核心概念 Scru…

计算机视觉目标检测-2

文章目录 摘要abstract1.Fast R-CNN1.1 RoI pooling1.2 End-to -End model1.3 多任务损失-Multi-task loss1.4 R-CNN、SPPNet、Fast R-CNN效果比对 2.Faster R-CNN2.1 RPN原理2.2 效果对比2.3 Faster R-CNN总结 3.总结4.参考文献 摘要 本周学习了Fast R-CNN和Faster R-CNN算法…

JavaScript网页设计案例:动态交互式任务列表

在现代网页开发中&#xff0c;JavaScript被广泛应用于实现动态交互效果。看完这一篇你就可以设计一个动态任务列表&#xff0c;全面展示HTML、CSS和JavaScript在前端开发中的实际应用。通过本案例&#xff0c;你将深入了解事件监听、DOM操作以及用户交互设计的实现过程。 案例需…

【MySQL】索引 面试题

文章目录 适合创建索引的情况创建索引的注意事项MySQL中不适合创建索引的情况索引失效的常见情况 索引定义与作用 索引是帮助MySQL高效获取数据的有序数据结构&#xff0c;通过维护特定查找算法的数据结构&#xff08;如B树&#xff09;&#xff0c;以某种方式引用数据&#xf…

使用Excel制作通达信自定义“序列数据“

序列数据的视频教程演示 Excel制作通达信自定义序列数据 1.序列数据的制作方法&#xff1a;删掉没有用的数据&#xff08;行与列&#xff09;和股代码格式处理&#xff0c;是和外部数据的制作方法是相同&#xff0c;自己上面看历史博文。只需要判断一下&#xff0c;股代码跟随的…

【ELK】ES单节点升级为集群模式--太细了!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言准备工作1. 查看现状【单节点】2. 原节点改集群模式3. 改es配置文件&#xff0c;增加集群相关配置项4. *改docker映射的端口* 启动新节点5. docker-compose起一…

关于区块链的安全和隐私

背景 区块链技术在近年来发展迅速&#xff0c;被认为是安全计算的突破&#xff0c;但其安全和隐私问题在不同应用中的部署仍处于争论焦点。 目的 对区块链的安全和隐私进行全面综述&#xff0c;帮助读者深入了解区块链的相关概念、属性、技术和系统。 结构 首先介绍区块链…

webauthn介绍及应用

1、webauthn介绍 官网&#xff1a;https://webauthn.io/ 1.1、什么是webauthn&#xff1f; webauthn即Web Authentication&#xff0c;是一个符合W3C标准的Web认证规范。它通过公私钥加密技术&#xff0c;实现无密码认证&#xff0c;用户仅需通过pin码、指纹、面部识别、usb …