Pytorch深度学习之神经网络入门详解

news2024/12/24 8:54:26

目录

Pytorch 入门

1.将每个图片的label作为txt文件写入另外一个文件夹(txt文件名与图片文件名相同)

2.tensorboard的summary writer

3.torchvision中的transforms

4.DataLoader

5.神经网络-卷积层Conv2d

6.最大池化层

7.非线性激活函数Relu

9.线性层

10.损失函数

11.反向传播和优化器

12.残差网络

13.CIFAR10模型结构


Pytorch 入门

1.将每个图片的label作为txt文件写入另外一个文件夹(txt文件名与图片文件名相同)

root_dir=r"F:\yolo\img"
target_dir="car_img"
print(os.path.join(root_dir,target_dir))
img_path_list=os.listdir(os.path.join(root_dir,target_dir))
print(img_path_list)
out_dir="car_label"
for i in img_path_list:
    file_name=i.split(".jpg")[0]
    f=open((os.path.join(root_dir,out_dir,file_name)+".txt"),"w")
    f.write("car")
    f.close()

2.tensorboard的summary writer

import numpy as np
import os
import cv2 as cv
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
writer=SummaryWriter("logs1")
cv_img=cv.imread(r"F:\yolo\img\street.jpg")
# for i in range(1,100):
#     writer.add_scalar("y=2x",2*i,i)
writer.add_image("test_img",cv_img,1,dataformats='HWC')
tensor_trans=transforms.ToTensor()
test_img1=tensor_trans(cv_img)
writer.add_image("test_img",test_img1,2)
writer.close()

查看可视化结果

控制台 tensorboard --logdir=logs1命令即可

3.torchvision中的transforms

torchvision.transforms是pytorch中的图像预处理包。一般用Compose把多个步骤整合到一起

transforms.Compose([
    transforms.CenterCrop(10),
    transforms.ToTensor(),
])

下面列举两个常用的 transforms中的函数:

class torchvision.transforms.Normalize(mean, std)

给定均值:(R,G,B) 方差:(R,G,B),将会把Tensor正则化。即:Normalized_image=(image-mean)/std

实例代码如下:

import cv2 as cv
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
writer=SummaryWriter("logs1")
cv_img=cv.imread(r"F:\yolo\img\street.jpg")
tensor_trans=transforms.ToTensor()
test_img1=tensor_trans(cv_img)
writer.add_image("test_img",test_img1,1)
print(test_img1[0][0][0])
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm=trans_norm(test_img1)
print(img_norm[0][0][0])
writer.add_image("test_img",img_norm,2)
writer.close()

class torchvision.transforms.ToTensor

把一个取值范围是[0,255]PIL.Image或者shape(H,W,C)numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]torch.FloadTensor

方法总结如下图:

4.DataLoader

数据加载器。组合数据集和采样器,并在数据集上提供单进程或多进程迭代器。

参数:

  • dataset (Dataset) – 加载数据的数据集。
  • batch_size (int, optional) – 每个batch加载多少个样本(默认: 1)。
  • shuffle (bool, optional) – 设置为True时会在每个epoch重新打乱数据(默认: False).
  • sampler (Sampler, optional) – 定义从数据集中提取样本的策略。如果指定,则忽略shuffle参数。
  • num_workers (int, optional) – 用多少个子进程加载数据。0表示数据将在主进程中加载(默认: 0)
  • collate_fn (callable, optional) –
  • pin_memory (bool, optional) –
  • drop_last (bool, optional) – 如果数据集大小不能被batch size整除,则设置为True后可删除最后一个不完整的batch。如果设为False并且数据集的大小不能被batch size整除,则最后一个batch将更小。(默认: False)
import cv2 as cv
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from torch.utils.data import DataLoader
import torchvision
train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True,transform=torchvision.transforms.ToTensor())
# shuffle 为true设置为打乱顺序
train_loader=DataLoader(dataset=train_set,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
writer=SummaryWriter("logs1")
step=0
for data in train_loader:
    imgs,targets=data
    writer.add_images("imgs",imgs,step)
    step=step+1
    break
writer.close()

5.神经网络-卷积层Conv2d

class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

Parameters:

  • in_channels(int) – 输入信号的通道
  • out_channels(int) – 卷积产生的通道
  • kerner_size(int or tuple) - 卷积核的尺寸
  • stride(int or tupleoptional) - 卷积步长
  • padding(int or tupleoptional) - 输入的每一条边补充0的层数
  • dilation(int or tupleoptional) – 卷积核元素之间的间距
  • groups(intoptional) – 从输入通道到输出通道的阻塞连接数
  • bias(booloptional) - 如果bias=True,添加偏置

import cv2 as cv
import torch
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from torch.utils.data import DataLoader
import torchvision
train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True,transform=torchvision.transforms.ToTensor())
# shuffle 为true设置为打乱顺序
train_loader=DataLoader(dataset=train_set,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
from torch import nn

class test(nn.Module):
    def __init__(self):
        super(test, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 3, stride=1, padding=0)

    def forward(self, x):
        x = self.conv1(x)
        return x
test=test()
writer=SummaryWriter("logs1")
step=0
for data in train_loader:
    imgs,targets=data
    writer.add_images("imgs",imgs,step)
    step=step+1
    output=test(imgs)
    # 由于图片只能以三个通道显示,因此要把6个channel改成3个
    # torch.size([64,6,30,30])->[???,3,30,30]
    # batch_size不知道写多少的时候就写-1,它会自动计算
    output=torch.reshape(output,(-1,3,30,30))
    writer.add_images("imgs", output, step)
    break
writer.close()

6.最大池化层

参数:class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

  • kernel_size(int or tuple) - max pooling的窗口大小
  • stride(int or tupleoptional) - max pooling的窗口移动的步长。默认值是kernel_size
  • padding(int or tupleoptional) - 输入的每一条边补充0的层数
  • dilation(int or tupleoptional) – 一个控制窗口中元素步幅的参数
  • return_indices - 如果等于True,会返回输出最大值的序号,对于上采样操作会有帮助
  • ceil_mode - 如果等于True,计算输出信号大小的时候,会使用向上取整,代替默认的向下取整的操作

import cv2 as cv
import torch
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
from torch.utils.data import DataLoader
import torchvision
from torch.nn import MaxPool2d
train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True,transform=torchvision.transforms.ToTensor())
# shuffle 为true设置为打乱顺序
train_loader=DataLoader(dataset=train_set,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
from torch import nn

class test(nn.Module):
    def __init__(self):
        super(test, self).__init__()
        self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)

    def forward(self, input):
        output = self.maxpool1(input)
        return output
test=test()
writer=SummaryWriter("logs1")
step=0
for data in train_loader:
    imgs,targets=data
    writer.add_images("imgs1",imgs,step)
    step=step+1
    output=test(imgs)
    writer.add_images("imgs1", output, step)
    break
writer.close()

7.非线性激活函数Relu

Relu函数的作用是将将小于0的数据变成为0,实例代码如下:

from torch.nn import ReLU
input=torch.tensor([[1,-0.5],
                    [-1,3]])
class test(nn.Module):
    def __init__(self):
        super(test, self).__init__()
        #inplace-选择是否进行覆盖运算
        self.relu1=ReLU(inplace=False)
    def forward(self,input):
        output=self.relu1(input)
        return output

test=test()
output=test(input)
print(output)

9.线性层

Linear layers

对输入数据做线性变换:y=Ax+b

参数:

  • in_features - 每个输入样本的大小
  • out_features - 每个输出样本的大小
  • bias - 若设置为False,这层不会学习偏置。默认值:True

形状:

  • 输入: (N,in_features)(N,in_features)
  • 输出: (N,out_features)(N,out_features)

变量:

  • weight -形状为(out_features x in_features)的模块中可学习的权值
  • bias -形状为(out_features)的模块中可学习的偏置

如下图:

 代码实例如下:

import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader
 
dataset=torchvision.datasets.CIFAR10("dataset",train=False,transform=torchvision.transforms.ToTensor(),
                                    download=True)
dataloader=DataLoader(dataset,batch_size=64,drop_last=True)
 
class test(nn.Module):
    def __init__(self):
        super(test, self).__init__()
        self.linear1=Linear(3072,10)
    def forward(self,input):
        output=self.linear1(input)
        return output
test1=test()
for data in dataloader:
    imgs,t=data
    print(imgs.shape)
    #将图片线性化
    output=torch.flatten(imgs)
    print(output.shape)
    output=test1(output)
    print(output.shape)
 
output:
#torch.Size([64, 3, 32, 32])
#torch.Size([64, 1, 1, 3072])
#torch.Size([64, 1, 1, 10])

10.损失函数

损失函数这里列举几个:

class torch.nn.L1Loss(size_average=True)[source]

创建一个衡量输入x(模型预测输出)和目标y之间差的绝对值的平均值的标准。

                              

  • x 和 y 可以是任意形状,每个包含n个元素。

  • n个元素对应的差值的绝对值求和,得出来的结果除以n

  • 如果在创建L1Loss实例的时候在构造函数中传入size_average=False,那么求出来的绝对值的和将不会除以n

代码如下实例

import torch
from torch.nn import L1Loss

input=torch.tensor([1,2,3],dtype=torch.float32)
output=torch.tensor([1,2,5],dtype=torch.float32)
loss=L1Loss()
result=loss(input,output)
print(result)

运行结果如下图,如果不需要求平均可以这样设置

loss=L1Loss(reduction="sum")

 

class torch.nn.MSELoss(size_average=True)[source]

创建一个衡量输入x(模型预测输出)和目标y之间均方误差标准。

  • x 和 y 可以是任意形状,每个包含n个元素。

  • n个元素对应的差值的绝对值求和,得出来的结果除以n

  • 如果在创建MSELoss实例的时候在构造函数中传入size_average=False,那么求出来的平方和将不会除以n

class torch.nn.CrossEntropyLoss(weight=None, size_average=True)

 当训练一个多类分类器的时候,这个方法是十分有用的。exp是以e为底的指数函数,在一个猫狗二分类问题中,一个图片经过神经网络模型输出为x[0.5,0.7],其中这张图片的target为0,0代表为猫,1代表为狗,损失函数的计算为-x[0(target)]+ln(exp(x[0])+exp(x[1])。

代码如下

import torch
from torch.nn import CrossEntropyLoss

x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
x=torch.reshape(x,(1,3))
loss=CrossEntropyLoss()
result=loss(x,y)
print(result)

11.反向传播和优化器

反向传播 loss.backward()

优化器一般是使用梯度下降的方法进行优化:在梯度法中,函数的取值从当前位置沿着梯度方向前进一定距离,然后在新的地方重新求梯度,再沿着新梯度方向前进,如此反复,不断地沿梯度方向前进。像这样,通过不断地沿梯度方向前进,逐渐减小函数值的过程就是梯度法(gradient method)。梯度法是解决机器学习中最优化问题的常用方法,特别是在神经网络的学习中经常被使用。根据目的是寻找最小值还是最大值,梯度法的叫法有所不同。严格地讲,寻找最小值的梯度法称为梯度下降法(gradient descent method),寻找最大值的梯度法称为梯度上升法(gradient ascent method)。但是通过反转损失函数的符号,求最小值的问题和求最大值的问题会变成相同的问题,因此“下降”还是“上升”的差异本质上并不重要。一般来说,神经网络(深度学习)中,梯度法主要是指梯度下降法。

反向传播和优化器代码实例如下:

test1=test()
#lossFunction模型
loss=nn.CrossEntropyLoss()
#优化器模型
optim=torch.optim.SGD(test1.parameters(),0.01)
#进行20次优化
for epcho in range (20):
    running_loss=0.0
    for data in dataloader:
        imgs,t=data
        output=test1(imgs)
        loss=loss(output,t)
        #将每个梯度清为0(初始化)
        optim.zero_grad()
        #反向传播,得到每个可调节参数对应的梯度(grad不再是none)
        loss.backward()
        #对每个参数进行改变,weight-data被改变
        optim.step()
        #计算每轮优化中每个变量的loss和
        running_loss=running_loss+result_loss
    print(running_loss)
 
output:
#总loss在逐渐变小
# tensor(18712.0938, grad_fn= < AddBackward0 >)
# tensor(16126.7949, grad_fn= < AddBackward0 >)
# tensor(15382.0703, grad_fn= < AddBackward0 >)

12.残差网络

传统的神经网络,由于网络层数增加,会导致梯度越来越小,这样会导致后面无法有效的训练模型,这样的问题成为梯度消弭。为了解决这样的问题,引入残差神经网络(Residual Networks),残差神经网络的核心是”跳跃”+“残差块”。通过引入RN网络,可以有效缓解梯度消失的问题,可以训练更深的网络。

下图是一个基本残差块。它的操作是把某层输入跳跃连接到下一层乃至更深层的激活层之前,同本层输出一起经过激活函数输出。

在这里插入图片描述

定义残差模型,根据最基本的残差块,残差中间需要经过卷积->激活->卷积这样的操作,为了保证输入输出大小一致,故中间两个卷积层的输入输出大小都和模型最初输入大小保持一致。

class ResidualBlock(nn.Module):
    def __init__(self, channels):
        super(ResidualBlock, self).__init__()
        self.channels = channels
        self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)

    def forward(self, x):
        y = F.relu(self.conv1(x))
        y = self.conv2(y)
        return F.relu(x + y)

13.CIFAR10模型结构

下面是利用CIFAR10模型结构进行图像分类数据的训练和预测。

import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
#import自己写的models
from p27_1model import *
 
train_data=torchvision.datasets.CIFAR10("../datasets",train=True,transform=torchvision.transforms.ToTensor(),
                                        download=True)
test_data=torchvision.datasets.CIFAR10("../datasets",train=False,transform=torchvision.transforms.ToTensor(),
                                        download=True)
#查看数据集长度
train_size=len(train_data)
test_size=len(test_data)
print("size of train,test is:{},{}".format(train_size,test_size))
#利用dataloader加载
train_dataloader=DataLoader(train_data,64)
test_dataloader=DataLoader(test_data,64)
#创建网络模型
test1=test()
#损失函数
loss_f=nn.CrossEntropyLoss()
#优化器
#1e-2=0.01
learning_rate=1e-2
opt=torch.optim.SGD(test1.parameters(),lr=learning_rate,)
#设置训练网络的参数
#记录训练次数
train_step=0
#测试次数
test_step=0
#训练轮数
epoch=10
#添加tensoeboard
writer=SummaryWriter("train_log")
 
 
for i in range(epoch):
    print("第{}轮训练开始".format(i+1))
    #训练步骤开始
    #有时不必要:test1.train()
    for data in train_dataloader:
        imgs,t=data
        output=test1(imgs)
        loss=loss_f(output,t)
        #优化器优化模型
        opt.zero_grad()
        loss.backward()
        opt.step()
        train_step=train_step+1
        #loss.item更加规范(.item不会打印数据类型,例如tensor(5))
        if train_step%100==0:
            print("训练次数{},loss值为{}".format(train_step,loss.item()))
            writer.add_scalar("train_loss",loss.item(),train_step)
    loss_total=0
    #测试步骤开始
    #有时不必要:test1.eval()
    total_correct=0
    with torch.no_grad():
        for data in test_dataloader:
            imgs,t=data
            output=test1(imgs)
            loss=loss_f(output,t)
            loss_total=loss_total+loss.item()
            test_step=test_step+1
            #argmax参数:1为横向比较,2为纵向比较,output为64,10的矩阵
            #output.argmax(1)==t是为了得到[Ture,False,True....]这种形式
            #.sum:T为1,F为0
            corect=(output.argmax(1)==t).sum()
            total_correct=total_correct+corect
            accuracy=total_correct/test_size
    print("测试集总loss{}".format(loss_total))
    writer.add_scalar("test_loss",loss_total,test_step)
    writer.add_scalar("accuracy",accuracy,test_step)
 
    torch.save(test1,"test1{}.pth".format(i))
    print("模型已保存")
 

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

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

相关文章

微信的大动作,很多人要颤抖了

4月25日&#xff0c;微信团队发布关于微信公众号营销内容合规规范通知&#xff0c;要求公众号在投放商业广告时需要标注广告字样。 刚开始觉得也没啥&#xff0c;无非就是加个广告的字样&#xff0c;让消费者可以及时识别出来&#xff0c; 但从效果来看&#xff0c;似乎效果并不…

华为OD机试真题B卷 Java 实现【猜密码】

一、题目描述 小杨申请了一个保密柜,但是他忘记了密码。只记得密码都是数字,而且所有数字都是不重复的。 请你根据他记住的数字范围和密码的最小数字数量,帮他算下有哪些可能的组合,规则如下: 输出的组合都是从可选的数字范围中选取的,且不能重复;输出的密码数字要按照…

意外的坚持,意外的收获!

前言&#xff1a; 转眼间&#xff0c;2023就快过了一半&#xff0c;回忆间感觉跟过完年没多久一样&#xff1b;时间是真的过的快...... 简单总结一下最近&#xff1a; 一、锻炼身体&#xff1a; 最近这段时间开始恢复锻炼身体&#xff0c;现在感觉一天下班回来&#xff0c;身体…

Java 21 新特性和改进

Java 21 是 Java 17 之后的下一个 LTS 版本。虚拟线程在 Java 21 中将成为正式功能。可以预期的是&#xff0c;Java 21 会成为一个很流行的 Java 版本。 Java 21 将在 2023 年 9 月 19 日发布。目前 Java 21 包含的内容已经基本确定了。下面来梳理一下 Java 21 中会包含的内容。…

【AI提示】ChatGPT提示工程课程(吴恩达OpenAI)转换文本(中文chatgpt版)

设置 翻译 通用翻译器 语调变换 格式转换 拼写检查/语法检查。 转换 在本笔记中&#xff0c;我们将探索如何使用大型语言模型进行文本转换任务&#xff0c;例如语言翻译、拼写和语法检查、语气调整和格式转换。 设置 import openai import osfrom dotenv import load_dotenv, f…

Maven初级

Maven初级 Maven简介 传统项目管理状态分析 jar包不统一&#xff0c;jar包不兼容工程升级维护过程操作繁琐 Maven是什么 Maven的本质是一个项目管理工具&#xff0c;将项目开发和管理过程抽象成一个项目对象模型&#xff08;POM&#xff09;POM&#xff1a;项目对象模型 Ma…

一图看懂 itsdangerous 模块:将受信任的数据传递到不受信任的环境的帮助工具,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 itsdangerous 模块&#xff1a;将受信任的数据传递到不受信任的环境的帮助工具&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&#x1f9ca;模块…

Ae:跟踪摄像机

在时间轴面板上选择要跟踪的素材图层&#xff0c;在跟踪器面板中单击跟踪摄像机 Track Camera按钮之后&#xff0c;会向素材图层添加“3D 摄像机跟踪器” 3D Camera Tracker效果&#xff0c;并立即对视频画面逐帧分析以反求原始摄像机运动。 还有其它几种添加 3D 摄像机跟踪器效…

GeForce RTX 3060 Ti+cuda 11.6+Anaconda3搭建Pytorch深度学习环境

室友新购入一个笔记本&#xff0c;笔记本的显卡是GeForce RTX 3060 Ti&#xff0c;记录一下使用GeForce RTX 3060 Ticuda 11.6Anaconda3搭建Pytorch深度学习环境。 安装很简单&#xff0c;当你有了Python环境时记住一个核心命令即可&#xff0c;显卡驱动因该在之前已经安装过了…

ChatGPT 与我合力开发 xargin blog archive 插件:曹大博客的新奇探险

之前写的批量删除 chatGPT 对话的插件[1]&#xff0c;最近我收到了一个五星好评&#xff1a; 虽然不赚钱&#xff0c;交个朋友嘛&#xff0c;还是挺高兴的。而且借助 chatGPT&#xff0c;我是在与全世界的用户交流&#xff0c;想想就激动。 最近我发现自己让 chatGPT 帮忙写前端…

jQuery其他方法及插件使用

1. 拷贝对象 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width,…

跨域 + 四种解决办法

目录 同源策略 解决方案 1、jsonp 2、前端代理 3、后端解决 4、Nginx代理 同源策略 说到跨域就不得不提到同源策略&#xff0c;什么是同源策略&#xff1f; 请求的时候拥有相同的 协议 域名 端口 只要有一个不同就属于跨域 解决方案 解决跨域问题一共有四种方式&#xff…

chatgpt赋能python:Python中的Join方法详解:简化拼接字符串的操作

Python中的Join方法详解&#xff1a;简化拼接字符串的操作 在Python编程中&#xff0c;拼接字符串是一项常见的操作。在过去&#xff0c;我们通常使用“”符号来连接多个字符串。但是&#xff0c;这种方法不是很高效&#xff0c;特别是当需要拼接大量字符串时。这时候&#xf…

基于html+css的图展示98

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

python+django+vue学生在线选课系统93pul

随着信息化时代的到来&#xff0c;网络系统都趋向于智能化、系统化&#xff0c;选课系统也不例外&#xff0c;但目前国内的有些学校仍都使用人工管理&#xff0c;学校规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#xff0c;…

初识Spring -- Spring入门保姆级教程(一)

文章目录 前言一、Spring是什么&#xff1f;1.概述2.了解spring家族3.spring系统概述4.spring优点5.spring学习路线 二、入门spring1.核心概念2.IOC入门案例3.DI入门案例4.bean的配置5.spring 中 bean的实例化--构造方法6.bean的实例化 -- 静态工厂实例化7.bean实例化--实例工厂…

IEEE802.3和IEEE802.11的分类(仅为分类)

IEEE802.3标准 IEEE802.3:10兆以太网 ●10Base&#xff0d;5 使用粗同轴电缆&#xff0c;最大网段长度为500m&#xff0c;基带传输方法&#xff1b; ●10Base&#xff0d;2 使用细同轴电缆&#xff0c;最大网段长度为185m&#xff0c;基带传输方法&#xff1b; ●10Base&am…

python+vue宠物用品商城网站django宠物领养系统31e70

我们也变得越来越忙碌、对生活的要求也变得更加严格&#xff0c;对快速和方便的服务的需求也在逐渐增加。因此&#xff0c;对宠物行业的管理、服务的要求也越来越严格。为适应时代的发展&#xff0c;各大宠物店开始广泛地使用电脑来进行管理&#xff0c;并推出在线宠物管理系统…

华为OD机试真题B卷 Java 实现【去除多余空格】,附详细解题思路

一、题目描述 去除文本多余空格&#xff0c;但不去除配对单引号之间的多余空格。给出关键词的起始和结束下标&#xff0c;去除多余空格后刷新关键词的起始和结束下标。 条件约束&#xff1a; 不考虑关键词起始和结束位置为空格的场景&#xff1b;单词的的开始和结束下标保证…

100天精通Python(可视化篇)——第89天:Bokeh库绘图可视化基础入门(参数说明+案例实战)

文章目录 专栏导读一、Bokeh是什么&#xff1f;二、安装与导入三、Bokeh接口介绍四、创建图表五、添加自定义渲染器切换主题添加图例图例位置图例方向图例背景和边界图例文本的外观行列布局网格布局 专栏导读 &#x1f525;&#x1f525;本文已收录于《100天精通Python从入门到…