深度学习课程:手写体识别示例代码和详细注释

news2024/11/18 9:46:31

Pytorch 的快速入门,参见 通过两个神经元的极简模型,清晰透视 Pytorch 工作原理。本文结合手写体识别项目,给出一个具体示例和直接关联代码的解释。

1. 代码

下面代码展示了完整的手写体识别的 Python 程序代码。代码中有少量注释。在本文后半部分,给出其中关键代码的详细注释。

import numpy as np
import torch
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
import torchvision

'''
运行说明
安装依赖命令,要安装这个版本。
pip install torch==1.4.0 torchvision==0.5.0
pip install matplotlib numpy
代码按照内容的顺序,方便阅读。
'''

# 1 导入数据集

train_loader = torch.utils.data.DataLoader(
    datasets.MNIST(root='./data', #root表示数据加载的相对目录
                   train=True, #train表示是否加载数据库的训练集,False时加载测试集
                   download=True,#download表示是否自动下载
                   transform=transforms.Compose([#transform表示对数据进行预处理的操作
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),batch_size=64, shuffle=True)#batch_size表示该批次的数据量  shuffle表示是否洗牌

'''
关于下面这段代码的说明:
	transform=transforms.Compose([#transform表示对数据进行预处理的操作
    	transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])

这段代码使用了PyTorch的transforms模块,将数据预处理操作组合到一起。

其中,transforms.Compose()函数用于将多个数据预处理操作(也称为transform)组合成一个可执行的函数。而在这个例子中,Compose()函数传入了两个transform函数:ToTensor()和Normalize()。

ToTensor()函数用于将PIL Image或numpy.ndarray数据类型转换成torch.FloatTensor类型,即将图片转换成tensor。

Normalize()函数则用于对tensor进行归一化操作。它需要传入两个参数,分别是均值和标准差。这个例子中,均值为0.1307,标准差为0.3081。这意味着对于每个通道,像素的值都将被减去均值后再除以标准差,使得处理后的数据均值为0,标准差为1。这样做的好处是可以使模型更容易地学习到数据的特征,加速训练过程。

因此,这段代码所做的工作是将输入的图片数据先转换为tensor,再进行归一化处理,最终返回处理后的tensor数据。
'''

test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('./data', train=False, transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),batch_size=64, shuffle=True)

def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

# 得到batch中的数据
dataiter = iter(train_loader) # 通过 iter(train_loader) 将 train_loader 转换为一个 Iterator 迭代器对象。
images, labels = dataiter.next() # 通过 dataiter.next() 获取这个迭代器对象的下一个元素,即从 train_loader 中取出一批数据。
                                 # 将这一批数据中的图像数据和标签数据分别赋值给变量 images 和 labels。   
# 展示图片
imshow(torchvision.utils.make_grid(images))


# 1.2.1  定义神经网络
import torch
import torch.nn as nn
import torch.nn.functional as F#可以调用一些常见的函数,例如非线性以及池化等

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # 输入图片是1 channel输出是6 channel 利用5x5的核大小
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # 全连接 从16 * 4 * 4的维度转成120
        self.fc1 = nn.Linear(16 * 4 * 4, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
    def forward(self, x):
        # 在(2, 2)的窗口上进行池化
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)#(2,2)也可以直接写成数字2
        x = x.view(-1, self.num_flat_features(x))#将维度转成以batch为第一维 剩余维数相乘为第二维
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    def num_flat_features(self, x):
        size = x.size()[1:]  # 第一个维度batch不考虑
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

net = Net()
print(net)

# 1.2.2  前向传播

image = images[:2]
label = labels[:2]
print(image.size())
print(label)
out = net(image)
print(out)

# 1.2.3  计算损失

image = images[:2]
label = labels[:2]
out = net(image)
criterion = nn.CrossEntropyLoss()
loss = criterion(out, label)
print(loss)

# 1.2.4  反向传播与更新参数

#创建优化器
import torch.optim as optim
optimizer = optim.SGD(net.parameters(), lr=0.01)#lr代表学习率
criterion = nn.CrossEntropyLoss()
# 在训练过程中
image = images[:2]
label = labels[:2]
optimizer.zero_grad()   # 消除累积梯度
out = net(image)
loss = criterion(out, label)
loss.backward()
optimizer.step()    # 更新参数

# 1.3  开始训练

def train(epoch):
    net.train() # 设置为training模式
    running_loss = 0.0
    for i, data in enumerate(train_loader):
        # 得到输入 和 标签
        inputs, labels = data
        # 消除梯度
        optimizer.zero_grad()
        # 前向传播 计算损失 后向传播 更新参数
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        # 打印日志
        running_loss += loss.item()
        if i % 100 == 0:    # 每100个batch打印一次
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 100))
            running_loss = 0.0

train(1)

# 1.4  观察模型预测效果

correct = 0
total = 0
with torch.no_grad():#或者model.eval()
    for data in test_loader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

2. 注释

2.1 transforms.Compose()

transform=transforms.Compose([#transform表示对数据进行预处理的操作
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])

这段代码使用了PyTorch的transforms模块,将数据预处理操作组合到一起。

其中,transforms.Compose()函数用于将多个数据预处理操作(也称为transform)组合成一个可执行的函数。而在这个例子中,Compose()函数传入了两个transform函数:ToTensor()和Normalize()。

  • ToTensor()函数用于将PIL Image或numpy.ndarray数据类型转换成torch.FloatTensor类型,即将图片转换成tensor。

  • Normalize()函数则用于对tensor进行归一化操作。它需要传入两个参数,分别是均值和标准差。这个例子中,均值为0.1307,标准差为0.3081。这意味着对于每个通道,像素的值都将被减去均值后再除以标准差,使得处理后的数据均值为0,标准差为1。这样做的好处是可以使模型更容易地学习到数据的特征,加速训练过程。

因此,这段代码所做的工作是将输入的图片数据先转换为tensor,再进行归一化处理,最终返回处理后的tensor数据。

2.2 transforms.ToTensor()

transforms.ToTensor() 是 PyTorch 中的一个数据预处理方法,用于将 PIL 图像或 numpy 数组转换为张量(Tensor)类型,并进行标准化。具体来说,该方法将 PIL 图像或 numpy 数组的值缩放到 [0, 1] 的范围内,并将其通道顺序从 H x W x C 转换为 C x H x W。

以下是一个简单的例子:

import torch
from torchvision import transforms
from PIL import Image

# 读取一张图片
img = Image.open("example.jpg")

# 对图片进行预处理
transform = transforms.Compose([
    transforms.Resize((224, 224)),  # 重设图片大小为 224x224
    transforms.ToTensor()  # 将 PIL 图像或 numpy 数组转换为张量类型
])
img_tensor = transform(img)

print(img_tensor.shape)  # 输出 (3, 224, 224)
print(torch.min(img_tensor), torch.max(img_tensor))  # 输出 0 和 1,表示值已经被缩放到 [0, 1] 的范围内

此示例从文件加载一张图像,并使用 transforms.Resize() 方法重设图像大小。然后使用 transforms.ToTensor() 方法将图像转换为张量。最后,将处理后的张量打印出来,显示它的形状和最小/最大值。

2.3 transforms.Normalize()

transforms.Normalize() 是 PyTorch 中的一个数据预处理方法,用于对张量进行标准化,即让所有元素都满足均值为 0、方差为 1 的分布。在深度学习中,对数据进行标准化是提高训练稳定性和效果的常用方法之一。

该方法需要传入两个参数:均值(mean)和标准差(std)。标准化公式为:

output = (input - mean) / std

在这个公式中,input 是输入的张量,mean 和 std 是指定的均值和标准差,在对每个元素逐一计算(减去均值再除以标准差)之后得到 output 张量。

以下是一个简单的示例:

import torch
from torchvision import transforms

# 构造一个三通道的张量,大小为 3x5
tensor = torch.tensor([
    [[1.0, 2.0, 3.0, 4.0, 5.0],
     [6.0, 7.0, 8.0, 9.0, 10.0],
     [11.0, 12.0, 13.0, 14.0, 15.0]],
    [[2.0, 3.0, 4.0, 5.0, 6.0],
     [7.0, 8.0, 9.0, 10.0, 11.0],
     [12.0, 13.0, 14.0, 15.0, 16.0]],
    [[3.0, 4.0, 5.0, 6.0, 7.0],
     [8.0, 9.0, 10.0, 11.0, 12.0],
     [13.0, 14.0, 15.0, 16.0, 17.0]]
])

# 求均值和标准差
mean = torch.mean(tensor)
std = torch.std(tensor)

# 借助 transforms.Normalize 对张量进行标准化
transform = transforms.Normalize(mean=mean, std=std)
normalized_tensor = transform(tensor)

print(normalized_tensor)

在这个例子中,我们构造了一个大小为 3x5 的张量,并对它进行了标准化。标准化的结果是把每个元素都减去了张量的均值,然后除以了张量的标准差。最后我们输出标准化后的结果。

更进一步的例子:

import torch
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt

# 读取一张图片
img = Image.open("example.jpg")
plt.imshow(img)
plt.show()

# 对图片进行预处理
transform = transforms.Compose([
    transforms.Resize((224, 224)),  # 重设图片大小为 224x224
    transforms.ToTensor()  # 将 PIL 图像或 numpy 数组转换为张量类型
])
img_tensor = transform(img)

print(img_tensor.shape)  # 输出 (3, 224, 224)
print(torch.min(img_tensor), torch.max(img_tensor))  # 输出 0 和 1,表示值已经被缩放到 [0, 1] 的范围内

# 转换张量维度,并把它转换为 numpy 数组
img_numpy = img_tensor.permute(1, 2, 0).numpy()
plt.imshow(img_numpy)
plt.show()

运行结果如下:
在这里插入图片描述

2.4 torchvision.utils.make_grid()

torchvision.utils.make_grid(images) 是 PyTorch 的一个函数,用于将多张图片合成一张组合图,可用于可视化多张图像的数据。

该函数的主要参数是 images,代表输入的张量的列表或者张量。除此之外,还可以接受一些其他参数来控制输出的组合图的样式和尺寸。

下面是一个简单的代码示例:

import torch
import torchvision
import matplotlib.pyplot as plt

# 读取一些用于示例的图片
images = [torch.randn((3, 256, 256)), torch.randn((3, 256, 256)), torch.randn((3, 256, 256))]

# 将图片进行组合,并转换为可显示的numpy数组格式  
grid_image = torchvision.utils.make_grid(images, padding=10)
numpy_image = grid_image.cpu().numpy().transpose((1, 2, 0))

# 显示组合图
plt.imshow(numpy_image)
plt.show()

在上面的示例中,我们模拟生成了三张 3 × 256 × 256 3\times 256\times 256 3×256×256 的图片,使用 torchvision.utils.make_grid 将这三张图片组合成一张 3 × 514 × 778 3\times 514 \times 778 3×514×778 的大图,并且添加了 padding=10 参数来增加每个小图之间的边框宽度,最后将组合图转换为numpy数组格式,并使用 matplotlib 库进行显示。执行上述代码,将会得到如下的组合图:
在这里插入图片描述

2.5 x.view()

x.view函数可以将一个PyTorch Tensor(张量)重塑成一个新的形状,这个新形状中每个维度的大小都可以指定。例如:对于一个形状为(2,3)的二维Tensor(张量),我们可以使用view(6)函数将其重塑成一个大小为(6,)的一维Tensor(张量)。在该语句x.view(-1, self.num_flat_features(x))中,-1的含义是我们不知道应该设定的维度数字,需要让PyTorch帮助我们计算,同时保证重塑后的张量元素数量与原来的张量一致。

作为一个例子,假设有一个形状为(2,3,4)的三维张量x,其中2表示batch size,3表示width,4表示height。我们可以使用以下代码将其重塑为一个2D张量:

x = x.view(-1, 3*4)  # 将width和height两个维度合并成为一个维度3*4

其中,-1指示在执行重塑操作时,根据原张量的shape自动计算剩余维度的大小,具体而言,在这个例子中,-1表示batch size保持不变,由原张量的batch size的值决定,而重塑后的张量每个元素都相同,都是一个大小为3*4的一维数组。

2.6 nn.CrossEntropyLoss()

nn.CrossEntropyLoss() 是一个用于计算分类问题中损失函数的PyTorch模块。该损失函数是基于交叉熵衡量预测输出和真实标签之间的距离,常用于多分类问题中。

假设我们有一个3分类的分类问题,每个样本有4个特征。我们可以使用以下代码来定义模型和损失函数:

import torch
import torch.nn as nn

# 定义模型
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.fc = nn.Linear(4, 3)  # 4个特征,3个类别

    def forward(self, x):
        out = self.fc(x)
        return out

model = MyModel()

# 定义损失函数
criterion = nn.CrossEntropyLoss()

接下来,我们可以加载训练数据,例如利用DataLoader将数据分成batch进行处理。假定一个batch中包含了10个样本,我们可以使用以下代码计算出这个batch中所有样本的损失函数值:

# 假设X是一个10*4的张量,y是一个包含10个整数的列表,表示10个样本的标签
X = torch.randn(10, 4)
y = torch.randint(0, 3, (10,))

# 前向传播,获取预测输出
outputs = model(X)

# 计算损失
loss = criterion(outputs, y)

其中,outputs是一个10*3的张量,表示对于这10个样本来说,模型对3个类别的预测输出。 y是一个长度为10的列表,表示这10个样本的标签(整数形式)。 criterion(outputs, y)计算了这个batch中所有样本的损失函数值,返回一个大小为1的tensor。

更具体地说,使用nn.CrossEntropyLoss()时,损失函数的具体计算过程如下:

  1. 对于每个预测输出(即模型对于一个样本对每个类别的预测概率),通过softmax函数将其转换为概率值;
  2. 找到该样本真实标签所对应的类别,并将其对应的概率值作为损失函数的一部分;
  3. 将所有样本的损失函数值进行求和或平均。

以下是使用nn.CrossEntropyLoss()计算损失的具体实现:

假设有一个3分类问题,我们已经得到了一个大小为 1 × 3 的张量outputs和一个大小为1的张量y。其中outputs表示模型对于这个样本属于每个类别的概率,例如outputs=[0.1, 0.8, 0.1]表示该样本对于第二个类别(对应0.8这个最大概率)的预测最准确。

import torch.nn.functional as F

outputs = torch.tensor([0.1, 0.8, 0.1])
y = torch.tensor([1])

# 将outputs通过softmax函数转化为概率值
probs = F.softmax(outputs, dim=0)
print('probs:', probs)  # 如 output=[0.1, 0.8, 0.1] 则 probs=[0.2119, 0.5761, 0.2120]

# 使用y作为索引从probs中选取对应的概率值
loss = F.nll_loss(torch.log(probs), y)
print('loss:', loss)  # tensor(0.5472) 

这里使用了nn.functional.nll_loss()函数的反向版本,该函数用于计算负对数似然损失,即输入是log概率而不是概率本身。其中,torch.log(probs)用于将概率转换成对数概率。上面的例子中,输出的loss值为0.5472。

关于 F.nll_loss 补充说明如下:

F.nll_lossPyTorch中计算负对数似然损失的函数,其使用方式一般与nn.CrossEntropyLoss()相同。使用F.nll_loss时,需要将模型输出(即经过softmax后得到的每个类别的概率)的log值以及真实标签作为该函数的输入。

在上面的例子中,我们首先使用了softmax函数对模型输出进行转换,得到了一个大小为1×3的概率张量probs,其中每个元素表示该样本属于这个类别的可能性。然后,使用torch.log函数获取probs的对数,以略微减少计算开销,并将其作为负对数似然损失函数的输入,同时传入真实标签y进行计算。

更具体地解释,原理如下:

首先,将probs进行对数化处理,可以把交叉熵函数转化为nll_loss函数。此处使用log函数。这样得到的结果就不会那么离散,让训练变得更加稳定。

然后,我们希望用probs的值来估算输出结果的概率真相性,因此需要找到对应的真实标签,这个标签被单独编码成了一个整数。这里使用了索引技巧:将每个样本的真实标签y作为索引,从probs张量中选取对应的概率值。由于处于计算负对数似然损失,需要对所选出的概率再取反。最终的结果即为使用该样本计算得到的损失值。

在上面的例子中,我们的模型输出[0.1, 0.8, 0.1]表示该样本可能属于第二个类别的概率最高,因此真实标签为1,可以得到以下计算过程:

  • outputs = [0.1, 0.8, 0.1]
  • probs = [0.266, 0.468, 0.266],对outputs使用了softmax函数转换为概率值
  • log_probs = [-1.3235, -0.7586, -1.3235],对probs使用了torch.log()函数, 进行log操作
  • nll_loss(log_probs, y) = 0.7586,函数使用y作为索引从log_probs中选取做为结果和计算梯度。

这个值可以用于反向传播和更新权重值,以提高模型预测能力。

2.7 loss.backward()

loss.backward() 是一个 PyTorch 中用来计算误差反向传播(Backpropagation)的函数,它将使用自动微分(Automatic differentiation)来计算图中每个参数的梯度。

在神经网络中,我们通常需要最小化模型输出与真实标签之间的误差。通过解析损失函数中的参数梯度,我们可以更新每个参数的值以使误差逐渐减少。这就是反向传播算法的核心思想。

在计算过程中,每一步计算结果都会被存储在计算图中,而 loss.backward() 函数就是用来计算该计算图中所有参数的梯度,并将它们累加到各自的变量对象中。

在具体使用时,用户需要在代码中定义所有涉及到的参数,并且对需要进行反向传播的损失函数调用 backward() 方法。例如:

import torch

# 定义神经网络
net = torch.nn.Linear(10, 1)

# 定义优化器
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)

# 定义损失函数
criterion = torch.nn.MSELoss()

# 模型训练
for epoch in range(10):
    optimizer.zero_grad()  # 梯度清零
    input = torch.randn(1, 10)  # 随机生成训练数据
    output = net(input)  # 将输入送入神经网络得到输出
    target = torch.randn(1, 1)  # 随机生成目标标签
    loss = criterion(output, target)  # 计算损失
    loss.backward()  # 反向传播
    optimizer.step()  # 更新优化器参数

print("Training finished!")

在这个简单的示例中,我们定义了一个简单的神经网络,使用随机数据进行训练。每个 epoch 中,我们执行一次正向传播以计算模型输出,然后计算损失。接着,调用 loss.backward() 函数计算梯度,最后使用优化器更新参数。

optimizer.step() 是一个 PyTorch 中用来更新模型参数的函数。在反向传播计算完成后,我们需要更新模型中各个参数的值,从而优化训练效果。

3. 代码中用到的几个代码 Python 包

这段代码使用了以下几个 Python 库:

  • numpy:Python 的开源数学计算库,用于处理向量、矩阵等多维数组数据,以及数值计算、线性代数等操作。

  • torch:PyTorch 是基于 Python 的开源机器学习框架,提供了动态计算图、自动微分等功能,可以方便地构建深度神经网络模型。

  • torchvision:PyTorch 的扩展库,提供了常用图像数据集、变换(transforms)、模型结构和预训练权重等功能。它可以帮助我们更方便地处理图像数据,并且提供了常见的网络结构(如 VGG、ResNet 等)。

  • matplotlib.pyplot:Python 的绘图库,提供了一些函数用于绘制图形,例如折线图、柱状图、散点图等。

  • torch.nn:PyTorch 中的模型层或损失函数等等都在这里。这个包只是一个为 nn 设定的空间,同样也会有定义网络中常见的层结构(如全连接层、卷积层、池化层等)的代码。

  • torch.nn.functional:PyTorch 中提供了各种常用的非线性函数、池化函数,以及 softmax 等函数。

  • torch.optim:PyTorch 提供了各种优化器,例如 SGD、Adam 等。这些优化器可以帮助我们更方便地更新神经网络中的参数,提高模型的训练效果。

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

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

相关文章

工业相机的Pixel Binning和Pixel Skipping

一般图像传感器的不同分辨率都对应着不同的帧率。如果想要提高帧率,就要考虑是否需要缩小视野。若不希望视野缩小,就需要减小分辨率(resolution)。常用的减少分辨率的两种采样方式是:Skipping和Binning。 什么是Binni…

【复盘】聊一下如何高效学习

对于大多数的人来说,从毕业之后其实大多数的可能就不会在认真学习专业和专业外的课程,但是对于程序员这个大群体来说,想要提高自己的技术,需要不断的提高自己的技术能力以及来提高薪资水平,那么有没有相关的高效学习的…

四种不同机器学习方法(线性回归模型,K近邻回归模型,决策树回归模型,随机森林回归模型)对光伏发电预测

1.数据集介绍(可以看短期光伏发电量短期预测(Python代码,基于LSTM模型)_深度学习的奋斗者的博客-CSDN博客) 两篇文章用的是同一个数据集,不同的的是本篇多了温度特征 这些是温度数据集中的列名&#xff1…

prettier 使用详细介绍

prettier 使用详细介绍 prettier是一个代码格式化工具,可以通过自定义规则来重新规范项目中的代码,去掉原始的代码风格,确保团队的代码使用统一相同的格式。 安装 npm i prettier -Dyarn add prettier --dev创建一个prettierrc.*配置文件&…

lambda、类

目录 1、lambda匿名函数 2、类 1、__init__() 2、继承 1、lambda匿名函数 语法 lambda arguments : expression 一个 lambda 函数,它把作为参数传入的数字加 10,然后打印结果 x lambda a : a 10print(x(5)) # 15 一个 lambda 函数&#x…

msys2 安装并使用 pacman 安装 dos2unix

问题描述 在 Windows 下使用 msys2 编译 Linux 环境的 代码时,经常遇到由于 【回车换行】造成某些配置文件,如 Kconfig 文件,无法正常解析导致编译失败的问题。 安装 msys2 安装 msys2 的方法很简单,只需要到官方 下载 http://w…

yum和repo详细解析

目录 一、rpm、yum、repo 二、repo文件详细解析 三、常用命令 四、更改epel.repo为清华源 一、rpm、yum、repo RPM RPM(Red-hat Package Manager),是一个由红帽最早开发出来的包管理器,目前已经是大多数Linux发行的默认包管理器。RPM管理的包都是以…

Docker镜像与制作

Docker镜像与制作 Docker镜像是没有内核的,镜像在启动为容器后将直接使用宿主机的内核。 Docker镜像的制作分为了手动制作和自动制作(基于DockerFile) 1、制作nginx镜像 先准备一个目录, mkdir docker-images && cd d…

借助ChatGPT实现 PPT | 导图 | 短视频文案生成【AIGC】

文章目录 1、chatgpt 自动制作 PPT2、chatgpt 生成 Excel 公式3、chatgpt 生成思维导图4、chatgpt 快速生成短视频5、总结 1、chatgpt 自动制作 PPT 步骤如下: ①要求 chatgpt 生成 PPT 内容,以 markdown 格式输出; ②借助网站 mindshow.fun…

【C++】 哈希 (上)

文章目录 1. 哈希概念2. 哈希表直接定址法(常用)除留余数法(常用)解决哈希冲突方法1 ——闭散列 3. 闭散列的实现如何处理删除数据?定义数据结构insertlen为 _tables.size() 还是 _tables.capacity()?线性探测负载因子扩容 FindErase完整代码 1. 哈希概念…

SpringBoot项目打包部署到Nginx【无需配置Nginx】

0.前置知识 springboot打包的项目共分为jar和war两种类型 jar包 jar类型项目使用SpringBoot打包插件打包时,会在打成的jar中 内置一个tomcat 的jar 所以我们可以使用jdk直接运行,将功能代码放到其内置的tomcat中运行。 war包 在打包时需要将 内置的tom…

2023-05-20 技术与管理的照本宣科教条主义与从事实中成长-反思

摘要: 最近的两份工作遇到了极其严重的教条主义, 有多严重呢?几乎可以说人成了教条的教徒,做事就成了照本宣科的死板硬套, 简直匪夷所思。 结果就是对于现实问题简直就像是建立在空中楼阁之上,不但涉及到管理,更有技术上的。 教…

实训三:MLP配置(多链路捆绑的配置)

实训三:MLP配置 【实验目的】 掌握多链路捆绑的配置。验证配置。 【实验拓扑】 实验拓扑如图所示。 设备参数如表所示。 设备 接口 IP地址 子网掩码 默认网关 R1 Multilink 1 192.168.12.1 255.255.255.0 N/A R2 Multilink 1 192.168.12.2 255.255…

6年心得,从功能测试到测试开发,送给在测试路上一路走到黑的你

蓦然回首,软件测试风风雨雨的这就几年,起初每天的工作只是鼠标点点点,我还真不知道怎么办,闲的时候真的怀疑自己的存在价值,每天拿着7000的工资,飘荡在繁华的深圳,吃不饱也饿不死,未…

1.2 IAR 环境配置及编译

目录 一. 新建源码文件夹 二. 添加源文件到工程中 三. 编写一个简单的测试程序 四. 设置字体和行号 五. 工程配置 六. 编译链接工程 一. 新建源码文件夹 (1)在保存工作空间和工程的目录下,新建一个code文件夹,用于保存源码&…

斯坦福、Nautilus Chain等联合主办的 Hackathon 活动,现已接受报名

由 Stanford Blockchain Accelerator、Zebec Protocol、 Nautilus Chain、Rootz Lab 共同主办的黑客松活动,现已接受优秀项目提交参赛申请。 在加密行业发展早期,密码极客们就始终在对区块链世界基础设施,在发展方向的无限可能性进行探索。而…

计算机组成原理实验三-修改二进制文件的程序改变最终运行结果

实验资料: https://wwpv.lanzoue.com/b05drr8qh 密码:6wjx 计算机组成原理实验三 修改二进制文件的程序改变最终运行结果 复习实验二GCC选项:-E -S -c -o -v .\gcc.exe 1.c -> a.exe .\gcc.exe 1.c -o 21001302xx.exe(1)…

Nacos之服务配置中心

1.基础配置 1.1.新建模块cloudalibaba-config-nacos-client3377 1.1.1.POM <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance…

JVM学习(五)

1.1 JVM 类加载机制 JVM 类加载机制分为五个部分&#xff1a;加载&#xff0c;验证&#xff0c;准备&#xff0c;解析&#xff0c;初始化&#xff0c;下面我们就分别来看一下这 五个过程。 1.1.1 加载 加载是类加载过程中的一个阶段&#xff0c; 这个阶段会在内存中生成一…

路径规划算法:基于教与学优化算法的路径规划算法- 附代码

路径规划算法&#xff1a;基于教与学优化优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于教与学优化优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能…