当前位置: 首页 > news >正文

【Block总结】TAdaConv时序自适应卷积,轻量高效的时间建模卷积|即插即用

论文解读:Temporally-Adaptive Models for Efficient Video Understanding

论文信息

  • 标题:Temporally-Adaptive Models for Efficient Video Understanding

  • 发表时间:2023年

  • 作者:黄子渊等

  • 论文链接:arXiv 论文

  • 代码链接:GitHub - TAdaConv
    在这里插入图片描述

创新点

  1. 时序自适应卷积(TAdaConv):提出了一种新的卷积操作,通过动态调整卷积核权重,使空间卷积具备时序建模能力。这种方法能够有效捕捉视频中的复杂时间动态。

  2. 因子化卷积核权重:TAdaConv将卷积核分解为基础权重和校准权重,校准权重根据输入数据动态生成。这种设计不仅保留了预训练模型的权重,还减少了训练资源的消耗。

  3. 模块化设计:引入了TAdaBlock模块,能够灵活嵌入现有的卷积网络和视觉Transformer中,提升模型的时序理解能力。
    在这里插入图片描述

方法

  • 因子化卷积核调整:TAdaConv通过结合每一帧的局部和全局时序上下文,因子化调整卷积核的权重。具体来说,卷积核权重被分解为基础权重( W b W_b Wb)和校准权重( α t \alpha_t αt),公式为:
    W t = α t ⋅ W b W_t = \alpha_t \cdot W_b Wt=αtWb
    其中,校准权重根据输入特征的全局描述符生成。

  • 多头自注意力机制:在改进版本TAdaConvV2中,引入了多头自注意力机制,以增强全局时序信息的建模能力。

  • 时序特征聚合:提供了高效的时序特征聚合方案(如T-Pool),结合时序降采样进一步压缩计算量。

因子化卷积核调整

TAdaConv的因子化卷积核权重是通过将卷积核分解为基础权重和校准权重来实现的。这种方法旨在增强模型对时序信息的捕捉能力,同时保持计算效率。具体实现过程如下:

  1. 卷积核权重分解:在TAdaConv中,每一帧的卷积核权重被分解为两个部分:

    • 基础权重(Base Weight):这是一个固定的权重,对于所有帧都是相同的。
    • 校准权重(Calibration Weight):这是一个动态生成的权重,依据输入数据的时序特征进行调整。

    这种分解可以表示为:
    W t = α t ⋅ W b W_t = \alpha_t \cdot W_b Wt=αtWb
    其中, W t W_t Wt是每一帧的卷积核权重, W b W_b Wb是基础权重, α t \alpha_t αt是根据时序上下文动态生成的校准权重。

  2. 动态调整机制:TAdaConv设计了专门的时序自适应模块,用于生成和更新校准权重。这个模块能够根据输入数据的局部和全局时序特征进行动态调整,使得卷积核能够更好地适应不同时间尺度的特征。

  3. 低计算开销:通过这种因子化设计,TAdaConv在几乎不增加额外计算量的情况下,实现了时序推理能力的显著提升。这种低计算开销的特性使得TAdaConv在处理长序列数据时表现出色,同时保持了较高的计算效率。

  4. Tucker分解:TAdaConv还采用了Tucker分解技术来实现卷积权重的高效分解。Tucker分解可以将一个四维张量(即卷积核)分解为多个较小的张量,从而捕捉不同通道之间的交互信息,并动态调整卷积核的形状和参数,以适应不同的时序特征。

通过这些技术,TAdaConv能够有效地捕捉输入数据的时序特征,从而提高模型的性能和泛化能力。这种因子化卷积核权重的实现为传统卷积神经网络在处理时序数据时的局限性提供了新的解决方案。

多头自注意力机制

在TAdaConvV2中,多头自注意力机制(Multi-Head Self-Attention, MHSA)起到了关键的作用,主要体现在以下几个方面:

  1. 增强全局时序信息建模:TAdaConvV2通过引入多头自注意力机制,能够有效捕捉视频数据中的全局时序信息。传统的卷积操作在处理时序数据时往往局限于局部特征,而多头自注意力机制允许模型在不同的表示子空间中并行关注输入序列的不同部分,从而更全面地理解视频中的动态变化。

  2. 并行处理能力:多头自注意力机制的设计使得模型能够同时处理多个注意力头,每个头可以学习到不同的特征和关系。这种并行处理能力不仅提高了模型的表达能力,还加快了计算速度,适合处理复杂的时序数据。

  3. 捕捉多样化的依赖关系:通过多个注意力头,TAdaConvV2能够捕捉到视频帧之间的多样化依赖关系。例如,某些头可能专注于捕捉快速运动的特征,而其他头则可能关注于较慢的变化或背景信息。这种多样性使得模型在理解视频内容时更加灵活和准确。

  4. 提升模型的适应性:结合多头自注意力机制,TAdaConvV2能够更好地适应不同类型的视频数据和任务需求。模型可以根据输入的特征动态调整注意力分配,从而在不同场景下表现出更好的性能。

  5. 与其他模块的协同作用:在TAdaConvV2中,多头自注意力机制与其他模块(如动态卷积和时序特征聚合)协同工作,形成一个高效的时序建模框架。这种协同作用使得模型在处理复杂视频理解任务时,能够充分利用各个模块的优势,提升整体性能。

多头自注意力机制在TAdaConvV2中不仅增强了模型对时序信息的建模能力,还提升了其处理复杂视频数据的效率和准确性,为视频理解任务提供了强有力的支持。

试验结果

  • 消融实验:实验结果表明,动态校准权重显著提高了模型的时序建模能力。放松时间维度的不变性进一步增强了分类准确率。

  • 性能提升:在多个视频理解基准测试中,TAdaConv在动作识别和定位任务中表现出色,能够在多种基线模型上提升性能,且计算开销微乎其微。

  • 与传统模型比较:TAdaConv在保持较低计算成本的同时,提供了与传统复杂时序模型(如3D卷积网络、复杂Transformer)相当甚至更优的性能。
    在这里插入图片描述

总结

TAdaConv及其改进版本TAdaConvV2通过动态校准卷积核权重,结合局部和全局时序上下文,显著增强了模型的时序建模能力。其模块化设计使得TAdaConv能够灵活嵌入现代卷积网络和Transformer中,提升在动作识别和定位任务中的性能。这种创新设计不仅提高了模型的效率,还确保了在保持较低计算成本的同时,提供与传统复杂时序模型相当甚至更优的性能。代码:

import math
import warningsimport torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.modules.utils import _tripledef _no_grad_trunc_normal_(tensor, mean, std, a, b):# Cut & paste from PyTorch official master until it's in a few official releases - RW# Method based on https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdfdef norm_cdf(x):# Computes standard normal cumulative distribution functionreturn (1. + math.erf(x / math.sqrt(2.))) / 2.if (mean < a - 2 * std) or (mean > b + 2 * std):warnings.warn("mean is more than 2 std from [a, b] in nn.init.trunc_normal_. ""The distribution of values may be incorrect.",stacklevel=2)with torch.no_grad():# Values are generated by using a truncated uniform distribution and# then using the inverse CDF for the normal distribution.# Get upper and lower cdf valuesl = norm_cdf((a - mean) / std)u = norm_cdf((b - mean) / std)# Uniformly fill tensor with values from [l, u], then translate to# [2l-1, 2u-1].tensor.uniform_(2 * l - 1, 2 * u - 1)# Use inverse cdf transform for normal distribution to get truncated# standard normaltensor.erfinv_()# Transform to proper mean, stdtensor.mul_(std * math.sqrt(2.))tensor.add_(mean)# Clamp to ensure it's in the proper rangetensor.clamp_(min=a, max=b)return tensordef trunc_normal_(tensor, mean=0., std=1., a=-2., b=2.):# type: (Tensor, float, float, float, float) -> Tensorr"""Fills the input Tensor with values drawn from a truncatednormal distribution. The values are effectively drawn from thenormal distribution :math:`\mathcal{N}(\text{mean}, \text{std}^2)`with values outside :math:`[a, b]` redrawn until they are withinthe bounds. The method used for generating the random values worksbest when :math:`a \leq \text{mean} \leq b`.Args:tensor: an n-dimensional `torch.Tensor`mean: the mean of the normal distributionstd: the standard deviation of the normal distributiona: the minimum cutoff valueb: the maximum cutoff valueExamples:>>> w = torch.empty(3, 5)>>> nn.init.trunc_normal_(w)"""return _no_grad_trunc_normal_(tensor, mean, std, a, b)class LayerNorm(nn.Module):r""" LayerNorm that supports two data formats: channels_last (default) or channels_first.The ordering of the dimensions in the inputs. channels_last corresponds to inputs withshape (batch_size, height, width, channels) while channels_first corresponds to inputswith shape (batch_size, channels, height, width)."""def __init__(self, normalized_shape, eps=1e-6, data_format="channels_last"):super().__init__()self.weight = nn.Parameter(torch.ones(normalized_shape))self.bias = nn.Parameter(torch.zeros(normalized_shape))self.eps = epsself.data_format = data_formatif self.data_format not in ["channels_last", "channels_first"]:raise NotImplementedErrorself.normalized_shape = (normalized_shape,)def forward(self, x):if self.data_format == "channels_last":return F.layer_norm(x, self.normalized_shape, self.weight, self.bias, self.eps)elif self.data_format == "channels_first":u = x.mean(1, keepdim=True)s = (x - u).pow(2).mean(1, keepdim=True)x = (x - u) / torch.sqrt(s + self.eps)if len(x.shape) == 5:x = self.weight[:, None, None, None] * x + self.bias[:, None, None, None]elif len(x.shape) == 3:x = self.weight[:, None] * x + self.bias[:, None]return xclass QuickGELU(nn.Module):def forward(self, x: torch.Tensor):return x * torch.sigmoid(1.702 * x)class RouteFuncwTransformer(nn.Module):"""The routing function for generating the calibration weights."""def __init__(self, c_in, ratio, kernels, with_bias_cal=False, bn_eps=1e-5, bn_mmt=0.1, zero_init_cal=True,head_dim=64):"""Args:c_in (int): number of input channels.ratio (int): reduction ratio for the routing function.kernels (list): temporal kernel size of the stacked 1D convolutions"""super().__init__()self.c_in = c_inself.head_dim = head_dimself.with_bias_cal = with_bias_calself.avgpool = nn.AdaptiveAvgPool3d((None, 1, 1))self.globalpool = nn.AdaptiveAvgPool3d(1)self.a = nn.Conv3d(in_channels=c_in,out_channels=int(c_in // ratio),kernel_size=[kernels[0], 1, 1],padding=[kernels[0] // 2, 0, 0],)self.norm = LayerNorm(int(c_in // ratio), eps=1e-6, data_format="channels_first")self.norm_transformer = LayerNorm(int(c_in // ratio), eps=1e-6, data_format="channels_first")self.gelu = QuickGELU()self.scale = int(c_in // ratio) ** -0.5self.qkv_proj = nn.Conv3d(in_channels=int(c_in // ratio),out_channels=int(c_in // ratio) * 3,kernel_size=1,padding=0,)self.attn_out = nn.Conv3d(in_channels=int(c_in // ratio),out_channels=int(c_in // ratio),kernel_size=1,padding=0,)self.b = nn.Conv3d(in_channels=int(c_in // ratio),out_channels=c_in,kernel_size=[kernels[1], 1, 1],padding=[kernels[1] // 2, 0, 0],bias=False)self.zero_init_cal = zero_init_calif zero_init_cal:self.b.skip_init = Trueself.b.weight.data.zero_()  # to make sure the initial values# for the output is 1.if with_bias_cal:self.b_bias = nn.Conv3d(in_channels=int(c_in // ratio),out_channels=c_in,kernel_size=[kernels[1], 1, 1],padding=[kernels[1] // 2, 0, 0],bias=False)if zero_init_cal:self.b_bias.skip_init = Trueself.b_bias.weight.data.zero_()  # to make sure the initial values# for the output is 1.def forward(self, x):x = self.avgpool(x)x = self.a(x)x = self.norm(x)x = self.gelu(x)x = x + self.forward_attention(self.norm_transformer(x))if self.with_bias_cal:if self.zero_init_cal:return [self.b(x) + 1, self.b_bias(x) + 1]else:return [self.b(x), self.b_bias(x)]else:if self.zero_init_cal:return self.b(x) + 1else:return self.b(x)def forward_attention(self, x):b, c, t, _, _ = x.shapeqkv = self.qkv_proj(x)[:, :, :, 0, 0].view(b, 3, self.head_dim, c // self.head_dim, t).permute(1, 0, 3, 4, 2)q, k, v = qkv[0], qkv[1], qkv[2]attn = (q @ k.transpose(-2, -1)) * self.scaleattn = attn.softmax(dim=-1)x = (attn @ v).transpose(-2, -1).reshape(b, c, t)[:, :, :, None, None]x = self.attn_out(x)return x
class TAdaConv2dV2(nn.Module):"""Performs temporally adaptive 2D convolution.Currently, only application on 5D tensors is supported, which makes TAdaConv2dessentially a 3D convolution with temporal kernel size of 1."""def __init__(self, in_channels, out_channels, kernel_size,stride=1, padding=0, dilation=1, groups=1, bias=True,cal_dim="cin", num_frames=None, rf_r=4, rf_k=[3, 3], head_dim=64,internal_rf_func=True, internal_temp_aggr=True):super().__init__()"""Args:in_channels (int): number of input channels.out_channels (int): number of output channels.kernel_size (list): kernel size of TAdaConv2d. stride (list): stride for the convolution in TAdaConv2d.padding (list): padding for the convolution in TAdaConv2d.dilation (list): dilation of the convolution in TAdaConv2d.groups (int): number of groups for TAdaConv2d. bias (bool): whether to use bias in TAdaConv2d.cal_dim (str): calibrated dimension in TAdaConv2d. Supported input "cin", "cout".head_dim (int): head dimension for MHA in the rourting function."""kernel_size = _triple(kernel_size)stride = _triple(stride)padding = _triple(padding)dilation = _triple(dilation)assert kernel_size[0] == 1assert stride[0] == 1assert padding[0] == 0assert dilation[0] == 1assert cal_dim in ["cin", "cout"]self.in_channels = in_channelsself.out_channels = out_channelsself.kernel_size = kernel_sizeself.stride = strideself.padding = paddingself.dilation = dilationself.groups = groupsself.cal_dim = cal_dimself.num_frames = num_framesif internal_rf_func:self.rf_func = RouteFuncwTransformer(c_in=out_channels,ratio=rf_r,kernels=rf_k,with_bias_cal=bias,zero_init_cal=False,head_dim=head_dim)if internal_temp_aggr:self.bn_a = nn.BatchNorm3d(out_channels)self.bn_b = nn.BatchNorm3d(out_channels)self.bn_b.skip_init = Trueself.bn_b.weight.data.zero_()self.bn_b.bias.data.zero_()self.avgpool = nn.AvgPool3d(kernel_size=(3, 1, 1), stride=(1, 1, 1), padding=(1, 0, 0))# base weights (W_b)self.weight = nn.Parameter(torch.Tensor(1, 1, out_channels, in_channels // groups, kernel_size[1], kernel_size[2]))if bias:self.bias = nn.Parameter(torch.Tensor(1, 1, out_channels))else:self.register_parameter('bias', None)trunc_normal_(self.weight, std=.02)if self.bias is not None:nn.init.constant_(self.bias, 0)self.apply(self._init_weights)def _init_weights(self, m):if isinstance(m, (nn.Conv3d, nn.Linear)):if hasattr(m, "skip_init") and m.skip_init:returntrunc_normal_(m.weight, std=.02)if m.bias is not None:nn.init.constant_(m.bias, 0)def forward(self, feat, reshape_required=True, alpha=None):"""Args:feat (tensor): feature to perform convolution on.reshape_required (bool): True if intput feat is the shape of (L, N, C),where N=B*T"""if reshape_required:assert self.num_frames is not Noneh = w = int(math.sqrt(feat.shape[0]))# L, N, C -> H, W, B, T, Cfeat = feat.reshape(h, w, -1, self.num_frames, feat.shape[-1]).permute(2, 4, 3, 0, 1)# generate calibration factorsif alpha is None:alpha = self.rf_func(feat)if isinstance(alpha, list):w_alpha, b_alpha = alpha[0], alpha[1]else:w_alpha = alphab_alpha = None_, _, c_out, c_in, kh, kw = self.weight.size()b, c_in, t, h, w = feat.size()feat = feat.permute(0, 2, 1, 3, 4).reshape(1, -1, h, w)if self.cal_dim == "cin":# w_alpha: B, C, T, H(1), W(1) -> B, T, C, H(1), W(1) -> B, T, 1, C, H(1), W(1)# corresponding to calibrating the input channelweight = (w_alpha.permute(0, 2, 1, 3, 4).unsqueeze(2) * self.weight).reshape(-1, c_in // self.groups, kh,kw)elif self.cal_dim == "cout":# w_alpha: B, C, T, H(1), W(1) -> B, T, C, H(1), W(1) -> B, T, C, 1, H(1), W(1)# corresponding to calibrating the input channelweight = (w_alpha.permute(0, 2, 1, 3, 4).unsqueeze(3) * self.weight).reshape(-1, c_in // self.groups, kh,kw)bias = Noneif self.bias is not None:if b_alpha is not None:# b_alpha: B, C, T, H(1), W(1) -> B, T, C, H(1), W(1) -> B, T, Cbias = (b_alpha.permute(0, 2, 1, 3, 4).squeeze() * self.bias).reshape(-1)else:bias = self.bias.repeat(b, t, 1).reshape(-1)output = F.conv2d(feat, weight=weight, bias=bias, stride=self.stride[1:], padding=self.padding[1:],dilation=self.dilation[1:], groups=self.groups * b * t)output = output.view(b, t, c_out, h, w).permute(0, 2, 1, 3, 4)if hasattr(self, "bn_a") and hasattr(self, "bn_b"):output = self.bn_a(output) + self.bn_b(self.avgpool(output))if reshape_required:output = output.permute(3, 4, 0, 2, 1).reshape(h * w, b * t, c_out)return outputdef __repr__(self):return f"TAdaConv2dV2({self.in_channels}, {self.out_channels}, kernel_size={self.kernel_size}, " + \f"stride={self.stride}, padding={self.padding}, bias={self.bias is not None}, cal_dim=\"{self.cal_dim}\")"if __name__ == '__main__':B, C,T, H, W = 1, 64, 8, 40, 40input_tensor = torch.randn(B, C,T, H, W)  # 随机生成输入张量alpha_tensor = torch.rand(1, 64, 8, 1, 1)# 初始化 CBlockdim = C  # 输入和输出通道数# 创建 CBlock 实例block = TAdaConv2dV2(in_channels=dim,out_channels=dim,kernel_size=[1,3,5],stride=[1,1,1],padding=[0,1,2])# 如果GPU可用将模块移动到 GPUdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu")block = block.to(device)print(block)input_tensor = input_tensor.to(device)alpha_tensor=alpha_tensor.to(device)# 执行前向传播output = block(input_tensor,False,alpha_tensor)# 打印输入和输出的形状print(f"Input: {input_tensor.shape}")print(f"Output: {output.shape}")

在这里插入图片描述

相关文章:

【Block总结】TAdaConv时序自适应卷积,轻量高效的时间建模卷积|即插即用

论文解读&#xff1a;Temporally-Adaptive Models for Efficient Video Understanding 论文信息 标题&#xff1a;Temporally-Adaptive Models for Efficient Video Understanding 发表时间&#xff1a;2023年 作者&#xff1a;黄子渊等 论文链接&#xff1a;arXiv 论文 代…...

Spring Boot 项目启动报错 “找不到或无法加载主类” 解决笔记

一、问题描述 在使用 IntelliJ IDEA 开发基于 Spring Boot 框架的 Java 程序时&#xff0c;原本项目能够正常启动。但在后续编写代码并重建项目后&#xff0c;再次尝试运行却出现了 “错误&#xff1a;找不到或无法加载主类 com.example.springboot.SpringbootApplication” 的…...

CSS 网络安全字体

适用于 HTML 和 CSS 的最佳 Web 安全字体 下面列出了适用于 HTM L和 CSS 的最佳 Web 安全字体&#xff1a; Arial (sans-serif)Verdana (sans-serif)Helvetica (sans-serif)Tahoma (sans-serif)Trebuchet MS (sans-serif)Times New Roman (serif)Georgia (serif)Garamond (se…...

Linux高并发服务器开发 第十五天(fork函数)

目录 1.fork 函数 1.1创建子进程 1.2getpid 函数 1.3getppid 函数 1.4getgid函数 1.5循环创建 n 个子进程 1.6fork后父子进程异同 1.6.1读时共享&#xff0c;写时复制 1.6.2fork后父子进程共享 1.6.3gdb调试父子进程 1.fork 函数 pid_t fork(void); 成功&#xff1a;…...

【人工智能】Python中的自动化机器学习(AutoML):如何使用TPOT优化模型选择

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门&#xff01; 解锁Python编程的无限可能&#xff1a;《奇妙的Python》带你漫游代码世界 随着机器学习在各行业的广泛应用&#xff0c;模型选择和优化成为了数据科学家面临的主要挑战之一。自动化机器学习&am…...

探秘自然地理:从太阳到地球的奇妙之旅与灾害预警

在浩瀚无垠的宇宙中&#xff0c;我们的地球与太阳紧密相连&#xff0c;它们的奥秘和变化&#xff0c;时刻影响着我们的生活。今天&#xff0c;就让我们一同深入探索自然地理的基础知识&#xff0c;揭开太阳与地球的神秘面纱&#xff0c;同时了解那些可能给我们带来巨大影响的自…...

go语言zero框架通过chromedp实现网页在线截图的设计与功能实现

在 GoZero 框架中实现网页在线截图的功能&#xff0c;可以通过集成 chromedp 库来控制 Chrome 浏览器进行截图。chromedp 是一个基于 Chrome DevTools 协议的 Go 包&#xff0c;可以用来在 Go 程序中模拟浏览器操作&#xff0c;如页面截图、DOM 操作、表单提交等。 下面是一个…...

AI发展困境:技术路径与实践约束的博弈

标题&#xff1a;AI发展困境&#xff1a;技术路径与实践约束的博弈 文章信息摘要&#xff1a; AI技术发展路径主要受实践约束驱动&#xff0c;而非纯理论优势。大型AI实验室的成功更依赖优质执行力和资源优势&#xff0c;而非独特技术创新。当前AI发展面临评估体系与实际应用脱…...

[前端算法]排序算法

在js中一般用到sort方法 arr.sort((a,b)>{return a-b })基础排序 冒泡排序 function bubbleSort(arr) {let len arr.length;for (let i 0; i < len; i) {for(let j0;j<len-i-1;j){if(arr[j]>arr[j1]){[arr[j],arr[j1]] [arr[j1],arr[j]]}}}console.log(arr);…...

Zemax STAR 模块的入门设置

Zemax OpticStudio 中的 STAR 模块允许直接导入来自有限元分析 &#xff08;FEA&#xff09; 软件的变形数据&#xff0c;从而将光学设计与热和结构分析联系起来。这种集成可以分析实际环境因素&#xff08;如热和机械应力&#xff09;对光学性能的影响。该模块有助于了解光学系…...

知识图谱的语义叙事:构建智慧的连贯之路

目录 前言1. 什么是知识图谱的语义叙事1.1 语义清晰性1.2 叙事连贯性1.3 背景关联性 2. 知识图谱语义叙事的核心功能2.1 增强信息的可理解性2.2 提供上下文支持2.3 支持推理与发现2.4 提升知识可视化效果 3. 语义叙事的关键实现技术3.1 自然语言处理&#xff08;NLP&#xff09…...

Oracle graph 图数据库体验-安装篇

服务端安装 环境准备 安装数据库 DOCKER 安装23AI FREE &#xff0c;参考&#xff1a; https://container-registry.oracle.com/ords/f?p113:4:111381387896144:::4:P4_REPOSITORY,AI_REPOSITORY,AI_REPOSITORY_NAME,P4_REPOSITORY_NAME,P4_EULA_ID,P4_BUSINESS_AREA_ID:1…...

Nginx:从入门到实战使用教程

全方位解析Nginx&#xff1a;从入门到实战使用教程 Nginx安装、配置详细教程 文章目录 全方位解析Nginx&#xff1a;从入门到实战使用教程导语一、Nginx简介二、Nginx安装与配置 1. 在CentOS系统上安装Nginx&#xff1a;2. 在Ubuntu系统上安装Nginx&#xff1a;3. Nginx配置文…...

网络安全:信息时代的守护者

随着互联网的快速发展&#xff0c;网络安全问题日益成为全球关注的焦点。无论是个人用户、企业组织还是政府部门&#xff0c;网络安全都已成为保障信息安全、保护隐私、确保社会秩序的基石。在这个数字化时代&#xff0c;如何应对复杂多变的网络安全威胁&#xff0c;成为了我们…...

Visual Studio Code + Stm32 (IAR)

记录一下&#xff0c; 以前看别人在 vsc 下配置 stm32 工程非常麻烦。 最近&#xff0c;突然发现&#xff0c; iar 官方出了两个插件&#xff0c; iar build 、 iar C-Spy 安装之后&#xff0c;配置一下 iar 软件路径。 然后&#xff0c;直接打开工程目录&#xff0c;编译…...

JavaScript语言的正则表达式

JavaScript语言的正则表达式详解 正则表达式&#xff08;Regular Expression&#xff0c;简称Regex或RegExp&#xff09;是一种强大的文本处理工具&#xff0c;可以在字符串中执行模式匹配和替换操作。在JavaScript中&#xff0c;正则表达式是处理字符串时不可或缺的部分&…...

R语言的编程范式

R语言的编程范式探讨 引言 R语言作为一种专门用于统计分析和数据可视化的编程语言&#xff0c;近年来得到了广泛的应用。无论是在学术研究、企业分析&#xff0c;还是在数据科学的各个领域&#xff0c;R语言凭借其强大的数据处理能力和丰富的图形化工具&#xff0c;吸引了大批…...

CentOS9 安装Docker+Dpanel+onlyoffice(https、更改字体、字号、去除限制)的避坑笔记

CentOS9 安装Dockeronlyoffice&#xff08;https、更改字体、字号、去除限制&#xff09;的避坑笔记 一、安装Docker二、更新docker镜像源&#xff1a;三、安装Dpanel四、安装onlyoffice五、更改字体和字号六、去除限制 动手前&#xff0c;预防遭遇各种莫名奇妙的问题&#xff…...

Excel 技巧11 - 如何使用Excel作成简单的排班表(★★),weekday 函数,TEXT函数

本文讲了如何在Excel中制作简单的排班表。 1&#xff0c;排班表Layout效果 - B2 单元格找那个输入 日期 - C3 - AG3 输入日&#xff0c;就是该月份的几号&#xff0c;比如1月5号&#xff0c;就输入5 如果是周六周日&#xff0c;背景色显示为绿色 - B4 ~ 输入员工名称 当 B2…...

StarRocks 怎么让特定的SQL路由到FE master节点的

背景 本文基于 StarRocks 3.1.7 大家都知道对于Starrocks来说 FE 是分 master和follower的&#xff0c;而只有master节点才能对元数据进行写操作。但是为什么呢&#xff1f;哪里有体现呢&#xff1f; 这其中的原因在网上是搜不到的&#xff0c;所以大家只知道只有master节点才…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)

Name&#xff1a;3ddown Serial&#xff1a;FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名&#xff1a;Axure 序列号&#xff1a;8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...