Pytorch语义分割网络的详细训练过程——以NYUv2数据集为例

news2024/10/1 17:34:31

目录

  • 一、构建数据集
      • 1. 对Dataset和DataLoader的理解
      • 2. torch.utils.data.Dataset
      • 3. torch.utils.data.DataLoader
      • 4. 代码分块解析
      • 5. 完整代码
      • 6. 可视化
  • 二、模型搭建
  • 三、定义损失函数和优化器
  • 四、迭代训练
  • 参考文章

一、构建数据集

1. 对Dataset和DataLoader的理解

  Pytorch提供了一种十分方便的数据读取机制,即使用DatasetDataLoader组合得到数据迭代器。在每次训练时,利用这个迭代器输出每一个batch的数据,并能在输出时对数据进行相应的预处理或数据增广操作。

  • 我们如果要自定义数据读取的方法,就需要继承torch.utils.data.Dataset,并将其封装到torch.utils.data.DataLoader中。

  • torch.utils.data.Dataset表示该数据集,继承该类可以重载其中的方法,实现多种数据读取及数据预处理

  • torch.utils.data.DataLoader 封装了Data对象,实现单(多)进程迭代器输出数据集

2. torch.utils.data.Dataset

  torch.utils.data.Dataset是代表自定义数据集方法的类,用户可以通过继承该类来自定义自己的数据集类,在继承时要求用户重载__len__()__getitem__()这两个方法。

  • __len__():返回的是数据集的大小。

  • __getitem__():实现索引数据集中的某一个数据。此外,可以在__getitem__()中实现数据预处理。

3. torch.utils.data.DataLoader

  • DataLoader将Dataset对象或自定义数据类的对象封装成一个迭代器;

  • 这个迭代器可以迭代输出Dataset的内容;

  • 同时可以实现多进程、shuffle、不同采样策略,数据校对等等处理过程。

4. 代码分块解析

  • 自定义的数据集类为NYUv2_Dataset,继承自torch.utils.data.Dataset
class NYUv2_Dataset(Dataset):
    def __init__(self, data_root, img_transforms):
        self.data_root = data_root
        self.img_transforms = img_transforms
        data_list, label_list = read_image_path(root=self.data_root)
        self.data_list = data_list
        self.label_list = label_list

    def __len__(self):
        return len(self.data_list)

    def __getitem__(self, item):
        img = self.data_list[item]
        label = self.label_list[item]

        img = cv2.imread(img)
        label = cv2.imread(label)

        img, label = self.img_transforms(img, label)

        return img,label
  • 在NYUv2_Dataset类中,使用到了read_image_path()函数,输入为数据集的路径,输出为数据和标签的地址列表。
# 定义需要读取的数据路径的函数
def read_image_path(root=r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\train.txt"):
# 原始图像路径输出为data,标签图像路径输出为label
    image = np.loadtxt(root, dtype=str)
    n =len(image)
    data, label = [None]*n, [None]*n
    for i,fname in enumerate(image):
        data[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\JPEGImages\%s.jpg" % (fname)
        label[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\Segmentation_40\%s.png" % (fname)
    return data, label
  • 在NYUv2_Dataset类中,还使用到了img_transforms()函数,用来将原始图像和类别标签转变为Tensor格式,并将标签转化为每个像素值为一类数据。
def image2label(image, colormap):
    # 将标签转化为每个像素值为一类数据
    cm2lbl = np.zeros(256**3)
    for i,cm in enumerate(colormap):
        cm2lbl[(cm[0]*256+cm[1]*256+cm[2])] = i
    # 对一张图像转换
    image = np.array(image, dtype="int64")
    ix = (image[:,:,0]*256+image[:,:,1]*256+image[:,:,2])
    image2 = cm2lbl[ix]
    return image2

def img_transforms(data, label):
# 将标记图像数据进行二维标签化的操作
# 输出原始图像和类别标签的张量数据
    data_tfs = transforms.Compose([
        transforms.ToTensor(),
    ])
    data = data_tfs(data)
    label = torch.from_numpy(image2label(label, colormap)) # 把数组转换成张量,且二者共享内存,对张量进行修改比如重新赋值,那么原始数组也会相应发生改变
    return data, label

5. 完整代码

  下面展示了构建NYUv2数据集的全部代码,其中colormap是NYUv2数据集中分割标签的像素值(即类别),该部分代码实现了读取数据、数据处理、创建数据加载器dataloader。

colormap = [[0, 0, 0],
            [1, 1, 1],
            [2, 2, 2],
            [3, 3, 3],
            [4, 4, 4],
            [5, 5, 5],
            [6, 6, 6],
            [7, 7, 7],
            [8, 8, 8],
            [9, 9, 9],
            [10, 10, 10],
            [11, 11, 11],
            [12, 12, 12],
            [13, 13, 13],
            [14, 14, 14],
            [15, 15, 15],
            [16, 16, 16],
            [17, 17, 17],
            [18, 18, 18],
            [19, 19, 19],
            [20, 20, 20],
            [21, 21, 21],
            [22, 22, 22],
            [23, 23, 23],
            [24, 24, 24],
            [25, 25, 25],
            [26, 26, 26],
            [27, 27, 27],
            [28, 28, 28],
            [29, 29, 29],
            [30, 30, 30],
            [31, 31, 31],
            [32, 32, 32],
            [33, 33, 33],
            [34, 34, 34],
            [35, 35, 35],
            [36, 36, 36],
            [37, 37, 37],
            [38, 38, 38],
            [39, 39, 39],
            [40, 40, 40]]


# 定义计算设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def image2label(image, colormap):
    # 将标签转化为每个像素值为一类数据
    cm2lbl = np.zeros(256**3)
    for i,cm in enumerate(colormap):
        cm2lbl[(cm[0]*256+cm[1]*256+cm[2])] = i
    # 对一张图像转换
    image = np.array(image, dtype="int64")
    ix = (image[:,:,0]*256+image[:,:,1]*256+image[:,:,2])
    image2 = cm2lbl[ix]
    return image2

# 定义需要读取的数据路径的函数
def read_image_path(root=r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\train.txt"):
# 原始图像路径输出为data,标签图像路径输出为label
    image = np.loadtxt(root, dtype=str)
    n =len(image)
    data, label = [None]*n, [None]*n
    for i,fname in enumerate(image):
        data[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\JPEGImages\%s.jpg" % (fname)
        label[i] = r"C:\Users\22476\Desktop\VOC_format_dataset\Segmentation_40\%s.png" % (fname)
    return data, label

# 单组图像的转换操作
def img_transforms(data, label):
# 将输入图像进行亮度、对比度、饱和度、色相的改变;将标记图像数据进行二维标签化的操作
# 输出原始图像和类别标签的张量数据
    data_tfs = transforms.Compose([
        transforms.ToTensor(),
    ])
    data = data_tfs(data)
    label = torch.from_numpy(image2label(label, colormap)) # 把数组转换成张量,且二者共享内存,对张量进行修改比如重新赋值,那么原始数组也会相应发生改变
    return data, label

class NYUv2_Dataset(Dataset):
    def __init__(self, data_root, img_transforms):
        self.data_root = data_root
        self.img_transforms = img_transforms
        data_list, label_list = read_image_path(root=self.data_root)
        self.data_list = data_list
        self.label_list = label_list

    def __len__(self):
        return len(self.data_list)

    def __getitem__(self, item):
        img = self.data_list[item]
        label = self.label_list[item]

        img = cv2.imread(img)
        label = cv2.imread(label)

        img, label = self.img_transforms(img, label)

        return img,label

nyuv2_train = NYUv2_Dataset(r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\train.txt", img_transforms)

nyuv2_val = NYUv2_Dataset(r"C:\Users\22476\Desktop\VOC_format_dataset\ImageSet\val.txt", img_transforms)


# 创建数据加载器每个batch使用4张图像
train_loader = Data.DataLoader(nyuv2_train, batch_size=2, shuffle=True, num_workers=0, pin_memory=True)
val_loader = Data.DataLoader(nyuv2_val, batch_size=2, shuffle=True, num_workers=0, pin_memory=True)

6. 可视化

  通过可视化一个batch的数据,检查数据预处理是否正确

# 检查训练数据集的一个batch的样本的维度是否正确
for step,(b_x,b_y) in enumerate(train_loader):
    if step > 0:
        break
# 输出训练图像的尺寸和标签的尺寸,以及接受类型
# print("Train数据:",b_x)
# print("Train标签:",b_y)
#
# print("b_x.shape:",b_x.shape)
# print("b_y.shape:",b_y.shape)

# 可视化一个batch的图像,检查数据预处理是否正确
b_x_numpy = b_x.data.numpy()
b_x_numpy = b_x_numpy.transpose(0,2,3,1)
plt.imshow(b_x_numpy[1])
plt.show()

b_y_numpy = b_y.data.numpy()
plt.imshow(b_y_numpy[1])
plt.show()

在这里插入图片描述
在这里插入图片描述

二、模型搭建

  本文以预训练好的VGG19模型作为Backbone,然后自己搭建上采样部分网络,从而完成整个语义分割网络的模型搭建。

high, width = 320, 480

# 使用预训练好的VGG19网络作为backbone
model_vgg19 = vgg19(pretrained=True)
# 不使用VGG19网络后面的AdaptiveAvgPool2d和Linear层
base_model = model_vgg19.features
base_model = base_model.cuda()
# summary(base_model,input_size=(3, high, width))

# 定义FCN语义分割网络
class FCN8s(nn.Module):
    def __init__(self, num_classes):
        super().__init__()
        self.num_classes = num_classes
        model_vgg19 = vgg19(pretrained=True)
        # 不使用VGG19网络后面的AdaptiveAvgPool2d和Linear层
        self.base_model = model_vgg19.features
        # 定义几个需要的层操作,并且使用转置卷积将特征映射进行升维
        self.relu = nn.ReLU(inplace=True)
        self.deconv1 = nn.ConvTranspose2d(512, 512, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1)
        self.bn1 = nn.BatchNorm2d(512)
        self.deconv2 = nn.ConvTranspose2d(512, 256, 3, 2, 1, 1, 1)
        self.bn2 = nn.BatchNorm2d(256)
        self.deconv3 = nn.ConvTranspose2d(256, 128, 3, 2, 1, 1, 1)
        self.bn3 = nn.BatchNorm2d(128)
        self.deconv4 = nn.ConvTranspose2d(128, 64, 3, 2, 1, 1, 1)
        self.bn4 = nn.BatchNorm2d(64)
        self.deconv5 = nn.ConvTranspose2d(64, 32, 3, 2, 1, 1, 1)
        self.bn5 = nn.BatchNorm2d(32)
        self.classifier = nn.Conv2d(32, num_classes, kernel_size=1)
        ## VGG19中MaxPool2d所在的层
        self.layers = {"4":"maxpool_1","9":"maxpool_2",
                       "18": "maxpool_3", "27": "maxpool_4",
                       "36": "maxpool_5"}
    def forward(self, x):
        output ={}
        for name, layer in self.base_model._modules.items():
            ## 从第一层开始获取图像的特征
            x = layer(x)
            ## 如果是layers参数指定的特征,那就保存到output中
            if name in self.layers:
                output[self.layers[name]] = x
        x5 = output["maxpool_5"]  ## size = (N, 512, x.H/32, x.W/32)
        x4 = output["maxpool_4"]  ## size = (N, 512, x.H/16, x.W/16)
        x3 = output["maxpool_3"]  ## size = (N, 512, x.H/8, x.W/8)
        ## 对特征进行相关的转置卷积操作,逐渐将图像放大到原始图像大小
        ## size = (N, 512, x.H/16, x.W/16)
        score = self.relu(self.deconv1(x5))
        ## 对应元素相加,size = (N, 512, x.H/16, x.W/16)
        score = self.bn1(score + x4)
        ## size = (N, 256, x.H/8, x.W/8)
        score = self.relu(self.deconv2(score))
        ## 对应元素相加,size = (N, 256, x.H/8, x.W/8)
        score = self.bn2(score + x3)
        ## size = (N, 128, x.H/4, x.W/4)
        score = self.bn3(self.relu(self.deconv3(score)))
        ## size = (N, 64, x.H/2, x.W/2)
        score = self.bn4(self.relu(self.deconv4(score)))
        ## size = (N, 32, x.H, x.W)
        score = self.bn5(self.relu(self.deconv5(score)))
        score = self.classifier(score)
        return score      ## size = (N, n_class, x.H/1, x.W/1)


fcn8s = FCN8s(41).to(device)
summary(fcn8s, input_size=(3, high, width))

  模型结构如下表所示:

Layer (type)Output ShapeParam
Conv2d-1[-1, 64, 320, 480]1,792
ReLU-2[-1, 64, 320, 480]0
Conv2d-3[-1, 64, 320, 480]36,928
ReLU-4[-1, 64, 320, 480]0
MaxPool2d-5[-1, 64, 160, 240]0
Conv2d-6[-1, 128, 160, 240]73,856
ReLU-7[-1, 128, 160, 240]0
Conv2d-8[-1, 128, 160, 240]147,584
ReLU-9[-1, 128, 160, 240]0
MaxPool2d-10[-1, 128, 80, 120]0
Conv2d-11[-1, 256, 80, 120]295,168
ReLU-12[-1, 256, 80, 120]0
Conv2d-13[-1, 256, 80, 120]590,080
ReLU-14[-1, 256, 80, 120]0
Conv2d-15[-1, 256, 80, 120]590,080
ReLU-16[-1, 256, 80, 120]0
Conv2d-17[-1, 256, 80, 120]590,080
ReLU-18[-1, 256, 80, 120]0
MaxPool2d-19[-1, 256, 40, 60]0
Conv2d-20[-1, 512, 40, 60]1,180,160
ReLU-21[-1, 512, 40, 60]0
Conv2d-22[-1, 512, 40, 60]2,359,808
ReLU-23[-1, 512, 40, 60]0
Conv2d-24[-1, 512, 40, 60]2,359,808
ReLU-25[-1, 512, 40, 60]0
Conv2d-26[-1, 512, 40, 60]2,359,808
ReLU-27[-1, 512, 40, 60]0
MaxPool2d-28[-1, 512, 20, 30]0
Conv2d-29[-1, 512, 20, 30]2,359,808
ReLU-30[-1, 512, 20, 30]0
Conv2d-31[-1, 512, 20, 30]2,359,808
ReLU-32[-1, 512, 20, 30]0
Conv2d-33[-1, 512, 20, 30]2,359,808
ReLU-34[-1, 512, 20, 30]0
Conv2d-35[-1, 512, 20, 30]2,359,808
ReLU-36[-1, 512, 20, 30]0
MaxPool2d-37[-1, 512, 10, 15]0
ConvTranspose2d-38[-1, 512, 20, 30]2,359,808
ReLU-39[-1, 512, 20, 30]0
BatchNorm2d-40[-1, 512, 20, 30]1,024
ConvTranspose2d-41[-1, 256, 40, 60]]1,179,904
ReLU-42[-1, 256, 40, 60]0
BatchNorm2d-43[-1, 256, 40, 60]512
ConvTranspose2d-44[-1, 128, 80, 120]295,040
ReLU-45[-1, 128, 80, 120]0
BatchNorm2d-46[-1, 128, 80, 120]256
ConvTranspose2d-47[-1, 64, 160, 240]73,792
ReLU-48[-1, 64, 160, 240]0
BatchNorm2d-49[-1, 64, 160, 240]128
ConvTranspose2d-50[-1, 32, 320, 480]18,464
ReLU-51[-1, 32, 320, 480]0
BatchNorm2d-52[-1, 32, 320, 480]64
Conv2d-53[-1, 41, 320, 480]1,353

三、定义损失函数和优化器

# 定义损失函数和优化器
LR = 0.0003
criterion = nn.NLLLoss()
optimizer = optim.Adam(fcn8s.parameters(), lr=LR,weight_decay=1e-4)

四、迭代训练

# 对模型进行迭代训练,对所有的数据训练epoch轮
fcn8s,train_process = train_model(
    fcn8s,criterion,optimizer,train_loader,
    val_loader, num_epochs=200)
## 保存训练好的模型fcn8s
torch.save(fcn8s,"fcnNYUv2.pt")
def train_model(model, criterion, optimizer, traindataloader, valdataloader, num_epochs = 25):
    """
    :param model: 网络模型
    :param criterion: 损失函数
    :param optimizer: 优化函数
    :param traindataloader: 训练的数据集
    :param valdataloader: 验证的数据集
    :param num_epochs: 训练的轮数
    """
    since = time.time()
    best_model_wts = copy.deepcopy(model.state_dict())
    best_loss = 1e10
    train_loss_all = []
    train_acc_all = []
    val_loss_all = []
    val_acc_all = []
    since = time.time()

    for epoch in range(num_epochs):
        print('Epoch {}/{}'.format(epoch, num_epochs-1))
        print('-' * 10)
        train_loss = 0.0
        train_num = 0
        val_loss = 0.0
        val_num = 0
        ## 每个epoch包括训练和验证阶段
        model.train()  ## 设置模型为训练模式
        for step,(b_x,b_y) in enumerate(traindataloader):
            optimizer.zero_grad()
            b_x = b_x.float().to(device)
            b_y = b_y.long().to(device)
            out = model(b_x)
            out = F.log_softmax(out, dim=1)
            pre_lab = torch.argmax(out,1) ## 预测的标签
            loss = criterion(out, b_y) ## 计算损失函数值
            loss.backward()
            optimizer.step()
            train_loss += loss.item() * len(b_y)
            train_num += len(b_y)
        ## 计算一个epoch在训练集上的损失和精度
        train_loss_all.append(train_loss / train_num)
        print('{} Train loss: {:.4f}'.format(epoch, train_loss_all[-1]))

        ## 计算一个epoch训练后在验证集上的损失
        model.eval() ## 设置模型为验证模式
        for step,(b_x,b_y) in enumerate(valdataloader):
            b_x = b_x.float().to(device)
            b_y = b_y.long().to(device)
            out = model(b_x)
            out = F.log_softmax(out, dim=1)
            pre_lab = torch.argmax(out,1) ## 预测的标签
            loss = criterion(out, b_y) ## 计算损失函数值
            val_loss += loss.item() * len(b_y)
            val_num += len(b_y)

        ## 计算一个epoch在验证集上的损失和精度
        val_loss_all.append(val_loss / val_num)
        print('{} Val loss: {:.4f}'.format(epoch, val_loss_all[-1]))

        ## 保存最好的网络参数
        if val_loss_all[-1] < best_loss:
            best_loss = val_loss_all[-1]
            best_model_wts = copy.deepcopy(model.state_dict())

        ## 每个epoch花费的时间
        time_use = time.time() - since
        print("Train and val complete in {:.0f}m {:.0f}s".format(time_use // 60, time_use %60))
    train_process = pd.DataFrame(
        data = {"epoch":range(num_epochs),
                "train_loss_all":train_loss_all,
                "val_loss_all":val_loss_all})
    ## 输出最好的模型
    model.load_state_dict(best_model_wts)
    return model,train_process

参考文章

Pytorch构建数据集——torch.utils.data.Dataset()和torch.utils.dataDataLoader()

Pytorch笔记05-自定义数据读取方式orch.utils.data.Dataset与Dataloader

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

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

相关文章

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解RTC的使用

&#x1f347; 博主主页&#xff1a; 【Systemcall小酒屋】&#x1f347; 博主追寻&#xff1a;热衷于用简单的案例讲述复杂的技术&#xff0c;“假传万卷书&#xff0c;真传一案例”&#xff0c;这是林群院士说过的一句话&#xff0c;另外“成就是最好的老师”&#xff0c;技术…

c++11 标准模板(STL)(std::unordered_map)(六)

定义于头文件 <unordered_map> template< class Key, class T, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator< std::pair<const Key, T> > > class unordered…

【Transformers】IMDB 分类

安装 transformers 库。 !pip install transformersimport numpy as np import pandas as pd import tensorflow as tf import tensorflow_datasets as tfdsfrom transformers import BertTokenizer from sklearn.model_selection import train_test_split from transformers i…

IO学习、拓展贴

1. 字节流 1.1 FileInputStream import org.junit.jupiter.api.Test;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException;/*** 演示FileInputStream的使用(字节输入流 文件--> 程序)*/ public class FileInputStream_ {pu…

10款最佳项目管理工具推荐,总有一款适合你

为什么需要项目管理工具&#xff1f; 如今企业规模不断扩大&#xff0c;业务逐渐复杂化&#xff0c;项目管理已经成为现代企业管理中不可或缺的一环&#xff1b; 如果没有合适的项目管理工具&#xff0c;我们的项目管理和跟踪就会变得非常困难。这可能导致项目延期或者出现一…

免费Api接口汇总(亲测可用,可写项目)

免费Api接口汇总&#xff08;亲测可用&#xff09;1. 聚合数据2. 用友API3. 天行数据4. Free Api5. 购物商城6. 网易云音乐API7. 疫情API8. 免费Api合集1. 聚合数据 https://www.juhe.cn/ 2. 用友API http://iwenwiki.com/wapicovid19/ 3. 天行数据 https://www.tianapi.com…

RK356x U-Boot研究所(命令篇)3.9 scsi命令的用法

平台U-Boot 版本Linux SDK 版本RK356x2017.09v1.2.3文章目录 一、设备树与config配置二、scsi命令的定义三、scsi命令的用法3.1 scsi总线扫描3.2 scsi设备读写一、设备树与config配置 RK3568支持SATA接口,例如ROC-RK3568-PC: 原理图如下: 可以新建一个rk3568-sata.config配…

Oracle listagg,wm_concat函数行转列结果去重Oracle 11g/19c版本

1、准备数据表 2、根据学生名(stu_name)分组&#xff0c;学生名相同的&#xff0c;学生年龄(stu_age)用逗号拼接&#xff0c;使用 listagg&#xff08;&#xff09;函数法拼接 3、上图中出现了两个12,12&#xff0c;实现去重 3.1 listagg&#xff08;&#xff09; 函数 去重 【…

网络协议(十一):单向散列函数、对称加密、非对称加密、混合密码系统、数字签名、证书

网络协议系列文章 网络协议(一)&#xff1a;基本概念、计算机之间的连接方式 网络协议(二)&#xff1a;MAC地址、IP地址、子网掩码、子网和超网 网络协议(三)&#xff1a;路由器原理及数据包传输过程 网络协议(四)&#xff1a;网络分类、ISP、上网方式、公网私网、NAT 网络…

怎么把tif格式转成jpg?快速无损转换

怎么把tif格式转成jpg&#xff1f;在编辑使用图片的时候&#xff0c;弄清各种图片格式的特点是很重要的&#xff0c;因为图片总因自身格式具备的特点不同常常出现打不开的情况&#xff0c;或者占的体积大&#xff0c;这都会直接影响我们的使用。所以目前很多的图片格式都需要提…

spring boot整合RabbitMQ

文章目录 目录 文章目录 前言 一、环境准备 二、使用步骤 2.1 RabbitMQ高级特性 2.1.1 消息的可靠性传递 2.1.2 Consumer Ack 2.2.3 TTL 2.2.4 死信队列 总结 前言 一、环境准备 引入依赖生产者和消费都引入这个依赖 <dependency><groupId>org.springframework…

自动化测试总结--断言

采购对账测试业务流程中&#xff0c;其中一个测试步骤总是失败&#xff0c;原因是用例中参数写错及断言不明确 一、问题现象&#xff1a; 采购对账主流程中&#xff0c;其中一个步骤失败了&#xff0c;会导致这个套件一直失败 图&#xff08;1&#xff09;测试报告视图中&…

Navicate远程连接Linux上docker安装的MySQL容器

Navicate远程连接Linux上docker安装的MySQL容器失败 来自&#xff1a;https://bluebeastmight.github.io/ 问题描述&#xff1a;windows端的navicat远程连接不上Linux上docker安装的mysql&#xff08;5.7版本&#xff09;容器&#xff0c;错误代码10060 标注&#xff1a; 1、…

XSS攻击防御

XSS攻击防御XSS Filter过滤方法输入验证数据净化输出编码过滤方法Web安全编码规范XSS Filter XSS Filter的作用是通过正则的方式对用户&#xff08;客户端&#xff09;请求的参数做脚本的过滤&#xff0c;从而达到防范XSS攻击的效果。 XSS Filter作为防御跨站攻击的主要手段之…

C++ Primer阅读笔记--书包程序

1--该章节新知识点 ① 在 UNIX 和 Windows 系统中&#xff0c;执行完一个程序后&#xff0c;可以通过 echo 命令获得其返回值&#xff1b; # UNIX系统中&#xff0c;通过如下命令获得状态 echo $? ② 在标准库中&#xff0c;定义了两个输出流 ostream 对象&#xff1a;cerr…

运维效率狂飙,都在告警管理上

随着数字化进程的加速&#xff0c;企业IT设备和系统越来越多&#xff0c;告警和流程中断风险也随之增加。每套系统和工具发出的警报&#xff0c;听起来像是一场喧嚣的聚会&#xff0c;各自谈论不同的话题。更糟糕的是&#xff0c;安全和运维团队正在逐渐丧失对告警的敏感度&…

2.Fully Convolutional Networks for Semantic Segmentation论文记录

欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; 文章目录1.基础介绍2.分类网络转换成全卷积分割网络3.转置卷积进行上采样4.特征融合5.一个pytorch源码实现参考资料1.基础介绍 论文:Fully Convolutional Networks for Semantic Segmentati…

如何用postman实现接口自动化测试

postman使用 开发中经常用postman来测试接口&#xff0c;一个简单的注册接口用postman测试&#xff1a; 接口正常工作只是最基本的要求&#xff0c;经常要评估接口性能&#xff0c;进行压力测试。 postman进行简单压力测试 下面是压测数据源&#xff0c;支持json和csv两个格…

Java反序列化漏洞——jdbc反序列化漏洞利用

漏洞原理如果攻击者能够控制JDBC连接设置项&#xff0c;那么就可以通过设置其指向恶意MySQL服务器进行ObjectInputStream.readObject()的反序列化攻击从而RCE。具体点说&#xff0c;就是通过JDBC连接MySQL服务端时&#xff0c;会有几个内置的SQL查询语句要执行&#xff0c;其中…

汽车用CAN通讯接口简介

随着新能源的普及,汽车用的芯片数量也越来越多,汽车在进行新四化(电动化、网联化、智能化、共享化),Gateway整车控制中心、TBox网联设备、IVI智能座舱、智驾域控制器等等ECU变得更智能,车控指令和车内通信变得更加丰富。车内ECU通讯比如CAN、LIN、蓝牙还有人提出高速以太…