使用pytorch深度学习框架搭建神经网络
简介
现在主流有两个框架pytorch和TensorFlow,本文主要介绍pytorch
- PyTorch:由 Facebook 的人工智能研究小组开发和维护。PyTorch 以其动态计算图(Dynamic Computational Graph)和易用性著称,非常适合研究人员和开发者进行实验和快速原型开发。
- TensorFlow:由 Google 开发和维护。TensorFlow 是一个更加成熟和全面的框架,支持大规模的生产环境部署,特别是在云计算和分布式计算方面具有优势。
然后介绍两个小工具:
dir()打开该包,看看里面有什么东西;如果IDE使用的是pycharm的话,按住Ctrl直接跳转,输入函数的参数的时候按住Ctrl+P可以看需要填哪些参数
help()官方解释文档,教你如何使用该工具
神经网络搭建步骤
数据集介绍
数据集为CIFAR10,
CIFAR-10 数据集由 10 个类的 60000 张 32x32 彩色图像组成,每个类有 6000 张图像。有 50000 张训练图像和 10000 张测试图像。图像大小为3x32x32
数据集分为 5 个训练批次和 1 个测试批次,每个批次有 10000 张图像。测试批次包含每个类中随机选择的 1000 张图像。训练批次包含按随机顺序排列的剩余图像,但某些训练批次可能包含来自一个类的图像多于另一个类的图像。在它们之间,训练批次正好包含来自每个类的 5000 张图像。
以下是数据集中的类,以及每个类的 10 张随机图像:
运行下列代码会导入数据集,没有下载的会自动下载
datasets导入数据集
dataloader分发数据,每批次送入64图片进入网络训练
transform更改图片数据的类型,比如将PIL改成tensor类型
train_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test = train_data.classes
print(test)
test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)
搭建网络
由官网可知(官网链接:PyTorch documentation — PyTorch 2.4 documentation),使用pytorch搭建网络至少需要重写2个函数,一个__init__() 初始化函数,另一个forward()前向传播函数,下图为官网截图:
按照官网给的例子我们重写,我们的网络结构如下图所示
网络结构如下图所示
代码思路:输入:3x32x32--->最后输出10个参数,具体过程如下图所示:
二维卷积参数计算公式如下图,根据输入输出计算padding和stride
代码实现
使用sequential()
class Wisdom(nn.Module):def __init__(self):super(Wisdom, self).__init__()self.model1 = Sequential(nn.Conv2d(3, 32, 5, padding=2),nn.MaxPool2d(2),nn.Conv2d(32, 32, 5, padding=2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, padding=2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10))def forward(self, x):x = self.model1(x)return x
不使用sequential()
class Wisdom(nn.Module):def __init__(self):super(Wisdom, self).__init__()self.conv1=Conv2d(3,32,5,padding=2)self.maxpool1=MaxPool2d(2)self.conv2=Conv2d(32,32,5,padding=2)self.maxpool2=MaxPool2d(2)self.conv3=Conv2d(32,64,5,padding=2)self.maxpool3=MaxPool2d(2)self.flatten=Flatten()self.linear1=Linear(1024,64)self.linear2= Linear(64, 10)def forward(self,x):x=self.conv1(x)x=self.maxpool1(x)x=self.conv2(x)x=self.maxpool2(x)x=self.conv3(x)x=self.maxpool3(x)x=self.flatten(x)x=self.linear1(x)x=self.linear2(x)return x
实例化神经网络对象,损失函数,优化器
#创建神经网络
wisdom = Wisdom()
wisdom=wisdom.cuda()
#损失函数
loss_fn= nn.CrossEntropyLoss()
loss_fn=loss_fn.cuda()
#优化器
learn_rate =0.01
optimizer = torch.optim.SGD(wisdom.parameters(),lr=learn_rate)
损失函数(Loss Function)
常见的损失函数包括:
选择哪种损失函数取决于具体的任务和模型类型。在训练过程中,目标是最小化损失函数的值,从而提高模型的预测准确性。
优化器
优化器(Optimizer)是机器学习中用于调整模型参数以最小化损失函数的算法。优化器通过迭代过程逐步更新模型的权重和偏置,以找到损失函数的最小值。以下是一些常用的优化器:
设置网络参数
使用writer = SummaryWriter("logs_train")可以可视化整个训练过程
#设置网络的一些参数
#记录的训练次数
total_train_step = 0
#记录测试次数
total_test_step = 0
#训练的轮数
epoch=10
#添加tensorboard
writer = SummaryWriter("logs_train")
训练和验证网络并将重要信息可视化屏幕
重要代码解析:
wisdom.train()标志网络进入训练状态
loss = loss_fn(outputs,targets)计算损失函数
optimizer.zero_grad() 梯度置零,防止上个梯度对本轮训练产生影响
loss.backward()反向传播
optimizer.step()梯度更新
wisdom.eval()模型进入测试状态
将损失值和精度闯入writer并绘制曲线图
writer.add_scalar("test_loss", total_test_loss, total_test_step) writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))保存训练好模型
for i in range(epoch):print("----第{}轮开始----".format(i+1))#开始训练#进入训练状态wisdom.train()for data in train_dataloader:imgs,targets = dataimgs=imgs.cuda()targets=targets.cuda()outputs = wisdom(imgs)loss = loss_fn(outputs,targets)#优化器调优optimizer.zero_grad()loss.backward()optimizer.step()total_train_step += 1if total_train_step % 100 ==0:print("训练次数:{},loss:{}:".format(total_train_step,loss))writer.add_scalar("train_loss",loss.item(),total_train_step)#模型测试#模型进入测试状态wisdom.eval()total_test_loss=0total_accuracy = 0with torch.no_grad():# 提高推理速度和节省内存for data in test_dataloader:imgs,targets = dataimgs = imgs.cuda()targets = targets.cuda()outputs = wisdom(imgs )loss = loss_fn(outputs,targets)total_test_loss=total_test_loss+loss.item()accuracy = (outputs.argmax(1)==targets).sum()total_accuracy=total_accuracy+accuracyprint("整体测试集合的loss:{}".format(total_test_loss))print("整体测试集合的准确率:{}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss", total_test_loss, total_test_step)writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)total_test_step +=1torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))print("模型已经保存!")#torch.save(wisdom.state_dict(),"./model_train/wisdom_{}.pth".format(i))
writer.close()
使用GPU加速训练
确保电脑有显卡并正确安装驱动,而且要正确下载对应cuda
下载教程:
进入pytorch官网
根据自己的系统选择,一般使用anaconda 在Windows下进行python环境管理,复制红框部分,在Anaconda Prompt 粘贴运行,注意自己的cuda版本是否支持
查看cuda版本,打开英伟达控制面板,桌面右键或者系统右下角,然后点击系统信息,之后点击组件
GPU程序设置
在神经网络,损失函数的实例对象后加.cuda()即可,以及在图片数据后加.cuda()
wisdom=wisdom.cuda()
loss_fn=loss_fn.cuda()
imgs=imgs.cuda()
targets=targets.cuda()
保存模型
torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))
使用训练好的网络进行分类任务
加载网络模型
model = torch.load("./model_train/wisdom_49.pth")
若出现runtime error 将模型加载方式换成下列语句,将GPU训练的模型映射到CPU
出现runtimer error 将模型加载方式换成下列语句,将GPU训练的模型映射到CPU
或者将分类的图片进行cuda加速
image = image.cuda()#使用GPU训练的模型需要加CUDA
使用SummaryWriter使训练可视化
打开Anaconda Prompt再激活环境后运行下列命令:
tensorboard --logdir "D:\pyc_workspace\learn_pytorch\logs_train
上列的地址根据train.py代码中的这个语句确定
writer = SummaryWriter("logs_train")
一定要改成自己的文件地址,具体操作见下图
可视化结果如下图所示
最后解释一个语句,with torch.no_grad()提高推理速度和节省内存
with torch.no_grad():# 提高推理速度和节省内存for data in test_dataloader:imgs,targets = dataimgs = imgs.cuda()targets = targets.cuda()outputs = wisdom(imgs )loss = loss_fn(outputs,targets)total_test_loss=total_test_loss+loss.item()accuracy = (outputs.argmax(1)==targets).sum()total_accuracy=total_accuracy+accuracy
程序汇总
train.py
使用cpu训练网络
import torchvision
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriterfrom model import *train_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)#length长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练集长度:{}".format(train_data_size))
print("测试集长度:{}".format(test_data_size))#使用dataloader加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)#创建神经网络
wisdom = Wisdom()
#损失函数
loss_fn= nn.CrossEntropyLoss()
#优化器
learn_rate =0.01
optimizer = torch.optim.SGD(wisdom.parameters(),lr=learn_rate)#设置网络的一些参数
#记录的训练次数
total_train_step = 0
#记录测试次数
total_test_step = 0
#训练的轮数
epoch=10
#添加tensorboard
writer = SummaryWriter("logs_train")
#tensorboard --logdir "D:\pyc_workspace\learn_pytorch\logs_train"for i in range(epoch):print("----第{}轮开始----".format(i+1))#开始训练#进入训练状态wisdom.train()for data in train_dataloader:imgs,targets = dataoutputs = wisdom(imgs)loss = loss_fn(outputs,targets)#优化器调优optimizer.zero_grad()loss.backward()optimizer.step()total_train_step += 1if total_train_step % 100 ==0:print("训练次数:{},loss:{}:".format(total_train_step,loss))writer.add_scalar("train_loss",loss.item(),total_train_step)#模型测试#模型进入测试状态wisdom.eval()total_test_loss=0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs,targets = dataoutputs = wisdom(imgs )loss = loss_fn(outputs,targets)total_test_loss=total_test_loss+loss.item()accuracy = (outputs.argmax(1)==targets).sum()total_accuracy=total_accuracy+accuracyprint("整体测试集合的loss:{}".format(total_test_loss))print("整体测试集合的准确率:{}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss", total_test_loss, total_test_step)writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)total_test_step +=1torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))print("模型已经保存!")#torch.save(wisdom.state_dict(),"./model_train/wisdom_{}.pth".format(i))
writer.close()
train_gpu.py
使用GPU训练网络
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWritertrain_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
test = train_data.classes
print(test)
test_data = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)class Wisdom(nn.Module):def __init__(self):super(Wisdom, self).__init__()self.model1 = Sequential(nn.Conv2d(3, 32, 5, padding=2),nn.MaxPool2d(2),nn.Conv2d(32, 32, 5, padding=2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, padding=2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10))def forward(self, x):x = self.model1(x)return x#length长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练集长度:{}".format(train_data_size))
print("测试集长度:{}".format(test_data_size))#使用dataloader加载数据集
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)#创建神经网络
wisdom = Wisdom()
wisdom=wisdom.cuda()
#损失函数
loss_fn= nn.CrossEntropyLoss()
loss_fn=loss_fn.cuda()
#优化器
learn_rate =0.01
optimizer = torch.optim.SGD(wisdom.parameters(),lr=learn_rate)#设置网络的一些参数
#记录的训练次数
total_train_step = 0
#记录测试次数
total_test_step = 0
#训练的轮数
epoch=10
#添加tensorboard
writer = SummaryWriter("logs_train")
#tensorboard --logdir "D:\pyc_workspace\learn_pytorch\logs_train"for i in range(epoch):print("----第{}轮开始----".format(i+1))#开始训练#进入训练状态wisdom.train()for data in train_dataloader:imgs,targets = dataimgs=imgs.cuda()targets=targets.cuda()outputs = wisdom(imgs)loss = loss_fn(outputs,targets)#优化器调优optimizer.zero_grad()loss.backward()optimizer.step()total_train_step += 1if total_train_step % 100 ==0:print("训练次数:{},loss:{}:".format(total_train_step,loss))writer.add_scalar("train_loss",loss.item(),total_train_step)#模型测试#模型进入测试状态wisdom.eval()total_test_loss=0total_accuracy = 0with torch.no_grad():# 提高推理速度和节省内存for data in test_dataloader:imgs,targets = dataimgs = imgs.cuda()targets = targets.cuda()outputs = wisdom(imgs )loss = loss_fn(outputs,targets)total_test_loss=total_test_loss+loss.item()accuracy = (outputs.argmax(1)==targets).sum()total_accuracy=total_accuracy+accuracyprint("整体测试集合的loss:{}".format(total_test_loss))print("整体测试集合的准确率:{}".format(total_accuracy/test_data_size))writer.add_scalar("test_loss", total_test_loss, total_test_step)writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)total_test_step +=1torch.save(wisdom,"./model_train/wisdom_{}.pth".format(i))print("模型已经保存!")#torch.save(wisdom.state_dict(),"./model_train/wisdom_{}.pth".format(i))
writer.close()
test.py
利用神经网络模型进行分类,记得把
img_path ="dog.jpg"改成自己的路径
import torch
import torchvision
from PIL import Image
from torch import nn
from torch.nn import Sequentialtrain_data = torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True)
classes_list = train_data.classes#分类物体列表img_path ="dog.jpg"
# img_path ="airplane.jpg"
image = Image.open(img_path)
#image = image.convert("RGB")#只保留为3通道transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32,)),torchvision.transforms.ToTensor()])
image = transform(image)
print(image.shape)
class Wisdom(nn.Module):def __init__(self):super(Wisdom, self).__init__()self.model1 = Sequential(nn.Conv2d(3, 32, 5, padding=2),nn.MaxPool2d(2),nn.Conv2d(32, 32, 5, padding=2),nn.MaxPool2d(2),nn.Conv2d(32, 64, 5, padding=2),nn.MaxPool2d(2),nn.Flatten(),nn.Linear(1024, 64),nn.Linear(64, 10))def forward(self, x):x = self.model1(x)return x#加载网络模型
model = torch.load("./model_train/wisdom_49.pth")
#出现runtimer error 将模型加载方式换成下列语句,将GPU训练的模型映射到CPU
#model = torch.load("./model_train/wisdom_9.pth",map_location=torch.device("cpu"))
print(model)image=torch.reshape(image,(1,3,32,32))#增加batch_size维度
model.eval()
with torch.no_grad():image = image.cuda()#使用GPU训练的模型需要加CUDAoutput = model(image)
print(output)
classes_index=output.argmax(1).item()
print(classes_list)print("测试图片为:{}".format(classes_list[classes_index]))
总结:------>多看官网 <------
相关文章:

使用pytorch深度学习框架搭建神经网络
简介 现在主流有两个框架pytorch和TensorFlow,本文主要介绍pytorch PyTorch:由 Facebook 的人工智能研究小组开发和维护。PyTorch 以其动态计算图(Dynamic Computational Graph)和易用性著称,非常适合研究人员和开发者进行实验和…...

Hive数据库与表操作全指南
目录 Hive数据库操作详解 创建数据库 1)语法 2)案例 查询数据库 1)展示所有数据库 (1)语法 (2)案例 2)查看数据库信息 (1)语法 (2&#…...

UniaApp引入Iconfont
一、下载图标资源 登录到阿里巴巴矢量图标库(iconfont)官网(https://www.iconfont.cn/)。找到你需要的图标并添加到购物车,然后点击购物车图标进入到管理界面,选择 “下载代码”。在下载选项中选择 “Font…...

面试题:软件测试缺陷产生的原因有哪些?
软件缺陷产生的原因多种多样,一般可能有以下几种原因: 1.需求表述、理解、编写引起的错误。 2.系统架构设计引起的错误。 3.开发过程缺乏有效的沟通及监督,甚至没有沟通或监督。 4.程序员编程中产生的错误。 5.软件开发工具本身隐藏的问…...

RabbitMQ 04 集群
01...

axure9勾选多个删除,弹框显示多个中继器编号
文本框 情形是删除逗号 文本框内插入数据...

Git 使用指南 --- 版本管理
序言 Git 是一个开源的 分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。对一个程序员来说,掌握 Git 的使用是必要的。 在这个系列中,将详细的介绍 Git 的使用和原理,话不多说,让我们开始吧。…...

C#进阶-ASP.NET实现可以缩放和旋转的图片预览页
本文详细介绍了如何在ASP.NET WebForms中实现一个功能丰富的图片预览页面。通过结合HTML、CSS和JavaScript,用户可以方便地对图片进行放大、缩小以及旋转操作。文章从页面的基本布局开始,逐步讲解了如何设置图片展示区、添加控制按钮、编写CSS样式以及实…...

【小程序 - 大智慧】深入微信小程序的核心原理
目录 课程目标背景双线程架构WebView 结构快速渲染 PageFrame编译原理Exparser通讯系统生命周期基础库解包跨端框架预编译半编译半运行运行时框架 主流技术Tarouni-app汇总 下周安排 课程目标 本次课程主要通过后台管理小程序回顾一下小程序的高阶语法,然后讲解整体…...

Qt 去掉QDialog对话框的问号
QT 对话框的问号是什么? QDialog默认的window flag中包含了Qt::WindowContextHelpButtonHint,这个flag意思是在窗口上提供“上下文帮助”按钮 使用方式/调用方式 void QWidget::setWhatsThis(const QString &)比如: ui->lineEdit_1->setWh…...

负载均衡 Ribbon 与 Fegin 远程调用原理
文章目录 一、什么是负载均衡二、Ribbon 负载均衡2.1 Ribbon 使用2.2 Ribbon 实现原理 (★)2.3 Ribbon 负载均衡算法 三、Feign 远程调用3.1 Feign 简述3.2 Feign 的集成3.3 Feign 实现原理 (★) 一、什么是负载均衡 《服务治理:Nacos 注册中心》 末尾提到了负载均…...
c/c++:CMakeLists.txt中添加编译/连接选项使用内存错误检测工具Address Sanitizer(ASan)
Address Sanitizer(ASan)是一个快速的内存错误检测工具。从gcc 4.8开始,AddressSanitizer成为gcc的一部分。 既然是gcc内置的内存检查工具,用起来比第三方的库更方便些。只要指定相应的编译链接参数就可以实现内存泄露检查了,如下是是cmake脚…...

armbian cups 远程打印机 1022
使用 CUPS Web 浏览器界面设置和管理打印机 - Oracle Solaris 管理:常见任务 N1刷armbian变身打印服务器,支持全平台无线打印PC扫描_存储设备_什么值得买 (smzdm.com) 第 6 章 使用 Web 界面向 CUPS 添加打印机 | Red Hat Product Documentation apt…...
three.js使用3DTilesRendererJS加载3d tiles数据
原生的 three.js 目前不支持 3d tiles 数据的加载,不过开源社区已经给出了一些解决方案,其中最活跃的要属 3DTilesRendererJS。它为 three.js 提供了加载和调度 3d tiles 数据的基本能力,虽说和 Cesium.js 对 3d tiles 的支持相比还有很大的差…...

坐牢第三十五天(c++)
一.作业 1.使用模版类自定义栈 代码: #include <iostream> using namespace std; template<typename T> // 封装一个栈 class stcak { private:T *data; //int max_size; // 最大容量int top; // 下标 public:// 无参构造函数stcak();// 有参…...

Conda离线部署django
要在没有网络连接的环境中使用conda部署Django,你需要预先在有网络连接的机器上创建一个包含所有必要包的环境,并导出该环境的配置文件。然后,你可以将这个配置文件和必要的包传输到目标机器上进行安装。 下面是详细的步骤: 1. …...
1. Fabric.js安装使用
安装 # 安装 fabricjs npm i fabric --save在需要使用的页面引入 import * as fabric from fabric...
Excel中.xls和.xlsx文件格式的区别,及C++操作Excel文件
文件结构和兼容性: XLS是Excel 97-2003版本的文件格式,而XLSX是Excel 2007及以上版本的文件格式。XLS格式是向下兼容的,意味着较新的Excel版本可以打开XLS文件,但较旧的版本无法打开XLSX文件。相反,XLSX格式是向上…...
php实用命令
php相关命令 命令错误级别 命令 命令命令介绍具体用法php -v查看php版本php -vphp -l检查php文件是否有语法错误php -lphp -m查看当前php安装的扩展php -mphp -i | grep extension_dir查看扩展安装的目录php -i | grep extension_dir 错误级别 命令命令介绍具体用法error_re…...

TypeError:未绑定方法
TypeError: unbound method 错误通常发生在类方法被调用时,但没有正确绑定到实例。这通常意味着你试图在类本身上调用一个实例方法,或者没有使用正确的方式创建类实例。 1、问题背景 某位开发者在尝试创建一个类似于经典的 Pratt 递归下降解析器时遇到了…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...