《PyTorch 深度学习实践》第11讲 卷积神经网络(高级篇)

news2024/12/23 17:41:25

文章目录

  • 1 Inception Module
    • 1.1 1×1卷积
    • 1.2 Inception模块结构
    • 1.3 完整代码
  • 2 残差网络(Residual Network)

该专栏内容为对该视频的学习记录:【《PyTorch深度学习实践》完结合集】
专栏的全部代码、数据集和课件全放在个人GitHub了,欢迎自取

1 Inception Module

GoogLeNet(又称为Inception-v1)是由谷歌公司在2014年提出的一个卷积神经网络架构,它是当时ImageNet图像识别挑战赛的冠军,其准确性超过了以往所有的卷积神经网络架构。

GoogLeNet主要的创新在于使用了一个名为“Inception”的模块,这个模块使用了多个不同尺寸的卷积核和池化核,从而可以在不同的尺度上提取图像特征。通过将多个Inception模块串联在一起,可以构建一个非常深的卷积神经网络,同时保持计算效率和准确性

除了Inception模块之外,GoogLeNet还采用了一些其他的技术来提高模型的准确性,比如使用全局平均池化层来代替全连接层,从而减少模型参数数量,防止过拟合等等。GoogLeNet的成功启示了后来很多卷积神经网络架构的设计,也成为了深度学习领域的一个里程碑。

image-20230417192448100

在Inception中有许多1×1的卷积核

image-20230417192718956

1.1 1×1卷积

在Inception网络中,1x1卷积核起到了非常重要的作用。它通常被用于在通道(channel)维度上进行降维和升维的操作,可以将输入特征图的通道数进行压缩或扩展,从而减少模型的计算复杂度和参数数量,提高计算效率和准确性

具体来说,使用1x1卷积核可以实现以下两种操作:

  1. 通道的降维:将输入特征图的通道数减少,从而减小模型参数的数量,提高计算效率。这种操作通常在Inception网络中的“线性池化”(bottleneck)结构中使用,它先使用1x1卷积核对输入特征图进行降维,然后再应用较大的卷积核进行特征提取。
  2. 通道的升维:将输入特征图的通道数扩展,从而增加模型的表示能力。这种操作通常在Inception网络中的“inception模块”中使用,它先使用1x1卷积核将输入特征图的通道数进行扩展,然后再使用不同尺寸的卷积核进行特征提取。

通过使用1x1卷积核,Inception网络可以实现在不同尺度上提取特征,从而提高模型的准确性和计算效率。

计算示例:下图为把三通道的输入变成一通道的输出

image-20230417192844328

在减少计算复杂程度上,相同形状的输出结果减少了接近一个数量级

image-20230417193136271

1.2 Inception模块结构

内部结构:在四个分支各自产生的输出根据通道维度拼接成该Inception块的输出。

image-20230417193253676

image-20230417193710583

image-20230417193822829

1.3 完整代码

这段代码的作用是定义了一个卷积神经网络模型,并准备了MNIST数据集进行训练。

具体来说,代码的主要功能如下:

  1. 通过torchvision库中的transforms模块,定义了一系列对MNIST数据集进行预处理的操作,包括将图片转换为Tensor类型,以及对Tensor进行标准化处理,使得数据的取值范围在[0,1]之间,并减去均值0.1307,除以标准差0.3081。
  2. 使用torchvision库中的datasets模块,分别准备了训练集和测试集,并通过DataLoader函数将它们打包成了可迭代的数据集对象,方便进行批量训练和测试。
  3. 定义了Inception块类InceptionA,它包含了4个分支,分别进行了不同的卷积操作,并将它们在通道维度上进行了拼接。其中,第1个分支为1x1卷积,第2个分支为1x1卷积 + 5x5卷积,第3个分支为1x1卷积 + 3x3卷积 + 3x3卷积,第4个分支为1x1卷积 + 平均池化。最终输出通道数为88
  4. 定义了卷积神经网络模型Net,包含了2个卷积层、2个Inception块、1个最大池化层和1个全连接层。其中,第1个卷积层的输入通道数为1,输出通道数为10,卷积核大小为5;第2个卷积层的输入通道数为88,输出通道数为20,卷积核大小为5;第1个Inception块的输入通道数为10,输出通道数为88;第2个Inception块的输入通道数为20,输出通道数为88;最大池化层的核大小为2;全连接层的输入大小为1408,输出大小为10。
  5. 在forward函数中,定义了模型的前向传播过程,包括了卷积、Inception块、池化和全连接层。其中,卷积和Inception块的输出使用ReLU作为激活函数,最终输出使用Softmax函数进行归一化。
  6. 在训练过程中,使用交叉熵损失函数作为评价指标,使用SGD优化器进行参数优化,训练次数为10个epoch。最终得到的模型在测试集上的准确率为98.97%。
import torch
import torch.nn.functional as F
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# 1、准备数据集
batch_size = 64
transform = transforms.Compose([  # 一系列的操作,Compose将其组合在一起
    transforms.ToTensor(),  # 将图片转换为Tensor
    transforms.Normalize((0.1307,), (0.3081,))  # 标准化到[0,1],均值和方差
])
train_dataset = datasets.MNIST(root='../P6 逻辑斯谛回归/data', train=True,
                               download=False,  # 在P6 逻辑斯谛回归中我已下载,这里不用下载了
                               transform=transform)
test_dataset = datasets.MNIST(root='../P6 逻辑斯谛回归/data', train=False, download=False, transform=transform)
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)  # 测试集设置为False,方便观察结果


# 2、设计模型

# 2.1 设计Inception块
class InceptionA(torch.nn.Module):
    def __init__(self, in_channels):  #in_channels为输入通道数
        super(InceptionA, self).__init__()
        self.branch1x1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)  # 1x1卷积

        self.branch5x5_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)  # 1x1卷积
        self.branch5x5_2 = torch.nn.Conv2d(16, 24, kernel_size=5, padding=2)  # 5x5卷积,padding=2保证输入输出大小一致

        self.branch3x3_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)  # 1x1卷积
        self.branch3x3_2 = torch.nn.Conv2d(16, 24, kernel_size=3, padding=1)  # 3x3卷积,padding=1保证输入输出大小一致
        self.branch3x3_3 = torch.nn.Conv2d(24, 24, kernel_size=3, padding=1)  # 3x3卷积

        self.branch_pool = torch.nn.Conv2d(in_channels, 24, kernel_size=1)  # 1x1卷积

    def forward(self, x):
        branch1x1 = self.branch1x1(x)  # 1x1卷积处理

        branch5x5 = self.branch5x5_1(x)
        branch5x5 = self.branch5x5_2(branch5x5)  # 5x5卷积处理

        branch3x3 = self.branch3x3_1(x)
        branch3x3 = self.branch3x3_2(branch3x3)
        branch3x3 = self.branch3x3_3(branch3x3)

        # 最大池化torch.nn.MaxPool2d()是一个类,而这里的平均池化F.avg_pool2d()是一个函数
        branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)  # 平均池化处理,这里的padding=1,保证输入输出大小一致
        branch_pool = self.branch_pool(branch_pool)

        # 将四个分支的输出在通道维度上进行拼接
        outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
        return torch.cat(outputs, dim=1)  # dim=1表示在通道维度上进行拼接


# 2.2 设计网络
class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 卷积层
        self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(88, 20, kernel_size=5)  #这里的88是Inception块的输出通道数

        # 实例化Inception块,返回结果为88通道,因为Inception块中有四个分支,每个分支输出通道数为16+24+24+24=88
        self.incep1 = InceptionA(in_channels=10)
        self.incep2 = InceptionA(in_channels=20)

        self.mp = torch.nn.MaxPool2d(2)  # 池化层
        self.l1 = torch.nn.Linear(1408, 10)  # 全连接层,不确定第一个参数为多少时,可以先随便写一个,然后运行程序,看报错信息

    def forward(self, x):
        # Flatten data from (n, 1, 28, 28) to (n, 784)
        batch_size = x.size(0)  #获取batch_size,这里的batch_size=64
        x = F.relu(self.mp(self.conv1(x)))  # 经过第一个卷积层+池化层+激活函数
        x = self.incep1(x)  #经过第一个Inception块处理
        x = F.relu(self.mp(self.conv2(x)))  # 经过第二个卷积层+池化层+激活函数
        x = self.incep2(x)  #经过第二个Inception块处理
        x = x.view(batch_size, -1)  # 将数据展平,方便全连接层处理
        x = self.l1(x)  # 全连接层
        return x


model = Net()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  # 判断是否有GPU加速
model.to(device)  # 将模型放到GPU上

# 3、构建损失和优化器
criterion = torch.nn.CrossEntropyLoss()  # 交叉熵损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)  # 优化器,lr为学习率,momentum为动量


# 4、训练和测试
def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)  # 将数据放到GPU上
        optimizer.zero_grad()  # 梯度清零
        # forward + backward + update
        outputs = model(inputs)  # outputs并不是概率,而是线性层的输出,但其大小顺序与概率分布相同
        loss = criterion(outputs, labels)
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数

        running_loss += loss.item()
        if batch_idx % 300 == 299:  # 每300个batch打印一次平均loss
            print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0


def test():
    correct = 0
    total = 0
    with torch.no_grad():  # 测试过程中不需要计算梯度
        for data in test_loader:
            images, labels = data
            images, labels = images.to(device), labels.to(device)  # 将数据放到GPU上
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)  # 返回每一行中最大值的那个元素,以及其索引
            total += labels.size(0)  # labels的size为[64],即64个样本
            correct += (predicted == labels).sum().item()  # 统计预测正确的样本个数
    accuracy = 100 * correct / total
    accuracy_list.append(accuracy)
    print('Accuracy on test set: %d %%' % accuracy)


if __name__ == '__main__':
    accuracy_list = []
    for epoch in range(10):
        train(epoch)
        test()
    plt.plot(accuracy_list)
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.grid()
    plt.show()
[1,   300] loss: 0.950
[1,   600] loss: 0.229
[1,   900] loss: 0.170
Accuracy on test set: 96 %
[2,   300] loss: 0.123
[2,   600] loss: 0.118
[2,   900] loss: 0.098
Accuracy on test set: 97 %
[3,   300] loss: 0.083
[3,   600] loss: 0.083
[3,   900] loss: 0.078
Accuracy on test set: 97 %
[4,   300] loss: 0.070
[4,   600] loss: 0.061
[4,   900] loss: 0.065
Accuracy on test set: 98 %
[5,   300] loss: 0.055
[5,   600] loss: 0.060
[5,   900] loss: 0.058
Accuracy on test set: 98 %
[6,   300] loss: 0.052
[6,   600] loss: 0.051
[6,   900] loss: 0.050
Accuracy on test set: 98 %
[7,   300] loss: 0.043
[7,   600] loss: 0.046
[7,   900] loss: 0.048
Accuracy on test set: 98 %
[8,   300] loss: 0.042
[8,   600] loss: 0.041
[8,   900] loss: 0.045
Accuracy on test set: 98 %
[9,   300] loss: 0.036
[9,   600] loss: 0.039
[9,   900] loss: 0.041
Accuracy on test set: 98 %
[10,   300] loss: 0.030
[10,   600] loss: 0.041
[10,   900] loss: 0.038
Accuracy on test set: 98 %

CNN_Inception

从图像可以看出,在epoch为10时,模型的准确率已经非常接近99%,并且还有上升的趋势,说明Inception块的引入使得模型的预测能力更强了。

同样地,我把epoch加到30,白嫖Kaggle的GPU跑出的结果如下图:

image-20230417194106004

可见,结果一直在99%上下波动。

2 残差网络(Residual Network)

Residual Network(ResNet)是一种深度神经网络结构,它的作用是解决深度神经网络中的梯度消失和梯度爆炸问题。这些问题会在网络层数增加时出现,导致训练变得困难甚至无法收敛。

image-20230417200142245

ResNet通过引入残差连接(residual connection)来解决这个问题。残差连接是指将网络的输入直接添加到网络的输出中,形成一个“shortcut”,使得在梯度反向传播时可以更容易地通过残差连接跳过一些层的信息,减轻了梯度消失和梯度爆炸的问题。同时,这种残差连接也使得网络能够更深,提高了模型的准确性和泛化能力

image-20230417200051107

ResNet的另一个作用是实现了端到端的训练,这意味着整个模型可以通过反向传播进行端到端的训练,而无需进行手动的特征工程和预训练。这大大简化了模型的训练流程和实现难度,也提高了模型的效率和准确性。

image-20230417200238742

下面这段代码是一个使用PyTorch实现的残差网络模型,在MNIST数据集上进行训练和测试。主要步骤包括:

  1. 数据集准备:使用torchvision.datasets加载MNIST数据集,并进行数据预处理(转为Tensor,标准化),然后使用torch.utils.data.DataLoader将数据集分成小批次进行加载。
  2. 模型设计:包含一个卷积层、两个残差块和一个全连接层。残差块采用两个卷积层,输入输出通道数一致,并通过加上输入再经过激活函数的方式来保证维度一致。卷积层和全连接层采用ReLU作为激活函数。
  3. 损失函数和优化器:采用交叉熵损失函数,优化器采用SGD,并在训练过程中使用动量。
  4. 训练和测试:采用mini-batch SGD来训练模型,每300个batch打印一次平均loss。训练完成后,使用测试集来评估模型的性能。

此外,代码还包括了一些常用的PyTorch操作,如将模型放到GPU上,将数据放到GPU上等。

import torch
import torch.nn.functional as F
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt

# 1、准备数据集
batch_size = 64
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_dataset = datasets.MNIST(root='../P6 逻辑斯谛回归/data', train=True, download=False, transform=transform)
test_dataset = datasets.MNIST(root='../P6 逻辑斯谛回归/data', train=False, download=False, transform=transform)
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)  # 测试集设置为False,方便观察结果


# 2、设计模型
# 2.1 残差块
class ResidualBlock(torch.nn.Module):
    def __init__(self, channels):
        super(ResidualBlock, self).__init__()
        self.channels = channels
        # 定义两个卷积层,卷积核大小为3,padding=1保证输入输出大小一致,输入输出通道数一致,目的保证维度一致,能将输入与输出相加
        self.conv1 = torch.nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.conv2 = torch.nn.Conv2d(channels, channels, kernel_size=3, padding=1)

    def forward(self, x):
        y = F.relu(self.conv1(x))  # 第一个卷积层+激活函数
        y = self.conv2(y)  # 第二个卷积层+激活函数
        return F.relu(x + y)  # 将输入与输出相加,再经过激活函数


# 2.2 设计网络
class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 卷积层
        self.conv1 = torch.nn.Conv2d(1, 16, kernel_size=5)
        self.conv2 = torch.nn.Conv2d(16, 32, kernel_size=5)

        # 残差块
        self.res1 = ResidualBlock(16)
        self.res2 = ResidualBlock(32)

        self.mp = torch.nn.MaxPool2d(2)  # 最大池化层
        self.l1 = torch.nn.Linear(512, 10)  # 全连接层,不确定第一个参数为多少时,可以先随便写一个,然后运行程序,看报错信息

    def forward(self, x):
        # Flatten data from (n, 1, 28, 28) to (n, 784)
        batch_size = x.size(0)  #获取batch_size,这里的batch_size=64
        x = self.mp(F.relu(self.conv1(x)))  # 经过第一个卷积层+激活函数+池化层
        x = self.res1(x)  #经过第一个残差块处理
        x = self.mp(F.relu(self.conv2(x)))  # 经过第二个卷积层+激活函数+池化层
        x = self.res2(x)  #经过第二个Inception块处理
        x = x.view(batch_size, -1)  # 将数据展平,方便全连接层处理
        x = self.l1(x)  # 全连接层
        return x


model = Net()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  # 判断是否有GPU加速
model.to(device)  # 将模型放到GPU上

# 3、构建损失和优化器
criterion = torch.nn.CrossEntropyLoss()  # 交叉熵损失函数
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)  # 优化器,lr为学习率,momentum为动量


# 4、训练和测试
def train(epoch):
    running_loss = 0.0
    for batch_idx, data in enumerate(train_loader, 0):
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)  # 将数据放到GPU上
        optimizer.zero_grad()  # 梯度清零
        # forward + backward + update
        outputs = model(inputs)  # outputs并不是概率,而是线性层的输出,但其大小顺序与概率分布相同
        loss = criterion(outputs, labels)
        loss.backward()  # 反向传播
        optimizer.step()  # 更新参数

        running_loss += loss.item()
        if batch_idx % 300 == 299:  # 每300个batch打印一次平均loss
            print('[%d, %5d] loss: %.3f' % (epoch + 1, batch_idx + 1, running_loss / 300))
            running_loss = 0.0


def test():
    correct = 0
    total = 0
    with torch.no_grad():  # 测试过程中不需要计算梯度
        for data in test_loader:
            images, labels = data
            images, labels = images.to(device), labels.to(device)  # 将数据放到GPU上
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)  # 返回每一行中最大值的那个元素,以及其索引
            total += labels.size(0)  # labels的size为[64],即64个样本
            correct += (predicted == labels).sum().item()  # 统计预测正确的样本个数
    accuracy = 100 * correct / total
    accuracy_list.append(accuracy)
    print('Accuracy on test set: %d %%' % accuracy)


if __name__ == '__main__':
    accuracy_list = []
    for epoch in range(10):
        train(epoch)
        test()
    plt.plot(accuracy_list)
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.grid()
    plt.show()
[1,   300] loss: 0.525
[1,   600] loss: 0.151
[1,   900] loss: 0.108
Accuracy on test set: 97 %
[2,   300] loss: 0.093
[2,   600] loss: 0.069
[2,   900] loss: 0.074
Accuracy on test set: 98 %
[3,   300] loss: 0.063
[3,   600] loss: 0.060
[3,   900] loss: 0.055
Accuracy on test set: 98 %
[4,   300] loss: 0.050
[4,   600] loss: 0.049
[4,   900] loss: 0.044
Accuracy on test set: 98 %
[5,   300] loss: 0.043
[5,   600] loss: 0.036
[5,   900] loss: 0.043
Accuracy on test set: 98 %
[6,   300] loss: 0.035
[6,   600] loss: 0.034
[6,   900] loss: 0.036
Accuracy on test set: 98 %
[7,   300] loss: 0.031
[7,   600] loss: 0.032
[7,   900] loss: 0.032
Accuracy on test set: 99 %
[8,   300] loss: 0.027
[8,   600] loss: 0.029
[8,   900] loss: 0.029
Accuracy on test set: 99 %
[9,   300] loss: 0.023
[9,   600] loss: 0.025
[9,   900] loss: 0.028
Accuracy on test set: 99 %
[10,   300] loss: 0.024
[10,   600] loss: 0.021
[10,   900] loss: 0.023
Accuracy on test set: 98 %

CNN_Residual

使用Residual Network后发现准确率确实很快就上升到了99%,但后面有下降的趋势,会一直下降吗?

将epoch增大到30时,结果如下图:在epoch大于15时,模型效果还是能够稳定超过99%,说明上图的下降趋势只是虚晃一枪。

image-20230417195557355

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

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

相关文章

数据库实验 | 第3关:建立和调用存储函数

任务描述 本关任务: 销售数据库有顾客、销售单数据表 顾客gk数据表有会员号hyh、姓名name、性别sex、电话tel、部门dept字段 销售单xsd数据表有销售单号xsdh、会员号hyh、雇员号gyh、销售日期xsrq、应付款yfk、实际付款sjfk字段 任务要求 建立存储过程 gkjb(nf …

Obsidian中如何创作思维导图Mind-map

使用插件 obsidian-mind-map 1.直接在社区下载安装 设置快捷键或者在左侧竖形打开命令面板搜索关键字“mind”, 或者为了便于使用,设置快捷键,在设置-第三方插件中-选择快捷键 然后按下你想设置的快捷键就可以 我这里设置成了CtrlAltM ,M是…

小程序的组件化开发

目录: 1 小程序组件化思想 2 自定义组件的过程 3 组件样式实现细节 4 组件使用过程通信 5 组件插槽定义使用 6 Component构造器 在小程序里面需要创建组件的话需要在最外层建component包,然后在使用新建component来创建类似page的4个文件&#xff…

知乎版ChatGPT「知海图AI」加入国产大模型乱斗,称效果与GPT-4持平

“2023知乎发现大会”上,知乎创始人、董事长兼CEO周源和知乎合作人、CTO李大海共同宣布了知乎与面壁智能联合发布“知海图AI”中文大模型。 周源据介绍,知乎与面壁智能达成深度合作,共同开发中文大模型产品并推进应用落地。目前,知…

AUTOSAR存储服务之FEE换页策略介绍

概述 如下图是AUTOSAR Memory Stack的架构图,对于Memory Stack的介绍请参考AUTOSAR MemoryStack详细介绍_钢琴上的汽车软件的博客-CSDN博客 随着现在MCU携带的内置flash空间越来越大,从成本节省以及方便使用等方面考虑,在产品设计和开发过程中常用Flash EEPROM Emulation技…

CTFHub | eval执行

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习,实训平台。提供优质的赛事及学习服务,拥有完善的题目环境及配套 writeup ,降低 CTF 学习入门门槛,快速帮助选手成长,跟随主流比赛潮流。 0x01 题目描述…

手推广告论文(二)Wide Deep 推荐系统算法Wide Deep Learning for Recommender Systems

Wide & Deep Learning for Recommender Systems 论文地址https://arxiv.org/pdf/1606.07792.pdf 摘要 广义线性模型结合非线性特征转换,在处理具有大规模稀疏输入的回归和分类问题中已被广泛应用。通过一系列交叉积特征转换来记忆特征交互既有效又具有解释性…

【分布式事务 本地部署Seata服务】分布式事务框架Seata本地部署详细讲解

前言 这篇文章我会从0到1详细搭建分布式事务框架seata的使用,那么我们首先要先了解一下什么是分布式事务? 本篇文章是本地启动seata服务并且注册到nacos中,在SpringCloud中整合seata框架请转移下方连接 点我跳转SpringCloud整合seata教程&…

VMware ESXi 8.0U1 Unlocker OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)

发布 ESXi 8.0U1 集成驱动版,在个人电脑上运行企业级工作负载 请访问原文链接:https://sysin.org/blog/vmware-esxi-8-u1-sysin/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 2023-04-18, VMware vSp…

【真北直播笔记】董越:简明DevOps学习地图

缘起 真北敏捷社区的宗旨是:求知、连接。求知就是学习,家里没矿的话,学习是一个人最重要的动力之源。连接就是把人拉在一起,我们相信人与人的互动会带来美好的变化。今天的直播是把大家拉在一起学习,就是求知、连接。 …

【万人推荐】黑客成长技术清单

最近两天,在reddit安全板块和Twitter上有个GitHub项目很火,叫“Awesome Hacking”。 “Awesome Hacking”在reddit上有超过四百个赞,但管理员后来认为不适合该板块(Awesome类项目没有新的内容),给了“rejec…

十大排序算法之插入排序、希尔排序、选择排序

个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【数据结构初阶(C实现)】 本篇主要讲解八大排序算法中的三种排序,分别是:插入排序、希尔排…

家用洗地机有什么优缺点?实用的洗地机分享

随着科技的不断发展,家庭清洁设备也在不断更新换代。现在市场上最常见的家用清洁设备包括洗地机、扫地机器人和吸尘器。这些设备各有优缺点,但在清洁效果、清洁范围和清洁方式等方面存在差异。洗地机是一种专业的清洁设备,它能够深度清洁地面…

SpringCloud之Gateway组件简介

网关的理解 网关类似于海关或者大门,出入都需要经过这个网关。别人不经过这个网关,永远也看不到里面的东西。可以在网关进行条件过滤,比如大门只有对应的钥匙才能入内。网关和大门一样,永远暴露在最外面 不使用网关 前端需要记住每…

Javascript进阶专题总结(函数、异步编程、设计模式)

函数式编程什么时候用 编程方法:函数式(js),面向对象(java,c),命令式 函数式(工具式操作) 优点:JavaScript种函数是一等公民,便于拆分组合可扩展性好,方便tree-shaking 缺点&…

【Linux系统】系统安全及应用二

开关安全控制一、开个安全控制1.1调整BIOS引导设置1.2GRUB限制1.3终端安全控制二、系统弱口令检查2.1安装JR工具三、网络端口扫描3.1NMAP端口扫描3.2NETSTAT,SS查看端口信息一、开个安全控制 1.1调整BIOS引导设置 将第一引导设备设为当前系统所在硬盘禁止从其他设…

1-时间复杂度分析

时间复杂度 ①what: 指执行当前算法所消耗的时间 ②简介结论: 时间复杂度由多项式T(n)中最高阶的项来决定,系数的影响忽略即可 例子: 操作数量T(n) 时间复杂度O(f(n)) 常数,比如 100000(即&#xff1…

ChatGPT将批量文档翻译成中文的方法

文档翻译成中文软件是指在处理文档时,自动将文档中的内容翻译成中文的软件。这些软件通常采用自然语言处理技术,通过对待翻译文本的分词、词义分析、语法分析等多种技术处理,实现对文本中的单词、短语、句子等级别的翻译。 文档翻译成中文软件…

CSDN,有幸遇见 ——我的三周年创作纪念日

一生二,二生三,三生万物 三年,与 CSDN 的相遇相识相知—— 前两年都没写,一是没纪念的概念,二是纪念日这天每年总是清明节。 还有就是不知道有勋章(( Meet 遇见 那年,我六年级&a…

JVM 垃圾回收详解之垃圾收集算法+垃圾收集器

标记-清除算法 该算法分为“标记”和“清除”阶段:首先标记出所有不需要回收的对象,在标记完成后统一回收掉所有没有被标记的对象。 它是最基础的收集算法,后续的算法都是对其不足进行改进得到。 这种垃圾收集算法会带来两个明显的问题&…