当前位置: 首页 > article >正文

PyTorch可视化工具——使用Visdom进行深度学习可视化

文章目录

  • 前置环境
  • Visdom
  • 安装并启动Visdom
  • Visdom图形API
    • Visdom静态更新API详解
    • 通用参数说明
    • 使用示例
    • Visdom动态更新API详解
      • 1. 使用`update='append'`参数
      • 2. ~~使用vis.updateTrace方法~~
      • 3. 完整训练监控示例
  • Visdom可视化操作
    • 散点图plot.scatter()
    • 散点图案例
    • 线性图vis.line()
      • `vis.line()` 参数说明
      • `opts` 选项明细表
      • 关键特性说明
    • 线性图案例
    • 茎叶图vis.stem
      • 🔄 Visdom茎叶图参数设计
      • ❓ 为什么Visdom这样设计
      • 💡 记忆技巧
      • 📊 修正后的代码解释
      • 🖼️ **可视化效果说明**
  • 深度学习训练案例

前置环境

  • 深度学习开发环境 Anaconda PyTorch
  • Jupyter Notebook

Visdom

  • Visdom是Facebook Research开发的一款开源可视化工具,专门为PyTorch等深度学习框架设计,但也可以用于其他机器学习任务的可视化。它提供了一个轻量级的Web服务,允许用户在浏览器中实时查看训练过程中的各种指标、图像和其他数据。
  • Visdom的主要特点包括:实时可视化训练过程、支持多种数据类型(标量、图像、文本、直方图等)、简单的API接口、可远程访问的Web界面、支持多环境组织实验。
  • Visdom可以直接接受来自PyTorch的张量,而不用转换成NumPy中的数组,运行效率很高。此外,Visdom可以直接在内存中获取数据,具有毫秒级刷新,速度很快。

安装并启动Visdom

  • Visdom本质上时一个类似于Jupyter Notebook的web服务器,在使用前需要在终端打开服务。
  1. 进入anaconda虚拟环境:
conda activate env_name
  1. 安装Visdom非常简单,只需使用pip:
pip install visdom
  1. 安装完成后,启动Visdom服务器:
python -m visdom.server
  • 默认情况下,Visdom会在http://localhost:8097启动服务。

Visdom图形API

Visdom静态更新API详解

API名称图形类型描述主要参数
vis.scatter2D/3D散点图绘制二维或三维散点图X: 数据点坐标
Y: 数据点标签(可选)
opts: 标题/颜色/大小等选项
vis.line线图绘制单条或多条线图,常用于展示训练曲线X: x轴数据
Y: y轴数据
opts: 标题/图例/坐标轴标签等选项
vis.updateTrace更新线图更新现有的线图或散点图数据X: 新x数据
Y: 新y数据
win: 要更新的窗口名
name: 线名称(可选)
vis.stem茎叶图绘制离散数据的茎叶图X: x轴数据
Y: y轴数据
opts: 标题/线条样式等选项
vis.heatmap热力图用颜色矩阵表示数据值大小X: 矩阵数据
opts: 标题/颜色映射/x,y轴标签等选项
vis.bar条形图绘制垂直或水平条形图X: 条形数据
opts: 标题/堆叠/方向(水平或垂直)等选项
vis.histogram直方图展示数据分布情况X: 输入数据
opts: 标题/箱数/颜色等选项
vis.boxplot箱线图展示数据分布的五数概括(最小值、Q1、中位数、Q3、最大值)X: 输入数据
opts: 标题/异常值显示等选项
vis.surf表面图绘制三维表面图X: 矩阵数据
opts: 标题/颜色映射/光照等选项
vis.contour等高线图绘制二维等高线图X: 矩阵数据
opts: 标题/线数/颜色映射等选项
vis.quiver矢量场图绘制二维矢量场(箭头图)X: 起点坐标
Y: 矢量分量
opts: 标题/箭头大小/颜色等选项
vis.mesh网格图绘制三维网格图X: 顶点坐标
Y: 面索引
opts: 标题/颜色/光照等选项

通用参数说明

  1. win: 可选参数,指定要绘制或更新的窗口名称。如果不指定,Visdom会自动分配一个新的pane。如果两次操作指定的win名字一样,新的操作将覆盖当前的pane内容,因此建议每次操作都重新指定win。
  2. opts: 字典形式的选项参数,可设置标题(title)、图例(legend)、坐标轴标签(xlabel/ylabel)、宽度(width)等,主要用于设置pane的显示格式。
  3. 大多数API接受PyTorch Tensor或Numpy数组作为输入数据。但不支持Python的int、float等类型,因此每次传入时都需先将数据转化成ndarray或tensor。
  4. env: 指定可视化环境(默认为’main’),用于组织不同实验的可视化结果。Visdom允许创建不同的"环境"来组织实验:
# 创建一个新环境
vis = visdom.Visdom(env='my_experiment')# 保存当前环境
vis.save(['my_experiment'])

使用示例

import visdom
import numpy as npvis = visdom.Visdom()# 线图示例
vis.line(X=np.arange(10),Y=np.random.rand(10),opts=dict(title='Random Line', showlegend=True)
)# 散点图示例
vis.scatter(X=np.random.rand(100, 2),Y=(np.random.rand(100) > 0.5).astype(int)+1,opts=dict(title='2D Scatter', markersize=10)
)

在这里插入图片描述

Visdom动态更新API详解

  • 在深度学习训练过程中,我们经常需要实时更新可视化图表来监控训练进度。Visdom提供了两种主要方式来实现数据的动态更新:

1. 使用update='append'参数

  • 最基础的动态更新方式,适用于大多数绘图API。
参数取值效果
updateNone(默认)覆盖窗口中的现有内容
'append'在现有图形上追加数据点
'replace'替换整个图形(与None不同,会保留窗口设置)

使用示例:

import visdom
import numpy as npvis = visdom.Visdom()# 初始化线图
vis.line(X=[0],Y=[0.5],win='loss',opts=dict(title='Training Loss')
)# 模拟训练过程
for epoch in range(1, 10):loss = np.random.rand() * 0.1 + 1.0/(epoch+1)vis.line(X=[epoch],Y=[loss],win='loss',update='append'  # 关键参数,避免覆盖)

在这里插入图片描述

2. 使用vis.updateTrace方法

  • 0.1.8版本之后已废弃
方法功能
vis.updateTrace()1. 在现有图形上追加数据点(类似update='append'
2. 添加新的独立轨迹

参数说明:

参数类型说明
Xarray/tensor新x坐标
Yarray/tensor新y坐标
winstr目标窗口名称
namestr轨迹名称(可选,用于区分多条轨迹)
appendboolTrue=追加到现有轨迹,False=创建新轨迹(默认True)

使用示例:

# 方法一:在现有轨迹上追加数据(等效于update='append')
vis.updateTrace(X=[epoch],Y=[train_loss],win='loss_win',name='train'  # 必须指定要更新的轨迹名称
)# 方法二:添加全新独立轨迹
vis.updateTrace(X=[epoch],Y=[val_loss],win='loss_win',name='validation',  # 新轨迹名称append=False  # 创建新轨迹
)

3. 完整训练监控示例

import visdom
import numpy as np
import timevis = visdom.Visdom(env='training_monitor')# 初始化所有窗口
vis.line(X=[0], Y=[0], win='loss', opts=dict(title='Loss', legend=['Train', 'Val']))
vis.line(X=[0], Y=[0], win='acc', opts=dict(title='Accuracy', legend=['Train', 'Val']))for epoch in range(1, 11):# 模拟训练数据train_loss = np.random.rand()*0.1 + 1.0/epochval_loss = np.random.rand()*0.1 + 1.2/epochtrain_acc = 1 - train_loss + np.random.rand()*0.1val_acc = 1 - val_loss + np.random.rand()*0.1# 更新损失曲线(两种方式等价)vis.line(X=[epoch], Y=[train_loss],win='loss', name='Train',update='append')vis.line(X=[epoch], Y=[val_loss],win='loss', name='Val',update='append')# 更新准确率曲线vis.line(X=[epoch], Y=[train_acc],win='acc', name='Train',update='append')vis.line(X=[epoch], Y=[val_acc],win='acc', name='Val',update='append')# 每5个epoch可视化一批样本if epoch % 5 == 0:samples = np.random.rand(16, 3, 64, 64)  # 模拟图像数据vis.images(samples,win='samples',opts=dict(title=f'Epoch {epoch} Samples'))time.sleep(0.5)  # 模拟训练时间

在这里插入图片描述

Visdom可视化操作

散点图plot.scatter()

  • scatter函数用来画2D或3D数据的散点图。需要输入 N × 2 N\times 2 N×2 N × 3 N\times 3 N×3的张量来指定N个点的位置。一个可供选择的长度为N的向量用来保存X中的点对应的标签。标签可以通过点的颜色反应出来。
  • Visdom vis.scatter 参数与选项说明
参数/选项类型描述默认值注意事项
基本参数
XTensor/ndarrayN×2(2D)或N×3(3D)数据点坐标必填不支持Python列表
YTensor/ndarray长度为N的标签向量(可选)None用于分类着色
winstr目标窗口名称自动生成留空则创建新窗口
标记样式选项
opts.markersymbolstr标记形状'dot'可选:‘circle’, ‘cross’, 'diamond’等
opts.markersizeint标记大小(像素)10非字符串类型
opts.markercolorTensor/ndarray颜色设置自动分配见下方颜色规则
布局选项
opts.legendlist图例名称列表None需与Y的类别数匹配
opts.textlabelslist每个点的文本标签None长度需等于N
opts.webglbool启用WebGL加速False大数据量时建议开启
高级选项
opts.layoutoptsdictPlotly布局参数None{'plotly': {'legend': {'x':0}}}
opts.traceoptsdictPlotly轨迹参数None{'plotly': {'mode':'markers'}}
  • markercolor 颜色编码规则
输入形状颜色模式示例值效果
N单通道灰度[0,127,255]0(黑)→255(红)
N×3RGB三通道[[0,0,255], [255,0,0]]蓝→红
K类别单通道[255, 0]类别1红/类别2黑
K×3类别RGB[[255,0,0], [0,255,0]]类别1红/类别2绿

散点图案例

  • 简单散点图
import visdom
import numpy as npvis=visdom.Visdom(env='training_monitor')Y=np.random.rand(100)old_scatter=vis.scatter(X=np.random.rand(100,2),Y=(Y[Y>0]+1.5).astype(int),opts=dict(legend=['Didnt', 'Update'], # 图例标签xtickmin=-50, # x轴刻度最小值xtickmax=50, # x轴刻度最大值xtickstep=0.5, # x轴刻度间隔ytickmin=-50, # y轴刻度最小值ytickmax=50, # y轴刻度最大值ytickstep=0.5, # y轴刻度间隔markersymbol='cross-thin-open', # 标记符号)
)
# 使用update_window_opts函数更新之前绘制的散点图的配置选项
vis.update_window_opts(win=old_scatter,opts=dict(legend=['2019年', '2020年'],xtickmin=0,xtickmax=1,xtickstep=0.5,ytickmin=0,ytickmax=1,ytickstep=0.5,markersymbol='cross-thin-open',),
)

在这里插入图片描述

  • 带文本标签的散点图
# 带文本标签的散点图
import visdom
import numpy as np
vis=visdom.Visdom(env='training_monitor')
vis.scatter(X=np.random.rand(6, 2),opts=dict(textlabels=['Label %d' % (i + 1) for i in range(6)])
)

在这里插入图片描述

  • 3D散点图
#三维散点图
import visdom
import numpy as np
# 设置环境
vis=visdom.Visdom(env='training_monitor')
# 绘制3D散点图
vis.scatter(# X轴数据 随机生成100行3列数据X=np.random.rand(100, 3),# Y轴数据 随机生成100行1列数据Y=(Y + 1.5).astype(int),opts=dict(legend=['男性', '女性'], # 图例标签markersize=5, # 标记大小xtickmin=0, # x轴刻度最小值xtickmax=2, # x轴刻度最大值xlabel='数量', # x轴标签xtickvals=[0, 0.75, 1.6, 2], # x轴刻度值ytickmin=0, # y轴刻度最小值ytickmax=2, # y轴刻度最大值ytickstep=0.5, # y轴刻度间隔ztickmin=0, # z轴刻度最小值ztickmax=1, # z轴刻度最大值ztickstep=0.5, # z轴刻度间隔)
)

在这里插入图片描述

线性图vis.line()

vis.line() 参数说明

参数类型描述默认值注意事项
XTensor/ndarrayX轴坐标值,N或N×M维None可省略(自动生成0-N)
YTensor/ndarrayY轴坐标值,N或N×M维必填M表示线条数量
winstr目标窗口名称自动生成留空则创建新窗口
optsdict绘图选项字典None见下方选项表格

opts 选项明细表

选项类型描述默认值有效值/示例
fillareabool是否填充线下区域FalseTrue/False
markersbool是否显示数据点标记FalseTrue/False
markersymbolstr标记形状'dot''circle', 'cross', 'diamond'
markersizeint标记大小(像素)10正整数(如 15
linecolornp.array线条颜色数组NoneRGB数组,如 np.array([255,0,0])
dashnp.array线条类型数组'solid''dash', 'dot', 'dashdot'
legendlist图例名称列表None['Train', 'Val']
layoutoptsdictPlotly布局扩展选项None{'plotly': {'legend': {'x':0, 'y':1}}}
traceoptsdictPlotly轨迹扩展选项None{'plotly': {'mode':'lines+markers'}}
webglbool是否启用WebGL加速False大数据量时建议 True

关键特性说明

  1. X/Y维度规则

    • 单线模式:Y为N×1,X为N×1(或省略)
    • 多线模式:Y为N×M,X为N×M或N×1(共享X轴)
  2. 颜色与线条控制

    opts = {'linecolor': np.array([[255,0,0], [0,0,255]]),  # 第一条红,第二条蓝'dash': np.array(['solid', 'dash'])  # 第一条实线,第二条虚线
    }
    

线性图案例

  • 简单线性图
import numpy as np
import visdomvis = visdom.Visdom()# 基本线图
vis.line(Y=np.random.rand(10),opts=dict(title='Basic Line', markers=True)
)# 多线带图例
vis.line(X=np.arange(10),Y=np.column_stack([np.sin(np.arange(10)), np.cos(np.arange(10))]),opts=dict(title='Trig Functions',legend=['Sin', 'Cos'],linecolor=np.array([[255,0,0], [0,0,255]]),  # 红蓝双线dash=np.array(['solid', 'dash']) )
)

在这里插入图片描述

  • 实线、虚线的线条图
#实线、虚线等不同线
import visdom
import numpy as npvis=visdom.Visdom(env='training_monitor')
# 绘制三种线
win = vis.line(#  X轴数据 将三个在0和1之间的等差数列组成一个3列的矩阵X=np.column_stack((np.arange(0, 10),np.arange(0, 10),np.arange(0, 10),)),# Y轴数据 将三个在5和10之间的线性插值分别加上5、10后组成一个3列的矩阵Y=np.column_stack((np.linspace(5, 10, 10),np.linspace(5, 10, 10) + 5,np.linspace(5, 10, 10) + 10,)),opts={'dash': np.array(['solid', 'dash', 'dashdot']),'linecolor': np.array([[0, 191, 255],[0, 191, 255],[255, 0, 0],]),'title': '不同类型的线'}
)
# 在之前创建的窗口win上继续绘制线条
vis.line(X=np.arange(0, 10), # X轴数据Y=np.linspace(5, 10, 10) + 15, # Y轴数据win=win, # 使用之前创建的窗口name='4', # 线条名称update='insert', # 更新方式为插入opts={ # 绘制选项'linecolor': np.array([ # 线条颜色[255, 0, 0], # 红色]),'dash': np.array(['dot']), # 线条样式 只包含点}
)

在这里插入图片描述

  • 堆叠区域线性图
#堆叠区域
import visdom
import numpy as npvis=visdom.Visdom(env='training_monitor')Y = np.linspace(0, 4, 200)
win = vis.line(Y=np.column_stack((np.sqrt(Y), np.sqrt(Y) + 2)),X=np.column_stack((Y, Y)),opts=dict(fillarea=True, # 填充区域showlegend=False, # 不显示图例width=380, # 宽度height=330, # 高度ytype='log', # y轴类型title='堆积面积图', # 标题marginleft=30, # 左边距marginright=30, # 右边距marginbottom=80, # 底边距margintop=30, # 上边距),
)

在这里插入图片描述

茎叶图vis.stem

  • 函数可绘制一个茎叶图。它接受一个N或N×M张量X作为输入,它指定M时间序列中N个点的值。还可以指定一个包含时间戳的可选N或NXM张量Y,如果Y是一个N张量,那么所有M个时间序列都假设有相同的时间戳。
  • opts.colormap: 色图(string; default = 'Viridis')
  • opts.legend:包含图例名称的表。
  • opts.layoutopts:图形后端为布局接受的任何附加选项的字典,比如layoutopts={plotly:{legend': {x':0, 'y':0}}}
    您完全正确!在Visdom的茎叶图(vis.stem)中,X和Y轴的设定确实容易让人混淆,因为它的参数命名与常规的数学绘图习惯相反。让我们重新梳理清楚:

🔄 Visdom茎叶图参数设计

vis.stem(X, Y)中:

  • Y参数:实际对应的是X轴数据(自变量)
  • X参数:实际对应的是Y轴数据(因变量)

❓ 为什么Visdom这样设计

Visdom的API设计可能源于:

  1. 数据优先原则X参数接受主要可视化数据(函数值更关键)
  2. 与线图一致vis.line(Y=values)的延续性
  3. 工程习惯:某些库将输入数据称为X(如机器学习中的特征矩阵)

💡 记忆技巧

想象茎叶图的物理形态:

  • 茎(Stem)的根部固定在Y值(X轴)
  • 茎的顶端达到X值(Y轴高度)

📊 修正后的代码解释

import math
import numpy as np
import visdomvis = visdom.Visdom(env='training_monitor')# 生成X轴数据(自变量:角度)
angles = np.linspace(0, 2 * math.pi, 70)  # 0到2π的70个点# 生成Y轴数据(因变量:函数值)
function_values = np.column_stack((np.sin(angles), np.cos(angles)))  # 两列:sin和cosvis.stem(X=function_values,  # 茎顶的位置(Y轴值)Y=angles,           # 茎的位置(X轴值)opts=dict(legend=['sin(θ)', 'cos(θ)'],title='茎叶图:sin和cos函数对比',xtickvals=np.arange(0, 7, 1).tolist(),      # 使用 .tolist() 转换为 Python 列表xticklabels=['0', '1', '2', '3', '4', '5', '6'],ytickvals=np.arange(-1, 1.5, 0.5).tolist()   # 同样使用 .tolist())
)

在这里插入图片描述

🖼️ 可视化效果说明

元素对应数据示例值
茎的位置Y=angles0, 0.1π, 0.2π,…
茎顶高度X=function_valuessin(0)=0, cos(0)=1
X轴角度(θ)0到2π
Y轴函数值-1到1

深度学习训练案例

  • 完整的PyTorch训练过程,使用Visdom进行可视化:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import visdom# 初始化Visdom
vis = visdom.Visdom(env='MNIST_Experiment')# 定义简单CNN模型
class SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = torch.relu(torch.max_pool2d(self.conv1(x), 2))x = torch.relu(torch.max_pool2d(self.conv2(x), 2))x = x.view(-1, 320)x = torch.relu(self.fc1(x))x = self.fc2(x)return torch.log_softmax(x, dim=1)# 准备数据
transform = transforms.Compose([transforms.ToTensor()])
train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('./data', train=False, transform=transform)train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)# 初始化模型和优化器
model = SimpleCNN()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)
criterion = nn.NLLLoss()# 训练函数
def train(epoch):model.train()for batch_idx, (data, target) in enumerate(train_loader):optimizer.zero_grad()output = model(data)loss = criterion(output, target)loss.backward()optimizer.step()if batch_idx % 100 == 0:vis.line(X=[epoch * len(train_loader) + batch_idx],Y=[loss.item()],win='training_loss',update='append' if epoch + batch_idx > 0 else None,opts=dict(title='Training Loss', xlabel='Iterations', ylabel='Loss'))# 测试函数
def test(epoch):model.eval()test_loss = 0correct = 0with torch.no_grad():for data, target in test_loader:output = model(data)test_loss += criterion(output, target).item()pred = output.argmax(dim=1, keepdim=True)correct += pred.eq(target.view_as(pred)).sum().item()test_loss /= len(test_loader.dataset)accuracy = 100. * correct / len(test_loader.dataset)vis.line(X=[epoch],Y=[test_loss],win='test_loss',update='append' if epoch > 0 else None,opts=dict(title='Test Loss', xlabel='Epoch', ylabel='Loss'))vis.line(X=[epoch],Y=[accuracy],win='test_accuracy',update='append' if epoch > 0 else None,opts=dict(title='Test Accuracy', xlabel='Epoch', ylabel='Accuracy (%)'))# 可视化一些测试样本和预测结果if epoch % 5 == 0:sample_data = next(iter(test_loader))[0][:10]outputs = model(sample_data)preds = outputs.argmax(dim=1)vis.images(sample_data,opts=dict(title=f'Predictions at Epoch {epoch}', caption=' '.join(str(p.item()) for p in preds)))# 运行训练和测试
for epoch in range(1, 11):train(epoch)test(epoch)

在这里插入图片描述
在这里插入图片描述

相关文章:

PyTorch可视化工具——使用Visdom进行深度学习可视化

文章目录 前置环境Visdom安装并启动VisdomVisdom图形APIVisdom静态更新API详解通用参数说明使用示例Visdom动态更新API详解1. 使用updateappend参数2. ~~使用vis.updateTrace方法~~3. 完整训练监控示例 Visdom可视化操作散点图plot.scatter()散点图案例线性图vis.line()vis.lin…...

Qt无边框界面添加鼠标事件

在Qt中实现无边框窗口的鼠标事件处理&#xff0c;主要涉及窗口拖动和调整大小功能。以下是分步实现的代码示例&#xff1a; 1. 创建无边框窗口 首先&#xff0c;创建一个继承自QWidget的自定义窗口类&#xff0c;并设置无边框标志&#xff1a; #include <QWidget> #in…...

企业级爬虫进阶开发指南

企业级爬虫进阶开发指南 一、分布式任务调度系统的深度设计 1.1 架构设计原理 图表 1.2 核心代码实现与注释 分布式锁服务 # distributed_lock.py import redis import timeclass DistributedLock:def __init__(self, redis_conn):self.redis = redis_connself.lock_key = …...

Ubuntu ping网络没有问题,但是浏览器无法访问到网络

我这边是尝试清楚DNS缓存然后重新访问就可以了。 使用 resolvectl 刷新 DNS 缓存 在 Ubuntu 20.04 及更高版本中&#xff0c;可以使用以下命令来刷新 DNS 缓存&#xff1a; sudo resolvectl flush-caches 使用 systemd-resolve&#xff08;适用于旧版本&#xff09; 如果你…...

网络安全-等级保护(等保) 2-7 GB/T 25058—2019 《信息安全技术 网络安全等级保护实施指南》-2019-08-30发布【现行】

################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…...

数据结构实验10.1:内部排序的基本运算

文章目录 一&#xff0c;实验目的二&#xff0c;实验内容1. 数据生成与初始化2. 排序算法实现&#xff08;1&#xff09;直接插入排序&#xff08;2&#xff09;二分插入排序&#xff08;3&#xff09;希尔排序&#xff08;4&#xff09;冒泡排序&#xff08;5&#xff09;快速…...

C#:多线程

一.线程常用概念 线程&#xff08;Thread&#xff09;&#xff1a;操作系统执行程序的最小单位 进程&#xff08;Process&#xff09;&#xff1a;程序在内存中的运行实例 并发&#xff08;Concurrency&#xff09;&#xff1a;多个任务交替执行&#xff08;单核CPU&#xff0…...

基于Zynq SDK的LWIP UDP组播开发实战指南

一、为什么选择LWIP组播? 在工业控制、智能安防、物联网等领域,一对多的高效数据传输需求日益增长。Zynq-7000系列SoC凭借其ARM+FPGA的独特架构,结合LWIP轻量级网络协议栈,成为嵌入式网络开发的理想选择。本文将带您实现: LWIP组播配置全流程动态组播组切换技术零拷贝数据…...

c#将json字符串转换为对象数组

在C#中&#xff0c;将JSON字符串转换为对象数组是一个常见的需求&#xff0c;特别是在处理来自Web API的响应或需要反序列化本地文件内容时。这可以通过使用Newtonsoft.Json&#xff08;也称为Json.NET&#xff09;库或.NET Core内置的System.Text.Json来完成。以下是如何使用这…...

机器学习在智能水泥基复合材料中的应用与实践

“机器学习在智能水泥基复合材料中的应用与实践” 课程 内容 机器学习基础模型与复合材料研究融合 机器学习在复合材料中的应用概述机器学习用于复合材料研究的流程复合材料数据收集与数据预处理 实例&#xff1a;数据的收集和预处理 复合材料机器学习特征工程与选择 实例&a…...

wps编辑技巧

1、编辑模式 2、图片提取方法&#xff1a;右键保存图片 可以直接右键保存下来看看是否是原始图&#xff0c;如果歪着的图&#xff0c;可能保存下来是正的&#xff0c;直接保存试下 3、加批注...

开放世界RPG:无缝地图与动态任务的拓扑学架构

目录 开放世界RPG:无缝地图与动态任务的拓扑学架构引言第一章 地图分块系统1.1 动态加载算法1.2 内存管理模型第二章 任务拓扑网络2.1 任务依赖图2.2 动态可达性分析第三章 NPC行为系统3.1 行为森林架构3.2 日程规划算法第四章 动态事件系统4.1 事件传播模型4.2 玩家影响指标第…...

【图像处理入门】1. 数字图像的本质:从像素到色彩模型

作为图像处理的开篇&#xff0c;本文将带你拆解数字图像的底层逻辑&#xff1a;从模拟图像到数字信号的神奇转换&#xff0c;到像素世界的微观构成&#xff0c;再到彩色图像的编码奥秘。通过 Python 代码实战&#xff0c;你将亲手触摸图像的 “基因”—— 像素值&#xff0c;并…...

(已解决:基于WSL2技术)Windows11家庭中文版(win11家庭版)如何配置和使用Docker Desktop

目录 问题现象&#xff1a; 问题分析&#xff1a; 拓展&#xff1a; 解决方法&#xff1a; 1、使用WSL2技术&#xff08;亲测有效&#xff09; 注意&#xff1a; 2、开启Hyper-V功能&#xff08;未经亲测&#xff0c;待研究&#xff09; 问题现象&#xff1a; 今天想在本…...

Ubuntu20.04部署KVM

文章目录 一. 环境准备关闭防火墙&#xff08;UFW&#xff09;禁用 SELinux更换镜像源检查 CPU 虚拟化支持 二. 安装KVM安装 KVM 及相关组件启动 libvirtd 服务验证安装创建虚拟机 一. 环境准备 4C8G&#xff0c;50G硬盘——VMware Workstation需要给虚拟机开启虚拟化引擎 roo…...

OpenCV CUDA 模块图像过滤------创建一个高斯滤波器函数createGaussianFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::createGaussianFilter 是 OpenCV CUDA 模块中的一个工厂函数&#xff0c;用于创建一个高斯滤波器。这个滤波器可以用来平滑图像&#…...

计算机视觉与深度学习 | matlab实现ARIMA-WOA-CNN-LSTM时间序列预测(完整源码和数据)

以下是一个基于MATLAB的ARIMA-WOA-CNN-LSTM时间序列预测框架。由于完整代码较长,此处提供核心模块和实现思路,完整源码和数据可通过文末方式获取。 1. 数据准备(示例数据) 使用MATLAB内置的航空乘客数据集: % 加载数据 data = readtable(airline-passengers.csv); data …...

可视化图解算法43:数组中的逆序对

1. 题目 ​牛客网 面试笔试TOP101 描述 在数组中的两个数字&#xff0c;如果前面一个数字大于后面的数字&#xff0c;则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007 数据范围&…...

【Python】使用Python实现调用API获取图片存储到本地

使用Python实现调用API获取图片存储到本地 目录 使用Python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现5、结果查看 1、项目概述 开发一个自动化工具&#xff0c;用于从JSON数据源中提取图像ID&#xff0c;通过调用指定API获取未经压缩的原始…...

腾讯2025年校招笔试真题手撕(一)

一、题目 有n 把钥匙&#xff0c;m 个锁&#xff0c;每把锁只能由一把特定的钥匙打开&#xff0c;其他钥匙都无法打开。一把钥匙可能可以打开多把锁&#xff0c;钥匙也可以重复使用。 对于任意一把锁来说&#xff0c;打开它的钥匙是哪一把是等概率的。但你无法事先知道是哪一把…...

Vue3 与 Vue2 区别

一、Vue3 与 Vue2 区别 对于生命周期来说&#xff0c;整体上变化不大&#xff0c;只是大部分生命周期钩子名称上 “on”&#xff0c;功能上是类似的。不过有一点需要注意&#xff0c;组合式API的Vue3 中使用生命周期钩子时需要先引入&#xff0c;而 Vue2 在选项API中可以直接…...

java集合详细讲解

Java 8 集合框架详解 Java集合框架是Java中最重要、最常用的API之一&#xff0c;Java 8对其进行了多项增强。下面我将全面讲解Java 8中的集合框架。 一、集合框架概述 Java集合框架主要分为两大类&#xff1a; Collection - 单列集合 List&#xff1a;有序可重复Set&#xf…...

嵌入式学习笔记 - STM32 U(S)ART 模块HAL 库函数总结

一 串口发送方式&#xff1a; ①轮训方式发送&#xff0c;也就是主动发送&#xff0c;这个容易理解&#xff0c;使用如下函数&#xff1a; HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout); ②中断方式发送&#xff…...

【VLNs篇】04:SayNav-为新环境中的动态规划到导航进行大型语言模型的基础构建

栏目内容论文标题SayNav: 为新环境中的动态规划到导航进行大型语言模型的基础构建 (SayNav: Grounding Large Language Models for Dynamic Planning to Navigation in New Environments)研究问题自主代理在未知环境中执行复杂导航任务&#xff08;如MultiON&#xff09;时&…...

MySQL中添加一个具有创建数据库权限的用户

要在MySQL中添加一个具有创建数据库权限的用户&#xff0c;可按以下步骤操作&#xff1a; 1. 登录MySQL 使用拥有足够权限&#xff08;一般是root用户 &#xff09;的账号登录到MySQL数据库。在命令行输入&#xff1a; mysql -u root -p然后输入对应的密码&#xff0c;即可进…...

oracle使用SPM控制执行计划

一 SPM介绍 Oracle在11G中推出了SPM&#xff08;SQL Plan management&#xff09;,SPM是一种主动的稳定执行计划的手段&#xff0c;能够保证只有被验证过的执行计划才会被启用&#xff0c;当由于种种原因&#xff08;比如统计信息的变更&#xff09;而导致目标SQL产生了新的执…...

[Java实战]Spring Boot整合Seata:分布式事务一致性解决方案(三十一)

[Java实战]Spring Boot整合Seata&#xff1a;分布式事务一致性解决方案&#xff08;三十一&#xff09; 引言 在微服务架构中&#xff0c;业务逻辑被拆分为多个独立的服务&#xff0c;每个服务可能拥有独立的数据库。当需要跨服务操作多个数据库时&#xff0c;如何保证数据的…...

Openwrt下使用ffmpeg配合自建RTSP服务器实现推流

目前在Openwrt下时mjpg_streamer实现UVC摄像头转网络摄像头的方案很多&#xff0c;这种方案视频服在路由模组中&#xff0c;在局域网中使用很方便。但是对于需要远程监控管理的情况&#xff0c;mjpg_streamer不适应&#xff0c;因为不在局域网中的播放器无法访问到路由模组中的…...

MySQL 索引的增删改查

MySQL 索引的增删改查 1 建表时创建索引 [UNIQUE|FULLTEXT|SPATIAL] INDEX|KEY [别名] (字段名 [(长度)] [ASC|DESC] )主键直接写&#xff1a; PRIMARY KEY (Id)例如&#xff1a; CREATE TABLE people (id int NOT NULL PRIMARY KEY AUTO_INCREMENT,last_name varchar(10)…...

MySQL Host 被封锁解决方案(全版本适用 + Java 后端优化)

引言 MySQL 中 “Host is blocked because of many connection errors” 是生产环境常见问题&#xff0c;若处理不当会导致服务中断。本文结合 MySQL 官方文档&#xff08;5.5/8.0&#xff09;、Java 后端最佳实践及企业级经验&#xff0c;提供从 “快速解封” 到 “根源优化”…...