PyTorch-基础(CUDA、Dataset、transforms、卷积神经网络、VGG16)

PyTorch-基础

环境准备

CUDA Toolkit安装(核显跳过此步骤)

CUDA Toolkit是NVIDIA的开发工具,里面提供了各种工具、如编译器、调试器和库

首先通过NVIDIA控制面板查看本机显卡驱动对应的CUDA版本,如何去下载对应版本的Toolkit工具,本人下载的是Toolkit 12.2

下载地址:https://developer.nvidia.com/cuda-toolkit-archive

在这里插入图片描述

下载完毕后打开cuda_12.2.2_windows_network.exe,这里会让你指定一个临时目录这个目录用于存放临时文件的,安装Toolkit 成功后会自动卸载

注意临时目录不要和安装目录指定相同位置,假如指定了相同位置后面是无法安装的

在这里插入图片描述

选择路径时可以切换到自定义的安装路径

路径最好和工具中一致,参考路径D:\NVIDIA CUDA\NVIDIA GPU Computing Toolkit\CUDA\v版本号

在这里插入图片描述

安装完后后我们需要添加CUDA环境变量

在这里插入图片描述

在这里插入图片描述

安装完毕后通过nvcc -V测试是否安装成功

在这里插入图片描述

CUDNN安装(核显跳过此步骤)

Cudnn是NVIDIA提供的一个深度神经网络加速库,它包含了一系列高性能的基本函数和算法,用于加速深度学习任务的计算,它可以与Cuda一起使用,提供了针对深度学习任务的高效实现。

下载地址:https://developer.nvidia.com/cudnn-downloads

选择对应CUDA版本下载,这里下载压缩包

在这里插入图片描述

下载完毕后将压缩包解压,将解压内容直接复制粘贴到CUDA安装目录下,本人安装目录是D:\NVIDIA CUDA\NVIDIA GPU Computing Toolkit\CUDA\v12.1

在这里插入图片描述

粘贴完毕后打开命令行执行nvidia-smi看到如下内容表示安装成功

在这里插入图片描述

Anaconda创建虚拟环境

#创建一个名为pytorch,python版本3.8的虚拟环境
conda create -n pytroch2.3.0 python=3.8
#切换到当前环境
conda activate pytroch2.3.0
#查看本机支持的CUDA版本(核显跳过)
nvidia-smi
#安装pytorch
#官网https://pytorch.org/get-started/locally/
#下载对应CUDA版本的pytorch(独显电脑执行该命令)
#如果与下载很慢,可以分开下载
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia
#下载对应CUDA版本的pytorch(核显电脑执行该命令)
conda install pytorch torchvision torchaudio cpuonly -c pytorch

测试PyTroch

在包都安装完毕后执行如下命令没有任何报错表示安装成功

#进入python命令行
python
#引入torch
import torch
#测试cuda(核显返回False,独显返回True)
torch.cuda.is_available()

编辑器选择

在开发过程中需要使用到2款编辑器,分别是PyCharm和Jupyter

PyCharm

PyCharm:https://www.jetbrains.com.cn/pycharm/download/

安装完毕后再PyCharm中Settings中找到Python Interpreter并且选择Add Interpreter将Conda添加进来,这样项目就可以选择指定Conda的环境运行

在这里插入图片描述

Jupyter

安装Anaconda时会顺便安装了Jupyter,但是Jupyter默认是Base环境,接下来我们需要在前面创建好的pytroch2.3.0环境下安装Jupyter

#切换到pytroch2.3.0
conda activate pytroch2.3.0
#安装Jupyter
conda install nb_conda
#安装完毕,
jupyter notebook

启动成功后创建一个文件,切换环境,执行测试代码

在这里插入图片描述

常用类库

Dataset

Pytroch提供Dataset用于存放数据集,使用方式很简单编写一个类继承Dataset,实现init、getitem、len方法即可简单使用Dataset,以下就是一个Dataset的简单使用

from torch.utils.data import Dataset
from PIL import Image
import osclass MyData(Dataset):#构造函数def __init__(self,root_dir,label_dir):self.root_dir = root_dirself.label_dir = label_dir#文件路径self.path = os.path.join(self.root_dir,self.label_dir)#图片列表self.img_path = os.listdir(self.path)#获取图片下标    def __getitem__(self, item):img_name = self.img_path[item]img_item_path = os.path.join(self.root_dir,self.label_dir,img_name)img = Image.open(img_item_path)label = self.label_dirreturn img,label#获取长度def __len__(self):return len(self.img_path)root_dir = 'E:\\Python-Project\\Torch-Demo\\dataset\\train'
#蚂蚁数据集
ants_label_dir = 'ants_image'
ants_dataset = MyData(root_dir,ants_label_dir)
#蜜蜂数据集
bees_label_dir = 'bees_image'
bees_dataset = MyData(root_dir,bees_label_dir)
#合并2个数据集
train_dataset = ants_dataset + bees_dataset

transforms

transforms是神经网络中一个非常重要的库,它提供了将数据转换为Tensor类型数据,Tensor包装了神经网络的数据参数如数据网络的数据格式、梯度、梯度方法等,并且transforms包含了很多操作数据的库可以对Tensor数据进行各种修改

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transformswriter = SummaryWriter('logs')img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)
#将图片转换为tensor类型
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor", img_tensor)#对tensor进行进行归一化,减少不同图片的色彩的差值,提升训练效果
#规划的计算公式 output[channel] = (input[channel] - mean[channel]) / std[channel]
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize", img_norm)#对PIL图片大小修改
trans_resize = transforms.Resize((512, 512))
img_resize = trans_resize(img)
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize)#对PIL图片进行整体缩放
trans_resize_2 = transforms.Resize(512)
trans_compose = transforms.Compose([trans_resize_2,trans_totensor])
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2,1)#对PIL图片进行随机裁剪
trans_random = transforms.RandomCrop((128,128))
trans_compose_2 = transforms.Compose([trans_random,trans_totensor])
for i in range(10):img_crop = trans_compose_2(img)writer.add_image("RandomCrop", img_crop,i)writer.close()

tensorboard

tensorboard提供训练可视化工具,通过图标的方式可以跟踪实验中不同阶段下的指标用于对比

依赖安装
#安装tensorboard可视化工具
conda install tensorboard
启动tensorboard
#--logdir 指定读取的文件目录
#--port 指定服务启动的端口
tensorboard --logdir=logs --port=6007
简单使用案例

以下创建1个函数y=2x,并且将内容输出到tensorboard

from torch.utils.tensorboard import SummaryWriter
#指定日志生成的目录
writer = SummaryWriter("logs")
#往writer写入数据
#参数1:图表名称
#参数2:Y轴值
#参数3:X轴值
for i in range(100):writer.add_scalar("y=2x", 2 * i, i)
#关闭流
writer.close()

在项目目录下使用tensorboard --logdir=logs启动tensorboard

常见问题:

多次重复执行时刷新tensorboard会发现图标很乱,解决方法有2种:

1、将logs下文件生成重新代码重新启动tensorboard

2、每次执行都创建一个新的logs文件,将图标写入新logs文件下

在这里插入图片描述

Dataset下载与转换

结合Dataset和Transforms对数据集进行下载并且转换,PyTorch提供了一些用于练习的数据集可以通过Dataset进行下载,一下就是一个案例

import torchvision
from torch.utils.tensorboard import SummaryWriter#定义一个转换操作,对dataset中的数据集进行操作
dataset_transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),
])#训练数据集,CIFAR10是PyTorch提供的一个数据集,会自动去下载
#https://www.cs.toronto.edu/~kriz/cifar.html
train_set = torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=dataset_transform,download=True)
#测试数据集
test_set = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=dataset_transform,download=True)#使用tensorboard显示数据集合,显示前面10张
writer = SummaryWriter("p10")
for i in range(10):img,target = test_set[i]writer.add_image("test_set",img,i)writer.close()

DataLoader

Dataset是数据集,那么需要获取数据集的数据那么就需要用到DataLoader,DataLoader可以将数据集安装指定规则分批、打乱后重新组合成一批一批的数据

import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter#测试数据集
test_data = torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
#加载数据集,batch_size=4每获取4张数据为一组,shuffle=True乱序获取
#加载完毕后元组(图片集合,标签集合)
test_loader = DataLoader(dataset=test_data,batch_size=4,shuffle=True,num_workers=0,drop_last=False)#打印Dataloader
writer = SummaryWriter("dataloder")
step = 0
for data in test_loader:imgs,targets = datawriter.add_images("test_data",imgs,step)step = step + 1
writer.close()

使用tensorboard --logdir=dataloder在控制台查看加载好的数据集

在这里插入图片描述

神经网络

PyTorch封装了很多神经网络的类库,文档地址 https://pytorch.org/docs/stable/nn.html

卷积神经网络(NN)

卷积层

卷积神经网络具体的计算过程可以参考:https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md

在这里插入图片描述

结合上图与参考地址中的动图案例可以总结出在计算过程中有几个重要参数:

  1. 输入(二维数组)
  2. 卷积核每次计算后移动的步长(stride)
  3. 是否对图像边填充,而增加图像大小(padding)
  4. 输出(二维数组)
import torch
import torch.nn.functional as F
#输入图像
input = torch.tensor([[1,2,0,3,1],[0,1,2,3,1],[1,2,1,0,0],[5,2,3,1,1],[2,1,0,1,1]
])
#卷积核
kernel = torch.tensor([[1,2,1],[0,1,0],[2,1,0]
])
#尺寸切换
input = torch.reshape(input,(1,1,5,5))
kernel = torch.reshape(kernel,(1,1,3,3))
#使用卷积核对图像进行卷积,卷积和在图像中滑动的步长1,可获得一个3X3输出
output = F.conv2d(input,kernel,stride=1,padding=0)
print(output)#使用卷积核对图像进行卷积,卷积和在图像中滑动的步长2,可获得一个3X3输出
output2 = F.conv2d(input,kernel,stride=2,padding=0)
print(output2)#使用卷积核对图像进行卷积,卷积和在图像中滑动的步长1,对图像外面填充一圈0的数据图像将变成7X7,可获得一个5X5输出
# [0, 0, 0, 0, 0, 0, 0]
# [0, 1, 2, 0, 3, 1, 0]
# [0, 0, 1, 2, 3, 1, 0]
# [0, 1, 2, 1, 0, 0, 0]
# [0, 5, 2, 3, 1, 1, 0]
# [0, 2, 1, 0, 1, 1, 0]
# [0, 0, 0, 0, 0, 0, 0]
output3 = F.conv2d(input,kernel,stride=1,padding=1)
print(output3)

案例

将PyTorch测试数据集CIFAR10下载下来,利用Conv2d对数据集中的图片进行卷积,卷积核大小为3x3,步长为1,输出6通道

import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter#使用测试集训练,以为训练集合数据太多了
dataset = torchvision.datasets.CIFAR10(root='./dataset', train=False, transform=torchvision.transforms.ToTensor(),download=True)
#加载数据
dataloader = DataLoader(dataset,batch_size=64)
#定义一个训练模型
class MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()#定义一个的卷积方法#参数1:输入3个通道的数据(图片又RBG 3个通道组成)#参数2:输出为6个通道的数据(进行6次卷积计算结果集堆叠在一起)#参数3:卷积核大小3X3#参数4:卷积核每次计算后移动步长1#参数5:不对图像边进行填充self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3,stride=1,padding=0)def forward(self, x):#对数据进行卷积x = self.conv1(x)return xmy_model = MyModel()writer = SummaryWriter('./logs_conv2d')
step = 0
#计算DataLoader中的每一组数据
for data in dataloader:imgs,targets = dataoutput = my_model(imgs)#torch.Size([64, 3, 32, 32])# print(imgs.shape)#torch.Size([64, 6, 30, 30])# print(output.shape)writer.add_images("input",imgs,step)#由于6个通道在tensorboard无法显示,强行转换为3个通道,参数1填写-1会根据后面的数自动推算output = torch.reshape(output,(-1,3,30,30))writer.add_images("output",output,step)step = step + 1writer.close()
最大池化核心层

最大池化的目的是将图像中的特质保留将图像缩小,比如一张5x5的图片池化后变成2x2的这样可以缩小图片提高计算过程

最大池化核,在每一片被池化核覆盖的区域内获取一个最大的值作为结果写入到结果集中,默认没获取完后池化核移动步长等于池化核大小

  1. Ceil_model=True:池化核覆盖区域超出图像范围时也要获取最大值
  2. Ceil_model=False:只获取池化核覆盖区域在图像范围内的最大值,超出范围的值丢弃

在这里插入图片描述

案例

将PyTorch测试数据集CIFAR10下载下来,对数据集进行池化

import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
#使用测试集训练,以为训练集合数据太多了
dataset = torchvision.datasets.CIFAR10(root='./dataset', train=False, download=True, transform=torchvision.transforms.ToTensor())
#加载数据
dataloader = DataLoader(dataset,batch_size=64)
#定义一个训练模型
class MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()#定义最大池化的规则#参数1:池化核3x3#参数2:磁化核溢出部分是否保留self.maxpool1 = MaxPool2d(kernel_size=3,ceil_mode=False)def forward(self, input):#对数据进行池化output = self.maxpool1(input)return outputmy_model = MyModel()writer = SummaryWriter('./logs_maxpool')
step = 0
#计算DataLoader中的每一组数据
for data in dataloader:imgs,targets = datawriter.add_images("input",imgs,step)output = my_model(imgs)writer.add_images("output",output,step)step += 1writer.close()
非线性激活

默认的图像都是线性的训练出来的模型就很死版,对数据集进行非线性集合后训练模型可以训练出符合各种曲线各种特征的模型

import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriterdataset = torchvision.datasets.CIFAR10(root='./dataset', train=False, download=True, transform=torchvision.transforms.ToTensor())
#加载数据
dataloader = DataLoader(dataset,batch_size=64)
class MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()#最简单的非线性激活,把数据中负数变为0(图像场景下不明显)self.relu1 = ReLU()#Sigmoid函数计算,输出值介于0-1之间self.sigmoid1 = Sigmoid()def forward(self, input):output = self.sigmoid1(input)return outputmy_model = MyModel()writer = SummaryWriter('./logs_relu')
step = 0
#计算DataLoader中的每一组数据
for data in dataloader:imgs,targets = dataoutput = my_model(imgs)writer.add_images("input",imgs,step)writer.add_images("output",output,step)step = step + 1writer.close()

网络模型搭建

PyTorch中的模型

PyTorch中提供了很多以实现的模型有的时候直接使用PyTorch的模型就可完成我们的需求,不需要直接去编写模型,官方文档中包含了完整的实例,例如图像处理模型地址如下:https://pytorch.org/vision/stable/models.html#classification

基于VGG16修改模型

在很多的需求的实现过程都拿vgg16作为前置的模型,在vgg16的基础上进行修改,以下就是基于vgg16模型修改适应CIFAR10数据集

import torchvision.datasets
from torch import nndataset = torchvision.datasets.CIFAR10(root='./dataset', train=False, transform=torchvision.transforms.ToTensor(),download=True)#获取一个已经训练过的vgg16模型,这会下载一个包
vgg16_true = torchvision.models.vgg16(pretrained=True)
#获取一个没有训练过的vgg16模型
vgg16_false = torchvision.models.vgg16(pretrained=False)
#打印vgg16模型
print(vgg16_true)#vgg16默认是输出1000个结果,CIFAR10数据集结果只有10类,让vgg16模型适应CIFAR10,操作方式有2种
#1. 在vgg16基础上添加一层线性层
vgg16_true.classifier.add_module("add_linear", nn.Linear(1000, 10))
print(vgg16_true)
#2. 直接修改第六层的逻辑
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)

模型的保存与加载

import torch
import torchvision#获取一个没有训练过的vgg16模型
vgg16 = torchvision.models.vgg16(pretrained=False)
#保存方式1:保存模型结构+参数文件
torch.save(vgg16,"vgg16_method1.pth")
#保存方式2:保存模型的参数(官方推荐)
torch.save(vgg16.state_dict(),"vgg16_method2.pth")#加载模型结构+参数文件(方式1加载时要有该网络模型的对象才能加载成功)
model = torch.load("vgg16_method1.pth")
print(model)
#加载模型的参数(官方推荐)
dict = torch.load("vgg16_method2.pth")
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dict(dict)
print(model)

CIFAR10分类模型案例

编写一段网络模型对CIFAR10中的数据集进行分类,最后输入一张图片得到分类,模型的搭建流程图像

在这里插入图片描述

import torchvision
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriterfrom model import *
#定义训练的设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#准备数据集
train_data = torchvision.datasets.CIFAR10(root='./dataset', train=True, download=True,transform=torchvision.transforms.ToTensor())
test_data = torchvision.datasets.CIFAR10(root='./dataset', train=False, download=True,transform=torchvision.transforms.ToTensor())#获得数据集的长度
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)#创建网络模型
my_model = MyModel()
my_model = my_model.to(device)  #使用GPU训练
#损失函数
loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device) #使用GPU训练
#优化器
learning_rate = 0.001
optimizer = torch.optim.SGD(my_model.parameters(), learning_rate)#设置训练网络的参数
total_train_step = 0 #训练的次数
total_test_step = 0  #测试的测试
epochs = 10          #训练轮数#添加tensorboard
writer = SummaryWriter('./logs_train')for i in range(epochs):print("--------------------第{}轮训练开始--------------------".format(i+1))#训练集数据my_model.train()for data in train_dataloader:imgs,targets = dataimgs = imgs.to(device) #使用GPU训练targets = targets.to(device) #使用GPU训练outputs = my_model(imgs)#计算损失函数loss = loss_fn(outputs, targets)#使用优化器优化模型optimizer.zero_grad()loss.backward()optimizer.step()#记录训练次数total_train_step += 1if total_train_step % 100 == 0: #每逢100才打印print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))writer.add_scalar("train_loss",loss.item(),total_train_step)#测试步骤开始my_model.eval()total_test_loss = 0total_accuracy = 0with torch.no_grad():for data in test_dataloader:imgs,targets = dataimgs = imgs.to(device)  # 使用GPU训练targets = targets.to(device)  # 使用GPU训练outputs = my_model(imgs)loss = loss_fn(outputs, targets)total_test_loss += loss.item()accuracy = (outputs.argmax(1) == targets).sum()total_accuracy += accuracy.item()print("整体测试集上的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 += 1#保存每一轮的训练结果torch.save(my_model,"./pth/my_model_{}.pth".format(i))print("模型已保存")writer.close()

编写测试程序加载训练好的模型,识别

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AWS-SAA中文版题库

一家公司收集多大洲城市的温度、湿度和大气压数据。该公司每天从每个站点收集的平均数据量为500GB。每个站点都有高速互联网连接。该公司希望尽快将所有这些全球站点的数据聚合到一个AmazonS3存储桶中。解决方案必须将操作复杂性降至最低。哪种解决方案满足这些要求&#xff1f…

Git操作整体流程

文章目录 1.Git创建个人仓库2、Git全局配置3、Git本地管理4. Git本地管理常用命令汇总5、使用Git命令将项目提交到远程码云管理6.使用IDEA进行管理7、Idea里面的终端8、关于提交总结 1.Git创建个人仓库 打开https://gitee.com/,登录个人账号,右上角加号…

微相E316实现FM电台监听

前面介绍了基于Matlab、矢量信号器或微相E316、HackRF One实现AM和FM调制解调,今天分享的内容是用微相E316、上位机和Matlab实现FM电台信号监听。注意本文仅用于科研和学习,私自搭建电台属于违法行为。 1.概述 微相E316、上位机和Matlab实现FM电台信号…

【总结】GraphRAG与传统RAG的深度对比及主流项目分析

GraphRAG和传统RAG的区别 GraphRAG和传统RAG都是为了增强大语言模型(LLMs)在特定领域的能力而发展出的技术,但它们在多个方面存在明显区别。 1. 知识组织方式 传统RAG:通常将大规模文本语料库分割成文本块,再利用嵌入…

SessionBox同一浏览器登录多账号独立IP教程

对于多账号运营的跨境营销人员来说,SessionBox提供了同一浏览器登录多账号的解决方案,但是很多人不仅需要多账号登录,对于登录Facebook、Instagram等账号来说,如何SessionBox与代理配合使用以确保真正的帐户分离更为重要&#xff…

图论 之 迪斯科特拉算法求解最短路径

文章目录 题目743.网络延迟时间3341.到达最后一个房间的最少时间I 求解最短路径的问题,分为使用BFS和使用迪斯科特拉算法,这两种算法求解的范围是有区别的 BFS适合求解,边的权值都是1的图中的最短路径的问题 图论 之 BFS迪斯科特拉算法适合求…

Docker+Dify部署DeepSeek-r1本地知识库

安装配置Docker Desktop 软件下载 Docker Desktop版本:4.38.0.181591 Docker Desktop下载地址:Docker: Accelerated Container Application Development 或者从这里下载:DockerDesktop-4.38.0.181591资源-CSDN文库 点击图下所示位置,下载windows-AMD64版本软件 启用Hy…

ubuntu ffmpeg 安装踩坑

ffmpeg 安装踩坑 安装命令: sudo apt update sudo apt install ffmpeg如果以上命令没有报错,那么恭喜你很幸运,可以关闭这篇文章了! 如果跟我一样,遇到如下报错,可以接着往下看: 报错信息: …

如何通过Windows环境远程控制MusicGPT在线生成高质量AI音乐

文章目录 前言1. 本地部署2. 使用方法介绍3. 内网穿透工具下载安装4. 配置公网地址5. 配置固定公网地址 前言 在这个快节奏的时代,音乐不仅是心灵的慰藉,更是创意的源泉。试想一下,在忙碌的工作间隙或悠闲的周末午后,只需轻敲几行…

大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(3)

Paimon的下载及安装,并且了解了主键表的引擎以及changelog-producer的含义参考: 大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(1) 利用Paimon表做lookup join,集成mysql cdc等参考: 大数据组件(四)快速入门实时数据…

Spring面试题2

1、compareable和compactor区别 定义与包位置:Comparable是一个接口,位于java.lang包,需要类去实现接口;而Compactor是一个外部比较器,位于java.util包 用法:Comparable只需要实现int compareTo(T o) 方法,比较当前对…

react(9)-redux

使用CRA快速创建react项目 npx create-react-app react-redux 安装配套工具 npm i reduxjs/toolkit react-redux 启动项目 在创建项目时候会出现一个问题 You are running create-react-app 5.0.0, which is behind the latest release (5.0.1). We no longer support…

HTTP SSE 实现

参考: SSE协议 SSE技术详解:使用 HTTP 做服务端数据推送应用的技术 一句概扩 SSE可理解为:服务端和客户端建立连接之后双方均保持连接,但仅支持服务端向客户端推送数据。推送完毕之后关闭连接,无状态行。 下面是基于…

STL —— 洛谷字符串(string库)入门题(蓝桥杯题目训练)(二)

目录 一、B2121 最长最短单词 - 洛谷 算法代码: 代码分析 变量定义 输入处理 单词长度计算 更新最长和最短单词的长度 输出最长单词 输出最短单词 评测记录:​编辑 二、B2122 单词翻转 - 洛谷 算法代码: 代码分析 引入头文件和定…

74. 搜索二维矩阵(LeetCode 热题 100)

题目来源; 74. 搜索二维矩阵 - 力扣(LeetCode) 题目内容: 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &am…

JUC并发—9.并发安全集合四

大纲 1.并发安全的数组列表CopyOnWriteArrayList 2.并发安全的链表队列ConcurrentLinkedQueue 3.并发编程中的阻塞队列概述 4.JUC的各种阻塞队列介绍 5.LinkedBlockingQueue的具体实现原理 6.基于两个队列实现的集群同步机制 4.JUC的各种阻塞队列介绍 (1)基于数组的阻塞…

SQL Server导出和导入可选的数据库表和数据,以sql脚本形式

一、导出 1. 打开SQL Server Management Studio,在需要导出表的数据库上单击右键 → 任务 → 生成脚本 2. 在生成脚本的窗口中单击进入下一步 3. 如果只需要导出部分表,则选择第二项**“选择具体的数据库对象(Select specific database objects)”**&am…

DDoCT:形态保持的双域联合优化用于快速稀疏视角低剂量CT成像|文献速递-医学影像人工智能进展

Title 题目 DDoCT: Morphology preserved dual-domain joint optimization for fast sparse-view low-dose CT imaging DDoCT:形态保持的双域联合优化用于快速稀疏视角低剂量CT成像 01 文献速递介绍 计算机断层扫描(CT)是当今广泛应用的…

【Linux】多线程 -> 线程同步与基于BlockingQueue的生产者消费者模型

线程同步 条件变量 当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。 例如:一个线程访问队列时,发现队列为空,它只能等待,直到其它线程将一个节点添加到队列中。这…

WPF的页面设计和实用功能实现

目录 一、TextBlock和TextBox 1. 在TextBlock中实时显示当前时间 二、ListView 1.ListView显示数据 三、ComboBox 1. ComboBox和CheckBox组合实现下拉框多选 四、Button 1. 设计Button按钮的边框为圆角,并对指针悬停时的颜色进行设置 一、TextBlock和TextBox…