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

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

    • 0. 前言
    • 1. 迁移学习
      • 1.1 迁移学习基本概念
      • 1.2 迁移学习的重要性
      • 1.3 ImageNet
      • 1.4 迁移学习流程
    • 2. VGG16 架构
    • 3. 使用预训练 VGG16 模型实现猫狗分类
    • 小结
    • 系列链接

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,792ReLU-2         [-1, 64, 224, 224]               0Conv2d-3         [-1, 64, 224, 224]          36,928ReLU-4         [-1, 64, 224, 224]               0MaxPool2d-5         [-1, 64, 112, 112]               0Conv2d-6        [-1, 128, 112, 112]          73,856ReLU-7        [-1, 128, 112, 112]               0Conv2d-8        [-1, 128, 112, 112]         147,584ReLU-9        [-1, 128, 112, 112]               0MaxPool2d-10          [-1, 128, 56, 56]               0Conv2d-11          [-1, 256, 56, 56]         295,168ReLU-12          [-1, 256, 56, 56]               0Conv2d-13          [-1, 256, 56, 56]         590,080ReLU-14          [-1, 256, 56, 56]               0Conv2d-15          [-1, 256, 56, 56]         590,080ReLU-16          [-1, 256, 56, 56]               0MaxPool2d-17          [-1, 256, 28, 28]               0Conv2d-18          [-1, 512, 28, 28]       1,180,160ReLU-19          [-1, 512, 28, 28]               0Conv2d-20          [-1, 512, 28, 28]       2,359,808ReLU-21          [-1, 512, 28, 28]               0Conv2d-22          [-1, 512, 28, 28]       2,359,808ReLU-23          [-1, 512, 28, 28]               0MaxPool2d-24          [-1, 512, 14, 14]               0Conv2d-25          [-1, 512, 14, 14]       2,359,808ReLU-26          [-1, 512, 14, 14]               0Conv2d-27          [-1, 512, 14, 14]       2,359,808ReLU-28          [-1, 512, 14, 14]               0Conv2d-29          [-1, 512, 14, 14]       2,359,808ReLU-30          [-1, 512, 14, 14]               0MaxPool2d-31            [-1, 512, 7, 7]               0
AdaptiveAvgPool2d-32            [-1, 512, 7, 7]               0Linear-33                 [-1, 4096]     102,764,544ReLU-34                 [-1, 4096]               0Dropout-35                 [-1, 4096]               0Linear-36                 [-1, 4096]      16,781,312ReLU-37                 [-1, 4096]               0Dropout-38                 [-1, 4096]               0Linear-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]               0Flatten-33                  [-1, 512]               0Linear-34                  [-1, 128]          65,664ReLU-35                  [-1, 128]               0Dropout-36                  [-1, 128]               0Linear-37                    [-1, 1]             129Sigmoid-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) == yreturn 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 = batchbatch_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 = batchis_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 = batchval_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)——类激活图

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测 目录 时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 ICEEMDAN-iMPA-BiLSTM功率/风速预测 基于改进的自适应经验模态分解改进海洋捕食者算法双向长短期记忆…

C语言深入理解指针(非常详细)(五)

目录 回调函数qsort使用举例qsort函数的模拟实现sizeof和strlen的对比sizeofstrlensizeof和strlen的对比一道关于sizeof的题 回调函数 回调函数就是一个通过函数指针调用的函数 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指…

Python小知识 - Python装饰器

Python装饰器 在Python中,装饰器是一个特殊的函数,可以将其他函数包装在装饰器函数中,并且将被包装的函数作为参数传递给装饰器函数。 使用装饰器的好处是可以自动在被包装的函数前后执行一些额外的代码,比如在函数执行前后打印日…

ClickHouse的Join算法

ClickHouse的Join算法 ClickHouse是一款开源的列式分析型数据库(OLAP),专为需要超低延迟分析查询大量数据的场景而生。为了实现分析应用可能达到的最佳性能,分析型数据库(OLAP)通常将表组合在一起形成一个…

电脑文件批量重命名:高效操作技巧

随着时间的推移,我们积累的文件和文件夹数量越来越多,需要对它们进行合理的命名和管理,以便更方便地查找和利用。而文件批量重命名功能可以帮助我们更高效地管理文件夹。下面介绍五种方式,帮助你更好地利用文件批量重命名工具&…

ADASAPA场景设计分享

相信大家都对于ADAS与APA这两个车机功能都不陌生,对其场景设计过程可能并不是很清楚。今天小怿就跟大家分享一下自己的设计心得。 首先,我们来看一下ADAS和APA的定义,以便我们更好地了解其功能和应用场景。 ADAS定义 ADAS的全称叫Advanced …

Nosql数据库服务之redis

Nosql数据库服务之redis 一图详解DB的分支产品 Nosql数据库介绍 是一种非关系型数据库服务,它能解决常规数据库的并发能力,比如传统的数据库的IO与性能的瓶颈,同样它是关系型数据库的一个补充,有着比较好的高效率与高性能。 专…

视频讲解|3014 含分布式电源的配电网优化重构

目录 1 主要内容 2 讲解视频链接 3 部分程序 1 主要内容 该视频为程序目录中编号1034的讲解内容,该程序的链接为配电网优化重构matlab智能算法,本次重点讲解了基本环矩阵原理以及代码两步实现过程、如何利用基本环向量去创造可行解、粒子群优化过程、…

list【2】模拟实现(含迭代器实现超详解哦)

模拟实现list 引言(实现概述)list迭代器实现默认成员函数operator* 与 operator->operator 与 operator--operator 与 operator!迭代器实现概览 list主要接口实现默认成员函数构造函数析构函数赋值重载 迭代器容量元素访问数据修改inserterasepush_ba…

Kafka3.0.0版本——消费者(消费者组详细消费流程图解及消费者重要参数)

目录 一、消费者组详细消费流程图解二、消费者的重要参数 一、消费者组详细消费流程图解 创建一个消费者网络连接客户端,主要用于与kafka集群进行交互,如下图所示: 调用sendFetches发送消费请求,如下图所示: (1)、Fet…

【halcon】halcon字符识别——OCR

前言 OCR(Optical Character Recongnition)光学字符识别。 halcon 的OCR,提供了几种方式,我们应该如何选择? 自动文本阅读器(find_text)手动文本阅读器(find_text)自己…

Android USB电源管理

The USB peripheral detects the lack of 3 consecutive SOF packets as a suspend request from the USB host. 1 驱动shutdown顺序 系统关机或重启的过程中,会调用设备驱动的shutdown函数来完成设备的关闭操作,有需要的设备可以在驱动中定义该函数。其…

Python一行命令搭建HTTP服务器并外网访问 - 内网穿透

文章目录 1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试 3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 Python作为热度比较高的编程语言,其语法简单且语句清晰,而且python有…

射频功率放大器的指标有哪些内容

射频功率放大器是射频系统中至关重要的组件,用于放大射频信号的功率。本文将详细介绍射频功率放大器的指标,包括功率增益、带宽、线性度、效率、稳定性等关键指标。 一、功率增益 功率增益是射频功率放大器最基本的指标之一,表示放大器将输入…

taro h5 点击页面任意地方关闭弹窗组件 --- findDOMNode 判断点击节点是否属于某个组件

场景:如图,弹窗在大组件中,点击小组件显示弹窗,要求点击除弹窗外的任何元素都能关闭弹窗并且能执行元素原有的逻辑 方法一 最简单的是弹窗背后有一个覆盖整个页面的透明的cover, 点击直接关闭,但是这样虽然点击页面…

Spring最佳实践: 构建高效可维护的Java应用程序

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

【docker】私有仓库搭建

Docker 私有仓库搭建 在 Docker 中,当我们执行 docker pull xxx 的时候 ,它实际上是从 registry.hub.docker.com 这个地址去查找,这就是Docker公司为我们提供的公共仓库。在工作中,我们不可能把企业项目push到公有仓库进行管理。…

试图替代 Python 的下一代AI编程语言:Mojo

文章目录 为什么叫 Mojo ?Python 家族的一员,MojoPython 的好处:Python 兼容性Python 的问题移动和服务器部署:Python 子集和其他类似 Python 的语言: Mojo 是一种创新的编程语言,结合了 Python 的可用性和…

浅谈redis未授权漏洞

redis未授权漏洞 利用条件 版本比较高的redis需要修改redis的配置文件,将bind前面#注释符去掉,将protected-mode 后面改为no 写入webshell config get dir #查看redis数据库路径 config set dir web路径# #修改靶机Redis数据库路径 config set dbfilen…

基于SSM的人事管理信息系统

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…