PyTorch深度学习实战(15)——迁移学习

2023-11-03

0. 前言

迁移学习( Transfer Learning )是一种利用从一项任务中获得的知识来解决另一项类似任务的技术。一个使用数百万张图像训练的模型,训练数据涵盖数千种对象类别,模型的卷积核将能够学习图像中的各种形状、颜色和纹理,通过重用这些卷积核可以学习到新图像的特征,并最终用于执行计算机视觉任务。随着训练数据集中可用图像数量的增加,模型的分类准确率会不断提高,然而,在实际训练模型过程中,获取大量具有标签的数据样本通常比较困难,需要耗费大量时间和人力成本,而迁移学习能够在训练数据不足的情况下实现更好的泛化性能。

1. 迁移学习

1.1 迁移学习基本概念

迁移学习指利用已经学习好的模型在新任务上具有良好的表现和推广能力的机器学习技术,能够将通用数据集上的模型学习迁移到特定数据集中。通常,用于执行迁移学习的预训练模型在数百万张图像(通用大型数据集)上进行训练,然后使用特定感兴趣数据集微调预训练模型。

迁移学习

1.2 迁移学习的重要性

假设我们需要处理道路图像,并根据图像包含的对象进行分类,而从零开始构建、训练模型可能会因为图像的数量不足,而难以学习到数据集中的各种变化,正如在猫狗分类模型中所看到的,对 8,000 张图像进行训练比在 2000 张图像上进行训练的模型准确率更高。在 ImageNet 上训练的预训练模型能够很好的解决该问题,在对 ImageNet 数据集进行训练期间,模型已经学习了很多与交通相关的特征,例如汽车、道路、树木和人等。因为模型已经学习了大量通用特征,因此,利用已经训练好的模型能够更快和更准确的训练新模型,只需要将预训练模型提取到的特征用于新模型的训练,就可以得到适用于目标任务的性能优异的新模型。

1.3 ImageNet

ImageNet 是一个大规模图像数据集,该数据集包含了超过 1400 万张标注图像,覆盖了 1 万多个分类标签。ImageNet 数据集被广泛用于计算机视觉领域中,包括自动驾驶、智能监控、医学影像分析等。ImageNet 挑战赛ImageNet 项目组于 2010 年开始举办,是计算机视觉领域的顶尖比赛之一。在本节中,将使用在 ImageNet 数据集上预训练的深度神经网络构建迁移学习模型。

1.4 迁移学习流程

迁移学习的一般流程如下:

  • 归一化输入图像,使用与预训练模型训练期间相同的均值和标准差进行归一化
  • 获取在大型数据集上进行预训练模型的架构与模型权重
  • 丢弃预训练模型的最后几层
  • 将截断的预训练模型连接到一个或多个新初始化的神经网络层,并确保最后一层的神经元与需要预测的类别数(输出)相同
  • 确保预训练模型的权重不可更新(即在反向传播期间冻结预训练模型参数),但新初始化的神经网络层权重是可训练的。因为预训练模型权重已经使用大型数据集进行了很好的训练,因此可以利用从大型模型中学习到的特征而无需对预训练模型进行训练,而只需要利用小数据集训练新初始化的神经网络层
  • 更新可训练参数,拟合模型

我们已经了解了如何实现迁移学习,接下来,我们介绍预训练卷积神经网络架构 VGG,并使用迁移学习将预训练模型应用于猫狗分类任务。

2. VGG16 架构

Visual Geometry Group (VGG) 是由牛津大学的研究人员在 2014 年提出的卷积神经网络架构,其中 16 代表模型中的层数,包含 13 层的卷积层,3 层的全连接层。 VGG16 分类模型在 2014 年的 ImageNet 比赛中获得了亚军,是一种广泛应用于计算机视觉任务的模型架构。VGG16 中的卷积层使用小尺寸的卷积核,以增加网络深度,提高模型的非线性能力,并且能够提取更丰富的特征。接下来,我们介绍 VGG16 架构以及如何在 PyTorch 中使用 VGG16 预训练模型。

(1) 导入所需要的库:

import torch
from torchvision import transforms,models,datasets
from torchsummary import summary
device = 'cuda' if torch.cuda.is_available() else 'cpu'

torchvision 包中的 models 模块提供了 PyTorch 中可用的预训练模型。

(2) 加载 VGG16 模型并在设备内注册模型:

model = models.vgg16(pretrained=True).to(device)

在以上代码中,models 类中调用了 vgg16 方法,通过使用 pretrained = True 指定加载用于在 ImageNet 竞赛中对图像进行分类的权重,然后将模型注册到设备中。

(3) 打印模型摘要:

print(summary(model, (3, 224, 224)))

模型摘要输出如下:

----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1         [-1, 64, 224, 224]           1,792
              ReLU-2         [-1, 64, 224, 224]               0
            Conv2d-3         [-1, 64, 224, 224]          36,928
              ReLU-4         [-1, 64, 224, 224]               0
         MaxPool2d-5         [-1, 64, 112, 112]               0
            Conv2d-6        [-1, 128, 112, 112]          73,856
              ReLU-7        [-1, 128, 112, 112]               0
            Conv2d-8        [-1, 128, 112, 112]         147,584
              ReLU-9        [-1, 128, 112, 112]               0
        MaxPool2d-10          [-1, 128, 56, 56]               0
           Conv2d-11          [-1, 256, 56, 56]         295,168
             ReLU-12          [-1, 256, 56, 56]               0
           Conv2d-13          [-1, 256, 56, 56]         590,080
             ReLU-14          [-1, 256, 56, 56]               0
           Conv2d-15          [-1, 256, 56, 56]         590,080
             ReLU-16          [-1, 256, 56, 56]               0
        MaxPool2d-17          [-1, 256, 28, 28]               0
           Conv2d-18          [-1, 512, 28, 28]       1,180,160
             ReLU-19          [-1, 512, 28, 28]               0
           Conv2d-20          [-1, 512, 28, 28]       2,359,808
             ReLU-21          [-1, 512, 28, 28]               0
           Conv2d-22          [-1, 512, 28, 28]       2,359,808
             ReLU-23          [-1, 512, 28, 28]               0
        MaxPool2d-24          [-1, 512, 14, 14]               0
           Conv2d-25          [-1, 512, 14, 14]       2,359,808
             ReLU-26          [-1, 512, 14, 14]               0
           Conv2d-27          [-1, 512, 14, 14]       2,359,808
             ReLU-28          [-1, 512, 14, 14]               0
           Conv2d-29          [-1, 512, 14, 14]       2,359,808
             ReLU-30          [-1, 512, 14, 14]               0
        MaxPool2d-31            [-1, 512, 7, 7]               0
AdaptiveAvgPool2d-32            [-1, 512, 7, 7]               0
           Linear-33                 [-1, 4096]     102,764,544
             ReLU-34                 [-1, 4096]               0
          Dropout-35                 [-1, 4096]               0
           Linear-36                 [-1, 4096]      16,781,312
             ReLU-37                 [-1, 4096]               0
          Dropout-38                 [-1, 4096]               0
           Linear-39                 [-1, 1000]       4,097,000
================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 218.78
Params size (MB): 527.79
Estimated Total Size (MB): 747.15
----------------------------------------------------------------

神经网络各层可视化结果如下:

VGG

该网络中约有 1.38 亿个参数(网络末端的线性层包括约 102 万 + 16 万 + 400 万 = 1.22 亿个参数),其中包括 13 个卷积层和 3 个线性层,可以使用 models 打印 VGG16 模型组件:

print(model)

输出结果如下所示:

VGG16模型架构
模型中包括三个主要的子模块——featuresavgpoolclassifier,通常,需要冻结 featuresavgpool 模块,删除分类器 (classifier) 模块并在其位置创建一个新的 classifier 模块,用于预测新任务所需的图像类别。

3. 使用预训练 VGG16 模型实现猫狗分类

接下来,我们介绍如何在实践中使用 VGG16 模型,仅使用 1000 张图像(猫、狗图像各 500 张)构建猫狗分类模型。

(1) 导入所需的库:

import torch.nn as nn
import torch
from torchvision import transforms,models
import matplotlib.pyplot as plt
import numpy as np
device = 'cuda' if torch.cuda.is_available() else 'cpu'
import cv2, glob, numpy as np
import matplotlib.pyplot as plt
from glob import glob
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, Dataset

(2) 下载猫狗分类数据集、解压并指定训练和测试目录:

train_data_dir = 'archive/training_set/training_set'
test_data_dir = 'archive/test_set/test_set'

(2) 定义 Dataset 类,用于返回猫狗数据集的输入-输出对,使用 transforms 模块中的 Normalize 调用 normalize 函数执行数据归一化,并获取每个文件夹中的前 500 张图像:

class CatsDogs(Dataset):
    def __init__(self, folder):
        cats = glob(folder+'/cats/*.jpg')
        dogs = glob(folder+'/dogs/*.jpg')
        self.fpaths = cats[:500] + dogs[:500]
        self.normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
        from random import shuffle, seed; seed(10); shuffle(self.fpaths)
        self.targets = [fpath.split('/')[-1].startswith('dog') for fpath in self.fpaths] 
    def __len__(self):
        return len(self.fpaths)
    def __getitem__(self, ix):
        f = self.fpaths[ix]
        target = self.targets[ix]
        im = (cv2.imread(f)[:,:,::-1])
        im = cv2.resize(im, (224,224))
        im = torch.tensor(im/255)
        im = im.permute(2,0,1)
        im = self.normalize(im) 
        return im.float().to(device), torch.tensor([target]).float().to(device)

在利用预训练模型时,必须对图像调整大小、交换通道顺序和归一化(根据所用预训练模型),图像将 3 个通道上的像素值缩放至 01 之间,然后使用指定平均值( [0.485, 0.456, 0.406] )和标准差( [0.229, 0.224, 0.225] )归一化 RGB 通道。

(3) 获取图像及其标签,抽样检查示例图像及其对应的类别标签:

data = CatsDogs(train_data_dir)

im, label = data[100]
plt.imshow(im.permute(1,2,0).cpu())
plt.show()
print(label)
# tensor([0.], device='cuda:0')

数据图像
(4) 定义模型,下载预训练的 VGG16 权重,冻结特征提取模块,并训练新的分类器。

首先,利用 models 类下载预训练的 VGG16 模型:

def get_model():
    model = models.vgg16(pretrained=True)

通过指定 param.requires_grad = False 在反向传播期间冻结模型参数:

    for param in model.parameters():
        param.requires_grad = False

替换 avgpool 模块以返回大小为 1 x 1 的特征图替换原模型中 7 x 7 的特征图,即输出尺寸变为 batch_size x 512 x 1 x 1

    model.avgpool = nn.AdaptiveAvgPool2d(output_size=(1,1))

PyTorch 中,nn.MaxPool2d 用于从特征图的每个部分中选择最大值,而 nn.AvgPool2d 会返回特征图每个部分的平均值,在这两个网络层中使用了固定大小的核。nn.AdaptiveAvgPool2d 是另一类池化层,可以指定输出特征图的尺寸,该层自动计算核大小,以便返回指定尺寸的特征图。例如,如果输入特征图尺寸为 batch_size x 512 x k x k,想要得到尺寸为的特征图 batch_size x 512 x 21 x 1,则池化核大小为 k x k,而使用 nn.AdaptiveAvgPool2d 层无论输入尺寸如何,其输出尺寸始终是固定的,因此,神经网络可以接受任何尺寸的输入图像。

定义模型的分类器模块,首先展平 avgpool 模块的输出,然后连接到具有 128 个单元的隐藏层,并在执行激活函数后连接到输出层:

    model.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(512, 128),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(128, 1),
            nn.Sigmoid()
    )

定义损失函数 (loss_fn)、优化器:

    loss_fn = nn.BCELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr= 1e-3)
    return model.to(device), loss_fn, optimizer

在以上代码中,我们首先冻结了预训练模型的所有参数,然后定义了新的 avgpool 和分类器模块,打印模型摘要:

from torchsummary import summary
model, criterion, optimizer = get_model()
print(summary(model, (3,224,224)))

输出结果如下所示:

----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1         [-1, 64, 224, 224]           1,792
              ......         ..................               .
        MaxPool2d-31            [-1, 512, 7, 7]               0
AdaptiveAvgPool2d-32            [-1, 512, 1, 1]               0
          Flatten-33                  [-1, 512]               0
           Linear-34                  [-1, 128]          65,664
             ReLU-35                  [-1, 128]               0
          Dropout-36                  [-1, 128]               0
           Linear-37                    [-1, 1]             129
          Sigmoid-38                    [-1, 1]               0
================================================================
Total params: 14,780,481
Trainable params: 65,793
Non-trainable params: 14,714,688
----------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 218.41
Params size (MB): 56.38
Estimated Total Size (MB): 275.36
----------------------------------------------------------------

输出中省去了与预训练模型中相同的网络层,模型共有 1470 万个参数,其中可训练参数的数量只有 65,793 个,因为模型中只有分类器模块具有要学习的权重。

(5) 定义函数获取数据、训练模型、计算准确度:

def train_batch(x, y, model, optimizer, loss_fn):
    prediction = model(x)
    batch_loss = loss_fn(prediction, y)
    batch_loss.backward()
    optimizer.step()
    optimizer.zero_grad()
    return batch_loss.item()

def accuracy(x, y, model):
    with torch.no_grad():
        prediction = model(x)
    is_correct = (prediction > 0.5) == y
    return is_correct.cpu().numpy().tolist()

def get_data():
    train = CatsDogs(train_data_dir)
    trn_dl = DataLoader(train, batch_size=32, shuffle=True, drop_last = True)
    val = CatsDogs(test_data_dir)
    val_dl = DataLoader(val, batch_size=32, shuffle=True, drop_last = True)
    return trn_dl, val_dl

@torch.no_grad()
def val_loss(x, y, model, loss_fn):
    prediction = model(x)
    val_loss = loss_fn(prediction, y)
    return val_loss.item()

(6) 初始化 get_data()get_model() 函数:

trn_dl, val_dl = get_data()
model, loss_fn, optimizer = get_model()

(7) 训练模型,并绘制模型训练过程中训练和测试准确率:

train_losses, train_accuracies = [], []
val_accuracies = []
for epoch in range(10):
    print(f" epoch {epoch + 1}/10")
    train_epoch_losses, train_epoch_accuracies = [], []
    val_epoch_accuracies = []

    for ix, batch in enumerate(iter(trn_dl)):
        x, y = batch
        batch_loss = train_batch(x, y, model, optimizer, loss_fn)
        train_epoch_losses.append(batch_loss) 
    train_epoch_loss = np.array(train_epoch_losses).mean()

    for ix, batch in enumerate(iter(trn_dl)):
        x, y = batch
        is_correct = accuracy(x, y, model)
        train_epoch_accuracies.extend(is_correct)
    train_epoch_accuracy = np.mean(train_epoch_accuracies)

    for ix, batch in enumerate(iter(val_dl)):
        x, y = batch
        val_is_correct = accuracy(x, y, model)
        val_epoch_accuracies.extend(val_is_correct)
    val_epoch_accuracy = np.mean(val_epoch_accuracies)

    train_losses.append(train_epoch_loss)
    train_accuracies.append(train_epoch_accuracy)
    val_accuracies.append(val_epoch_accuracy)

epochs = np.arange(10)+1
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
plt.plot(epochs, train_accuracies, 'bo', label='Training accuracy')
plt.plot(epochs, val_accuracies, 'r', label='Validation accuracy')
plt.gca().xaxis.set_major_locator(mticker.MultipleLocator(1))
plt.title('Training and validation accuracy with VGG16 \nand 1K training data points')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.ylim(0.95,1)
plt.gca().set_yticklabels(['{:.0f}%'.format(x*100) for x in plt.gca().get_yticks()]) 
plt.legend()
plt.grid('off')
plt.show()

模型性能
可以看到,在第一个 epoch 结束时模型准确率就可以达到 98%,即使训练数据集中仅包含 1,000 张图像(每个类别 500 张图像)。
除了 VGG16,也可以使用 VGG11VGG19 预训练神经网络架构,它们的工作方式与 VGG16 类似,仅层数不同。 VGG19VGG16 有更多的参数,因为它有更多的网络层。
使用 VGG11VGG19 代替 VGG16 预训练模型时的训练和验证准确率如下:

模型性能

可以看到,基于 VGG19 模型的准确率略高于基于 VGG16 的模型,在验证数据上的准确率为 98%,基于 VGG11 模型的准确率略低,为 97%

小结

迁移学习通过利用相关任务或领域的知识,帮助解决新任务或领域中的学习挑战,可以提高模型的泛化能力、加速模型训练,并在实际应用中取得良好的效果。在图像分类、目标检测、机器翻译等任务中,迁移学习已经展现出巨大的应用价值。在本节中,介绍了迁移学习的基本概念,并使用 PyTorch 构建了迁移学习模型,利用预训练模型 VGG 加速学习过程并提高性能。

系列链接

PyTorch深度学习实战(1)——神经网络与模型训练过程详解
PyTorch深度学习实战(2)——PyTorch基础
PyTorch深度学习实战(3)——使用PyTorch构建神经网络
PyTorch深度学习实战(4)——常用激活函数和损失函数详解
PyTorch深度学习实战(5)——计算机视觉基础
PyTorch深度学习实战(6)——神经网络性能优化技术
PyTorch深度学习实战(7)——批大小对神经网络训练的影响
PyTorch深度学习实战(8)——批归一化
PyTorch深度学习实战(9)——学习率优化
PyTorch深度学习实战(10)——过拟合及其解决方法
PyTorch深度学习实战(11)——卷积神经网络
PyTorch深度学习实战(12)——数据增强
PyTorch深度学习实战(13)——可视化神经网络中间层输出
PyTorch深度学习实战(14)——类激活图

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PyTorch深度学习实战(15)——迁移学习 的相关文章

  • 用我自己的值初始化pytorch卷积层

    我想知道是否有办法用我自己的值初始化 pytorch 卷积过滤器 例如 我有一个元组 0 8423 0 3778 3 1070 2 6518 我想用这些值初始化 2X2 过滤器 我该怎么做 我查找了一些答案 但他们大多使用火炬正态分布和其他
  • 如何检查 PyTorch 是否正在使用 GPU?

    如何检查 PyTorch 是否正在使用 GPU 这nvidia smi命令可以检测 GPU 活动 但我想直接从 Python 脚本内部检查它 这些功能应该有助于 gt gt gt import torch gt gt gt torch cu
  • 将 CNN Pytorch 中的预训练权重传递到 Tensorflow 中的 CNN

    我在 Pytorch 中针对 224x224 大小的图像和 4 个类别训练了这个网络 class CustomConvNet nn Module def init self num classes super CustomConvNet s
  • pytorch grad 在 .backward() 之后为 None

    我刚刚安装火炬 1 0 0 on Python 3 7 2 macOS 并尝试tutorial https pytorch org tutorials beginner blitz autograd tutorial html sphx g
  • 使用 KL 散度时,变分自动编码器为每个输入 mnist 图像提供相同的输出图像

    当不使用 KL 散度项时 VAE 几乎完美地重建 mnist 图像 但在提供随机噪声时无法正确生成新图像 当使用 KL 散度项时 VAE 在重建和生成图像时都会给出相同的奇怪输出 这是损失函数的 pytorch 代码 def loss fu
  • 在pytorch张量中过滤数据

    我有一个张量X like 0 1 0 5 1 0 0 1 2 0 我想实现一个名为的函数filter positive 它可以将正数据过滤成新的张量并返回原始张量的索引 例如 new tensor index filter positive
  • 一次热编码期间出现 RunTimeError

    我有一个数据集 其中类值以 1 步从 2 到 2 i e 2 1 0 1 2 其中 9 标识未标记的数据 使用一种热编码 self one hot encode labels 我收到以下错误 RuntimeError index 1 is
  • torch.mm、torch.matmul 和 torch.mul 有什么区别?

    阅读完 pytorch 文档后 我仍然需要帮助来理解之间的区别torch mm torch matmul and torch mul 由于我不完全理解它们 所以我无法简明地解释这一点 B torch tensor 1 1207 0 3137
  • 如何在pytorch中查看DataLoader中的数据

    我在 Github 上的示例中看到类似以下内容 如何查看该数据的类型 形状和其他属性 train data MyDataset int 1e3 length 50 train iterator DataLoader train data b
  • 下载变压器模型以供离线使用

    我有一个训练有素的 Transformer NER 模型 我想在未连接到互联网的机器上使用它 加载此类模型时 当前会将缓存文件下载到 cache 文件夹 要离线加载并运行模型 需要将 cache 文件夹中的文件复制到离线机器上 然而 这些文
  • pytorch 中的 keras.layers.Masking 相当于什么?

    我有时间序列序列 我需要通过将零填充到矩阵中并在 keras 中使用 keras layers Masking 来将序列的长度固定为一个数字 我可以忽略这些填充的零以进行进一步的计算 我想知道它怎么可能在 Pytorch 中完成 要么我需要
  • Blenderbot 微调

    我一直在尝试微调 HuggingFace 的对话模型 Blendebot 我已经尝试过官方拥抱脸网站上给出的传统方法 该方法要求我们使用 trainer train 方法来完成此操作 我使用 compile 方法尝试了它 我尝试过使用 Py
  • 将 Keras (Tensorflow) 卷积神经网络转换为 PyTorch 卷积网络?

    Keras 和 PyTorch 使用不同的参数进行填充 Keras 需要输入字符串 而 PyTorch 使用数字 有什么区别 如何将一个转换为另一个 哪些代码在任一框架中获得相同的结果 PyTorch 还采用参数 in channels o
  • 如何有效地对一个数组中某个值在另一个数组中的位置出现的次数求和

    我正在寻找一种有效的 for 循环 避免解决方案来解决我遇到的数组相关问题 我想使用一个巨大的一维数组 A gt size 250 000 用于一维索引的 0 到 40 之间的值 以及用于第二维索引的具有 0 到 9995 之间的值的相同大
  • torch.stack() 和 torch.cat() 函数有什么区别?

    OpenAI 的强化学习 REINFORCE 和 actor critic 示例具有以下代码 加强 https github com pytorch examples blob master reinforcement learning r
  • pytorch 的 IDE 自动完成

    我正在使用 Visual Studio 代码 最近尝试了风筝 这两者似乎都没有 pytorch 的自动完成功能 这些工具可以吗 如果没有 有人可以推荐一个可以的编辑器吗 谢谢你 使用Pycharmhttps www jetbrains co
  • 如何从已安装的云端硬盘文件夹中永久删除?

    我编写了一个脚本 在每次迭代后将我的模型和训练示例上传到 Google Drive 以防发生崩溃或任何阻止笔记本运行的情况 如下所示 drive path drive My Drive Colab Notebooks models if p
  • PyTorch 中的交叉熵

    交叉熵公式 但为什么下面给出loss 0 7437代替loss 0 since 1 log 1 0 import torch import torch nn as nn from torch autograd import Variable
  • 如何在 PyTorch 中对子集使用不同的数据增强

    如何针对不同的情况使用不同的数据增强 转换 Subset在 PyTorch 中吗 例如 train test torch utils data random split dataset 80000 2000 train and test将具
  • PyTorch:如何批量进行推理(并行推理)

    如何在PyTorch中批量进行推理 如何并行进行推理以加快这部分代码的速度 我从进行推理的标准方法开始 with torch no grad for inputs labels in dataloader predict inputs in

随机推荐

  • QT控件之(TableView)的居中效果

    T将tableView中的表头以及文本内容都进行居中处理 1 需要在构造函数中增加一句 以下增加的是表头的效果 ui gt tableView gt horizontalHeader gt setSectionResizeMode QHea
  • SQL注入之布尔盲注

    布尔盲注 如果确定页面注入点存在 如果页面没有回显并且没有报错信息可以考虑使用布尔盲注 布尔盲注的判断条件是页面布尔类型状态 当传递参数 id 1 and 1 1 这里以sqlilab的闯关为例 当传递参数 id 1 and 1 2 比较两
  • MyBatis学习(三):解析MyBatis的SQL映射XML文件写法和使用原理

    上面的两篇文章 分别是MyBatis的入门小程序和MyBatis的配置XML解析 有需要的可以先去看看这两篇文章 本篇文章 会来讲解SQL映射XML文件的写法以及如何使用 MyBatis真正的力量在于其映射语句 这里应该是奇迹发生的地方 S
  • Vue传参出现 Required String parameter 'username' is not present

    场景描述 在 使用axios 发送HTTP请求时 传递了后端指定的请求参数 但是后端报错 描述信息为 Required String parameter username is not present 分析问题 开始找原因 确定前端传递的参
  • jsp页面整合ECharts绘制图表(以折线图为例)

    文章目录 jsp页面整合ECharts绘制折线图 先看效果图 前端代码 后端测试代码 jsp页面整合ECharts绘制折线图 官网 https echarts apache org zh index html 官网上有demo可以直接调试样
  • 2021-06-15 好用的STF-Git项目

    好用的STF Git项目 1 基于openstf二次开发的群控管理平台 快速开始 Mac Linux centos 相关工具 测试使用版本 2 deploy stf docker 在Ubuntu上使用一键操作部署STF主服务器的脚本 1 基
  • Pyecharts——Python高级可视化

    Pyecharts是百度开源的移植到Python上的可视化工具 里面方法调用起来像是标记性语言 因此代码的可读性很强 一目了然 下面是一个绘制散点图的例子 import pyecharts options as opts from pyec
  • 出现 DeprecationWarning: BICUBIC is deprecated and will be removed in Pillow 10 的解决方法

    目录 1 问题所示 2 原理分析 3 解决方法 1 问题所示 使用plt代码模块的时候 问题如下 home kkjz anaconda3 envs py17 lib python3 7 site packages ipykernel lau
  • 强推,黑白照片一步完美上色,Picture Colorizer Pro Mac版

    今天在国外一个网站偶尔发现一个超棒的软件Picture Colorizer Pro专业版 黑白照片或老旧照片自动上色 心动不如行动 马上下载上手使用 效果超棒 它的强在在于色彩还原非常真实 有老照片的胶片感 边缘过度很精细 没有粗糙的感觉
  • 在C++中如何使用httpClient,用Newtonsoft解析JSON

    现在C 也不行了吗 网上找不到相关代码 为了搞清楚C 中如何使用httpClient和Newtonsoft 研究了一下午 我从未用C 编程 一直用C 现学现卖 https download csdn net download cnwjl 1
  • 深入浅出java并发编程(AbstractQueuedSynchronizer)(AQS)

    前言 Abstract抽象的 Ownable拥有 Synchronizer同步器 Queued队列 AbstractOwnableSynchronizer简称为AOS AbstractQueuedSynchronizer简称为AQS Abs
  • Springboot+mybatis+druid的整合

    最近的公司项目后端用到了Springboot框架 把阿里的druid作为数据源 采用mybatis druid的方式 本人之前也是在这里踩了很多坑 因此感觉有必要出个博客来记录一下 首先 用druid最为数据源的好处就不多说了 灵活动态切换
  • docker保存和加载tar及其tar.gz

    1 导出和加载tar 1 1 save和load命令 save命令 docker save options images images 示例 docker save o nginx tar nginx latest 或 docker sav
  • 005_关于QT之QWidget的事件处理机制

    一 eventFilter函数 事件过滤函数 一般用于容器组件来决定是否将事件传递给子组件 当前组件的事件过滤函数 在事件直接发生在当前组件时该组件的过滤函数是不被调用的 二 event函数 用于组件内部事件函数的分发 在这个函数内部调用事
  • opencv esp32cam的初步应用

    import urllib request import numpy as np import cv2 def cam esp32cam的ip地址 url 192 168 43 1 png 获取esp32cam的镜头 imgResp url
  • verilog case语句_verilog语法进阶

    欢迎FPGA工程师加入官方微信技术群 模块的结构 数据类型 变量和基本运算符号 3 1 模块的结构 Verilog的基本设计单元是 模块 block 一个模块是由两部分组成的 一部分描述接口 另一部分描述逻辑功能 即定义输入是如何影响输出的
  • 解决:Failed to execute goal org.apache.maven.pluginsmaven-archetype-plugin3.1.2generate

    问题 Failed to execute goal org apache maven plugins maven archetype plugin 3 1 2 generate default cli on project standalo
  • webpack server.js本机模拟数据

    文件路径 data json seller name 粥品香坊 回龙观 description 蜂鸟专送 deliveryTime 38 score 4 2 serviceScore 4 1 foodScore 4 3 rankRate 6
  • ffmpeg 视频解码一

    1 ffmpeg 视频解码一 2 ffmpeg 视频解码二 3 ffmpeg 音频解码一 4 ffmpeg 音频解码二 5 ffmpeg 音视频解码 6 ffmpeg 视频编码一 7 ffmpeg 视频编码一 精简版 8 ffmpeg 视频
  • PyTorch深度学习实战(15)——迁移学习

    PyTorch深度学习实战 15 迁移学习 0 前言 1 迁移学习 1 1 迁移学习基本概念 1 2 迁移学习的重要性 1 3 ImageNet 1 4 迁移学习流程 2 VGG16 架构 3 使用预训练 VGG16 模型实现猫狗分类 小结