1. pytorch mnist 手写数字识别

文章目录

    • 一、数据集介绍
      • 1.1、简介
      • 1.2 详细介绍
        • 1、数据量
        • 2、标注量
        • 3. 标注类别
        • 4.数据下载
        • 5.数据集解读
    • 二、读取、加载数据集
      • 1、pytorch 自带库函数
      • 2、通过重构Dataset类读取特定的MNIST数据或者制作自己的MNIST数据集
    • 三、模型构建
    • 四、 run
      • train
      • test
      • 评估模型的性能
      • 检查点的持续训练

一、数据集介绍

1.1、简介

MNIST是一个手写体数字的图片数据集,该数据集来由美国国家标准与技术研究所(National Institute of Standards and Technology (NIST))发起整理,一共统计了来自250个不同的人手写数字图片,其中50%是高中生,50%来自人口普查局的工作人员。

该数据集的收集目的是希望通过算法,实现对手写数字的识别。

MNIST数据集是从NIST的两个手写数字数据集:Special Database 3 和Special Database 1中分别取出部分图像,并经过一些图像处理后得到的。

MNIST数据集共有70000张图像,其中训练集60000张,测试集10000张。所有图像都是28×28的灰度图像,每张图像包含一个手写数字。

1.2 详细介绍

1、数据量

训练集60000张图像,其中30000张来自NIST的Special Database 3,30000张来自NIST的Special Database 1。

测试集10000张图像,其中5000张来自NIST的Special Database 3,5000张来自NIST的Special Database 1。

2、标注量

每张图像都有标注。

3. 标注类别

共10个类别,每个类别代表0~9之间的一个数字,每张图像只有一个类别。

4.数据下载

官网上提供了数据集的下载,主要包括四个文件:
在这里插入图片描述

5.数据集解读

训练集和测试集的标签文件的格式(train-labels-idx1-ubyte和t10k-labels-idx1-ubyte)

idx1-ubtype的文件数据格式如下:

[offset] [type]          [value]          [description]
0000     32 bit integer0x00000801(2049) magic number (MSB first)
0004     32 bit integer  60000            number of items
0008     unsigned byte   ??               label
0009     unsigned byte   ??               label
........
xxxx     unsigned byte   ??               label
  • 第0 ~ 3字节,是32位整型数据,取值为0x00000801(2049),即用幻数2049记录文件数据格式,这里的格式为文本格式。
  • 第4~7个字节,是32位整型数据,取值为60000(训练集时)或10000(测试集时),用来记录标签数据的个数;
  • 第8个字节 ~ ),是一个无符号型的数,取值为对应0~9 之间的标签数字,用来记录样本的标签

训练集和测试集的图像文件的格式(train-images-idx3-ubyte和t10k-images-idx3-ubyte)

idx3-ubtype的文件数据格式如下:

[offset] [type]          [value]          [description]
0000     32 bit integer  0x00000803(2051) magic number
0004     32 bit integer  60000            number of images
0008     32 bit integer  28               number of rows
0012     32 bit integer  28               number of columns
0016     unsigned byte   ??               pixel
0017     unsigned byte   ??               pixel
........
xxxx     unsigned byte   ??               pixel
  • 第0 ~ 3字节,是32位整型数据,取值为0x00000803(2051),即用幻数2051记录文件数据格式,这里的格式为图片格式。

  • 第4~7个字节,是32位整型数据,取值为60000(训练集时)或10000(测试集时),用来记录图片数据的个数;

  • 第8~11个字节,是32位整型数据,取值为28,用来记录图片数据的高度;

  • 第12~15个字节,是32位整型数据,取值为28,用来记录图片数据的宽度;

  • 第16个字节 ~ ),是一个无符号型的数,取值为0~255之间的灰度值,用来记录图片按行展开后得到的灰度值数据,其中0表示背景(白色),255表示前景(黑色)

二、读取、加载数据集

导入PyTorch的两个核心库torch和torchvision,这两个库基本包含了PyTorch会用到的许多方法和函数,其他库为下面所需要的一些辅助库。

import gzip
import osimport torch
import torchvision
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, Dataset

1、pytorch 自带库函数

TorchVision提供了许多方便的转换,比如裁剪或标准化。

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

其中:

  • root 指定MNIST数据集存放的路径
  • train 设置为True表示导入的是训练集合,否则为测试集合
  • transform 指定导入数据集时需要进行何种变换操作.
    此处ToTensor()将shape为(H, W, C)的nump.ndarray或img转为shape为(C, H, W)的tensor,其将每一个数值归一化到[0,1],其归一化方法比较简单,直接除以255即可
  • download 设置为True表示当root参数指定的数据集存放的路径下没有数据时,则自动从网络上下载MNIST数据集,否则就不自动下载

注意: 返回值为一个二元组(data,target),一般是与torch.utils.data.DataLoader配合使用,也可自己对数据进行处理,见二、2。

加载MNIST数据集代码:

train_data_loader = torch.utils.data.DataLoader(dataset=train_data,batch_size=64,shuffle=True,drop_last=True)test_data_loader = torch.utils.data.DataLoader(dataset=test_data,batch_size=64,shuffle=False,drop_last=False)

其中:

  • dataset 指定欲装载的MNIST数据集
  • batch_size 设置了每批次装载的数据图片为64个(自行设置)
  • shuffle 设置为True表示在装载数据时随机乱序,常用于进行多批次的模型训练
  • drop_last 设置为True表示当数据集size不能整除batch_size时,则删除最后一个batch_size,否则就不删除

直接构建数据集方式

train_loader = torch.utils.data.DataLoader(torchvision.datasets.MNIST('./data/', train=True, download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize((0.1307,), (0.3081,)) # 归一化,softmax归一化指数函数,其中0.1307是mean均值和0.3081是std标准差])),batch_size=batch_size_train, shuffle=True)
test_loader = torch.utils.data.DataLoader(torchvision.datasets.MNIST('./data/', train=False, download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize((0.1307,), (0.3081,))])),batch_size=batch_size_test, shuffle=True)

在加载完成后,可以选取其中一个批次的数据进行预览:

********************
images, labels = next(iter(train_data_loader))	# images:Tensor(64,1,28,28)、labels:Tensor(64,)
********************
img = torchvision.utils.make_grid(images)	# 把64张图片拼接为1张图片# pytorch网络输入图像的格式为(C, H, W),而numpy中的图像的shape为(H,W,C)。故需要变换通道才能有效输出
img = img.numpy().transpose(1, 2, 0) 
std = [0.5, 0.5, 0.5]
mean = [0.5, 0.5, 0.5]
img = img * std + mean
print(labels)
plt.imshow(img)
plt.show()

下图展示的是一个batch数据集(64张图片)的显示:
在这里插入图片描述
对其中某一个图片进行像素化展示:

# images:Tensor(64,1,28,28)、labels:Tensor(64,)	
images, labels = next(iter(train_data_loader))  #(1,28,28)表示该图像的 height、width、color(颜色通道,即单通道)
images = images.reshape(64, 28, 28) 
img = images[0, :, :]	# 取batch_size中的第一张图像
np.savetxt('img.txt', img.cpu().numpy(), fmt="%f", encoding='UTF-8')	# 将像素值写入txt文件,以便查看
img = img.cpu().numpy()	#转为numpy类型,方便有效输出fig = plt.figure(figsize=(12, 12))
ax = fig.add_subplot(111)
ax.imshow(img, cmap='gray')
width, height = img.shape
thresh = img.max()/2.5for x in range(width):for y in range(height):val = round(img[x][y], 2) if img[x][y] !=0 else 0ax.annotate(str(val), xy=(y, x),horizontalalignment='center',verticalalignment='center',color='white' if img[x][y] < thresh else 'black')
plt.show()

在这里插入图片描述

2、通过重构Dataset类读取特定的MNIST数据或者制作自己的MNIST数据集

定义一个子类,继承Dataset类, 重写 len(),getitem() 方法。

  • getitem 是获取样本对,模型直接通过这一函数获得一对样本对{ x:y }
  • len 是指数据集长度

① 读取MNIST文件夹下processed文件中的training.pt、test.pt数据集

class Data_Loader(Dataset):def __init__(self, root, transform=None):self.data, self.targets = torch.load(root)	#采用torch.load进行读取,读取之后的结果为torch.Tensor形式self.transform = transformdef __getitem__(self, index):img, target = self.data[index], int(self.targets[index])img = Image.fromarray(img.numpy(), mode='L')if self.transform is not None:img = self.transform(img)img = transforms.ToTensor()(img)return img, targetdef __len__(self):return len(self.data)

接下来,调用我们自定义的Data_Loader类来读取数据集:

# root 为training.pt、test.pt文件所在的绝对路径
train_data = Data_Loader(root='./mnist/MNIST/processed/training.pt', transform= None)
test_data = Data_Loader(root='./mnist/MNIST/processed/test.pt', transform= None)

再使用torch.utils.data.DataLoadertrain_datatest_data进行加载,展示。

② 读取MNIST文件夹下raw文件中的数据集

class Data_Loader(Dataset):def __init__(self, folder, data_name, label_name, transform=None):(train_set, train_labels) = load_data(folder, data_name, label_name)self.train_set = train_setself.train_labels = train_labelsself.transform = transformdef __getitem__(self, index):img, target = self.train_set[index], int(self.train_labels[index])if self.transform is not None:img = self.transform(img)return img, targetdef __len__(self):return len(self.train_set)def load_data(data_folder, data_name, label_name):with gzip.open(os.path.join(data_folder, label_name), 'rb') as lbpath:  # rb表示的是读取二进制数据y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)with gzip.open(os.path.join(data_folder, data_name), 'rb') as imgpath:x_train = np.frombuffer(imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)return x_train, y_train

接下来,调用我们自定义的Data_Loader类来读取数据集:

#	folder:MNIST数据集中raw文件的绝对路径# 读取MNIST数据集中的训练集
train_data = Data_Loader('./MNIST/MNIST/raw', "train-images-idx3-ubyte.gz","train-labels-idx1-ubyte.gz", transform=transforms.ToTensor())# 读取MNIST数据集中的测试集
test_data = Data_Loader('./MNIST/MNIST/raw', "t10k-images-idx3-ubyte.gz","t10k-labels-idx1-ubyte.gz", transform=transforms.ToTensor())

再使用torch.utils.data.DataLoadertrain_datatest_data进行加载,展示。

三、模型构建

开始始建立网络。将使用两个2d卷积层,然后是两个全连接(或线性)层。作为激活函数,选择整流线性单元(简称ReLUs),作为正则化的手段,使用两个dropout层。

在PyTorch中,构建网络的一个好方法是希望构建的网络创建一个新类。

import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optimclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.conv2_drop = nn.Dropout2d()self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = F.relu(F.max_pool2d(self.conv1(x), 2))x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))x = x.view(-1, 320)x = F.relu(self.fc1(x))x = F.dropout(x, training=self.training)x = self.fc2(x)return F.log_softmax(x)

初始化网络和优化器。

network = Net()
optimizer = optim.SGD(network.parameters(), lr=learning_rate,momentum=momentum)

四、 run

train

首先,我们要确保我们的网络处于训练模式。然后,每个epoch对所有训练数据进行一次迭代。加载单独批次由DataLoader处理
我们需要使用optimizer.zero_grad()手动将梯度设置为零,因为PyTorch在默认情况下会累积梯度。然后,我们生成网络的输出(前向传递),并计算输出与真值标签之间的负对数概率损失。

现在,我们收集一组新的梯度,并使用optimizer.step()将其传播回每个网络参数。有关PyTorch自动渐变系统内部工作方式的详细信息,请参阅autograd的官方文档(强烈推荐)。

我们还将使用一些打印输出来跟踪进度。为了在以后创建一个良好的培训曲线,我们还创建了两个列表来节省培训和测试损失。在x轴上,我们希望显示网络在培训期间看到的培训示例的数量

train_losses = []
train_counter = []
test_losses = []
test_counter = [i*len(train_loader.dataset) for i in range(n_epochs + 1)]

在开始训练之前,我们将运行一次测试循环,看看仅使用随机初始化的网络参数可以获得多大的精度/损失

def train(epoch):network.train()for batch_idx, (data, target) in enumerate(train_loader):optimizer.zero_grad()output = network(data)loss = F.nll_loss(output, target)loss.backward()optimizer.step()if batch_idx % log_interval == 0:print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch, batch_idx * len(data), len(train_loader.dataset),100. * batch_idx / len(train_loader), loss.item()))train_losses.append(loss.item())train_counter.append((batch_idx*64) + ((epoch-1)*len(train_loader.dataset)))torch.save(network.state_dict(), './model.pth')torch.save(optimizer.state_dict(), './optimizer.pth')

神经网络模块以及优化器能够使用.state_dict()保存和加载它们的内部状态。

这样,如果需要,我们就可以继续从以前保存的状态dict中进行训练——只需调用.load_state_dict(state_dict)。

test

进入测试循环。在这里,我们总结了测试损失,并跟踪正确分类的数字来计算网络的精度

def test():network.eval()test_loss = 0correct = 0with torch.no_grad():for data, target in test_loader:output = network(data)test_loss += F.nll_loss(output, target, size_average=False).item()pred = output.data.max(1, keepdim=True)[1]correct += pred.eq(target.data.view_as(pred)).sum()test_loss /= len(test_loader.dataset)test_losses.append(test_loss)print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(test_loss, correct, len(test_loader.dataset),100. * correct / len(test_loader.dataset)))

评估模型的性能

就是这样。仅仅经过3个阶段的训练,我们已经能够达到测试集97%的准确率!我们开始使用随机初始化的参数,正如预期的那样,在开始训练之前,测试集的准确率只有10%左右。

我们来画一下训练曲线。

test()  不加这个,后面画图就会报错:x and y must be the same size
for epoch in range(1, n_epochs + 1):train(epoch)test()
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.scatter(test_counter, test_losses, color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')
plt.show()

在这里插入图片描述
从训练曲线来看,看起来我们甚至可以继续训练几个epoch!

但在此之前,让我们再看看几个例子,正如我们之前所做的,并比较模型的输出。

examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)
with torch.no_grad():output = network(example_data)
fig = plt.figure()
for i in range(6):plt.subplot(2,3,i+1)plt.tight_layout()plt.imshow(example_data[i][0], cmap='gray', interpolation='none')plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))plt.xticks([])plt.yticks([])
plt.show()

在这里插入图片描述

检查点的持续训练

现在让我们继续对网络进行训练,或者看看如何从第一次培训运行时保存的state_dicts中继续进行训练。我们将初始化一组新的网络和优化器。

continued_network = Net()
continued_optimizer = optim.SGD(network.parameters(), lr=learning_rate,momentum=momentum)

使用.load_state_dict(),我们现在可以加载网络的内部状态,并在最后一次保存它们时优化它们。

network_state_dict = torch.load('model.pth')
continued_network.load_state_dict(network_state_dict)
optimizer_state_dict = torch.load('optimizer.pth')
continued_optimizer.load_state_dict(optimizer_state_dict)

同样,运行一个训练循环应该立即恢复我们之前的训练。为了检查这一点,我们只需使用与前面相同的列表来跟踪损失值。由于我们为所看到的训练示例的数量构建测试计数器的方式,我们必须在这里手动添加它。

# 注意不要注释前面的“for epoch in range(1, n_epochs + 1):”部分,
# 不然报错:x and y must be the same size
# 为什么是“4”开始呢,因为n_epochs=3,上面用了[1, n_epochs + 1)
for i in range(4, 9):test_counter.append(i*len(train_loader.dataset))train(i)test()

参考文献:

  • https://blog.csdn.net/Iron802/article/details/121826385
  • https://blog.csdn.net/OpenDataLab/article/details/125716623
  • https://nextjournal.com/gkoehler/pytorch-mnist
  • https://blog.csdn.net/qq_45588019/article/details/120935828
  • https://blog.csdn.net/ali1174/article/details/130294224

完整代码如下:

import torch
import torchvision
from torch.utils.data import DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as pltn_epochs = 3
batch_size_train = 64
batch_size_test = 1000
learning_rate = 0.01
momentum = 0.5
log_interval = 10
random_seed = 1
torch.manual_seed(random_seed)train_loader = torch.utils.data.DataLoader(torchvision.datasets.MNIST('./data/', train=True, download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize((0.1307,), (0.3081,))])),batch_size=batch_size_train, shuffle=True)
test_loader = torch.utils.data.DataLoader(torchvision.datasets.MNIST('./data/', train=False, download=True,transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor(),torchvision.transforms.Normalize((0.1307,), (0.3081,))])),batch_size=batch_size_test, shuffle=True)examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)
# print(example_targets)
# print(example_data.shape)fig = plt.figure()
for i in range(6):plt.subplot(2, 3, i + 1)plt.tight_layout()plt.imshow(example_data[i][0], cmap='gray', interpolation='none')plt.title("Ground Truth: {}".format(example_targets[i]))plt.xticks([])plt.yticks([])
plt.show()class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.conv2_drop = nn.Dropout2d()self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = F.relu(F.max_pool2d(self.conv1(x), 2))x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))x = x.view(-1, 320)x = F.relu(self.fc1(x))x = F.dropout(x, training=self.training)x = self.fc2(x)return F.log_softmax(x, dim=1)network = Net()
optimizer = optim.SGD(network.parameters(), lr=learning_rate, momentum=momentum)train_losses = []
train_counter = []
test_losses = []
test_counter = [i * len(train_loader.dataset) for i in range(n_epochs + 1)]def train(epoch):network.train()for batch_idx, (data, target) in enumerate(train_loader):optimizer.zero_grad()output = network(data)loss = F.nll_loss(output, target)loss.backward()optimizer.step()if batch_idx % log_interval == 0:print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch, batch_idx * len(data),len(train_loader.dataset),100. * batch_idx / len(train_loader),loss.item()))train_losses.append(loss.item())train_counter.append((batch_idx * 64) + ((epoch - 1) * len(train_loader.dataset)))torch.save(network.state_dict(), './model.pth')torch.save(optimizer.state_dict(), './optimizer.pth')def test():network.eval()test_loss = 0correct = 0with torch.no_grad():for data, target in test_loader:output = network(data)test_loss += F.nll_loss(output, target, reduction='sum').item()pred = output.data.max(1, keepdim=True)[1]correct += pred.eq(target.data.view_as(pred)).sum()test_loss /= len(test_loader.dataset)test_losses.append(test_loss)print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(test_loss, correct, len(test_loader.dataset),100. * correct / len(test_loader.dataset)))train(1)test()  # 不加这个,后面画图就会报错:x and y must be the same size
for epoch in range(1, n_epochs + 1):train(epoch)test()fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.scatter(test_counter, test_losses, color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)
with torch.no_grad():output = network(example_data)
fig = plt.figure()
for i in range(6):plt.subplot(2, 3, i + 1)plt.tight_layout()plt.imshow(example_data[i][0], cmap='gray', interpolation='none')plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))plt.xticks([])plt.yticks([])
plt.show()# ----------------------------------------------------------- #continued_network = Net()
continued_optimizer = optim.SGD(network.parameters(), lr=learning_rate, momentum=momentum)network_state_dict = torch.load('model.pth')
continued_network.load_state_dict(network_state_dict)
optimizer_state_dict = torch.load('optimizer.pth')
continued_optimizer.load_state_dict(optimizer_state_dict)# 注意不要注释前面的“for epoch in range(1, n_epochs + 1):”部分,
# 不然报错:x and y must be the same size
# 为什么是“4”开始呢,因为n_epochs=3,上面用了[1, n_epochs + 1)
for i in range(4, 9):test_counter.append(i*len(train_loader.dataset))train(i)test()fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.scatter(test_counter, test_losses, color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')
plt.show()

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

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

相关文章

Postman接口测试(附教程)

前言 之前还没实际做过接口测试的时候呢&#xff0c;对接口测试这个概念比较渺茫&#xff0c;只能靠百度&#xff0c;查看各种接口实例&#xff0c;然后在工作中也没用上&#xff0c;现在呢是各种各样的接口都丢过来…

2024,智能汽车走出独立曲线

文&#xff5c;刘俊宏 新能源汽车正在带领中国车市走向新的高峰。 在2023年&#xff0c;新能源汽车的增速显著超越整体车市。据中汽协预测&#xff0c;2023年&#xff0c;汽车总销量有望突破3000万辆&#xff0c;同比增长11.7%。其中&#xff0c;乘用车预计达到2600万辆&…

Web(10)XSS漏洞

XSS跨站脚本攻击 XSS是什么 XSS(cross-site-scripting) 即是跨站脚本攻击&#xff0c;是一种网站应用程序的安全漏洞攻击&#xff0c;是代码注入的一种。它允许恶意用户将代码注入到网页上&#xff0c;其他用户在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及用户端…

一条查询SQL是如何执行的?更新、新增、删除呢?

你好&#xff0c;我是田哥 本文共14629字&#xff0c;读完预计需要37分钟&#xff0c;建议先收藏。 大部分朋友估计都只知道写sql然后执行&#xff0c;但是并不知道MySQL背后到底是怎么实现的。 八股文中也有这么一道题&#xff1a;在MySQL中&#xff0c;一条SQL到底是如何执行…

【记录问题排查系列】记录CPU飙高问题排查过程篇(1)

CPU飙高问题排查 ✔️问题排查与解决✔️总结与思考 &#x1f341;前段时间我们新上了一个新的应用&#xff0c;因为流量一直不大&#xff0c;集群OPS大概只有5左右&#xff0c;写接口的t在30ms左右。 因为最近接入了新的业务&#xff0c;业务方给出的数据是日常QPS可以达到20…

无人职守自动安装linux操作系统

无人职守自动安装linux操作系统 1. 大规模部署案例2. PXE 技术3. Kickstart 技术4. 配置安装服务器4.1 DHCP服务4.2 TFTP 服务4.3 NFS服务 5. 示例5.1 搭建server1. 启动dhcp并设为开机自启2. 设置并启动tftp3. 将客户端所需启动文件复制到TFTP服务器4. 创建Kickstart自动应答文…

【IO】IO模型与零拷贝

前言&#xff1a; 正在运行的程序其实就是系统中的一个进程&#xff0c;操作系统会为每一个进程分配内存空间&#xff0c;而内存空间分为两部分&#xff0c;一部分是用户空间&#xff0c;这是用户进程访问的内存区域&#xff1b;另一部分是内核空间&#xff0c;是操作系统内核访…

20种常用的软件测试方法,建议先收藏再观看

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

简单的喷淋实验(2):(1)根据土壤湿度自动控制喷淋开关;(2)根据光照强度控制风扇以及灯的开关---嵌入式实训

目录 简单的喷淋实验(2)&#xff1a; &#xff08;1&#xff09;根据土壤湿度自动控制喷淋开关&#xff1b; &#xff08;2&#xff09;根据光照强度控制风扇以及灯的开关---嵌入式实训 任务2&#xff1a; 具体过程&#xff1a; 所用的头文件&#xff1a; data_global.h …

gin框架使用系列之三——获取表单数据

系列目录 《gin框架使用系列之一——快速启动和url分组》《gin框架使用系列之二——uri占位符和占位符变量的获取》 一、获取get参数 get请求的参数是直接加在url后面的&#xff0c;在gin中获取get请求的参数主要用Query()和DefaultQuery()两个方法&#xff0c;示例代码如下…

【Unity地形】使用地形工具创建场景环境-Terrain

如上图Unity的地形工具可以让我们实现创建复杂、丰富的3D室外环境。 我们创建地形很简单&#xff0c;在层级面板中右键-3Dobject-Terrain 就可以创建一个默认的地形模型&#xff01;这个模型是Unity内置的。 接下来的地形编辑功能全部集中在这个地形的组件上 主要功能如下&…

WPS中如何根据身份证号生成出生日期并排序

1. wps中如何根据身份证号导出出生日期并排序 1.1 wps中建一张表 1.2 使用转日期格式导出出生日期 DATE(VALUE(MID(C2,7,4)),VALUE(MID(C2,11,2)),VALUE(MID(C2,13,2)))MID(C2, 7, 4)&#xff1a;这部分从单元格 C2 中提取文本字符串&#xff0c;从第7个字符开始提取长度为4的…

[python]python使用M-LSD直线检测算法onnx部署模型实时检测

介绍 github地址&#xff1a;https://github.com/navervision/mlsd LSD (M-LSD)一种用于资源受限环境的实时轻量线段检测器。它利用了极其高效的 LSD 架构和新颖的训练方案&#xff0c;包括 SoL 增强和几何学习方案。模型可以在GPU、CPU甚至移动设备上实时运行。算法已开源&a…

【elk-day01】es和kibana搭建及验证---Mac-Docker

Mac系统使用Docker下载搭建和验证eskibana Docker下载安装es安装es验证kibana安装kibana验证 Docker下载安装 Docker Desktop官网安装下载地址 说明一下为什么要安装desktop版本的docker&#xff0c;因为docker作为工具使用&#xff0c;我们需要的是开箱即用&#xff0c;没有必…

windows搭建MySQL 8.25主从配置

1.本次搭建的版本 mysql-8.0.25-win-x64 2.在解压完成后的文件内并没有对应的my.ini的配置文件这个my.ini是需要的主配置文件需要自行创建。 注&#xff1a;安装路径及数据存放路径需根据实际安装情况进行修改&#xff08;其它配置信息可结合实际情况进行修改&#xff09; 3.在…

vue+element实现动态表格:根据后台返回的属性名和字段动态生成可变表格

现有一个胡萝卜厂生产不同品种的胡萝卜&#xff0c;为了便于客户了解产品&#xff0c;现需在官网展示胡萝卜信息。现有的萝卜信息&#xff1a;编号&#xff08;id&#xff09;、名称&#xff08;name&#xff09;、保质期&#xff08;age&#xff09;、特点&#xff08;remark&…

深度学习:计算机技术的革命性突破

深度学习&#xff1a;计算机技术的革命性突破 随着科技的飞速发展&#xff0c;深度学习已经成为计算机技术领域的一股强大力量。它改变了我们与机器的交互方式&#xff0c;为人工智能领域带来了革命性的突破。本篇博客将深入探讨深度学习的原理、应用和发展趋势。 一、深度学…

【python】爬取斗鱼直播照片保存到本地目录【附源码+文末免费送书】

一、导入必要的模块&#xff1a; 这篇博客将介绍如何使用Python编写一个爬虫程序&#xff0c;从斗鱼直播网站上获取图片信息并保存到本地。我们将使用requests模块发送HTTP请求和接收响应&#xff0c;以及os模块处理文件和目录操作。 如果出现模块报错 进入控制台输入&#xff…

【基础篇】五、类的双亲委派机制

文章目录 1、双亲委派机制2、Java代码中去主动加载一个类3、“父”加载器4、Q & A5、打破双亲委派机制 1、双亲委派机制 JVM中有多个类加载器&#xff0c;某个类A&#xff0c;到底该由谁去加载 ⇒ 双亲委派机制 该机制的作用&#xff1a; 保证类加载的安全性&#xff1a;避…

Grafana 配置告警

配置告警 配置告警 1. Grafana 配置文件配置 #################################### SMTP / Emailing ########################## [smtp] enabled true host smtp.qq.com:587 user 9**qq.com # If the password contains # or ; you have to wrap it with triple quotes…