【机器学习】PyTorch-MNIST-手写字识别

news2024/11/20 2:20:32

文章目录

  • 前言
  • 完成效果
  • 一、下载数据集
    • 手动下载
    • 代码下载MNIST数据集:
  • 二、 展示图片
  • 三、DataLoader数据加载器
  • 四、搭建神经网络
  • 五、 训练和测试
    • 第一次运行:
  • 六、优化模型
    • 第二次优化后运行:
  • 七、完整代码
  • 八、手写板实现输入识别功能

前言

注意:本代码需要安装PyTorch未安装请看之前的文章https://blog.csdn.net/qq_39583774/article/details/132070870
MNIST(Modified National Institute of Standards and Technology)是一个常用于机器学习和计算机视觉领域的数据集,用于手写数字识别。它包含了一系列28x28像素大小的灰度图像,每个图像都表示了一个手写的数字(0到9之间)。MNIST数据集共有60,000个训练样本和10,000个测试样本,可用于训练和测试各种图像分类算法。
通过使用MNIST数据集,研究人员和开发者可以测试和验证各种机器学习模型和算法的性能,特别是在图像分类领域。这个数据集成为了计算机视觉领域中的基准,许多研究论文和教程都使用它来演示各种图像处理和机器学习技术的效果。

完成效果

准确率有待提高,可能是因为测试数据集和训练数据集的数据是国外,写法有点不一样,如果你能提高这个模型的成功率可以分享给我,感谢。
在这里插入图片描述

一、下载数据集

下载可以使用代码也可以使用手动方式下载:
数据集网站:http://yann.lecun.com/exdb/mnist/

手动下载

在这里插入图片描述

代码下载MNIST数据集:

#MNIST--手写字识别
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor

#创建一个MNIST数据集的实例,其中包括训练图像和标签
training_data = datasets.MNIST(
    root="data", #下载的跟目录
    train=True, #加载训练数据集
    download=True,#如果数据集不存在,将自动下载
    transform=ToTensor(), #将图像数据转换为Tensor格式的数据(张量),pytorch使用tensor数据流所以这里要转换
)
print(len(training_data))

在这里插入图片描述
运行:
在这里插入图片描述

打印训练数量:

在这里插入图片描述
读取测试数据集:

代码下载工作原理:按住ctrl建跳转源代码
在这里插入图片描述
从上面看是通过爬虫方式下载,和我们的手动下载方式差不多
在这里插入图片描述
可以看到我们下载好的数据集:

在这里插入图片描述
前言中我们有训练数据和测试数据上面是读取训练数据下面我们读取测试数据集:

test_data = datasets.MNIST(
    root="data", #下载的跟目录
    train=False, #加载测试数据集
    download=True,#如果数据集不存在,将自动下载
    transform=ToTensor(), #将图像数据转换为Tensor格式的数据(张量),pytorch使用tensor数据流所以这里要转换
)
print(len(test_data))

运行一下:
在这里插入图片描述

二、 展示图片

#展示训练数据集图片和标签
from matplotlib import pyplot as plt #导入matplotlib库中的pyplot模块,用于绘制图像
figure = plt.figure() #创建一个新的图像画布
for i in range(12):#遍历前12张图片0-12
    img, label = training_data[i]
    figure.add_subplot(3, 4, i+1)
    plt.title(label)
    plt.axis("off")
    plt.imshow(img.squeeze(), cmap="gray")#使用imshow函数显示图像,其中img.squeeze()将图像的通道维度去除,cmap="gray"表示使用灰度颜色映射
plt.show()

在这里插入图片描述

三、DataLoader数据加载器

为什么要做这一步:因为数据集有6万个数据集,通过打包方式将64个为一组,打包起来一起传入,内存这样可以大大加快处理的速度,不然就是6万多个数据集一个一个传入导致速度变慢。

train_dataloader = DataLoader(training_data, batch_size=64)#创建一个训练数据加载器,将training_data(训练数据集)分成64张图像一组的批次
test_dataloader = DataLoader(test_data, batch_size=64)#创建一个测试数据加载器,将test_data(测试数据集)分成64张图像一组的批次。
for X, y in test_dataloader:#X是表示打包好的每一个数据包
    #打印当前批次图像数据X的形状,其中N表示批次大小,C表示通道数,H和W表示图像的高度和宽度
    print(f"Shape of X [N, C, H, W]: {X.shape}")
    #打印当前批次标签数据y的形状和数据类型
    print(f"Shape of y: {y.shape} {y.dtype}")
    break#这里测试一下第一个组中的形状
'''
此代码段的作用是检查当前系统是否支持CUDA(GPU计算),
如果支持,则使用CUDA设备;如果不支持CUDA,它还会检查是否支持多进程模式(MPS),
如果支持,则使用MPS设备;最后,如果都不支持,则使用CPU设备。然后,它会打印出所选择的设备类型。'''

device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")

第一组中中有64张图像,大小为28*28,使用GPU计算

在这里插入图片描述

四、搭建神经网络

构造示意图:输出层为固定参数十个,因为数字数字0-9一共就十个
在这里插入图片描述

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()  # 将图像展平
        self.hidden1 = nn.Linear(28*28, 128)  # 第一个隐藏层,输入维度为28*28,输出维度为128
        self.hidden2 = nn.Linear(128, 256)    # 第二个隐藏层,输入维度为128,输出维度为256
        self.out = nn.Linear(256, 10)         # 输出层,输入维度为256,输出维度为10(对应10个数字类别)

    def forward(self, x):
        x = self.flatten(x)        # 将输入图像展平
        x = self.hidden1(x)        # 第一个隐藏层的线性变换
        x = torch.sigmoid(x)       # 使用Sigmoid激活函数
        x = self.hidden2(x)        # 第二个隐藏层的线性变换
        x = torch.sigmoid(x)       # 使用Sigmoid激活函数
        x = self.out(x)            # 输出层的线性变换(未经激活函数)
        return x                   # 返回模型的输出
model = NeuralNetwork().to(device)#传入对应设备,根据上面识别的设备进行传入,这里传入GPU
print(model)

从分类中也可以看出分类:
在这里插入图片描述
运行代码:
在这里插入图片描述

五、 训练和测试

#训练数据
def train(dataloader, model, loss_fn, optimizer):
    model.train()
#pytorch提供2种方式来切换训练和测试的模式,分别是:model.train() 和 model.eval()。
# 一般用法是:在训练开始之前写上model.trian(),在测试时写上 model.eval() 。
    batch_size_num = 1
    for X, y in dataloader:                 #其中batch为每一个数据的编号
        X, y = X.to(device), y.to(device)   #把训练数据集和标签传入cpu或GPU
        pred = model.forward(X)             #自动初始化 w权值
        loss = loss_fn(pred, y)             #通过交叉熵损失函数计算损失值loss
        # Backpropagation 进来一个batch的数据,计算一次梯度,更新一次网络
        optimizer.zero_grad()               #梯度值清零
        loss.backward()                     #反向传播计算得到每个参数的梯度值
        optimizer.step()                    #根据梯度更新网络参数

        loss = loss.item()                  #获取损失值
        print(f"loss: {loss:>7f}  [number:{batch_size_num}]")
        batch_size_num += 1
#测试数据
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()    #梯度管理
    test_loss, correct = 0, 0
    with torch.no_grad():   #一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。这可以减少计算所用内存消耗。
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model.forward(X)
            test_loss += loss_fn(pred, y).item() #
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
            a = (pred.argmax(1) == y)  #dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号
            b = (pred.argmax(1) == y).type(torch.float)
    test_loss /= num_batches#计算正确率
    correct /= size#计算损失
    print(f"Test result: \n Accuracy: {(100*correct)}%, Avg loss: {test_loss}")
# 多分类使用交叉熵损失函数
loss_fn = nn.CrossEntropyLoss() #创建交叉熵损失函数对象,因为手写字识别中一共有10个数字,输出会有10个结果
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)#创建一个优化器,SGD为随机梯度下降算法??
#params:要训练的参数,一般我们传入的都是model.parameters()。
#lr:learning_rate学习率,也就是步长。

调用函数训练:

#训练模型
train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader, model, loss_fn)

多次训练:

epochs = 5 #
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    # test(test_dataloader, model, loss_fn)
print("Done!")
test(test_dataloader, model, loss_fn)

第一次运行:

成功率只有可怜的16,loss高达2.2
在这里插入图片描述

六、优化模型

使用Adam(自适应矩估计):
修改代码118行:

# 多分类使用交叉熵损失函数
loss_fn = nn.CrossEntropyLoss() #创建交叉熵损失函数对象,因为手写字识别中一共有10个数字,输出会有10个结果
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)#创建一个优化器

防止梯度爆炸和梯度消失使用relu函数替换:

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()  # 将图像展平
        self.hidden1 = nn.Linear(28*28, 128)  # 第一个隐藏层,输入维度为28*28,输出维度为128
        self.hidden2 = nn.Linear(128, 256)    # 第二个隐藏层,输入维度为128,输出维度为256
        self.out = nn.Linear(256, 10)         # 输出层,输入维度为256,输出维度为10(对应10个数字类别)

    def forward(self, x):
        x = self.flatten(x)        # 将输入图像展平
        x = self.hidden1(x)        # 第一个隐藏层的线性变换
        x = torch.relu(x)       # 使用Sigmoid激活函数/修改为relu
        x = self.hidden2(x)        # 第二个隐藏层的线性变换
        x = torch.relu(x)       # 使用Sigmoid激活函数/修改为relu
        x = self.out(x)            # 输出层的线性变换(未经激活函数)
        return x                   # 返回模型的输出


#传入GPU
model = NeuralNetwork().to(device)#传入对应设备,根据上面识别的设备进行传入
print(model)

增加训练次数:

epochs = 15 #
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    # test(test_dataloader, model, loss_fn)
print("Done!")
test(test_dataloader, model, loss_fn)

第二次优化后运行:

成功率大大提高:
Accuracy: 97.67%, Avg loss: 0.12269500801303047
在这里插入图片描述

七、完整代码

#MNIST--手写字识别

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor

#创建一个MNIST数据集的实例,其中包括训练图像和标签
training_data = datasets.MNIST(
    root="data", #下载的跟目录
    train=True, #加载训练数据集
    download=True,#如果数据集不存在,将自动下载
    transform=ToTensor(), #将图像数据转换为Tensor格式的数据(张量)
)
print(len(training_data))

#创建一个MNIST数据集的实例,其中包括训练图像和标签
test_data = datasets.MNIST(
    root="data", #下载的跟目录
    train=False, #加载测试数据集
    download=True,#如果数据集不存在,将自动下载
    transform=ToTensor(), #将图像数据转换为Tensor格式的数据(张量),pytorch使用tensor数据流所以这里要转换
)
print(len(test_data))

#展示训练数据集图片和标签
from matplotlib import pyplot as plt #导入matplotlib库中的pyplot模块,用于绘制图像
figure = plt.figure() #创建一个新的图像画布
for i in range(12):#遍历前12张图片
    img, label = training_data[i]
    figure.add_subplot(3, 4, i+1)
    plt.title(label)
    plt.axis("off")
    plt.imshow(img.squeeze(), cmap="gray")#使用imshow函数显示图像,其中img.squeeze()将图像的通道维度去除,cmap="gray"表示使用灰度颜色映射
plt.show()


#DataLoader数据加载器
train_dataloader = DataLoader(training_data, batch_size=64)#创建一个训练数据加载器,将training_data(训练数据集)分成64张图像一组的批次
test_dataloader = DataLoader(test_data, batch_size=64)#创建一个测试数据加载器,将test_data(测试数据集)分成64张图像一组的批次。
for X, y in test_dataloader:#X是表示打包好的每一个数据包
    #打印当前批次图像数据X的形状,其中N表示批次大小,C表示通道数,H和W表示图像的高度和宽度
    print(f"Shape of X [N, C, H, W]: {X.shape}")
    #打印当前批次标签数据y的形状和数据类型
    print(f"Shape of y: {y.shape} {y.dtype}")
    break

'''
此代码段的作用是检查当前系统是否支持CUDA(GPU计算),
如果支持,则使用CUDA设备;如果不支持CUDA,它还会检查是否支持多进程模式(MPS),
如果支持,则使用MPS设备;最后,如果都不支持,则使用CPU设备。然后,它会打印出所选择的设备类型。'''

device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()  # 将图像展平
        self.hidden1 = nn.Linear(28*28, 128)  # 第一个隐藏层,输入维度为28*28,输出维度为128
        self.hidden2 = nn.Linear(128, 256)    # 第二个隐藏层,输入维度为128,输出维度为256
        self.out = nn.Linear(256, 10)         # 输出层,输入维度为256,输出维度为10(对应10个数字类别)

    def forward(self, x):
        x = self.flatten(x)        # 将输入图像展平
        x = self.hidden1(x)        # 第一个隐藏层的线性变换
        x = torch.relu(x)       # 使用Sigmoid激活函数/修改为relu
        x = self.hidden2(x)        # 第二个隐藏层的线性变换
        x = torch.relu(x)       # 使用Sigmoid激活函数/修改为relu
        x = self.out(x)            # 输出层的线性变换(未经激活函数)
        return x                   # 返回模型的输出


#传入GPU
model = NeuralNetwork().to(device)#传入对应设备,根据上面识别的设备进行传入
print(model)


#训练数据
def train(dataloader, model, loss_fn, optimizer):
    model.train()
#pytorch提供2种方式来切换训练和测试的模式,分别是:model.train() 和 model.eval()。
# 一般用法是:在训练开始之前写上model.trian(),在测试时写上 model.eval() 。
    batch_size_num = 1
    for X, y in dataloader:                 #其中batch为每一个数据的编号
        X, y = X.to(device), y.to(device)   #把训练数据集和标签传入cpu或GPU
        pred = model.forward(X)             #自动初始化 w权值
        loss = loss_fn(pred, y)             #通过交叉熵损失函数计算损失值loss
        # Backpropagation 进来一个batch的数据,计算一次梯度,更新一次网络
        optimizer.zero_grad()               #梯度值清零
        loss.backward()                     #反向传播计算得到每个参数的梯度值
        optimizer.step()                    #根据梯度更新网络参数

        loss = loss.item()                  #获取损失值
        print(f"loss: {loss:>7f}  [number:{batch_size_num}]")
        batch_size_num += 1
#测试数据
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()    #梯度管理
    test_loss, correct = 0, 0
    with torch.no_grad():   #一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。这可以减少计算所用内存消耗。
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model.forward(X)
            test_loss += loss_fn(pred, y).item() #
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
            a = (pred.argmax(1) == y)  #dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号
            b = (pred.argmax(1) == y).type(torch.float)
    test_loss /= num_batches#计算正确率
    correct /= size#计算损失
    print(f"Test result: \n Accuracy: {(100*correct)}%, Avg loss: {test_loss}")

# 多分类使用交叉熵损失函数
loss_fn = nn.CrossEntropyLoss() #创建交叉熵损失函数对象,因为手写字识别中一共有10个数字,输出会有10个结果
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)#创建一个优化器
#params:要训练的参数,一般我们传入的都是model.parameters()。
#lr:learning_rate学习率,也就是步长。


#训练模型
train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader, model, loss_fn)


epochs = 15 #
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    # test(test_dataloader, model, loss_fn)
print("Done!")
test(test_dataloader, model, loss_fn)

八、手写板实现输入识别功能

在原来的基础上实现,手写数字然后识别,训练完成后使用pygame做一个手写版实现手写,保存图片,然后将图片的大小修改为模型可以识别的大小,然后传入模型识别:

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
from PIL import Image
import torchvision.transforms as transforms
import pygame
import sys ;sys.setrecursionlimit(sys.getrecursionlimit() * 5)
from pygame.locals import *

# 创建一个MNIST数据集的实例
training_data = datasets.MNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor(),
)

test_data = datasets.MNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor(),
)

# 创建一个神经网络模型
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.hidden1 = nn.Linear(28 * 28, 128)
        self.hidden2 = nn.Linear(128, 256)
        self.out = nn.Linear(256, 10)

    def forward(self, x):
        x = self.flatten(x)
        x = self.hidden1(x)
        x = torch.relu(x)
        x = self.hidden2(x)
        x = torch.relu(x)
        x = self.out(x)
        return x


# 训练模型和测试模型的函数
def train(dataloader, model, loss_fn, optimizer):
    model.train()
    for X, y in dataloader:
        X, y = X.to(device), y.to(device)
        pred = model.forward(X)
        loss = loss_fn(pred, y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        loss = loss.item()
        print(f"loss: {loss:>7f}")


def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model.forward(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"Test result: \n Accuracy: {(100 * correct)}%, Avg loss: {test_loss}")


# 定义一个函数来识别手写数字
def recognize_handwritten_digit(image_path, model):
    image = Image.open(image_path).convert('L')

    preprocess = transforms.Compose([
        transforms.Resize((28, 28)),
        transforms.ToTensor(),
    ])
    input_tensor = preprocess(image)
    input_batch = input_tensor.unsqueeze(0)
    input_batch = input_batch.to(device)

    with torch.no_grad():
        output = model(input_batch)

    _, predicted_class = torch.max(output, 1)

    return predicted_class.item()


# 检查是否支持CUDA,然后选择设备
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")

# 创建数据加载器
train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

# 创建模型并传入设备
model = NeuralNetwork().to(device)

# 定义损失函数和优化器
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# 训练模型
for epoch in range(20):#训练次数
    print(f"Epoch {epoch + 1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)


# 识别手写数字
def get_handwritten_input():
    pygame.init()

    # 设置窗口
    window = pygame.display.set_mode((280, 280))
    pygame.display.set_caption('Handwritten Input')
    window.fill((0, 0, 0))  # 设置背景为黑色

    drawing = False
    last_pos = None

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == MOUSEBUTTONDOWN:
                drawing = True
            elif event.type == MOUSEMOTION:
                if drawing:
                    mouse_x, mouse_y = pygame.mouse.get_pos()
                    if last_pos:
                        pygame.draw.line(window, (255, 255, 255), last_pos, (mouse_x, mouse_y), 15)  # 设置绘画颜色为白色
                    last_pos = (mouse_x, mouse_y)
            elif event.type == MOUSEBUTTONUP:
                drawing = False
                last_pos = None
            pygame.display.update()
            if event.type == KEYDOWN and event.key == K_RETURN:
                pygame.image.save(window, 'handwritten_input.png')
                return 'handwritten_input.png'

def main():
    while True:  # 死循环保证程序一直运行,直到关闭
        image_path = get_handwritten_input()
        predicted_digit = recognize_handwritten_digit(image_path, model)
        print(f"The predicted digit is: {predicted_digit}")

if __name__ == "__main__":
    main()

在这里插入图片描述

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

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

相关文章

Cesium Vue(一)— 项目初始化配置

1. 创建VUE项目工程 创建项目 vue create cesium-vue配置Vue3 2. 创建vue.config.js文件 const { defineConfig } require(vue/cli-service)// The path to the CesiumJS source code const cesiumSource node_modules/cesium/Source; const cesiumWorkers ../Build/C…

Elasticsearch:什么是大语言模型 (LLMs)?

假设你想参加流行的游戏节目 Jeopardy(这是一个美国电视游戏节目,参赛者将获得答案并必须猜测问题)。 要参加演出,你需要了解任何事情的一切。 所以你决定在接下来的三年里每天都花时间阅读互联网上的所有内容。 你很快就会意识到…

跨境电商:为民营经济注入新活力

中国的民营经济一直以来都是国家经济发展的中流砥柱,而近年来,跨境电商产业崭露头角,为民营经济注入了新的活力和机遇。本文将探讨跨境电商如何成为中国民营企业的助推引擎,以及其对民营经济的积极影响。 民营经济的支柱地位 中国…

elasticsearch (六)filebeat 安装学习

filebeat 安装:文件节拍快速入门:安装和配置 |文件节拍参考 [7.17] |弹性的 (elastic.co) 解压缩后,以配置nginx日志为例。 Nginx module | Filebeat Reference [7.17] | Elastic filebeat 配置中, - module: nginx access: …

私人服务器可以干嘛

目录 搭建个人网站或博客: 远程桌面: 作为网盘储存: 作为测试和学习环境: 推广产品: 游戏私服(注意,仅限于个人自己单机玩): 个人服务器可以用于多种用途,以下是一些常见的用途:…

解密zkLogin:探索前沿的Sui身份验证解决方案

由于钱包复杂性导致的新用户入门障碍是区块链中一个长期存在的问题,而zkLogin是其简单的解决方案。通过使用前沿的密码学和技术,zkLogin既优雅又复杂。本文深入探讨了zkLogin的工作原理,涵盖了用户和开发者的安全性方面,并解释了S…

44.日期交叉问题(品牌活动天数计算)

思路分析: (1)计算表中每一条数据所对应的活动天数days (2)使用posexplode函数对days炸裂求其索引值index (3)使用开始日期index补全后面每一个活动日期in_date (4)按品牌…

Jmeter实现一次登录,多次业务请求(不同线程组间共享cookie和变量)

实现目的 很多时候,在进行性能测试时,需要先登录,然后再对需求的事务进行相关性能测试,此时的登录操作,并不在本次性能测试的范围内,所以我们只需要登录一次,然后获取登录成功后的cookie等&…

回顾 | E³CI效能认知与改进论坛,助力企业研发效能度量和提升

2023年8月,TiD质量竞争力大会组委会和ECI专家委员会成功举办TiD大时段课程“度量驱动研发效能提升”与“ECI效能认知与改进论坛”。与会专家以《ECI软件研发效能度量规范》团体标准为要点,为企业研发效能度量和提升分享诸多实践成果与经验。 《ECI软件研…

浅析ArkTS的起源和演进

1 引言 Mozilla创造了JS,Microsoft创建了TS,Huawei进一步推出了ArkTS。 从最初的基础的逻辑交互能力,到具备类型系统的高效工程开发能力,再到融合声明式UI、多维状态管理等丰富的应用开发能力,共同组成了相关的演进脉…

二十六、【颜色调整】

文章目录 1、色相/饱和度2、色彩平衡3、曲线4、可选颜色 1、色相/饱和度 色相其实就是颜色的亮度,就是我们往颜色里边加白色,白色越多颜色越淡。饱和度就是我们往颜色里边加黑色,黑色越多颜色越浓。如下图,我们调整拾色器里边的颜…

NAT网关在阿里云的应用

NAT网关(Network Address Translation Gateway)是一种网络地址转换服务,提供NAT代理(SNAT和DNAT)能力。NAT是用于在本地网络中使用私有地址,在连接互联网时转而使用全局 IP 地址的技术。NAT实际上是为解决I…

408计算机组成原理需要背的部分

1.第一章 1.1计算机发展历程 1.发展历程:电子管-》晶体管-》中小规模集成电路-》超大规模集成电路 2.系统组成:控制器,运算器,存储器,输入设备,输出设备 3.性能指标(常考部分): 机器字长&#x…

橙河网络:怎么学习python?

大家好,我是橙河网络,今天聊一聊怎么学习python? 学习Python编程可以采取以下步骤: 1.理解Python基础知识:了解Python的基本语法、数据类型、控制流语句、函数、模块和包等基础知识,这些是Python编程的基…

【LeetCode刷题(数据结构与算法面试题)】:最小高度树

给定一个有序整数数组 元素各不相同且按升序排列 编写一个算法 创建一棵高度最小的二叉搜索树 示例: 给定有序数组: [-10,-3,0,5,9] 一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树 0 / \ -3 9 / / -10 5 确定最小高…

股票价格预测 | Python基于RNN股票预测实战

循环神经网络(RNN)是基于序列数据(如语言、语音、时间序列)的递归性质而设计的,是一种反馈类型的神经网络,其结构包含环和自重复,因此被称为“循环”。它专门用于处理序列数据,如逐字生成文本或预测时间序列数据(例如股票价格)。 (1)one to one:其实和全连接神经网络…

网页版微信客户管理系统,常见疑问解答

1.系统怎么登陆? 请使用谷歌浏览器打开和使用系统,避免出现浏览器不兼容的问题,不建议使用其他浏览器。打开后输入登陆账号和密码即可登陆。 2.怎么登陆微信号? 登陆系统后,点击左上角这个 “” ,选择 “…

性能测试-redis常见问题

缓存击穿、缓存穿透、缓存雪崩 缓存雪崩 解决办法 1.设置缓存失效时间,不要在同一时间 2.redis集群部署 3.不设置缓存设置时间 4.定时刷缓存的时间 缓存穿透 请求不管返回什么数据都返回给redis对参数合法器进行验证,不合法的时候直接过滤掉使用布…

Raiden Network(二)—— Mediated transfers(多跳支付里的中介传输)

什么是Mediated transfers 在雷电网络中,节点可以通过中间节点进行Mediated transfers向其他节点进行支付。Mediated transfers的步骤: Allocation(分配): 使用锁定的转移消息(locked transfer message&am…

建陶行业标杆『诺贝尔瓷砖』企企通供应链协同系统一期项目上线,数字采购领航企业高质量发展

企企通与全球领先的高端装饰材料系统服务商【杭州诺贝尔陶瓷有限公司】(以下简称“诺贝尔瓷砖”)联合开发的供应链协同系统一期项目正式上线,这意味着诺贝尔瓷砖供应链变革管理迈上新的台阶,数字化采购进入新高速时代。 01、高端装…