计算机视觉中的数据预处理与模型训练技巧总结

news2024/11/17 11:26:55

计算机视觉主要问题有图像分类、目标检测和图像分割等。针对图像分类任务,提升准确率的方法路线有两条,一个是模型的修改,另一个是各种数据处理和训练的技巧(tricks)。图像分类中的各种技巧对于目标检测、图像分割等任务也有很好的作用,因此值得好好总结。本文在精读论文的基础上,总结了图像分类任务的各种tricks如下:

  • Warmup

  • Linear scaling learning rate

  • Label-smoothing

  • Random image cropping and patching

  • Knowledge Distillation

  • Cutout

  • Random erasing

  • Cosine learning rate decay

  • Mixup training

  • AdaBoud

  • AutoAugment

  • 其他经典的tricks

1. Warmup

学习率是神经网络训练中最重要的超参数之一,针对学习率的技巧有很多。Warm up是在ResNet论文[1]中提到的一种学习率预热的方法。由于刚开始训练时模型的权重(weights)是随机初始化的(全部置为0是一个坑,原因见[2]),此时选择一个较大的学习率,可能会带来模型的不稳定。学习率预热就是在刚开始训练的时候先使用一个较小的学习率,训练一些epoches或iterations,等模型稳定时再修改为预先设置的学习率进行训练。论文[1]中使用一个110层的ResNet在cifar10上训练时,先用0.01的学习率训练直到训练误差低于80%(大概训练了400个iterations),然后使用0.1的学习率进行训练。

上述的方法是constant warmup,18年Facebook又针对上面的warmup进行了改进[3],因为从一个很小的学习率一下变为比较大的学习率可能会导致训练误差突然增大。论文[3]提出了gradual warmup来解决这个问题,即从最开始的小学习率开始,每个iteration增大一点,直到最初设置的比较大的学习率。

from torch.optim.lr_scheduler import _LRScheduler
class GradualWarmupScheduler(_LRScheduler):
    """
    Args:
        optimizer (Optimizer): Wrapped optimizer.
        multiplier: target learning rate = base lr * multiplier
        total_epoch: target learning rate is reached at total_epoch, gradually
        after_scheduler: after target_epoch, use this scheduler(eg. ReduceLROnPlateau)
    """
    def __init__(self, optimizer, multiplier, total_epoch, after_scheduler=None):
        self.multiplier = multiplier
        if self.multiplier <= 1.:
            raise ValueError('multiplier should be greater than 1.')
        self.total_epoch = total_epoch
        self.after_scheduler = after_scheduler
        self.finished = False
        super().__init__(optimizer)
    def get_lr(self):
        if self.last_epoch > self.total_epoch:
            if self.after_scheduler:
                if not self.finished:
                    self.after_scheduler.base_lrs = [base_lr * self.multiplier for base_lr in self.base_lrs]
                    self.finished = True
                return self.after_scheduler.get_lr()
            return [base_lr * self.multiplier for base_lr in self.base_lrs]
        return [base_lr * ((self.multiplier - 1.) * self.last_epoch / self.total_epoch + 1.) for base_lr in self.base_lrs]
    def step(self, epoch=None):
        if self.finished and self.after_scheduler:
            return self.after_scheduler.step(epoch)
        else:
            return super(GradualWarmupScheduler, self).step(epoch)

2. Linear scaling learning rate

Linear scaling learning rate是在论文[3]中针对比较大的batch size而提出的一种方法。

在凸优化问题中,随着批量的增加,收敛速度会降低,神经网络也有类似的实证结果。随着batch size的增大,处理相同数据量的速度会越来越快,但是达到相同精度所需要的epoch数量越来越多。也就是说,使用相同的epoch时,大batch size训练的模型与小batch size训练的模型相比,验证准确率会减小。

上面提到的gradual warmup是解决此问题的方法之一。另外,linear scaling learning rate也是一种有效的方法。在mini-batch SGD训练时,梯度下降的值是随机的,因为每一个batch的数据是随机选择的。增大batch size不会改变梯度的期望,但是会降低它的方差。也就是说,大batch size会降低梯度中的噪声,所以我们可以增大学习率来加快收敛。

具体做法很简单,比如ResNet原论文[1]中,batch size为256时选择的学习率是0.1,当我们把batch size变为一个较大的数b时,学习率应该变为 0.1 × b/256

3. Label-smoothing

在分类问题中,我们的最后一层一般是全连接层,然后对应标签的one-hot编码,即把对应类别的值编码为1,其他为0。这种编码方式和通过降低交叉熵损失来调整参数的方式结合起来,会有一些问题。这种方式会鼓励模型对不同类别的输出分数差异非常大,或者说,模型过分相信它的判断。但是,对于一个由多人标注的数据集,不同人标注的准则可能不同,每个人的标注也可能会有一些错误。模型对标签的过分相信会导致过拟合。

标签平滑(Label-smoothing regularization,LSR)是应对该问题的有效方法之一,它的具体思想是降低我们对于标签的信任,例如我们可以将损失的目标值从1稍微降到0.9,或者将从0稍微升到0.1。标签平滑最早在inception-v2[4]中被提出,它将真实的概率改造为:

其中,ε是一个小的常数,K是类别的数目,y是图片的真正的标签,i代表第i个类别,是图片为第i类的概率。总的来说,LSR是一种通过在标签y中加入噪声,实现对模型约束,降低模型过拟合程度的一种正则化方法。

import torch
import torch.nn as nn
class LSR(nn.Module):
    def __init__(self, e=0.1, reduction='mean'):
        super().__init__()
        self.log_softmax = nn.LogSoftmax(dim=1)
        self.e = e
        self.reduction = reduction
    def _one_hot(self, labels, classes, value=1):
        """
            Convert labels to one hot vectors
        Args:
            labels: torch tensor in format [label1, label2, label3, ...]
            classes: int, number of classes
            value: label value in one hot vector, default to 1
        Returns:
            return one hot format labels in shape [batchsize, classes]
        """
        one_hot = torch.zeros(labels.size(0), classes)
        #labels and value_added  size must match
        labels = labels.view(labels.size(0), -1)
        value_added = torch.Tensor(labels.size(0), 1).fill_(value)
        value_added = value_added.to(labels.device)
        one_hot = one_hot.to(labels.device)
        one_hot.scatter_add_(1, labels, value_added)
        return one_hot
    def _smooth_label(self, target, length, smooth_factor):
        """convert targets to one-hot format, and smooth
        them.
        Args:
            target: target in form with [label1, label2, label_batchsize]
            length: length of one-hot format(number of classes)
            smooth_factor: smooth factor for label smooth
        Returns:
            smoothed labels in one hot format
        """
        one_hot = self._one_hot(target, length, value=1 - smooth_factor)
        one_hot += smooth_factor / length
        return one_hot.to(target.device)

 4. Random image cropping and patching

Random image cropping and patching (RICAP)[7]方法随机裁剪四个图片的中部分,然后把它们拼接为一个图片,同时混合这四个图片的标签。RICAP在caifar10上达到了2.19%的错误率。

 如下图所示,Ix, Iy是原始图片的宽和高。w和h称为boundary position,它决定了四个裁剪得到的小图片的尺寸。w和h从beta分布Beta(β, β)中随机生成,β也是RICAP的超参数。最终拼接的图片尺寸和原图片尺寸保持一致。

 5. Knowledge Distillation

 提高几乎所有机器学习算法性能的一种非常简单的方法是在相同的数据上训练许多不同的模型,然后对它们的预测进行平均。但是使用所有的模型集成进行预测是比较麻烦的,并且可能计算量太大而无法部署到大量用户。Knowledge Distillation(知识蒸馏)[8]方法就是应对这种问题的有效方法之一。

在知识蒸馏方法中,我们使用一个教师模型来帮助当前的模型(学生模型)训练。教师模型是一个较高准确率的预训练模型,因此学生模型可以在保持模型复杂度不变的情况下提升准确率。比如,可以使用ResNet-152作为教师模型来帮助学生模型ResNet-50训练。在训练过程中,我们会加一个蒸馏损失来惩罚学生模型和教师模型的输出之间的差异。

给定输入,假定p是真正的概率分布,z和r分别是学生模型和教师模型最后一个全连接层的输出。之前我们会用交叉熵损失l(p,softmax(z))来度量p和z之间的差异,这里的蒸馏损失同样用交叉熵。所以,使用知识蒸馏方法总的损失函数是

上式中,第一项还是原来的损失函数,第二项是添加的用来惩罚学生模型和教师模型输出差异的蒸馏损失。其中,T是一个温度超参数,用来使softmax的输出更加平滑的。实验证明,用ResNet-152作为教师模型来训练ResNet-50,可以提高后者的准确率。

6. Cutout

Cutout[9]是一种新的正则化方法。原理是在训练时随机把图片的一部分减掉,这样能提高模型的鲁棒性。它的来源是计算机视觉任务中经常遇到的物体遮挡问题。通过cutout生成一些类似被遮挡的物体,不仅可以让模型在遇到遮挡问题时表现更好,还能让模型在做决定时更多地考虑环境(context)。

import torch
import numpy as np
class Cutout(object):
    """Randomly mask out one or more patches from an image.
    Args:
        n_holes (int): Number of patches to cut out of each image.
        length (int): The length (in pixels) of each square patch.
    """
    def __init__(self, n_holes, length):
        self.n_holes = n_holes
        self.length = length
    def __call__(self, img):
        """
        Args:
            img (Tensor): Tensor image of size (C, H, W).
        Returns:
            Tensor: Image with n_holes of dimension length x length cut out of it.
        """
        h = img.size(1)
        w = img.size(2)
        mask = np.ones((h, w), np.float32)
        for n in range(self.n_holes):
            y = np.random.randint(h)
            x = np.random.randint(w)
            y1 = np.clip(y - self.length // 2, 0, h)
            y2 = np.clip(y + self.length // 2, 0, h)
            x1 = np.clip(x - self.length // 2, 0, w)
            x2 = np.clip(x + self.length // 2, 0, w)
            mask[y1: y2, x1: x2] = 0.
        mask = torch.from_numpy(mask)
        mask = mask.expand_as(img)
        img = img * mask
        return img

 7. Random erasing

Random erasing[6]其实和cutout非常类似,也是一种模拟物体遮挡情况的数据增强方法。区别在于,cutout是把图片中随机抽中的矩形区域的像素值置为0,相当于裁剪掉,random erasing是用随机数或者数据集中像素的平均值替换原来的像素值。而且,cutout每次裁剪掉的区域大小是固定的,Random erasing替换掉的区域大小是随机的。

from __future__ import absolute_import
from torchvision.transforms import *
from PIL import Image
import random
import math
import numpy as np
import torch
class RandomErasing(object):
    '''
    probability: The probability that the operation will be performed.
    sl: min erasing area
    sh: max erasing area
    r1: min aspect ratio
    mean: erasing value
    '''
    def __init__(self, probability = 0.5, sl = 0.02, sh = 0.4, r1 = 0.3, mean=[0.4914, 0.4822, 0.4465]):
        self.probability = probability
        self.mean = mean
        self.sl = sl
        self.sh = sh
        self.r1 = r1
    def __call__(self, img):
        if random.uniform(0, 1) > self.probability:
            return img
        for attempt in range(100):
            area = img.size()[1] * img.size()[2]
            target_area = random.uniform(self.sl, self.sh) * area
            aspect_ratio = random.uniform(self.r1, 1/self.r1)
            h = int(round(math.sqrt(target_area * aspect_ratio)))
            w = int(round(math.sqrt(target_area / aspect_ratio)))
            if w < img.size()[2] and h < img.size()[1]:
                x1 = random.randint(0, img.size()[1] - h)
                y1 = random.randint(0, img.size()[2] - w)
                if img.size()[0] == 3:
                    img[0, x1:x1+h, y1:y1+w] = self.mean[0]
                    img[1, x1:x1+h, y1:y1+w] = self.mean[1]
                    img[2, x1:x1+h, y1:y1+w] = self.mean[2]
                else:
                    img[0, x1:x1+h, y1:y1+w] = self.mean[0]
                return img
        return img

8.  Cosine learning rate decay

在warmup之后的训练过程中,学习率不断衰减是一个提高精度的好方法。其中有step decay和cosine decay等,前者是随着epoch增大学习率不断减去一个小的数,后者是让学习率随着训练过程曲线下降。

对于cosine decay,假设总共有T个batch(不考虑warmup阶段),在第t个batch时,学习率 \eta t为:

这里,η代表初始设置的学习率。这种学习率递减的方式称之为cosine decay。

下面是带有warmup的学习率衰减的可视化图[4]。其中,图(a)是学习率随epoch增大而下降的图,可以看出cosine decay比step decay更加平滑一点。图(b)是准确率随epoch的变化图,两者最终的准确率没有太大差别,不过cosine decay的学习过程更加平滑。

 在pytorch的torch.optim.lr_scheduler中有更多的学习率衰减的方法,至于哪个效果好,可能对于不同问题答案是不一样的。对于step decay,使用方法如下:

# Assuming optimizer uses lr = 0.05 for all groups
# lr = 0.05     if epoch < 30
# lr = 0.005    if 30 <= epoch < 60
# lr = 0.0005   if 60 <= epoch < 90
from torch.optim.lr_scheduler import StepLR
scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
for epoch in range(100):
    scheduler.step()
    train(...)
    validate(...)

 9. Mixup training

Mixup[10]是一种新的数据增强的方法。Mixup training,就是每次取出2张图片,然后将它们线性组合,得到新的图片,以此来作为新的训练样本,进行网络的训练,如下公式,其中x代表图像数据,y代表标签,则得到的新的\hat{x}\hat{y}

其中,λ是从Beta(α, α)随机采样的数,在[0,1]之间。在训练过程中,仅使用(  ,  )。

Mixup方法主要增强了训练样本之间的线性表达,增强网络的泛化能力,不过mixup方法需要较长的时间才能收敛得比较好。

for (images, labels) in train_loader:
    l = np.random.beta(mixup_alpha, mixup_alpha)
    index = torch.randperm(images.size(0))
    images_a, images_b = images, images[index]
    labels_a, labels_b = labels, labels[index]
    mixed_images = l * images_a + (1 - l) * images_b
    outputs = model(mixed_images)
    loss = l * criterion(outputs, labels_a) + (1 - l) * criterion(outputs, labels_b)
    acc = l * accuracy(outputs, labels_a)[0] + (1 - l) * accuracy(outputs, labels_b)[0]

 10. AdaBound

AdaBound是最近一篇论文[5]中提到的,按照作者的说法,AdaBound会让你的训练过程像adam一样快,并且像SGD一样好。如下图所示,使用AdaBound会收敛速度更快,过程更平滑,结果更好。

 另外,这种方法相对于SGD对超参数的变化不是那么敏感,也就是说鲁棒性更好。但是,针对不同的问题还是需要调节超参数的,只是所用的时间可能变少了。

当然,AdaBound还没有经过普遍的检验,也有可能只是对于某些问题效果好。

使用方法如下:安装AdaBound

pip install adabound

使用AdaBound(和其他PyTorch optimizers用法一致)

optimizer = adabound.AdaBound(model.parameters(), lr=1e-3, final_lr=0.1)

 11. AutoAugment

数据增强在图像分类问题上有很重要的作用,但是增强的方法有很多,并非一股脑地用上所有的方法就是最好的。那么,如何选择最佳的数据增强方法呢?AutoAugment[11]就是一种搜索适合当前问题的数据增强方法的方法。该方法创建一个数据增强策略的搜索空间,利用搜索算法选取适合特定数据集的数据增强策略。此外,从一个数据集中学到的策略能够很好地迁移到其它相似的数据集上。

12. 其他经典的tricks

常用的正则化方法为

  • Dropout

  • L1/L2正则

  • Batch Normalization

  • Early stopping

  • Random cropping

  • Mirroring

  • Rotation

  • Color shifting

  • PCA color augmentation

其他

  • Xavier init[12]

参考文献

  • [1] Deep Residual Learning for Image Recognition(https://arxiv.org/pdf/1512.03385.pdf)

  • [2] http://cs231n.github.io/neural-networks-2/

  • [3] Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour(https://arxiv.org/pdf/1706.02677v2.pdf)

  • [4] Rethinking the Inception Architecture for Computer Vision(https://arxiv.org/pdf/1512.00567v3.pdf)

  • [4]Bag of Tricks for Image Classification with Convolutional Neural Networks(https://arxiv.org/pdf/1812.01187.pdf)

  • [5] Adaptive Gradient Methods with Dynamic Bound of Learning Rate(https://www.luolc.com/publications/adabound/)

  • [6] Random erasing(https://arxiv.org/pdf/1708.04896v2.pdf)

  • [7] RICAP(https://arxiv.org/pdf/1811.09030.pdf)

  • [8] Distilling the Knowledge in a Neural Network(https://arxiv.org/pdf/1503.02531.pdf)

  • [9] Improved Regularization of Convolutional Neural Networks with Cutout(https://arxiv.org/pdf/1708.04552.pdf)

  • [10] Mixup: BEYOND EMPIRICAL RISK MINIMIZATION(https://arxiv.org/pdf/1710.09412.pdf)

  • [11] AutoAugment: Learning Augmentation Policies from Data(https://arxiv.org/pdf/1805.09501.pdf)

  • [12] Understanding the difficulty of training deep feedforward neural networks(http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf)

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

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

相关文章

制造业中的微小缺陷检测——应用场景分析与算法选择(YoloV8/CANet)

一、缺陷检测任务 缺陷检测的任务通常可以分为三个主要阶段&#xff0c;包括缺陷分类、缺陷定位和缺陷分割。 1.缺陷分类 缺陷分类是检测过程的第一步&#xff0c;目的是将检测到的缺陷区域分类为不同的类别&#xff0c;通常是根据缺陷的性质或类型进行分类。分类的类别包括…

深度学习使用Keras进行迁移学习提升网络性能

上一篇文章我们用自己定义的模型来解决了二分类问题,在20个回合的训练之后得到了大约74%的准确率,一方面是我们的epoch太小的原因,另外一方面也是由于模型太简单,结构简单,故而不能做太复杂的事情,那么怎么提升预测的准确率了?一个有效的方法就是迁移学习。 迁移学习其…

C#反射的应用及相关代码示例

在C#编程中&#xff0c;反射是一种强大的工具&#xff0c;它允许程序在运行时动态地获取类型信息、访问和操作类成员。反射为开发人员提供了更大的灵活性和扩展性&#xff0c;使得我们可以编写更加通用和动态的代码。本文将探讨C#反射的应用&#xff0c;并提供一些相关的代码示…

程序员加油!最新最全Java面试题及解答(上百道题,近5w字,包括Redis、MySQL、框架、微服务、消息中间件、集合、jvm,多线程、常见技术场景)

刚看完黑马教程的新版Java面试专题视频教程&#xff0c;java八股文面试全套真题深度详解&#xff08;含大厂高频面试真题&#xff09;&#xff0c;对面试题分专题整理&#xff0c;方便面试突击 Redis相关面试题 Redis相关面试题 面试官&#xff1a;什么是缓存穿透 ? 怎么解决…

软考系列(系统架构师)- 2016年系统架构师软考案例分析考点

试题一 软件架构&#xff08;质量属性、架构风格对比、根据描述填空&#xff09; 试题二 系统开发&#xff08;用例图参与者、用例关系、类图关系&#xff09; 学生、教师、管理员、时间、打印机【问题2】&#xff08;7分&#xff09; 用例是对系统行为的动态描述&#xff0c;用…

【强连通+背包】CF1763E

Problem - E - Codeforces 题意 思路 首先&#xff0c;先考虑第一个条件&#xff0c;要保证是p个节点互相到达且节点数最少&#xff0c;一定是个强连通&#xff0c;图的形态一定就是和强连通相关的。 然后&#xff0c;因为在这个前提上&#xff0c;要让单向节点数尽可能多&a…

归并排序与计数排序(含代码)

目录 目录&#xff1a; 1:归并排序递归 2:归并排序的非递归 3&#xff1a;计数排序的思想 1&#xff1a;归并排序递归 思路&#xff1a;归并排序是采用分治算法的一种排序&#xff0c;将两个有序的子数组合并到一个数组中去使得数组完全有序&#xff0c;所以我们先使子数组有序…

CAN测量模块总线负载率,你关注了吗?

一 背景 随着新能源汽车的飞速发展&#xff0c;整车系统日趋复杂&#xff0c;整车性能的可靠性也变得愈发重要。在车辆测试过程中&#xff0c;为应对更加多样的试验需求&#xff0c;传感器的种类和数量会随着测量种类而增加&#xff0c;数据量也会因此变得越发庞大&#xff0c…

docker部署prometheus+grafana服务器监控(一)

docker-compose 部署prometheusgrafana Prometheus Prometheus 是有 SoundCloud 开发的开源监控系统和时序数据库&#xff0c;基于 Go 语言开发。通过基于 HTTP 的 pull 方式采集时序数据&#xff0c;通过服务发现或静态配置去获取要采集的目标服务器&#xff0c;支持多节点工…

Kubernetes 部署 kubeflow1.7.0

KubeFlow 是一个开源的项目&#xff0c;旨在为 Kubernetes 提供可组合、便携式、可扩展的机器学习技术栈。它最初是为了解决在 Kubernetes 上运行分布式机器学习任务所带来的挑战而创建的。Kubernetes 本身是一个容器平台&#xff0c;但在近年来&#xff0c;越来越多的公司开始…

【Html】交通灯问题

效果 实现方式 计时器&#xff1a;setTimeout或setInterval来计时。setInterval和 setTimeout 在某些情况下可能会出现计时不准确的情况。这通常是由于JavaScript的事件循环机制和其他代码执行所需的时间造成的。 问询&#xff1a;通过getCurrentLight将每个状态的持续时间设置…

解密分布式事务:CAP理论、BASE理论、两阶段提交(2PC)、三阶段提交(3PC)、补偿事务(TCC)、MQ事务消息、最大努力通知

文章目录 &#x1f34a; CAP理论&#x1f34a; BASE理论&#x1f34a; 两阶段提交&#xff08;2PC&#xff09;&#x1f389; XA事务 &#x1f34a; 三阶段提交&#xff08;3PC&#xff09;&#x1f34a; 补偿事务&#xff08;TCC&#xff09;&#x1f34a; MQ事务消息&#x1…

web开发初级工程师学习笔记ing(持续更新)!!!

web开发初级工程师学习笔记 前端开发工具实验1 VS Code 初体验介绍 前端开发工具 实验1 VS Code 初体验 介绍 VS Code 环境提供的是一个可以在浏览器中使用原生 VS Code 编辑代码的程序。在该环境中&#xff0c;你可以使用到与本地安装近乎一致的 VS Code 程序来编辑代码文件…

计算机网络(谢希仁)第八版课后题答案(第二章)

1.物理层要解决哪些问题&#xff1f;物理层的主要特点是什么&#xff1f; (1)物理层要尽可能地屏蔽掉物理设备和传输媒体&#xff0c;通信手段的不同&#xff0c;使数据链路层感觉不到这些差异&#xff0c;只考虑完成本层的协议和服务。 (2)给其服务用户&#xff08;数据链路…

IO多路复用技术

IO多路复用 一、概念 IO多路复用技术 是一种 网络通信 的方式&#xff0c;通过这种方式可以同时检测多个 文件描述符&#xff08;这个过程是阻塞的&#xff09;&#xff0c;一旦检测到某一个文件描述符&#xff08;状态是 可读 或者 可写 的&#xff09;是就绪的&#xff0c;…

苏州健雄职业技术学院人工智能学院学生在“火焰杯”软件测试开发选拔赛总决赛获奖

3月22日&#xff0c;第三届“火焰杯”软件测试开发选拔赛颁奖仪式在人工智能学院D2-102机房举行&#xff0c;软件工程20级学生和软件测试社团全体社团成员参加本次活动。本次活动由测吧&#xff08;北京&#xff09;科技有限公司项目总监王雪冬担任颁奖嘉宾&#xff0c;并为同学…

使用Windows平台的Hyper-V虚拟机安装CentOS7的详细过程

Hyper-V虚拟机安装CentOS7 前言常见Linux系统CentOSUbuntuDebianKaliFedoraArch LinuxMintManjaroopenSUSE Hyper-V开启Hyper-V打开Hyper-V Hyper-V的使用新建虚拟机开始安装分区配置开始安装 修改yum源为阿里源 前言 作为一名开发者&#xff0c;就服务器而言&#xff0c;接触最…

SpringMVC 报文信息转换器(HttpMessageConverter)

文章目录 描述1、RequestBody2、RequestEntity3、ResponseBody4、SpringMVC处理json5、SpringMVC处理ajax6、RestController注解7、ResponseEntity 描述 HttpMessageConverter&#xff0c;报文信息转换器&#xff0c;将请求报文转换为Java对象&#xff0c;或将Java对象转换为响…

Linux:firewalld防火墙-(实验2)-IP伪装与端口转发(4)

实验环境 本章实验环境要建立在上一章之上&#xff0c;ip等都是继承上一章&#xff0c;完全在上一章之下的操作 Linux&#xff1a;firewalld防火墙-小环境实验&#xff08;3&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/133996151?spm1001.2014.3…

动态链接函数(dlopen/dlsym/dlclose)使用总结

一、简介 动态链接函数操作&#xff08;显式运行时链接&#xff09;主要包含头文件dlfcn.h&#xff08;/usr/include/dlfcn.h&#xff09;&#xff0c;涉及的常用的函数主要有dlopen&#xff0c;dlysm&#xff0c;dlclose。主要作用是从动态库中加载函数到程序中使用&#xff…