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

文章目录

  • 前言
  • 完成效果
  • 一、下载数据集
    • 手动下载
    • 代码下载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-12img, 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,输出维度为128self.hidden2 = nn.Linear(128, 256)    # 第二个隐藏层,输入维度为128,输出维度为256self.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 = 1for X, y in dataloader:                 #其中batch为每一个数据的编号X, y = X.to(device), y.to(device)   #把训练数据集和标签传入cpu或GPUpred = 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, 0with 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,输出维度为128self.hidden2 = nn.Linear(128, 256)    # 第二个隐藏层,输入维度为128,输出维度为256self.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激活函数/修改为relux = self.hidden2(x)        # 第二个隐藏层的线性变换x = torch.relu(x)       # 使用Sigmoid激活函数/修改为relux = 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,输出维度为128self.hidden2 = nn.Linear(128, 256)    # 第二个隐藏层,输入维度为128,输出维度为256self.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激活函数/修改为relux = self.hidden2(x)        # 第二个隐藏层的线性变换x = torch.relu(x)       # 使用Sigmoid激活函数/修改为relux = 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 = 1for X, y in dataloader:                 #其中batch为每一个数据的编号X, y = X.to(device), y.to(device)   #把训练数据集和标签传入cpu或GPUpred = 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, 0with 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, 0with 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_batchescorrect /= sizeprint(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 = Falselast_pos = Nonewhile True:for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()elif event.type == MOUSEBUTTONDOWN:drawing = Trueelif 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 = Falselast_pos = Nonepygame.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.mzph.cn/news/108431.shtml

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

相关文章

vue重修【005】自定义路由、插槽

文章目录 版权声明自定义指令指令初识指令中配置项指令语法指令值v-loading指令的封装分析实现 插槽默认插槽插槽默认值具名插槽作用域插槽使用步骤完整案例 版权声明 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明,所有版权属于黑马程…

如何快速定位BUG?BUG定位技巧及测试人员定位的N板斧

很多测试人员可能会说,我的职责就是找到bug,至于找原因并修复,那是开发的事情,关我什么事? 好,我的回答是,如果您只想做一个测试人员最基本最本分的事情,那么可以这么想。但是&#…

微信批量发朋友圈,多个号同步

近年来,随着数字营销的飞速发展,越来越多的企业开始将客户引至微信,并通过群发广告和发布朋友圈等方式进行产品推广,以实现高效率、低成本和良好的转化效果。随着号多起来了,朋友圈推广工作变得愈发繁琐,需…

Vue3 + Nodejs 实战 ,文件上传项目--实现图片上传

目录 技术栈 1. 项目搭建前期工作(不算太详细) 前端 后端 2.配置基本的路由和静态页面 3.完成图片上传的页面(imageUp) 静态页面搭建 上传图片的接口 js逻辑 4.编写上传图片的接口 5.测试效果 结语 博客主页:専心_前端,javascript,mys…

TiDB 7.4 发版:正式兼容 MySQL 8.0

MySQL 是全球最受欢迎的开源数据库,长期位于 DB-Engines Ranking 排行榜第二名,在世界范围内拥有数量庞大的企业用户和开发者。然而,随着时间的推移,MySQL 用户正面临新挑战。Oracle 官宣将在 2023 年 10 月终止 MySQL 5.7 版本的…

2023,简历石沉大海?软件测试岗位真的已经饱和了....

各大互联网公司的接连裁员,政策限制的行业接连消失,让今年的求职雪上加霜,想躺平却没有资本,还有人说软件测试岗位饱和了,对此很多求职者深信不疑,因为投出去的简历回复的越来越少了。 另一面企业招人真的…

【halcon】halcon轮廓总结之select_contours_xld

前言 select_contours_xld 我认为是一个非常常用且实用的算子,用于对轮廓进行筛选。 简介 这段文档描述了一个名为"SelectContoursXld"的操作,用于根据不同特征选择XLD(XLD是一种图像数据表示形式,表示轮廓线&#x…

竞赛 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数:3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 *…

Golang学习:基础知识篇(二)—— 数组及切片

Golang学习:基础知识篇(二)—— 数组及切片 前言什么是Golang?Go语言的基础语法数组声明数组初始化数组访问数组知识点补充 切片定义切片切片初始化len() 和 cap() 函数空(nil)切片切片截取append() 和 copy() 函数知识点补充 前言…

ubuntu20.04安装FTP服务

安装 sudo apt-get install vsftpd# 设置开机启动并启动ftp服务 systemctl enable vsftpd systemctl start vsftpd#查看其运行状态 systemctl status vsftpd #重启服务 systemctl restart vsftpdftp用户 sudo useradd -d /home/ftp/ftptest -m ftptest sudo passwd ftptest…

使用 Python 和蒙特卡罗计算未来股价走势以及历史波动率和隐含波动率

一、简介 预测金融市场是定量精度和全球经济细微差别的复杂融合。在这一探索中,蒙特卡罗模拟脱颖而出,成为首要的统计工具,指导我们对未来股票价格的理解。 这种方法以摩纳哥著名的蒙特卡洛赌场命名,并不依靠运气,而是植根于严格的概率模型。想象一下在受控环境中精心策划…

vue3后台管理框架之技术栈

vue3全家桶技术 基础构建: vue3vite4TypeScript 代码格式 : eslintprettystylelint git生命周期钩子: husky css预处理器: sass ui库: element-plus 模拟数据: mock 网络请求: axios 路由: vue…

SAP MM学习笔记37 - 请求书照合中的 追加请求/追加Credit 等概念/ 请求书的取消

有关请求书照合,之前学习了一部分,现在再来学其中的一些概念。 其实这些概念也许并不常用,但是你又不能不知道,因为客户会问。 有关请求书,贴一些以前学习的文章,以方便阅读。 SAP MM学习笔记33 - 请求书…

38.迪杰斯特拉(Dijkstra)算法

概述 我们在上一篇中面对修路的问题讲述了普利姆算法的实现方式,本篇我们参照迪杰斯特拉算法来对修路问题做进一步拆解。 我们回顾一下之前的问题: “要想富,先修路”,郝乡长最近为了德胜乡修路的事情愁白了头。 得胜乡有A、B、C…

《3D 数学基础》几何检测-最近点

目录 1. 直线上的最近点 2. 射线上的最近点 3. 点到平面的距离 4. 圆或球上的最近点 5. AABB上的最近点 1. 直线上的最近点 q是距离q的最近点,也就是q在直线上的投影。 其中p是直线上的点(向量表示),n是直线的法向量&#x…

selenium教程 —— css定位

说明:本篇博客基于selenium 4.1.0 selenium-css定位 element_css driver.find_element(By.CSS_SELECTOR, css表达式) 复制代码 css定位说明 selenium中的css定位,实际是通过css选择器来定位到具体元素,css选择器来自于css语法 css定位优点…

史上最短的“牛熊转换”:BTC价格昨夜起飞,但却来自一条假新闻!

昨夜,加密市场经历了史上最短的一次“牛熊转换”。 在短短10分钟内,BTC快速走出多根阳线,价格直接起飞,连续突破28000美元、29000美元、30000美元的整数关口,最高触及30535.8美元,涨幅近10%(数据…

接口自动化测试之HttpRunner测试框架

引言 接口自动化测试的实现方案有很多,没有编程基础的可以使用 PostmanNewman 或 JmeterAnt 来实现,有编程基础的则可以结合自动化测试框架来实现。基于Python的测试框架有:Unittest、HttpRunner、Robot Framework、Pytest等,本文…

python接口自动化测试(六)-unittest-单个用例管理

前面五节主要介绍了环境搭建和requests库的使用,可以使用这些进行接口请求的发送。但是如何管理接口案例?返回结果如何自动校验?这些内容光靠上面五节是不行的,因此从本节开始我们引入python单元测试框架 unittest,用它…

OpenCV模板匹配实现银行卡数字识别

目录 1,项目流程 2,代码流程解读 2.1 导入工具包 2.2 设置参数 2.3 指定信用卡类型 2.4 展示图像 ​编辑 2.5 读取一个模板图像 2.6 转化为灰度图--------->再转化为二值图像 2.7 计算轮廓 ​编辑 2.8 导入我们要识别的图像&…