1. pytorch mnist 手写数字识别

news2024/11/17 7:33:18

文章目录

    • 一、数据集介绍
      • 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 integer

  0x00000801(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 os

import 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.5

for x in range(width):
    for y in range(height):
        val = round(img[x][y], 2) if img[x][y] !=0 else 0
        ax.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 = transform
		
    def __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, target

    def __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_set
        self.train_labels = train_labels
        self.transform = transform

    def __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, target

    def __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 optim

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)

初始化网络和优化器。

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 = 0
  correct = 0
  with 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 plt
 
n_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 = 0
    correct = 0
    with 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.coloradmin.cn/o/1338908.html

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

相关文章

element-plus修改主题颜色

一、自定义scss文件 在src\css\styles\element目录下新建index.scss 代码如下 forward "element-plus/theme-chalk/src/common/var.scss" with ($colors: ("primary": ("base": #d61b1a,"color": #fff,),) );use "element-plus…

STANFORD斯坦福FS725铷钟

FS725在一个紧凑的半宽2U机箱中集成了一个铷原子振荡器&#xff08;SRS型号PRS10&#xff09;、一个低噪声通用交流电源和分配放大器。它提供稳定和可靠的性能&#xff0c;估计20年的老化率低于510-9&#xff0c;并证明铷原子振荡器的MTBF超过20万小时。FS725是校准和研发实验室…

【JavaWeb学习笔记】18 - 文件上传下载

项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/fileupdown 目录 文件上传 一、基本介绍 二、文件上传的基本原理 ​编辑 三、文件上传应用实例 四、文件上传的注意细节 1.解决中文乱码问题 2.分割文件夹 3.防止重名 4.百度WebUploader 5.空…

Doris:为企业数据查询加速

Doris是一款由百度开发的开源数据仓库查询引擎&#xff0c;它能够帮助用户高效地查询和分析大规模数据。Doris具有高性能、易用性强、可扩展性高等特点&#xff0c;让数据分析变得更加简单。 二、场景&#xff1a; Doris适用于各种数据仓库场景&#xff0c;无论是大数据分析、…

搭建WebDAV服务+cpolar内网穿透公网同步Zotero科研文献

文章目录 一、Zotero安装教程二、群晖NAS WebDAV设置三、Zotero设置四、使用公网地址同步Zotero文献库五、使用永久固定公网地址同步Zotero文献库 Zotero 是一款全能型 文献管理器,可以 存储、管理和引用文献&#xff0c;不但免费&#xff0c;功能还很强大实用。 ​ Zotero 支…

图灵日记之java奇妙历险记--类和对象

目录 类的定义和使用类的定义格式 类的实例化类和对象的说明 this引用this引用的特性 对象的构造及初始化就地初始化构造方法 封装包导入包中的类自定义包 static成员static修饰成员变量static修饰成员方法 代码块代码块概念及分类构造代码块静态代码块 匿名对象 类的定义和使用…

Python入门学习篇(十)——函数定义函数传参方式

1 相关定义和概念 1.1 函数的理解 一段被封装的可以重复调用的代码。 1.2 函数定义语法结构 def 函数名(形参1,形参2):要封装的逻辑代码 # 注意:函数可以有返回值也可以没有返回值,没有返回值的结果是None1.3 函数调用的语法结构 函数名(形参1,形参2)1.4 简单实例 1.4.1 …

不浪费时间,昂首资本1分钟如何快速学习MT4价差

不要浪费时间在手工计算上&#xff0c;昂首资本解释一下如何快速学习MT4价差&#xff0c;。 想要在MT4中输入交易时&#xff0c;需要在交易窗口中设置未来交易的参数。在同一个窗口中&#xff0c;可以看到卖价和买价。如果在上面的例子中比较这两个价格&#xff0c;就会发现两…

如何查看NX UI对话框内的控件(使用UIFW侦查)

一、概述 在NX二次开发中有很多命令从界面上看起开相似&#xff0c;但实质确不同&#xff0c;个人人为一是出于对软件产权的保护&#xff0c;增加二次开发的难度&#xff0c;二是由于NX在不断地发展和版本交替中为了保留老用户的操作习惯&#xff0c;故意用新控件做成老控件的…

LeetCode刷题--- N 皇后

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​​​​http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递归…

模式识别与机器学习-特征选择和提取

模式识别与机器学习-特征选择和提取 特征选择一些距离测度公式独立特征的选择准则一般特征的散布矩阵准则 离散K-L变换 谨以此博客作为复习期间的记录。 常见分类问题的流程&#xff0c;数据预处理和特征选择提取时机器学习环节中最重要的两个流程。这两个环节直接决定了最终性…

数模学习02-Matlab基础知识入门

先把matlab下载好。然后你就会发现电脑有少了几十个GB。服啦~ 修改字体 字体真的是太小了&#xff0c;其实我无论是使用什么编辑器我一般都会先改字体&#xff0c;字体在开始中有一个预设&#xff0c;可以修改字体&#xff0c;这样眼睛看着也会舒服一点 命令行窗口的使用 这…

亚马逊美国站ASTM F2613儿童折叠椅和凳子强制性安全标准

ASTM F2613折叠椅和凳子安全标准 美国消费品安全委员会&#xff08;CPSC&#xff09;发布的ASTM F2613儿童折叠椅和凳子的强制性安全标准&#xff0c;已于2020年7月6日生效&#xff0c;并被纳入联邦法规《16 CFR 1232儿童折叠椅和凳子安全标准》。 亚马逊要求在美国站上架的儿…

GaussDB元命令使用指导

所谓元命令就是在gsql里输入的任何以不带引号的反斜杠开头的命令。本课程通过实际使用gsql实践&#xff0c;介绍GaussDB数据库gsql所提供的元命令。 本课程仅展示基础的元命令使用。 一、操作步骤 步骤1 使用gsql连接到GaussDB实例。 gsql工具使用-d参数指定目标数据库名…

何时为 SEO 创建本地化文件夹和页面

您可以为新网站创建主题支柱页面吗&#xff1f; 您网站的使用年限与您如何构建内容和文件夹无关紧要。在重建已有 10 年历史的域或启动新 URL 时&#xff0c;可以做到这一点。 您应该始终构建您的网站&#xff0c;以便它帮助最终用户了解网站的层次结构&#xff0c;并显示该部…

详解Vue3中的插槽(slot)

本文主要介绍Vue3中的插槽&#xff08;slot&#xff09;。 目录 一、在普通写法中使用插槽&#xff08;slot&#xff09;作用域插槽默认插槽 二、在setup写法中使用插槽&#xff1a;注意事项 在Vue3中&#xff0c;插槽&#xff08;slot&#xff09;是一种用于在父组件中向子组件…

【2】Docker Compose编排

Docker Compose 使用 Docker 帮助我们解决服务的打包安装的问题&#xff0c;随着而来的问题就是服务过多的带来如下问题&#xff1a; 多次使用 Dockerfile、Build、Image 命令或者 DockerHub 拉取 Image&#xff1b;需要创建多个 Container&#xff0c;多次编写启动命令&…

Python——yolov8识别车牌2.0

目录 一、前言 二、关于项目UI 2.1、修改界面内容的文本 2.2、修改界面的图标和图片 三、项目修改地方 四、其他配置问题 一、前言 因为后续有许多兄弟说摄像头卡顿&#xff0c;我在之前那个MATS上面改一下就可以了&#xff0c;MAST项目&#xff1a;基于YOLOv8的多端车流检…

51 单片机基础

一、51 单片机 开发环境配置&#xff0c;vscodeSDCC 编辑器、编译器 最常用的集成开发环境 keil c51 1、vscode SDCC 开发环境搭建 vscode 插件&#xff08; 或者 PlatformIO IDE&#xff09; EIDE 的使用&#xff1a;详细自学 PlatformIO IDE&#xff1a;详细自学 vsc…

C#高级 02异步编程

基础知识 1.什么是异步任务 包含了异步任务的各种状态的一个引用类型 1)正在运行、完成、结果、报错等 2)另有ValueTask值类型版本对于异步任务的抽象 1)开启异步任务后&#xff0c;当前线程并不会阻塞&#xff0c;而是可以去做其他事情 2)异步任务&#xff08;默认&#xff…