使用Pytorch+Numpy+Matplotlib实现手写字体分类和图像显示

文章目录

  • 1.引用
  • 2.内置图片数据集加载
  • 3.处理为batch类型
  • 4.设置运行设备
  • 5.查看数据
  • 6.绘图查看数据图片
    • (1)不显示图片标签
    • (2)打印图片标签
    • (3)图片显示标签
  • 7.定义卷积函数
  • 8.卷积实例化、损失函数、优化器
  • 9.训练和测试损失、正确率
    • (1)训练
    • (2)测试
    • (3)循环
    • (4)损失和正确率曲线
    • (5)输出数据到表格
  • 10.额外添加
    • (1)添加dropout减少过拟合
      • ①未添加dropout层
      • ②添加dropout层
    • (2)循环同时输出时间
    • (3)每个类别分类正确率输出
      • ①输出到控制台
      • ②输出到表格
    • (4)模型保存/加载
    • (5)保存后的网络模型可视化
    • (6)训练过程可视化
    • (7)显示彩色图片
      • ①灰色图片
      • ②彩色图片
    • (8)每次卷积后特征图显示
    • (9)运行过程中忽视警告

1.引用

   torchvision提供了一些常用的数据集、模型、转换函数等

import torchvision
from torchvision import transforms
import numpy as np
import matplotlib.pyplot as plt

2.内置图片数据集加载

  torch的内置图片数据集均在datasets模块下,包含Catletch、CelebA、CIFAR、Cityscapes、COCO、Fashion-MNIST、ImageNet、MNIST等。
  MNIST数据集是0-9手写数字数据集。

  train=True表示是训练数据
  torchvision.transforms包含了转换函数
  这里用到了ToTensor类,该类的主要作用有以下3点:
  ①将输入转换成张量
  ②读取图片的格式规范为(channel,heigth,width)
  ③将图片像素的取值范围归一化0-1

train_ds=torchvision.datasets.MNIST('data/',train=True,transform=transforms.ToTensor(),download=True)
test_ds=torchvision.datasets.MNIST('data/',train=False,transform=transforms.ToTensor(),download=True)

3.处理为batch类型

  DataLoader有以下4个目的:
  ①使用shuffle参数对数据集做乱序的操作(随机打乱)
  ②将数据采样为小批次,可用batch_size参数指定批次大小(小批次)
  ③可以充分利用多个子进程加速数据预处理(多线程)
  ④可通过collate_fn参数传递批次数据中的处理函数,实现对批次数据进行转换处理(转换处理)

train_dl=torch.utils.data.DataLoader(train_ds,batch_size=64,shuffle=True)
test_dl=torch.utils.data.DataLoader(test_ds,batch_size=64)

  上述两行代码创建了DataLoader类型的train_dl和test_dl
  DataLoader是可迭代对象,next方法返回一个批次的图像imgs和对应一个批次的标签labels

4.设置运行设备

  机器学习或者深度学习需要选择程序运行的设备是CPU还是GPU,GPU就是通常所说的需要有显卡。

device='cuda' if torch.cuda.is_available() else 'cpu'
print('use {} device'.format(device))

5.查看数据

imgs,labels=next(iter(train_dl))
print(imgs.shape)
print(labels.shape)
结果:
torch.Size([64, 1, 28, 28])
torch.Size([64])

6.绘图查看数据图片

  imgs[:10]查看前10条数据
  np.squeeze从数组的形状中删除维度为 1 的维度。
  np.unsqueeze从数组的形状中添加维度为 1 的维度。
  注:只有数组长度在该维度上为 1,那么该维度才可以被删除。如果不是1,那么删除的话会报错
  报错信息:cannot select an axis to squeeze out which has size not equal to one

(1)不显示图片标签

plt.figure(figsize=(10,1))
for i,img in enumerate(imgs[:10]):
    npimg=img.numpy()
    npimg=np.squeeze(npimg)#形状由(1,28,28)转换为(28,28)
    plt.subplot(1,10,i+1)
    plt.imshow(npimg)      #在子图中绘制单张图片
    plt.axis('off')        #关闭显示子图坐标    
print(labels[:10])
plt.show()

(2)打印图片标签

classes = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
class_label_str=''

img_label_list=list(zip(imgs,labels))
for i,(img,label) in enumerate(img_label_list):
    nimg=np.array(img)
    nimg=np.squeeze(nimg)
    plt.subplot(8,8,i+1)
    plt.title(str(label.item()))
    plt.imshow(nimg)
    plt.axis('off')
    '''按照图片显示格式打印所有标签:i!=0实现按行打印的同时第一行前面无空行,按每行8列打印'''
    if i!=0 and i%8==0:
        class_label_str +='\n'
    class_label_str += classes[label.item()]+'\t'
print(class_label_str)
plt.show()

(3)图片显示标签

  我这里以'airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'这些类别示例,作用于手写字体图像分类时,要更改成0-9

classes = ('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

img_label_list=list(zip(imgs,labels))
for i,(img,label) in enumerate(img_label_list):
    nimg=img.transpose(0, 2)
    nimg=nimg.numpy()
    plt.subplot(5,5,i+1)
    plt.title(classes[label.item()])
    plt.imshow(nimg)
    plt.axis('off')
plt.show()

7.定义卷积函数

  定义卷积函数才是算法模型的真正开始,卷积层一般是必不可少的,是机器学习和深度学习的灵魂与基石所在。

class net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1=nn.Conv2d(1,6,5)
        self.conv2=nn.Conv2d(6,16,5)
        self.linear1 = nn.Linear(16*4*4,20)
        self.linear2 = nn.Linear(20,10)

    def forward(self,input):
        x=torch.max_pool2d(torch.relu(self.conv1(input)),2)
        x=torch.max_pool2d(torch.relu(self.conv2(x)),2)
        x=x.view(x.size(0),-1)
        x=torch.relu(self.linear1(x))
        x=self.linear2(x)
        return x

  算法模型流程示意:

8.卷积实例化、损失函数、优化器

model=net().to(device)
loss_f=nn.CrossEntropyLoss()
opti=optim.Adam(model.parameters(), lr=0.005)

9.训练和测试损失、正确率

(1)训练

def train(dataloader,model,loss_f,opt):
    model.train()                  #模型为训练模式
    num_batches=len(dataloader)    #总批次数
    size=len(dataloader.dataset)   #样本总数(所有的批次里所有的数据点)
    loss_zhi=0                     #所有批次的损失之和
    correct=0                      #预测正确的样本总数

    for x,y in dataloader:
        x,y=x.to(device),y.to(device)
        pred=model(x)
        loss=loss_f(pred,y)        
        '''梯度清零、反向传播、梯度更新是专属'''
        opt.zero_grad()
        loss.backward()
        opt.step()

        with torch.no_grad():
        loss_zhi+=loss.item()
            correct+=(pred.argmax(1)==y).type(torch.float).sum().item()
            
    loss_zhi/=num_batches  #loss_zhi是所有批次的损失之和,所以计算全部样本的平均损失需要除以总批次数
    correct/=size          #correct是预测正确的样本总数,若计算每个批次总体正确率,需除以样本总数量
    return loss_zhi,correct

  注:当前代码里的pred.argmax(1)会返会类似Tensor([4,6,...,0])Tensor,而y也是类似形状的tensor,因此二者可以用==比较

(2)测试

def test(dataloader, model):
    model.eval()                   #模型为测试模式
    num_batches=len(dataloader)    #总批次数
    size=len(dataloader.dataset)   #样本总数(所有的批次里所有的数据点)
    loss_zhi=0                     #所有批次的损失之和
    correct=0                      #预测正确的样本总数

    for x, y in dataloader:
        x,y=x.to(device),y.to(device)
        pred = model(x)
        loss = loss_f(pred, y)

        with torch.no_grad():
        loss_zhi += loss.item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    loss_zhi /= num_batches
    correct /= size
    return loss_zhi, correct

(3)循环

epochs = 200
train_loss = []
train_acc = []
test_loss = []
test_acc = []
for epoch in range(epochs):
    epoch_train_loss,epoch_train_acc=train(train_dl,model,loss_f,opt)
    epoch_test_loss,epoch_test_acc=test(test_dl,model)

    train_loss.append(epoch_train_loss)
    train_acc.append(epoch_train_acc)
    test_loss.append(epoch_test_loss)
    test_acc.append(epoch_test_acc)

    tishi='epoch:{},train_loss:{:.4f},train_acc:{:.2f}%,test_loss:{:.4f},test_acc:{:.2f}%'
    print(tishi.format(epoch,train_loss[-1],train_acc[-1]*100,test_loss[-1],test_acc[-1]*100))
print('batch over!')

(4)损失和正确率曲线

plt.figure(figsize=(10,4))
plt.subplot(121)
#打印损失
plt.plot(range(1,epochs+1),train_loss,label='train_loss')
plt.plot(range(1,epochs+1),test_loss,label='test_loss')
plt.title('train+test:loss')
plt.xlabel('epoch')
plt.legend(loc='upper right')
plt.subplot(122)
#打印正确率
plt.plot(range(1,epochs+1),train_acc,label='train_acc')
plt.plot(range(1,epochs+1),test_acc,label='test_acc')
plt.title('train+test:acc')
plt.xlabel('epoch')
plt.legend(loc='lower right')
plt.show()
plt.savefig('D:/loss+acc.png')

(5)输出数据到表格

table={'train_loss':train_loss,
        'train_acc':train_acc,
        'test_loss':test_loss,
        'test_acc':test_acc}
data_shuju=pd.DataFrame(table,index=list(range(1,epochs+1)))
data_shuju.to_excel('D:/loss+acc.xlsx')

10.额外添加

(1)添加dropout减少过拟合

  卷积后添加Dropout层较少使用,效果也不是很明显,这是因为相邻元素之间有相关性,随机地丢弃卷积输出特征像素点,抑制过拟合的效果有限。
  Dropout的第一个参数是输入的tensor,第二个参数p代表的是丢弃的神经元的比例,默认为0.5

①未添加dropout层

class net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1=nn.Conv2d(1,6,5)
        self.conv2=nn.Conv2d(6,16,5)
        self.linear1 = nn.Linear(16*4*4,20)
        self.linear2 = nn.Linear(20,10)

    def forward(self,input):
        x=torch.max_pool2d(torch.relu(self.conv1(input)),2)
        x=torch.max_pool2d(torch.relu(self.conv2(x)),2)
        x=x.view(x.size(0),-1)
        x=torch.relu(self.linear1(x))
        x=self.linear2(x)
        return x

  dropoutloss+acc图像:

②添加dropout层

class net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1=nn.Conv2d(1,6,5)
        self.conv2=nn.Conv2d(6,16,5)
        self.linear1 = nn.Linear(16*4*4,20)
        self.linear2 = nn.Linear(20,10)

    def forward(self,input):
        x=torch.max_pool2d(torch.relu(self.conv1(input)),2)
        x=torch.max_pool2d(torch.relu(self.conv2(x)),2)
        x=x.view(x.size(0),-1)
        x=torch.dropout(x, p=0.5, train=self.training)
        x=torch.relu(self.linear1(x))
        x=torch.dropout(x, p=0.5, train=self.training)
        x=self.linear2(x)
        return x

  dropoutloss+acc图像:
在这里插入图片描述

(2)循环同时输出时间

import time

epochs=1
train_loss=[]
train_acc=[]
test_loss=[]
test_acc=[]
epoch_time=[]
start=time.time()
for epoch in range(epochs):
    epoch_train_loss,epoch_train_acc=train(train_dl,model,loss_f,opt)
    epoch_test_loss, epoch_test_acc = test(test_dl, model)

    train_loss.append(epoch_train_loss)
    train_acc.append(epoch_train_acc)
    test_loss.append(epoch_test_loss)
    test_acc.append(epoch_test_acc)
    epoch_time.append(time.time()-start)
    tishi='epoch:{},train_loss:{:.4f},train_acc:{:.2f}%,test_loss:{:.4f},test_acc:{:.2f}%,time:{:.2f}'
    print(tishi.format(epoch,train_loss[-1],train_acc[-1]*100,test_loss[-1],test_acc[-1]*100,epoch_time[-1]))
print('epoch over!')

table={'train_loss':train_loss,
        'train_acc':train_acc,
        'test_loss':test_loss,
        'test_acc':test_acc,
        'epoch_time':epoch_time}
data_shuju=pd.DataFrame(table,index=list(range(1,epochs+1)))
data_shuju.to_excel('loss+acc.xlsx')
print('save over!')

(3)每个类别分类正确率输出

①输出到控制台

  注:需要在网络循环loss+acc之后使用,若是提前使用正确率只有个位数

class_correct = list(0 for i in range(10))  #每个类别预测正确的数量
class_total   = list(0 for i in range(10))  #每个类别的总数量
with torch.no_grad():
    # 从测试数据中取出数据
    for x, y in test_dl: 
        x, y= x.to(device), y.to(device)
        outputs = model(x)
        _, predicted = torch.max(outputs, 1)
        # 预测正确的返回True,预测错误的返回False;squeeze将数据转换为一维数据
        c = (predicted == y).squeeze()
        for i in range(10):
            label = y[i]  # 提取标签
            class_correct[label] += c[i].item()  # 预测正确个数
            class_total[label] += 1  # 总数
for i in range(10):
    print('{}的准确率:{:.2f}%'.format(classes[i], 100 * class_correct[i] / class_total[i]))
结果:
0的准确率:98.03%
1的准确率:100.00%
2的准确率:100.00%
3的准确率:98.08%
4的准确率:97.74%
5的准确率:97.62%
6的准确率:98.44%
7的准确率:99.39%
8的准确率:98.60%
9的准确率:97.60%

②输出到表格

class_test_dic={}
for i in range(10):
    print('{:.10s}的准确率:{:.2f}%'.format(classes[i], 100 * class_correct[i] / class_total[i]))
    class_test_dic['{:.12s}'.format(classes[i])]=[100 * class_correct[i] / class_total[i],'{:.2f}%'.format(100 * class_correct[i] / class_total[i])]
class_dic = pd.DataFrame(class_test_dic,index=list(range(2)))
class_dic.to_excel('model5s_class_test_dic.xlsx')
print('save over!')

(4)模型保存/加载

torch.save(model,"K:\\classifier3.pt")    #保存完整模型
load_model = torch.load("K:\\classifier3.pt")

  测试图片:

path='./MNIST_data.pth'
test_model = net()
test_model.load_state_dict(torch.load(path))

test_image = Image.open(file)  # 加载要测试的图片

test_transform = torchvision.transforms.Compose([
    torchvision.transforms.Resize((28, 28)),
    torchvision.transforms.Grayscale(),  # 训练的是灰色图片需要加上,不然通道数不对
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize((0.1307,), (0.3081,))
])

test_image = test_transform(test_image)
test_image = test_image.unsqueeze(0)  # 添加批次维度

output = test_model(test_image)  # 输入图片到模型中进行推理
_, predicted = torch.max(output, 1)  # 获取预测结果
self.label_result.setText(str(predicted.item()))

(5)保存后的网络模型可视化

  浏览器输入链接:netron

  点击按钮,打开保存的.pt文件,就可以显示网络机构
  例:

(6)训练过程可视化

def visualize(train_loss,val_loss,val_acc):
    train_loss = np.array(train_loss)
    val_loss = np.array(val_loss)
    val_acc = np.array(val_acc)
    plt.grid(True)
    plt.xlabel("epoch")
    plt.ylabel("value")
    plt.title("train_loss and valid_acc")
    plt.plot(np.arange(len(val_acc)),val_acc, label=r"valid_acc",c="g")
    plt.plot(np.arange(len(train_loss)),train_loss,label=r"train_loss",c="r")
    plt.legend()
    plt.savefig("K:\\a.png")
    
visualize(train_loss_list,valid_loss_list,valid_accuracy_list)

(7)显示彩色图片

  问题1:TypeError: Invalid shape (3, 224, 224) for image data

①灰色图片

img_label_list=list(zip(img,label))
for i,(img,label) in enumerate(img_label_list):
    nimg=np.array(img)
    nimg=np.squeeze(nimg)
    plt.subplot(8,8,i+1)
    plt.title(str(label.item()))
    plt.imshow(nimg)
    plt.axis('off')
plt.show()

②彩色图片

img_label_list=list(zip(img,label))
for i,(img,label) in enumerate(img_label_list):
    nimg=img.transpose(0, 2)  彩色图像是3*n*n需要先将3移到最后!
    nimg=nimg.numpy()
    plt.subplot(5,5,i+1)
    plt.title(str(label.item()))
    plt.imshow(nimg)
    plt.axis('off')
plt.show()

  问题2:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
  matplotlib.pyplot.imshow()函数在处理灰度图像时,自动将其值做归一化处理而在处理彩色图像时则不会,而是将浮点值变换至[0,1],整数值变换到[0, 255]范围

(8)每次卷积后特征图显示

  需要先修改transform

transform=transforms.Compose([
                              transforms.ToTensor(),   #转换成张量
                              transforms.Normalize(mean=[0.485,0.456,0.406],
                                                   std=[0.229,0.224,0.225])
                            ])
#保存数据集一张图像
imgs,labels=next(iter(train_dl))
img_label_list=list(zip(imgs,labels))
for i,(img,label) in enumerate(img_label_list):
    nimg=img.transpose(0, 2)
    nimg=nimg.numpy()
    plt.imshow(nimg)
    plt.axis('off')
    plt.savefig('1.png')
    if i==0:
        break

# 传入图片
from PIL import Image

image=Image.open(str(r'1.png')).convert('RGB')
image=transform(image)
print('\n输入图尺寸:{}'.format(image.shape))

image=image.unsqueeze(0)
image=image.to(device)

# 计算卷积个数
model_weights=[] #卷积层参数
conv_layers=[]   #卷积层本身
model_children=list(model.children())
counter=0        #卷积层个数
for i in range(len(model_children)):
    if type(model_children[i])==nn.Conv2d:
        counter+=1
        model_weights.append(model_children[i].weight)
        conv_layers.append(model_children[i])
    elif type(model_children[i])==nn.Sequential:
        for j in range(len(model_children[i])):
            for child in model_children[i][j].children():
                if type(child)==nn.Conv2d:
                    counter+=1
                    model_weights.append(child.weight)
                    conv_layer.append(child)
                    
outputs=[]
names=[]
for layer in conv_layers[0:]:
    image=layer(image)
    outputs.append(image)
    names.append(str(layer))
print('特征图尺寸:{}'.format(outputs[1].shape))

#具体绘制特征图
processed=[]
for feature_map in outputs:
    feature_map=feature_map.squeeze(0)
    gray_scale=torch.sum(feature_map,0)
    gray_scale=gray_scale/feature_map.shape[0]
    processed.append(gray_scale.data.cpu().numpy())
fig=plt.figure()

for i in range(len(processed)):
    a=fig.add_subplot(5,4,i+1)
    imgplot=plt.imshow(processed[i])
    a.axis('off')
    a.set_title(names[i].split('(')[0],fontsize=10)
plt.savefig('feature_map.png',bbox_inches='tight')
print('over!')

(9)运行过程中忽视警告

import warnings
warnings.filterwarnings("ignore")

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spark_累加器

分布式共享只写变量 实现原理:  累加器用来把Executor端变量信息聚合到Driver端,在Driver程序中定义的变量,在Executor端的每个Task都会得到这个变量的一份新的副本,每个task更新这些副本的值后,传回Driver端进行mer…

执行node.js获取本机Ip命令,报:Error: Cannot find module ‘ip‘错误

Error: Cannot find module ip是由于没有改模块的依赖包,需要进行安装,以管理员的身份打开命令行,执行npm install ip 获取当前电脑的ip地址 方法一: const ip require("ip")/*** 1:获取当前电脑的ip地址*/ console.…

PPT技巧:保护PPT文件的方法有哪些?

PPT文件制作好之后保证文件不出错应该是很重要的,毕竟是要拿出去展示的,今天分享PPT加密方法给大家。希望能够帮助大家保护好自己的PPT文件。 打开密码 如果想要其他人需要输入正确的密码才能够打开文件查看并编辑,我们可以给PPT文件设置打…

Github优质项目推荐 - 第六期

文章目录 Github优质项目推荐 - 第六期一、【WiFiAnalyzer】,3.4k stars - WiFi 网络分析工具二、【penpot】,33k stars - UI 设计与原型制作平台三、【Inpaint-Anything】,6.4k stars - 修复图像、视频和3D 场景中的任何内容四、【Malware-P…

gitee开源商城diygw-mall

DIYGW可视化开源商城系统。所的界面布局显示都通过低代码可视化开发工具生成源码实现。支持集成微信小程序支付。 DIYGW可视化开源商城系统是一款基于thinkphp8 framework、 element plus admin、uniapp开发而成的前后端分离系统。 开源商城项目源码地址:diygw商城…

stm32定时器中断和外部中断

一,中断系统的介绍 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行 中…

知识图谱入门——7:阶段案例:使用 Protégé、Jupyter Notebook 中的 spaCy 和 Neo4j Desktop 搭建知识图谱

在 Windows 环境中结合使用 Protg、Jupyter Notebook 中的 spaCy 和 Neo4j Desktop,可以高效地实现从自然语言处理(NLP)到知识图谱构建的全过程。本案例将详细论述环境配置、步骤实现以及一些扩展和不足之处。 源文件已上传我的资源区。 文章…

【深海王国】初中生也能画的电路板?目录合集

Hi٩(๑ ^ o ^ ๑)۶, 各位深海王国的同志们,早上下午晚上凌晨好呀~辛勤工作的你今天也辛苦啦 (o゜▽゜)o☆ 今天大都督为大家带来系列文章《初中生也能画的电路板》,帮你一周内快速入门PCB设计,手把手教你从元器件库添加、电路原理图绘制、…

初阶C语言-结构体

一.结构体的声明 1.结构体类型的声明 1.1结构的基础知识 结构是一些值的集合,这些值称为称为变量。结构的每个成员可以是不同类型的变量。 1.2结构的声明 struct tag //struct是结构体关键字,tag是结构体类型名称 { member - list;//成员变…

minio集群部署

最近接触到minio, 将本地集群部署,分别在ubuntu、centos stream9上进行了搭建,目前看里面的小坑不小,记录以下教程,以备忘、以供他人借鉴。 #### 准备 1、因新版本的minio要求,集群部署必须使用挂载非 roo…

AAA Mysql与redis的主从复制原理

一 :Mysql主从复制 重要的两个日志文件:bin log 和 relay log bin log:二进制日志(binnary log)以事件形式记录了对MySQL数据库执行更改的所有操作。 relay log:用来保存从节点I/O线程接受的bin log日志…

Java中System类和RunTime类的Api

目录 System 类 1)out 2)err 3)in 4)currentTimeMillis() 5)nanoTime() 6)arraycopy(Object 要从里面复制东西的数组, int 要从里面复制东西数组的索引起始位置, Object 获得复制元素的数组, int 获得复制元素数组的起始索引, int 要复制东西的个数) 7)gc() 8)exit(int status)…

51单片机的无线通信智能车库门【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块红外传感器光照传感器时钟模块步进电机蓝牙按键、LED、蜂鸣器等模块构成。适用于智能车库自动门、无线控制车库门等相似项目。 可实现功能: 1、LCD1602实时显示北京时间和自动/手动模式,以及验证是否成…

【Arduino IDE安装】Arduino IDE的简介和安装详情

目录 🌞1. Arduino IDE概述 🌞2. Arduino IDE安装详情 🌍2.1 获取安装包 🌍2.2 安装详情 🌍2.3 配置中文 🌍2.4 其他配置 🌞1. Arduino IDE概述 Arduino IDE(Integrated Deve…

使用 Go 和 Gin 框架构建简单的用户和物品管理 Web 服务

使用 Go 和 Gin 框架构建简单的用户和物品管理 Web 服务 在本项目中,我们使用 Go 语言和 Gin 框架构建了一个简单的 Web 服务,能够管理用户和物品的信息。该服务实现了两个主要接口:根据用户 ID 获取用户名称,以及根据物品 ID 获…

模拟实现消息队列(基于SpringBoot实现)

项目代码 提要:此处的消息队列是仿照RabbitMQ实现(参数之类的),实现一些基本的操作:创建/销毁交互机(exchangeDeclare,exchangeDelete),队列(queueDeclare&a…

【电路笔记】-求和运算放大器

求和运算放大器 文章目录 求和运算放大器1、概述2、反相求和放大器3、同相求和放大器4、减法放大器5、应用5.1 音频混合器5.2 数模转换器 (DAC)6、总结1、概述 在我们之前有关运算放大器的大部分文章中,仅将一个输入应用于反相或非反相运算放大器的输入。在本文中,将讨论一种…

Python:条件分支 if 语句全讲解

Python:条件分支 if 语句全讲解 如果我拿出下面的代码,阁下该做何应对? if not reset_excuted and (terminated or truncated):... else:...---- 前言: 消化论文代码的时候看到这个东西直接大脑冻结,没想过会在这么…

5个免费ppt模板网站推荐!轻松搞定职场ppt制作!

每次过完小长假,可以明显地感觉到,2024这一年很快又要结束了,不知此刻的你有何感想呢?是满载而归,还是准备着手制作年终总结ppt或年度汇报ppt呢? 每当说到制作ppt,很多人的第一反应&#xff0c…

ElasticSearch备考 -- Multi match

一、题目 索引task有3个字段a、b、c,写一个查询去匹配这三个字段为mom,其中b的字段评分比a、c字段大一倍,将他们的分数相加作为最后的总分数 二、思考 通过题目要求对多个字段进行匹配查询,可以考虑multi match、bool query操作。…