2024.6.9周报

目录

摘要

ABSTRACT

一、文献阅读

1、相关信息

2、摘要

3、文献解读

1、Introduction

2、文章主要贡献

3、模型架构

4、实验

4、结论

二、代码实现

总结

摘要

本周我阅读了一篇题目为《Unlocking the Potential of Transformers in Time Series Forecasting with Sharpness-Aware Minimization and Channel-Wise Attention》的文献,该文献引入了一种浅层、轻量级的Transformer模型(SAMformer),该模型采用锐度感知优化技术。SAMformer不仅能克服不良的局部最小值,而且在各种真实世界的多变量时间序列数据集中的表现也超过了领先的TSMixer模型14.33%,同时其参数数量大约少了4倍。其次通过其代码实现,对论文中的实验部分有了更深的了解。

ABSTRACT

This week, a literature review was conducted on a paper titled "Unlocking the Potential of Transformers in Time Series Forecasting with Sharpness-Aware Minimization and Channel-Wise Attention". In this paper, a shallow, lightweight transformer model known as SAMformer was introduced, which is optimized using sharpness-aware techniques. The SAMformer not only overcomes poor local minima but also outperforms the leading TSMixer model by 14.33% across various real-world multivariate time series datasets, while having approximately four times fewer parameters. Furthermore, a deeper understanding of the experimental section of the paper was gained through the implementation of its code.

一、文献阅读

1、相关信息

Title:Unlocking the Potential of Transformers in Time Series Forecasting with Sharpness-Aware Minimization and Channel-Wise Attention

期刊/会议:ICML 2024

链接:https://arxiv.org/abs/2402.10198

2、摘要

基于Transformer的模型在自然语言处理和计算机视觉中表现出色,但在多变量长期预测中的表现却不如简单的线性模型。本研究揭示了尽管Transformer的模型复杂,但在基本的线性预测场景中,它们难以达到最优解决方案,主要是因为它们的注意力机制的泛化能力较低。为了解决这个问题,我们引入了一种浅层、轻量级的Transformer模型(SAMformer),该模型采用锐度感知优化技术。SAMformer不仅能克服不良的局部最小值,而且在各种真实世界的多变量时间序列数据集中的表现也超过了领先的TSMixer模型14.33%,同时其参数数量大约少了4倍。

Transformer-based models excel in natural language processing and computer vision but underperform compared to simple linear models in multivariate long-term forecasting. This study reveals that despite their complexity, transformers struggle to reach optimal solutions in a basic linear forecasting scenario, primarily due to their attention mechanism's low generalization ability. To address this, we introduce a shallow, lightweight transformer model (SAMformer) optimized with sharpness-aware techniques. SAMformer not only overcomes poor local minima but also outperforms the leading TSMixer model by 14.33% across various real-world multivariate time series datasets, all while being significantly more parameter-efficient.

3、文献解读

1、Introduction

Transformer在处理序列数据方面表现出特别的效率,这自然促使其应用于时间序列分析。不少研究试图提出针对时间序列的特定的Transformer架构,以利用其捕捉时间交互的能力。然而,当前在多变量时间序列预测方面的最先进模型是基于简单的MLP(多层感知机)模型,它显著优于基于Transformer的方法。最近将Transformer应用于时间序列数据的研究主要集中在两个方面:一是实现高效的注意力机制,以降低其计算成本;二是分解时间序列以更好地捕捉其中的模式。本文的研究提出了一种浅层的Transformer模型,名为SAMformer,该模型采用了研究社区提出的最佳实践,包括可逆实例归一化和通道注意力。我们展示了通过使用锐度感知最小化(SAM)优化这样一个简单的Transformer,可以收敛到具有更好泛化能力的局部最小值。我们的实证结果表明,我们的方法在常见的多变量长期预测数据集上具有优越性。SAMformer在平均性能上提高了14.33%,同时参数数量大约减少了四倍。

2、文章主要贡献

1、Transformer推广不佳,收敛到尖锐的局部极小值,即使在一个简单的玩具线性预测问题,作者确定主要是注意力的原因。

2、文章提出了一个浅层Transformer模型,称为SAMformer,它结合了研究界提出的最佳实践,包括可逆实例归一化和通道注意力。文章表明,优化这样一个简单的Transformer与sharpnessware最小化(SAM)允许收敛到局部最小值,更好的推广。

3、SAMformer将当前最先进的多变量模型TSMixer平均提高了14.33%,同时参数减少了104倍。

3、模型架构

首先将可逆实例归一化(RevIN)应用于X(该技术被证明在处理时间序列中训练数据和测试数据之间的转换方面是有效的)。其次使用SAM优化模型,使其收敛到平坦的局部最小值。

4、实验

1、数据集

数据集:the 4 Electricity Transformer Temperature datasets ETTh1, ETTh2, ETTm1 and ETTm2 , Electricity, Exchange , Traffic , and Weather datasets.

数据量:4个电力变压器温度数据集ETTm1、ETTm2、ETTh1和ETTh2 包含了2016年7月至2018年7月电力变压器采集的时间序列。Electricity 包含了321个客户从2012年到2014年的用电量时间序列。Exchange 包含了1990年至2016年8个国家之间每日汇率的时间序列。Traffic包含2015年1月至2016年12月862个传感器捕获的道路占用率时间序列。Weather包含了2020年21个天气指标记录的气象信息的时间序列。

2、参数设置

对于SAMformer和Transformer,模型的维数设置为16,在我们所有的实验中保持不变,使用Adam优化器,批量大小为32,对于使用SAM训练的SAMformer和TSMixer,使用的邻域大小ρ*值如表3所示。ETT数据集的训练/验证/测试分割为12/4/4个月,其他数据集为70%/20%/10%。我们使用回看窗口L = 512,并使用步幅为1的滑动窗口来创建序列。训练损失是多元时间序列上的MSE。训练在300个epoch中进行,我们使用提前停止,patience为5个epoch。对于每个数据集、基线和预测水平H∈{96,192,336,720},每个实验用不同的种子运行5次,我们显示5次试验的测试MSE和MAE的平均值和标准差。

3、实验结果

在SAMformer的训练中引入SAM,使其损耗比Transformer更平滑。我们在上图a中通过比较
在ETTh1和Exchange上训练后Transformer和SAMformer的\lambda _{max}值来说明这一点。我们的观察表明,Transformer表现出相当高的清晰度,而SAMformer有一个理想的行为,损失景观清晰度是一个数量级小。 

SAMformer演示了针对随机初始化的反业务。图5b - 1给出了SAMformer和Transformer在ETTh1
和Exchange上5种不同种子的试验MSE分布,预测水平为H = 96。SAMformer在不同的种子选择中始终保持性能稳定性,而Transformer表现出显著的差异,因此高度依赖于权重初始化。

SAMformer在8个数据集中的7个上明显优于其竞争对手。特别是,它比其最
佳竞争对手TSMixer+SAM提高了5.25%,比独立TSMixer提高了14.33%,比基于变压器的最佳模型FEDformer提高了12.36%。此外,它比Transformer提高了16.96%。对于每个数据集和视界,SAMformer被排名第一或第二。值得注意的是,SAM的集成提高了TSMixer的泛化能力,平均提高了9.58%。

4、结论

作者提出的SAMformer,通过锐度感知最小化优化,与现有的预测基线相比,可以获得显着的性能提升,并受益于跨数据集和预测范围的高通用性和鲁棒性。在时间序列预测中,channel-wise attention比以前常用的temporal attention在计算和性能方面都更有效。我们相信这一令人惊讶的发现可能会在我们的简单架构之上激发许多进一步的工作,以进一步改进它。

二、代码实现

1、attention实现

这段代码定义了一个使用PyTorch库的函数,实现了缩放点积注意力机制,用于模型中的注意力计算。它接受查询(query)、键(key)和值(value)张量,并可选地接受注意力掩码和丢失概率参数。函数首先计算查询和键的点积,并根据查询的维度大小进行缩放。如果指定了因果关系或提供了注意力掩码,它会修改注意力权重以避免未来信息的泄露或应用额外的掩码。最后,它使用Softmax函数规范化注意力权重,并通过点积操作与值张量结合,输出最终的注意力加权结果。

import torch

import numpy as np


def scaled_dot_product_attention(query, key, value, attn_mask=None, dropout_p=0.0, is_causal=False, scale=None):
    """
    A copy-paste from https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_dot_product_attention.html
    """
    L, S = query.size(-2), key.size(-2)
    scale_factor = 1 / np.sqrt(query.size(-1)) if scale is None else scale
    attn_bias = torch.zeros(L, S, dtype=query.dtype, device=query.device)
    if is_causal:
        assert attn_mask is None
        temp_mask = torch.ones(L, S, dtype=torch.bool, device=query.device).tril(diagonal=0)
        attn_bias.masked_fill_(temp_mask.logical_not(), float("-inf"))
        attn_bias.to(query.dtype)

    if attn_mask is not None:
        if attn_mask.dtype == torch.bool:
            attn_bias.masked_fill_(attn_mask.logical_not(), float("-inf"))
        else:
            attn_bias += attn_mask
    attn_weight = query @ key.transpose(-2, -1) * scale_factor
    attn_weight += attn_bias
    attn_weight = torch.softmax(attn_weight, dim=-1)
    attn_weight = torch.dropout(attn_weight, dropout_p, train=True)
    return attn_weight @ value

2、dataset处理

这段代码定义了一个Python类 LabeledDataset,它是一个继承自 torch.utils.data.Dataset 的自定义数据集类,用于处理带有标签的数据。该类的主要作用是将 NumPy 数组格式的数据和标签转换为 PyTorch 张量格式,并提供了一些基本的数据处理方法,使其可以用于 PyTorch 的数据加载和预处理流程中。

import torch

from torch.utils.data import Dataset


class LabeledDataset(Dataset):
    def __init__(self, x, y):
        """
        Converts numpy data to a torch dataset
        Args:
            x (np.array): data matrix
            y (np.array): class labels
        """
        self.x = torch.FloatTensor(x)
        self.y = torch.FloatTensor(y)

    def transform(self, x):
        return torch.FloatTensor(x)

    def __len__(self):
        return self.y.shape[0]

    def __getitem__(self, idx):
        examples = self.x[idx]
        labels = self.y[idx]
        return examples, labels

3、Revin

这段代码定义了一个名为 RevIN(Reversible Instance Normalization)的 Python 类,它继承自 PyTorch 的 nn.Module。这个类实现了可逆的实例归一化,主要用于神经网络中,可以在正向传播时进行标准化,并在需要时进行反向去标准化。

import torch
import torch.nn as nn


class RevIN(nn.Module):
    """
    Reversible Instance Normalization (RevIN) https://openreview.net/pdf?id=cGDAkQo1C0p
    https://github.com/ts-kim/RevIN
    """
    def __init__(self, num_features: int, eps=1e-5, affine=True):
        """
        :param num_features: the number of features or channels
        :param eps: a value added for numerical stability
        :param affine: if True, RevIN has learnable affine parameters
        """
        super(RevIN, self).__init__()
        self.num_features = num_features
        self.eps = eps
        self.affine = affine
        if self.affine:
            self._init_params()

    def forward(self, x, mode:str):
        if mode == 'norm':
            self._get_statistics(x)
            x = self._normalize(x)
        elif mode == 'denorm':
            x = self._denormalize(x)
        else: raise NotImplementedError
        return x

    def _init_params(self):
        # initialize RevIN params: (C,)
        self.affine_weight = nn.Parameter(torch.ones(self.num_features))
        self.affine_bias = nn.Parameter(torch.zeros(self.num_features))

    def _get_statistics(self, x):
        dim2reduce = tuple(range(1, x.ndim-1))
        self.mean = torch.mean(x, dim=dim2reduce, keepdim=True).detach()
        self.stdev = torch.sqrt(torch.var(x, dim=dim2reduce, keepdim=True, unbiased=False) + self.eps).detach()

    def _normalize(self, x):
        x = x - self.mean
        x = x / self.stdev
        if self.affine:
            x = x * self.affine_weight
            x = x + self.affine_bias
        return x

    def _denormalize(self, x):
        if self.affine:
            x = x - self.affine_bias
            x = x / (self.affine_weight + self.eps*self.eps)
        x = x * self.stdev
        x = x + self.mean
        return x

4、sam 

这段代码定义了一个名为 SAM 的 Python 类,它是一个用于优化神经网络训练的自定义优化器,继承自 PyTorch 的 OptimizerSAM 代表 Sharpness-Aware Minimization,这是一种用于改进模型泛化能力的优化技术,通过最小化损失函数的锐度来实现。

import torch

from torch.optim import Optimizer


class SAM(Optimizer):
    """
    SAM: Sharpness-Aware Minimization for Efficiently Improving Generalization https://arxiv.org/abs/2010.01412
    https://github.com/davda54/sam
    """

    def __init__(self, params, base_optimizer, rho=0.05, adaptive=False, **kwargs):
        assert rho >= 0.0, f"Invalid rho, should be non-negative: {rho}"

        defaults = dict(rho=rho, adaptive=adaptive, **kwargs)
        super(SAM, self).__init__(params, defaults)

        self.base_optimizer = base_optimizer(self.param_groups, **kwargs)
        self.param_groups = self.base_optimizer.param_groups

    @torch.no_grad()
    def first_step(self, zero_grad=False):
        grad_norm = self._grad_norm()
        for group in self.param_groups:
            scale = group["rho"] / (grad_norm + 1e-12)

            for p in group["params"]:
                if p.grad is None:
                    continue
                e_w = (
                    (torch.pow(p, 2) if group["adaptive"] else 1.0)
                    * p.grad
                    * scale.to(p)
                )
                p.add_(e_w)  # climb to the local maximum "w + e(w)"
                self.state[p]["e_w"] = e_w

        if zero_grad:
            self.zero_grad()

    @torch.no_grad()
    def second_step(self, zero_grad=False):
        for group in self.param_groups:
            for p in group["params"]:
                if p.grad is None:
                    continue
                p.sub_(self.state[p]["e_w"])  # get back to "w" from "w + e(w)"

        self.base_optimizer.step()  # do the actual "sharpness-aware" update

        if zero_grad:
            self.zero_grad()

    @torch.no_grad()
    def step(self, closure=None):
        assert (
            closure is not None
        ), "Sharpness Aware Minimization requires closure, but it was not provided"
        closure = torch.enable_grad()(
            closure
        )  # the closure should do a full forward-backward pass

        self.first_step(zero_grad=True)
        closure()
        self.second_step()

    def _grad_norm(self):
        shared_device = self.param_groups[0]["params"][
            0
        ].device  # put everything on the same device, in case of model parallelism
        norm = torch.norm(
            torch.stack(
                [
                    ((torch.abs(p) if group["adaptive"] else 1.0) * p.grad)
                    .norm(p=2)
                    .to(shared_device)
                    for group in self.param_groups
                    for p in group["params"]
                    if p.grad is not None
                ]
            ),
            p=2,
        )
        return norm

5、samformer

这段代码定义了两个主要的 Python 类,SAMFormerArchitectureSAMFormer,它们基于 PyTorch 框架用于构建和训练一个深度学习模型,具体是用于时间序列预测任务。这些类利用了一些先进的技术如可逆实例归一化(RevIN)、注意力机制和锐度感知最小化(SAM)来改善模型的预测性能和泛化能力。

import torch
import random
import numpy as np

from tqdm import tqdm
from torch import nn
from torch.utils.data import DataLoader

from .utils.attention import scaled_dot_product_attention
from .utils.dataset import LabeledDataset
from .utils.revin import RevIN
from .utils.sam import SAM


class SAMFormerArchitecture(nn.Module):
    def __init__(self, num_channels, seq_len, hid_dim, pred_horizon, use_revin=True):
        super().__init__()
        self.revin = RevIN(num_features=num_channels)
        self.compute_keys = nn.Linear(seq_len, hid_dim)
        self.compute_queries = nn.Linear(seq_len, hid_dim)
        self.compute_values = nn.Linear(seq_len, seq_len)
        self.linear_forecaster = nn.Linear(seq_len, pred_horizon)
        self.use_revin = use_revin

    def forward(self, x):
        # RevIN Normalization
        if self.use_revin:
            x_norm = self.revin(x.transpose(1, 2), mode='norm').transpose(1, 2) # (n, D, L)
        else:
            x_norm = x
        # Channel-Wise Attention
        queries = self.compute_queries(x_norm) # (n, D, hid_dim)
        keys = self.compute_keys(x_norm) # (n, D, hid_dim)
        values = self.compute_values(x_norm) # (n, D, L)
        if hasattr(nn.functional, 'scaled_dot_product_attention'):
            att_score = nn.functional.scaled_dot_product_attention(queries, keys, values) # (n, D, L)
        else:
            att_score = scaled_dot_product_attention(queries, keys, values) # (n, D, L)
        out = x_norm + att_score # (n, D, L)
        # Linear Forecasting
        out = self.linear_forecaster(out) # (n, D, H)
        # RevIN Denormalization
        if self.use_revin:
            out = self.revin(out.transpose(1, 2), mode='denorm').transpose(1, 2) # (n, D, H)
        return out.reshape([out.shape[0], out.shape[1]*out.shape[2]])


class SAMFormer:
    """
    SAMFormer pytorch trainer implemented in the sklearn fashion
    """
    def __init__(self, device='cuda:0', num_epochs=100, batch_size=256, base_optimizer=torch.optim.Adam,
                 learning_rate=1e-3, weight_decay=1e-5, rho=0.5, use_revin=True, random_state=None):
        self.network = None
        self.criterion = nn.MSELoss()
        self.device = device
        self.num_epochs = num_epochs
        self.batch_size = batch_size
        self.base_optimizer = base_optimizer
        self.learning_rate = learning_rate
        self.weight_decay = weight_decay
        self.rho = rho
        self.use_revin = use_revin
        self.random_state = random_state

    def fit(self, x, y):
        if self.random_state is not None:
            torch.manual_seed(self.random_state)
            random.seed(self.random_state)
            np.random.seed(self.random_state)
            torch.cuda.manual_seed_all(self.random_state)

        self.network = SAMFormerArchitecture(num_channels=x.shape[1], seq_len=x.shape[2], hid_dim=16,
                                             pred_horizon=y.shape[1] // x.shape[1], use_revin=self.use_revin)
        self.criterion = self.criterion.to(self.device)
        self.network = self.network.to(self.device)
        self.network.train()

        optimizer = SAM(self.network.parameters(), base_optimizer=self.base_optimizer, rho=self.rho,
                        lr=self.learning_rate, weight_decay=self.weight_decay)

        train_dataset = LabeledDataset(x, y)
        data_loader_train = DataLoader(train_dataset, batch_size=self.batch_size, shuffle=True)

        progress_bar = tqdm(range(self.num_epochs))
        for epoch in progress_bar:
            loss_list = []
            for (x_batch, y_batch) in data_loader_train:
                x_batch = x_batch.to(self.device)
                y_batch = y_batch.to(self.device)
                # =============== forward ===============
                out_batch = self.network(x_batch)
                loss = self.criterion(out_batch, y_batch)
                # =============== backward ===============
                if optimizer.__class__.__name__ == 'SAM':
                    loss.backward()
                    optimizer.first_step(zero_grad=True)

                    out_batch = self.network(x_batch)
                    loss = self.criterion(out_batch, y_batch)

                    loss.backward()
                    optimizer.second_step(zero_grad=True)
                else:
                    optimizer.zero_grad()
                    loss.backward()
                    optimizer.step()
                loss_list.append(loss.item())
            # =============== save model / update log ===============
            train_loss = np.mean(loss_list)
            self.network.train()
            progress_bar.set_description("Epoch {:d}: Train Loss {:.4f}".format(epoch, train_loss), refresh=True)
        return

    def forecast(self, x, batch_size=256):
        self.network.eval()
        dataset = torch.utils.data.TensorDataset(torch.tensor(x, dtype=torch.float))
        dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=False)
        outs = []
        for _, batch in enumerate(dataloader):
            x = batch[0].to(self.device)
            with torch.no_grad():
                out = self.network(x)
            outs.append(out.cpu())
        outs = torch.cat(outs)
        return outs.cpu().numpy()

    def predict(self, x, batch_size=256):
        return self.forecast(x, batch_size=batch_size)

总结

本文讨论了在时间序列预测中运用转换器模型的挑战与创新。传统的基于Transformer的模型虽然在自然语言处理和计算机视觉领域表现出色,但在多变量长期预测任务上,它们的性能却不及简单的线性模型。研究中指出,这些模型在基本的线性预测场景中难以实现最佳解决方案,主要问题在于其注意力机制的泛化能力较差。为应对这一问题,研究提出了一种新型的浅层、轻量级Transformer模型,即SAMformer。该模型采用锐度感知优化(SAM),有效克服了不良的局部最小值,显著提高了模型在多变量时间序列数据集上的性能,性能提升幅度达14.33%,且模型的参数数量大约减少了四倍。此外,SAMformer展示了优越的泛化能力和鲁棒性,其在多个数据集上的表现均优于当前先进的多变量模型TSMixer。研究结果表明,采用channel-wise注意力机制的SAMformer在计算和性能方面都比传统的temporal attention更为有效,为时间序列预测领域提供了新的视角和方法。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

三十四篇:办公效率革命:深入探索办公自动化系统的全面策略

办公效率革命:深入探索办公自动化系统的全面策略 1. 引言 1.1 办公自动化系统(OAS)的定义与关键作用 在当前的企业环境中,办公自动化系统(Office Automation System, OAS)已成为提高效率和执行力的关键技…

全面守护你的健康ZL-0891A小动物多参数监护仪

简单介绍: 12.1英寸彩色TFT显示,分辨率800X600,采用数字血氧DSP算法,低灌注,小动物多参数监护仪具有优良的抗运动性能;动物用血压算法,支持测量各种动物类型,特有的中英文语音报警;支持USB数据导出,可以在…

嵌入式学习记录6.6(拷贝构造/友元函数/常成员函数)

一.拷贝构造函数和拷贝赋值函数 1.1拷贝构造函数功能,格式 拷贝构造函数是一种特殊的构造函数,用来将一个类对象给另一个类对象初始化使用的。 1> 用一个类对象给另一个类对象初始化时,会自动调用拷贝构造函数。 2> 当一个类对作为函数的实参&…

jdk快速配置

在系统变量新建两个变量先下载,直接安装 jdk-****-windows-x64 名称,看看面对java安装目录,我这里是默认目录为例 1.JAVA_HOME C:\Program Files\Java\jdk-1.82.CLASSPATH .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jarpath里新建这两个…

韩顺平0基础学java——第18天

p374-395 类变量和类方法 类变量(静态变量) 例: class Child{ public static Int count;//这个count可以被所有Child实例共享 /..../ } 内存中,static在堆中是独立存放的,并不在某个对象的空间中。 由于…

【数据结构】C语言实现二叉树的基本操作——二叉树的遍历(先序遍历、中序遍历、后序遍历)

C语言实现二叉树的基本操作 导读一、二叉树的遍历二、先序遍历三、中序遍历四、后序遍历五、结点序列六、递归算法与非递归算法的转化结语 导读 大家好,很高兴又和大家见面啦!!! 通过前面的介绍,我们已经认识了二叉树…

SAP 限制物料类型在BOM组件中简介

我们在创建BOM的时候通常是基于成品或者是半成品虚拟件创建BOM。正常情况下某些特殊的物料类型是不存在BOM中的。我们可以通过系统后台配置的方式对物料类型进行控制,控制对应的物料类型是否允许出现在BOM的组件中 1、后台配置路径: SPRO—生产—基本信息—物料清单—项目数…

【Linux取经路】网络套接字编程——TCP篇

文章目录 前言十、Tcp Server 端代码10.1 socket、bind10.1 listen——监听一个套接字10.2 accept——获取一个新连接10.3 read——从套接字中读取数据10.4 write——向套接字中进行写入10.5 Tcp Service 端完整代码(单进程版)10.6 Tcp Server 端代码&am…

【ZYNQ】CPU 私有定时器

Zynq 的每个 Cortex-A9 处理器都有自己的专用 32 位定时器和 32 位看门狗定时器,两个处理器共享一个全局 64 位定时器,这些计时器的时钟频率始终为 CPU 频率的 1/2。本文主要介绍 Zynq 芯片 CPU 私有定时器的工作特性,以及私有定时器的基本使…

(面试官问我微服务与naocs的使用我回答了如下,面试官让我回去等通知)微服务拆分与nacos的配置使用

微服务架构 正常的小项目就是所有的功能集成在一个模块中,这样代码之间不仅非常耦合,而且修改处理的时候也非常的麻烦,应对高并发时也不好处理,所以 我们可以使用微服务架构,对项目进行模块之间的拆分,每一…

精选网络安全书单:打造数字世界的钢铁长城!

目录 1.前言 2.书单推荐 2.1. 《内网渗透实战攻略》 2.2. 《Kali Linux高级渗透测试(原书第4版)》 2.3. 《CTF那些事儿》 2.4. 《权限提升技术:攻防实战与技巧》 2.5. 《数字政府网络安全合规性建设指南:密码应用与数据安全…

C++:红黑树

红黑树的概念 红黑树是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路 径会比其他路径长出两倍,因而是接近平衡…

ArrayList——简单洗牌算法

特殊语法介绍&#xff1a; List<List<E>> 该语法情况比较特殊&#xff0c;相当于一个“二维数组”存着一个个线性表的结构&#xff0c;如图&#xff1a; 该语法的灵活性强&#xff0c;可适用于多种类型和多种情况。接下来就使用该语法来实现一个简单的洗牌操作。…

halo进阶-主题插件使用

开始捣鼓捣鼓halo&#xff0c;换换主题&#xff0c;加个页面 可参考&#xff1a;Halo 文档 安装/更新主题 主题如同壁纸&#xff0c;萝卜青菜各有所爱&#xff0c;大家按需更换即可&#xff1b; Halo好在一键更换主题&#xff0c;炒鸡方便。 安装/更新插件 此插件还扩展了插件…

CR80通用清洁卡:证卡打印机、ATM机、POS机、读卡器等卡片设备清洁维护的好助手!

随着科技的进步&#xff0c;ATM机、POS终端、门禁系统、证卡打印机、读卡器等卡片设备在我们的日常生活中扮演着越来越重要的角色&#xff0c;些设备在长时间使用和环境因素的影响下&#xff0c;容易积聚油脂、灰尘和其他污染物&#xff0c;从而对其性能和功能产生负面影响。 深…

Xcode 打包报错Command PhaseScriptExecution failed with a nonzero exit code

解决办法: 1、在Xcode项目中 Pods -> Targets Support Files -> Pods-项目名 -> Pods-项目名-frameworks 中(大约在第44行) 加上 -f 2、CocoaPods版本太旧了,可以尝试升级CocoaPods版本 使用sudo gem update cocoapods更新cocoapods&#xff0c;问题将在1.12.1版本已…

力扣2968.执行操作使频率分数最大

力扣2968.执行操作使频率分数最大 方法一&#xff1a;滑窗 前缀和 求前缀和数组s 求一个数组补齐到中位数的差值 枚举右端点 class Solution {public:int maxFrequencyScore(vector<int>& nums, long long k) {int res0,n nums.size();sort(nums.begin(),nums…

单元测试AIR原则:提升代码质量的秘密武器

文章目录 引言一、AIR原则1. Automatic&#xff08;自动化&#xff09;2. Independent&#xff08;独立性&#xff09;3. Repeatable&#xff08;可重复性&#xff09; 二、Automatic&#xff08;自动化&#xff09;三、Independent&#xff08;独立性&#xff09;四、Repeatab…

GIF录屏工具Gif123 v3.3.0单文件

软件介绍 GIF的优势是小、轻、快&#xff0c;适合时间短、画面小、需要嵌入其他页面&#xff0c;打开就自动循环播放的动画。Gif123可录制合成鼠标轨迹,可调整鼠标指针大小,可在设置中打开鼠标指针高亮光圈功能,高亮光圈可跟随鼠标移动以指示鼠标位置。软件极其简单&#xff0…

C语言实现教学计划编制问题,Dev C++编译器下可运行(240606最新更新)

背景&#xff1a; 问题描述 大学的每个专业都要编制教学计划。假设任何专业都有固定的学习年限&#xff0c;每学年含两学期&#xff0c; 每学期的时间长度和学分上限都相等。每个专业开设的课程都是确定的&#xff0c;而且课程的开设时间的安排必须满足先修关系。每个课程的先…