猫狗分类图像识别

news2024/11/19 19:41:30

根据深度学习的基本框架,我们要做以下工作:

1,构建神经网络。
2,预处理数据。
3,用训练集训练权重。
4,用测试集进行测试。

首先我们从创建神经网络开始:

先上代码:

import torch
from torch import nn
import torch.nn.functional as F
class MyAlexNet(nn.Module):
    def __init__(self):
        super(MyAlexNet, self).__init__()
        self.c1=nn.Conv2d(in_channels=3,out_channels=48,kernel_size=11,stride=4,padding=2)
        self.ReLU=nn.ReLU()
        self.c2=nn.Conv2d(in_channels=48,out_channels=128,kernel_size=5,stride=1,padding=2)
        self.s2=nn.MaxPool2d(2)
        self.c3=nn.Conv2d(in_channels=128,out_channels=192,kernel_size=3,stride=1,padding=1)
        self.s3=nn.MaxPool2d(2)
        self.c4=nn.Conv2d(in_channels=192,out_channels=192,kernel_size=3,stride=1,padding=1)
        self.c5=nn.Conv2d(in_channels=192,out_channels=128,kernel_size=3,stride=1,padding=1)
        self.s5=nn.MaxPool2d(kernel_size=3,stride=2)
        self.flatten=nn.Flatten()
        self.f6=nn.Linear(128*6*6,2048)
        self.f7=nn.Linear(2048,2048)
        self.f8=nn.Linear(2048,1000)
        self.f9=nn.Linear(1000,2)
    def forward(self,x):
        x=self.ReLU(self.c1(x))
        x=self.ReLU(self.c2(x))
        x=self.s2(x)
        x=self.ReLU(self.c3(x))
        x=self.s3(x)
        x=self.ReLU(self.c4(x))
        x=self.ReLU(self.c5(x))
        x=self.s5(x)
        x=self.flatten(x)
        x=self.f6(x)
        x=F.dropout(x,p=0.5)
        x=self.f7(x)
        x=F.dropout(x,p=0.5)
        x=self.f8(x)
        x=F.dropout(x,p=0.5)
        x=self.f9(x)
        return x
if __name__ == '__main__':
    x=torch.rand([1,3,224,224])
    model=MyAlexNet()
    y=model(x)





当然,经典神经网络的创建离不开torch.nn.Module,其中包含一系列函数,我们经常用到的是
卷积函数(torch.nn.Conv2d),我们可以在参数列表选择输入和输出的通道,卷积核大小,以及进行广播,选择跨度(padding stride)。
激活函数,包括(ReLU函数,tanh函数,sigmoid函数等),对我们输入的张量进行非线性处理。
池化函数,包括最大池化,最小池化,平均池化,注意池化层是没有参数的,只是对权重的选择(或进行均值处理)。参数表示池化窗口的大小。
平展函数,flatten,我们构建神经网络的时候,经常要将卷积处理之后的张量放入全链接层,为了保持维度的一致性,我们要对张量进行平展处理。将卷积处理得到的张量包含的所有权重进行平展。
全连接层:linear,对向量(一维)进行线性处理,可以按照我们的意愿得到我们希望的维度,但是需要较多的权重,一个比较好的解决办法是在卷积层的时候,将张量权重元素的输出尽量控制到一个较小的范围,但是会影响提取能力。

下面来看我们的层:

self.c1=nn.Conv2d(in_channels=3,out_channels=48,kernel_size=11,stride=4,padding=2)
        self.ReLU=nn.ReLU()
        self.c2=nn.Conv2d(in_channels=48,out_channels=128,kernel_size=5,stride=1,padding=2)
        self.s2=nn.MaxPool2d(2)
        self.c3=nn.Conv2d(in_channels=128,out_channels=192,kernel_size=3,stride=1,padding=1)
        self.s3=nn.MaxPool2d(2)
        self.c4=nn.Conv2d(in_channels=192,out_channels=192,kernel_size=3,stride=1,padding=1)
        self.c5=nn.Conv2d(in_channels=192,out_channels=128,kernel_size=3,stride=1,padding=1)
        self.s5=nn.MaxPool2d(kernel_size=3,stride=2)
        self.flatten=nn.Flatten()
        self.f6=nn.Linear(128*6*6,2048)
        self.f7=nn.Linear(2048,2048)
        self.f8=nn.Linear(2048,1000)
        self.f9=nn.Linear(1000,2)

我们选取神经网络层是根据相关论文。是实验表明较好的选择。

构建神经网络:

    def forward(self,x):
        x=self.ReLU(self.c1(x))
        x=self.ReLU(self.c2(x))
        x=self.s2(x)
        x=self.ReLU(self.c3(x))
        x=self.s3(x)
        x=self.ReLU(self.c4(x))
        x=self.ReLU(self.c5(x))
        x=self.s5(x)
        x=self.flatten(x)
        x=self.f6(x)
        x=F.dropout(x,p=0.5)
        x=self.f7(x)
        x=F.dropout(x,p=0.5)
        x=self.f8(x)
        x=F.dropout(x,p=0.5)
        x=self.f9(x)
        return x

可见每经过一个卷积层,都要进行非线性处理,也就是带入激活函数中,当然,池化层不算做卷积层(很多同学因为池化层经常配合卷积层使用,错认为池化层也是卷积层)。

当我们卷积层处理完之后(最后一个池化后),将得到的张量带入flatten函数,进行平展处理。

处理之后送入全连接层,进行线性层的处理。

但是值得注意的是,在每一个全连接层处理之后,我们将得到的结果带入F.dropout函数,目的在于放弃其中部分的连接网络,因为太多的连接网络易造成过拟合。随机消失一部分有利于保留输入和标签之间的线性关系。

经过多个全连接层+网络消失的处理之后,我们得到的x就作为我们的输出。

下面我们进行验证。我们输出结果看一下:

这里我们得到是一个张量,[[0.0139,0.0212]]。我们如果需要得到其中的数据。需要用y[0][0].item()
这里用到的是两个括号。

下一步我们进行数据的预处理:

先上代码:

import os
from shutil import copy
import random
def mkdir(file):
    if not os.path.exists(file):
        os.makedirs(file)
#获取data文件夹下所有文件夹名(即需要分类的类名)
file_path='E:/BaiduNetdiskDownload/Kaggle猫狗大战/train'
flower_class= [cla for cla in os.listdir(file_path)]
#创建训练集train文件夹,并由类名在其目录下创建子目录
mkdir('data/train')
mkdir('data/train/cat')
mkdir('data/train/dog')
mkdir('data/val')
mkdir('data/val/cat')
mkdir('data/val/dog')
split_rate=0.1
for cla in flower_class:
    cla_path=file_path+'/'+cla
    #"E:\BaiduNetdiskDownload\Kaggle猫狗大战\train\train\cat.0.jpg"
    images=os.listdir(cla_path)
    print(cla_path)
    num=len(images)
    eval_index=random.sample(images,k=int(num*split_rate))

    for index,image in enumerate(images):
        if image in eval_index:
            image_path = cla_path+'/'+image
            if "cat" in image_path:
                new_path = 'data/val/cat/'
            else:
                new_path = 'data/val/dog/'
            copy(image_path,new_path)

        else:
            image_path=cla_path+'/'+image
            if "cat" in image_path:
                new_path='data/train/cat/'
            else:
                new_path='data/train/dog/'
            copy(image_path,new_path)
        print("\r[{}]processing[{}/{}]".format(cla,index+1,num),end="")
    print()
print("processing done!")





首先我们要导入进行文件处理的库os。

导入进行图像文件复制的函数:from shutil import copy。

我们创建mkdir函数用来生成不存在的文件夹。

然后我们定义了我们的资源图片路径,也就是file_path。但是我们在copy的过程中,得到不同级目录之间是\符号,我们要主动进行处理,将其改为/符号。

之后对我们的资源文件进行遍历,找到其下一级目录。

这个函数指的是得到由我们的file_path文件夹下文件组成的列表。

split_rate是进行数据集划分,表示测试集占的比例。

得到file_path文件夹下级目录,我们得到的images是由该目录下图像文件的文件名组成的列表。也就是我们希望得到的图片路径。

这段代码使用random.sample函数从images列表中随机选择num*split_rate个元素,并将这些元素存储在名为eval_index的列表中,这通常用于划分数据集,例如将图片按照一定的比例分为数据集和训练集。

得到我们需要的图片在数据集中的路径,然后将图片内容复制到我们创建的文件夹下。

创建好数据集后,我们要对数据集进行训练:

import torch
from torch import nn
from net import MyAlexNet
import numpy as np
from torch.optim import lr_scheduler
import os
from torchvision import transforms
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False
ROOT_TRAIN = 'C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/train'
ROOT_TEST='C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/val'
normalize=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
train_transform=transforms.Compose([
    transforms.Resize((224,224)),
    transforms.RandomVerticalFlip(),
    transforms.ToTensor(),
    normalize
])
val_transform=transforms.Compose([
    transforms.Resize((224,224)),
    transforms.ToTensor(),
    normalize
])
#ImageFolder函数会根据文件夹的名称为每张图片分配一个类别标签,在这个训练集中,类别标签分别为0(表示cat)1(表示dog)
train_dataset=ImageFolder(ROOT_TRAIN,transform=train_transform)
val_dataset=ImageFolder(ROOT_TEST,transform=val_transform)
train_dataloader=DataLoader(train_dataset,batch_size=32,shuffle=True)
val_dataloader=DataLoader(val_dataset,batch_size=32,shuffle=True)
model=MyAlexNet()
loss_fn=nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(model.parameters(),lr=0.01,momentum=0.9)
lr_scheduler=lr_scheduler.StepLR(optimizer,step_size=10,gamma=0.5)
def train(dataloader,model,loss_fn,optimizer):
    loss,current,n =0.0,0.0,0.0
    for batch,(x,y) in enumerate(dataloader):


        image,y =x,y
        output=model(image)
        cur_loss=loss_fn(output,y)
        _,pred=torch.max(output,axis=1)
        cur_acc=torch.sum(y==pred)/output.shape[0]
        optimizer.zero_grad()
        cur_loss.backward()
        optimizer.step()
        loss+=cur_loss.item()
        current+=cur_acc.item()
        n+=1
    train_loss=loss/n
    train_acc=current/n
    print('train_loss'+str(train_loss))
    print('train_acc'+str(train_acc))
    return train_loss,train_acc
def val(dataloader,model,loss_fn):
    model.eval()
    loss,current,n=0.0,0.0,0.0
    with torch.no_grad():
        for batch,(x,y) in enumerate(dataloader):
            image,y =x,y
            output=model(image)
            cur_loss=loss_fn(output,y)
            _,pred=torch.max(output,axis=1)
            cur_acc=torch.sum(y==pred)/output.shape[0]
            loss+=cur_loss.item()
            current+=cur_acc.item()
            n+=1
    val_loss=loss/n
    val_acc=current/n
    print('val_loss'+str(val_loss))
    print('val_acc'+str(val_acc))
    return val_loss,val_acc
def matplot_loss(train_loss,val_loss):
    plt.plot(train_loss,label='train_loss')
    plt.plot(val_loss,label='val_loss')
    plt.legend(loc='best')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.title("训练集和验证集loss值对比图")
    plt.show()
def matplot_acc(train_loss,val_loss):
    plt.plot(train_acc,label='train_acc')
    plt.plot(val_acc,label='val_acc')
    plt.legend(loc='best')
    plt.ylabel('acc')
    plt.xlabel('epoch')
    plt.title("训练集和验证集acc值对比图")
    plt.show()
loss_train=[]
acc_train=[]
loss_val=[]
acc_val=[]
epoch=20
min_acc=0
for t in range(epoch):
    lr_scheduler.step()
    print(f"epoch{t+1}\n----------------")
    train_loss,train_acc=train(train_dataloader,model,loss_fn,optimizer)
    val_loss,val_acc=val(val_dataloader,model,loss_fn)
    loss_train.append(train_loss)
    acc_train.append(train_acc)
    loss_val.append(val_loss)
    acc_val.append(val_acc)
    if val_acc>min_acc:
        folder='save_model'
        if not os.path.exists(folder):
            os.mkdir('save_model')
        min_acc=val_acc
        print(f"save best model,第{t+1}轮")
        torch.save(model.state_dict(),'save_model/best.model.pth')
    if t==epoch-1:
        torch.save(model.state_dict(),'save_model/last_model.pth')
print('Done')





这段代码较长,其中一个细节处理事,进行绘图中文输出:

我们使用:

plt.rcParams['font.sans-serif']=['SimHei']
plt.rdParams;'axes.unicode_minus']=False
表示进行中文绘制图表输出。

transforms.Compose函数是对数据预处理的操作序列,transforms.Compose函数的作用是将多个对数据处理的操作转化为一个整体的数据转化流水线,可以将多个数据处理步骤按顺序串联起来,方便对数据进行一系列的处理操作。具体处理事将图像大小缩放为224*224,将训练集进行随机垂直翻转(用于增强数据的多样性,有助于提高模型的泛化能力,防止过拟合)。之后将图像转化为张量,再对得到的张量进行归一化处理。

这一段函数是从我们的设定路径中加载我们的图像,并对其进行数据操作(我们在上面已经定义过)。ImageFolder函数会根据文件夹的名称为每一张图片分配一个类别标签,在这个训练集中,我们一共生成两个类别标签。(分别是0和1,对应cat和dog)。我们得到的是一个二维张量。

创建一个用于加载数据集的数据加载器,batch_size表示每个批次的样本数量。shuffle表示每个epoch开始时是否对数据进行随机重排序,数据加载器可以帮助有效的加载数据并组织成批次,以便于模型训练与验证。

表示计算的损失是交叉熵损失。

SGD是随机梯度下降算法的优化器,是深度学习中最常用的优化器之一,通过不断的迭代更新模型的权重使损失函数逐渐收敛到最小值,从而提高模型的准确性,第一个参数表示优化的是整个模型中所有的权重,第二个参数表示优化率是0.01,第三个参数表示动量,是随机梯度下降算法实现的一个必要因素,模拟物理模型中的动量,动量小比较容易根据之前优化路线进行前进,受到先验优化影响较大,比较易于我们跳出鞍点,动量大易于我们在最优解附近进行精致的收敛,当然二者的优势也是另一方的劣势,所以我们需要尽量在优势和劣势之间平衡,取值范围是0到1。

lr——scheduler是用于动态调整学习率的工具,在训练神经网络中非常有用,可以帮助模型收敛并获得更好的性能,称之为学习率调度器。常见的学习率调度策略包括学习率衰减,学习率周期性变化等,我们使用的StepLR是指学习率衰减,step_size指的是按照给定的步骤进行衰减,也就是每隔十轮进行衰减一次,衰减因子是gamma,表示每次调整使得学习率*gamma。

接下来我们进行一轮训练:批次是我们选择用于训练的样本数量。

_,pred=torch.max(output,axis=1):torch.max函数返回的是参数列表的最大值及其对应的索引。axis表示按照第一个维度进行搜索。

而后进行经典的梯度归零,反向传播,优化。

这里还是要强调一下batch_size的内涵,batch_size表示在训练过程中每个批次中包含的样本数量。在神经网络的训练过程中,通常将大量的数据按若干个批次进行训练。每个批次中包含的样本数量就是batch_size。

那么这段代码中批次的数量就是len(dataloader)/batch_size。

指的是将模型中所有权重的参数保存到给定的.pth文件中。

下面进行我们的最后一个部分:

进行测试,先上代码:

import torch
from net import MyAlexNet
from torch.autograd import variable
from torchvision import datasets,transforms
from torchvision.transforms import ToPILImage
from torchvision.datasets import ImageFolder
from torchvision.transforms import ToTensor
from torch.utils.data import DataLoader
ROOT_TRAIN = 'C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/train'
ROOT_TEST='C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/data/val'
normalize=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
train_transform=transforms.Compose([
    transforms.Resize((224,224)),
    transforms.RandomVerticalFlip(),
    transforms.ToTensor(),
    normalize
])
val_transform=transforms.Compose([
    transforms.Resize((224,224)),
    transforms.ToTensor(),
    normalize
])
train_dataset=ImageFolder(ROOT_TRAIN,transform=train_transform)
val_dataset=ImageFolder(ROOT_TEST,transform=val_transform)
train_dataloader=DataLoader(train_dataset,batch_size=32,shuffle=True)
val_dataloader=DataLoader(val_dataset,batch_size=32,shuffle=True)
model=MyAlexNet()
model.load_state_dict(torch.load("C:/Users/86156/PycharmProjects/pythonProject1/cat-dog/save_model/best.model.pth"))
classes=[
    "cat",
    "dog",
]
show=ToPILImage()
model.eval()
for i in range(50):
    x,y = val_dataset[i][0],val_dataset[i][1]
    show(x).show()
    x=torch.tensor(torch.unsqueeze(x,dim=0).float(),requires_grad=True)
    x=torch.tensor(x)
    with torch.no_grad():
        pred=model(x)
        print(pred)
        predicted,actual=classes[torch.argmax(pred[0])],classes[y]
        print(f'predicted:"{predicted}",Actual:"{actual}"')







我们如何载入数据和对数据进行处理方法同训练过程。

但是不同的是,我们直接加载训练过的权重。

也就是我们之前保存的pth文件。

我们使用ToPILImage函数用于将我们经过处理得到的张量转化为图像形式。

我们的val_dataset张量的0维度是一个3的通道的图片张量,1维是标签,是在ImageFolder中生成的分类。

然后我们在处理的时候将图像张量使用unsqueeze函数扩充一个0维度。再转化为浮点型张量,之所以转化为浮点型是因为有很多关于张量处理的操作(如梯度自动求导)只在浮点型张量的情况下才能实现。

with no grad表示的是不进行张量的计算。

但是有一个问题是我们在输出图片的时候,输出的是明显被处理过的图片,我们想要输出原图的话,只需要把val_transform=transforms.Compose中的参数normalize函数去掉就行了。(这个函数对图像进行归一化处理,很显然,我们的图像之所以输出不正常是归一化处理造成的。因为ImageToTensor函数和ToTensor函数互为逆函数)。

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

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

相关文章

第五十回 插翅虎枷打白秀英 美髯公误失小衙内-mayfly-go:web 版 linux、数据库等管理平台

晁盖宋江和吴用到山下迎接雷横上山,宋江邀请雷横入伙,雷横以母亲年事已高为由拒绝了。 雷横回到郓城,听李小二说从东京新来了个表演的叫白秀英,吹拉弹唱跳,样样精通,于是雷横和李小二一起到戏院去看演出。…

【鸿蒙 HarmonyOS 4.0】多设备响应式布局

一、背景 在渲染页面时,需要根据不同屏幕大小渲染出不同的效果,动态的判断设备屏幕大小,便需要采用多设备响应式布局。这种设计方法能够动态适配各种屏幕大小,确保网站在不同设备上都能呈现出最佳的效果。 二、媒体查询&#xf…

js形参传递特殊字符

在前端我们给其他页面传值或者传数据到后台的时候,字符串经常将一些特殊符号识别成字符集。这种情况下会将数据打断或者打乱,比如字符串里面包含*/&这些符号的时候就会错误。 我们可以通过将字符中的特殊字符替换成十六进制的字符,一些特…

单例服务拆分为分布式架构

将独立业务服务拆分为分布式 为啥会有这个想法?因为我要造锤子,拿着造好的锤子,去找锤子,没有造锤子的经验无法找一个造锤子的坑。 现有情况说明 单机软件:就是将软件安装在自己的电脑上,自己用的那种&…

一本书讲透ChatGPT,实现从理论到实践的跨越!大模型技术工程师必读!

一本书讲透ChatGPT,实现从理论到实践的跨越!大模型技术工程师必读 个人简介前言内容简介作者简介专家推荐读者对象购买链接直播预告参与方式 个人简介 🏘️🏘️个人主页:以山河作礼。 🎖️🎖️:…

Cisco Secure ACS 5.8.0.32 安装 + Crack 教程

Cisco Secure ACS 5.8.0.32 安装 Crack 教程 前言系统环境开始安装 开始破解导入授权文件 前言 在ESXi 6.7 上经历过无数次的安装尝试 测试了各种兼容版本都没有安装成功,记最后一次安装成功的过程. 系统环境 服务器 : Dell R720xd CPU : E5-2620 v2 系统 : ESXi 6.7…

SQL技巧笔记(一):连续3人的连号问题—— LeetCode601.体育馆的人流量

SQL 技巧笔记 前言:我发现大数据招聘岗位上的应聘流程都是需要先进行笔试,其中占比很大的部分是SQL题目,经过一段时间的学习之后,今天开了一个力扣年会员,我觉得我很有必要去多练习笔试题目,这些题目是有技…

C语言面试笔试||rtthread面试笔试全家桶

目录 1.rtthread内核框架与线程调度介绍 2.rtthread内核功能启动流程及汇编阶段 3.rtthread内存分布 4.内核对象管理系统 5.内核配置和剪裁 6.线程5种状态 7.进程与线程 8.CPU的内部结构 9.中断的优缺点 10.GPIO的输入输出模式 11.tcp为什么需要3次握手?…

基于粒子群优化算法的图象聚类识别matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于粒子群优化算法的图象聚类识别。通过PSO优化方法,将数字图片的特征进行聚类,从而识别出数字0~9. 2.测试软件版本以及运行结果展示 M…

It is also possible that a host key has just been changed

问题:ssh失败,提示如上图 分析: ssh的key存在上图里的路径里。 解决:win10删这个文件C:\Users\admin\.ssh\known_hosts , linux删这个文件.ssh\known_hosts ,或者删除这个文件里的制定ip的那一行,例如“106.1.1.22 ecdsa-sha2-…

SpringCloud-用nacos做服务注册与调用

步骤1:下载和安装Nacos 首先,你需要从Nacos的官方网站上下载并安装Nacos Server。根据你的操作系统选择合适的版本,并按照官方文档中的说明进行安装和配置。 步骤2:创建Spring Boot项目 在你喜欢的IDE中创建一个新的Spring Boot项…

VIMA:多模态提示的通用机器人操纵

机器人任务的表述有三种形式,分别是模仿one-shot演示、跟随语言指令、以及实现视觉目标。然而,这三种方式处理的任务不同,且模型也不同。基于提示的学习在自然语言处理领域展现了通用能力,单个模型可以处理各种各样的任务。VIMA是…

2024高频前端面试题 Vue2 和 Vue3 篇

* Vue2 和 Vue3的区别: 1)双向数据绑定原理的区别 2)根节点的不同 Vue2只能一个根节点 Vue3在组件中可以放置多个根节点 3)Vue3中采用composition API vue2:采用的选项型API(opsition API) vue3:采用的组合型API(composition A…

2024第二次培训:win11系统下使用nginx、JDK、mysql搭建基于vue2、java前后端分离的web应用运行环境

一.背景 公司安排了带徒弟的任务,给培训写点材料。前面分开介绍了mysql、jdk、nginx的安装,都只是零星的介绍,只能算零散的学习。学习了有什么用呢?能解决什么问题?能完成什么工作? 今天我们要用之前的几篇…

蓝桥杯(3.5)

789. 数的范围 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int q sc.nextInt();int[] res new int[n];for(int i0;i<n;i)res[i] sc.nextInt();while(q-- ! 0) {int…

鱼哥赠书活动第⑩期:一本书讲透ChatGPT,实现从理论到实践的跨越!大模型技术工程师必读

鱼哥赠书活动第⑩期&#xff1a; 内容简介&#xff1a;作者简介&#xff1a;读者对象&#xff1a;直播预告&#xff1a;购书链接&#xff1a;赠书抽奖规则:往期赠书福利&#xff1a; OpenAI 在 2022 年 11 月推出了人工智能聊天应用—ChatGPT。它具有广泛的应用场景&#xff0c…

#QT(串口助手-实现)

1.IDE&#xff1a;QTCreator 2.实验 3.记录 &#xff08;1&#xff09;在widget.h中加入必要文件&#xff0c;并且定义一个类指针 &#xff08;2&#xff09;如果有类的成员不知道怎么写&#xff0c;可以通过以下途径搜索 &#xff08;2&#xff09;设置串口数据 void Widget…

【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(一)-向量扩展编程模型

1. 引言 以下是《riscv-v-spec-1.0.pdf》文档的关键内容&#xff1a; 这是一份关于向量扩展的详细技术文档&#xff0c;内容覆盖了向量指令集的多个关键方面&#xff0c;如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量…

CAN总线位时序的介绍

CAN控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平和隐性电平&#xff0c;二者必居其一。发送方通过使总线电平发生变化&#xff0c;将消息发送给接收方。 显性电平对应逻辑 0&#xff0c;CAN_H 和 CAN_L 之差为 2.5V 左右。而隐性电平对应逻辑 1&#xff0c…

【Datawhale组队学习:Sora原理与技术实战】AIGC技术基础知识

AIGC是什么 AIGC全称叫做AI generated content&#xff0c;AlGC (Al-Generated Content&#xff0c;人工智能生产内容)&#xff0c;是利用AlI自动生产内容的生产方式。 在传统的内容创作领域中&#xff0c;PGC&#xff08;Professionally-generated Content&#xff0c;专业生…