尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
DeepLabv3+语义分割实战:PyTorch跑通VOC与Cityscapes
简介基于PyTorch在VOC与Cityscapes数据集上训练DeepLabv3图像分割算法的完整项目面向已有Python基础、希望快速上手语义分割实战的开发者也适合作为课程设计或算法预研的参考。资源共包含43个文件其中23个Python脚本分工清晰覆盖数据加载与增强、模型搭建含ASPP空洞空间金字塔池化模块与解码器、优化器与学习率策略设定、损失函数计算以及IoU指标评估并提供了训练、预测等入口供直接调用17张PNG图片展示了不同图像的分割结果、原始图像与标签叠加对比方便直观判断模型表现。另有README和说明文档概述目录结构与运行要点。整套资源仅2.13MB体量精简而代码组织模块化特别适合边阅读边动手调试。目前已有492人学习借助该源码既能了解VOC、Cityscapes两大数据集的预处理和训练流程又能深入理解DeepLabv3如何利用空洞卷积扩大感受野、结合解码器细化边缘最终可迁移到自动驾驶、遥感等领域完成自定义分割任务。1. 图像分割实战在 VOC 和 Cityscapes 上用 PyTorch 把 DeepLabv3 完整跑通图像分割模型的代码网上遍地都是但能直接对着 VOC 和 Cityscapes 两个数据集完整跑训练、出评估指标的 PyTorch 工程并不多。这套 DeepLabv3 项目源码把模型结构、数据加载、训练、评估、推理可视化全部按模块拆开拿到手里可以直接开始复现。网络部分基于 DeepLabv3 的典型结构backbone 独立放在 modeling.py 里方便切换主干和加载预训练权重datasets 模块对两个数据集分别封装了 data 类类别数不同、标注格式不同但底层统一成模型能直接吃的张量。metrics 目录里手写了流式 IoU 指标类不依赖外部评估库想改评估策略也很方便。适合正在做语义分割课程设计和研究课题的学生也适合需要在自定义数据上验证 DeepLabv3 效果、不想从零写代码的算法工程师。2. DeepLabv3 网络结构与双数据集加载从 ASPP 模块、类别映射到数据集代码走读2.1 ASPP 编码器与解码器空洞卷积的并行多尺度设计DeepLabv3 的核心在网络部分项目的 network 目录下拆了三个文件_deeplab.py 定义整体模型backbone/modeling.py 放 ResNet 系列的基础编码网络network/utils.py 负责权重初始化和预训练加载。模型主体是编码器-解码器结构编码器先用 ResNet 提特征再把最后一个特征图送进 ASPPAtrous Spatial Pyramid Pooling模块。ASPP 的设计思路很简单同一张特征图用不同 dilation rate 的空洞卷积并行提取多尺度上下文信息最后拼接到一起。空洞卷积的原理是往卷积核的采样点之间插入间隔dilation6 的 3x3 卷积等效于普通 13x13 卷积的感受野但参数量仍然是九个。这样做的好处不用多谈scale 变化大的场景里模型能同时看到路面的全局上下文和栏杆的局部纹理而计算量只增加了少量空洞卷积的运算。DeepLabv3 相比 DeepLabv3 的改进在于加了 Decoder 部分把 ASPP 的低分辨率输出上采样 4 倍与 ResNet 中层的低层高分辨率特征做 concat再经过 3x3 卷积和上采样得到最终掩码这样边界细节能保留得更好。下面是这份代码中 ASPP 模块的典型实现结构# network/_deeplab.py 中的 ASPP 模块 import torch import torch.nn as nn import torch.nn.functional as F class ASPP(nn.Module): def __init__(self, in_channels, out_channels256, rates(6, 12, 18)): super().__init__() # 1x1 卷积分支等价于 dilation1 的普通卷积 self.branch1 nn.Sequential( nn.Conv2d(in_channels, out_channels, 1, biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue), ) # 三个并行的空洞卷积分支padding 与 dilation 保持一致 self.branch2 nn.Sequential( nn.Conv2d(in_channels, out_channels, 3, paddingrates[0], dilationrates[0], biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue), ) self.branch3 nn.Sequential( nn.Conv2d(in_channels, out_channels, 3, paddingrates[1], dilationrates[1], biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue), ) self.branch4 nn.Sequential( nn.Conv2d(in_channels, out_channels, 3, paddingrates[2], dilationrates[2], biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue), ) # 全局图像池化分支用于捕捉整图上下文 self.branch5 nn.Sequential( nn.AdaptiveAvgPool2d(1), nn.Conv2d(in_channels, out_channels, 1, biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue), ) # 五路特征拼接后统一降维到 out_channels self.project nn.Sequential( nn.Conv2d(out_channels * 5, out_channels, 1, biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue), ) def forward(self, x): size x.size()[2:] f1 self.branch1(x) f2 self.branch2(x) f3 self.branch3(x) f4 self.branch4(x) # 全局池化输出是 1x1拼接前必须插值回当前特征图尺寸 f5 F.interpolate(self.branch5(x), sizesize, modebilinear, align_cornersTrue) out torch.cat([f1, f2, f3, f4, f5], dim1) return self.project(out)注意几个容易忽略的点分支 5 的全局池化输出只有 1x1 分辨率拼接前必须双线性上采样回当前特征图的尺寸代码里用 F.interpolate 处理align_cornersTrue 是和 backbone 内部对齐保持一致的关键。BN 层在空洞卷积后是默认配置训练时和预测时的行为差异会直接影响结果精度这是后面避坑部分会列出来的问题。rates 用固定的 (6, 12, 18)当输入分辨率变化较大时一般不需要调整改动它反而会让预训练权重失去适配含义。2.2 VOC 和 Cityscapes 的类别映射从原始标注到训练标签VOC 数据集的语义分割标签有 21 个类背景加 20 个物体类别包括飞机、自行车、鸟、船、瓶子、公交车、汽车、猫、椅子、牛、餐桌、狗、马、摩托车、人、盆栽、羊、沙发、火车和电视显示器。Cityscapes 数据集是针对城市街景的原始标注类别有 30 个左右但绝大多数实现只用其中 19 个有效类参与训练剩下的类——比如天空、地形里不可辨识的小块——映射到 ignore_index 255不参与 loss 计算。这个类别映射的关键点在于两个数据集的 class id 并不是连续的。VOC 的 id 基本连续 1-20背景是 0而 Cityscapes 的原始 id 里有大量空洞比如车辆类从 26 到 35 跨了十个 id直接送进 CrossEntropyLoss 网络是学不出来的。datasets/data/cityscapes.py 里通常维护一张 30 到 19 的映射表把可训练类映射到 0-18void 类统一映射到 255。# datasets/data/cityscapes.py 中的类别 id 映射片段 # 原始 Cityscapes label id 到训练类别的映射255 表示忽略 cityscapes_id_to_train_id { 0: 255, # unlabeled 1: 255, # ego vehicle # ... 部分类别略 7: 0, # road - 训练 id 0 8: 1, # sidewalk - 训练 id 1 # ... 中间类别略 24: 18, # motorcycle - 训练 id 18 33: 255, # pole部分实现不使用 } def convert_label(label, id_to_trainid): label_copy label.copy() for orig_id, train_id in id_to_trainid.items(): label_copy[label orig_id] train_id return label_copy这里要提醒一句不同实现里 19 类的选择略有不同有的把 pole 和 traffic light 合并成一个类有的把 terrain 单独保留所以拿到新工程的第一个动作是数一下 cityscapes.py 里 train_id 最后的最大值确认类别数和 loss 里 ignore_index 的配置一致。2.3 datasets/data/voc.py 和 cityscapes.py 的读取与增强流程VOC 的标注是 PNG 格式的 index 图PIL 打开时要用 P 模式直接转成 RGB 再当普通图像处理会在边界处产生混乱的过渡值。项目里 datasets/data/voc.py 的基本读取流程是把 image 和 mask 同时加载经过 transform 后返回张量对。# datasets/data/voc.py 的核心结构 import os from PIL import Image import torch.utils.data as data class VOCSegmentation(data.Dataset): def __init__(self, root, image_settrain, transformNone): self.root root self.transform transform # ImageSets/Segmentation 下的 txt 文件列出图片 id with open(os.path.join(root, ImageSets, Segmentation, f{image_set}.txt)) as f: self.images [line.strip() for line in f.readlines()] def __len__(self): return len(self.images) def __getitem__(self, index): img_id self.images[index] # 注意 mask 必须以 P 模式打开保留像素索引 image Image.open(os.path.join(self.root, JPEGImages, f{img_id}.jpg)).convert(RGB) target Image.open(os.path.join(self.root, SegmentationClass, f{img_id}.png)) if self.transform is not None: image, target self.transform(image, target) return image, target在这种 Transform 体系下数据增强要同步作用于原图和 mask不能对二者做不同的随机操作。utils/ext_transforms.py 里封装的 ExtRandomScale、ExtRandomCrop、ExtRandomHorizontalFlip 就是按双输入同步方式实现的这里简单列一个常见的训练增强组合# utils/ext_transforms.py 中的训练增强组合 train_transform ext_transforms.ExtCompose([ # 原图随机缩放 0.5~2.0mask 同步插值 ext_transforms.ExtRandomScale((0.5, 2.0)), # 随机裁剪到 512x512不足补边 ext_transforms.ExtRandomCrop(size(512, 512), pad_if_neededTrue), # 随机水平翻转 ext_transforms.ExtRandomHorizontalFlip(), # 转成 tensor并做 ImageNet 均值方差归一化 ext_transforms.ExtToTensor(), ext_transforms.ExtNormalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ])对 Cityscapes 的训练通常用 crop size 768需要把 RandomCrop 的 size 相应调大否则大图上的小目标容易裁不到。验证时的增强要简单得多只做 resize 到固定尺寸加归一化不做随机翻转。3. main.py 训练主流程参数配置、损失函数、poly 学习率与训练循环3.1 训练入口与参数面板main.py 是整个训练的入口所有超参数通过 argparse 传入。实际部署时经常用到的是这几个参数# VOC 数据集训练示例 python main.py \ --dataset voc \ --data-root /data/VOCdevkit \ --batch-size 16 \ --crop-size 512 \ --base-lr 0.007 \ --epochs 50 # Cityscapes 数据集训练示例图更大所以 crop 更大 python main.py \ --dataset cityscapes \ --data-root /data/cityscapes \ --batch-size 8 \ --crop-size 768 \ --base-lr 0.01 \ --epochs 100以表格列出几个关键参数的经验值参数VOC 常用值Cityscapes 常用值说明batch size168实际以显存为准V100 16G 可再调大crop size512768配合 ResNet 输出 stride 8 使用需能被 16 整除base_lr0.0070.01SGD poly 时常用Adam 要降到 1e-4epochs50100Cityscapes 数据量大迭代次数要更多weight_decay1e-41e-4过大会让 BN 层的 scale 不稳定momentum0.90.9SGD 标配注意 crop size 和 backbone 的 downsampling stride 有连带关系。DeepLabv3 的 ResNet 输出 stride 一般设成 8输入 512x512 对应最后特征图 64x64这个尺寸既能保留足够空间信息又不至于让 ASPP 的感受野互相重叠太多。把 crop size 改成非 16 倍数的值会直接触发断言报错。3.2 损失函数CrossEntropy 与 ignore_index项目里 utils/loss.py 主要是对 CrossEntropyLoss 的封装。语义分割最常用的损失还是逐像素交叉熵但对带忽略区域的标签要处理到位。# utils/loss.py 的核心封装 import torch.nn as nn class SegmentationLoss(nn.Module): def __init__(self, ignore_index255, reductionmean): super().__init__() self.criterion nn.CrossEntropyLoss( ignore_indexignore_index, reductionreduction ) def forward(self, pred, target): # pred 是 (N, C, H, W) 的 logitstarget 是 (N, H, W) 的类别 id return self.criterion(pred, target)ignore_index 的作用是让标签里等于 255 的位置完全不参与梯度计算。VOC 的标注里人和物体边界上有少量 255 像素Cityscapes 的 void 区域更是大面量出现如果忽略这个参数loss 会被这些无意义像素拉高模型收敛后边缘区域也会出现奇怪的伪影。另一个点是 reduction 默认用 mean但有的实现用 sum对小目标类别比较敏感的场景可以实验性切换。3.3 poly 学习率调度与训练循环DeepLab 系列论文里惯用的是 poly 衰减策略学习率随着迭代步数线性指数下降到 0。这个策略对分割任务很有效越到后期学习率越低能稳定收敛到比较好的极值点。# utils/scheduler.py 中的 PolyLR 调度器 class PolyLR: def __init__(self, optimizer, base_lr, max_iters, power0.9): self.optimizer optimizer self.base_lr base_lr self.max_iters max_iters self.power power def get_lr(self, iteration): return self.base_lr * (1 - iteration / self.max_iters) ** self.power def step(self, iteration): lr self.get_lr(iteration) for param_group in self.optimizer.param_groups: param_group[lr] lr注意 max_iters 应该是 total_iterations等于 epochs 乘每 epoch 的 batch 数量不是 epoch 数。很多入门实现在这里把 max_iters 填成 epochs结果是学习率在第 1 个 epoch 内就快速衰减到零后续 step 全成了小学习率的空转。训练主循环的骨架不复杂重点在验证时机的选择# main.py 中的训练主循环伪代码 model.train() for epoch in range(epochs): for i, (images, targets) in enumerate(train_loader): images, targets images.cuda(), targets.cuda() outputs model(images) # 前向 loss criterion(outputs, targets) # 交叉熵损失 optimizer.zero_grad() loss.backward() optimizer.step() scheduler.step(global_iter) # poly 调度 global_iter 1 # 每 500 步在验证集上统计一次 mIoU if global_iter % 500 0: model.eval() val_metrics run_validation(model, val_loader, metrics) model.train()验证时一定要切回 eval 模式把 BN 层和 Dropout 关掉否则拿到的是不稳定的随机结果。这个验证掉点的问题很多新手会碰上后面避坑部分会单独解释。4. 评估与推理stream_metrics 流式 IoU 计算与 predict.py 可视化4.1 stream_metrics.py 的流式指标实现语义分割评估最常用的指标是 mIoUmean Intersection over Union项目里 metrics/stream_metrics.py 自己实现了流式版本不依赖外部评估包。流式的意思是维护一个全局混淆矩阵每个 batch 往里面累加统计最后统一计算各类别的 IoU。这种做法在验证集很大的时候很有用不用把整个预测结果存在内存里。# metrics/stream_metrics.py 的核心逻辑 import numpy as np class StreamSegMetrics: def __init__(self, n_classes): self.n_classes n_classes self.confusion_matrix np.zeros((n_classes, n_classes), dtypenp.int64) def reset(self): self.confusion_matrix np.zeros( (self.n_classes, self.n_classes), dtypenp.int64 ) def update(self, pred, target): pred pred.flatten() target target.flatten() # 只统计有效类别区域忽略 255 mask (target 0) (target self.n_classes) # 一次 bincount 统计出所有组合计数满秩 reshape 成混淆矩阵 cm np.bincount( self.n_classes * target[mask] pred[mask], minlengthself.n_classes ** 2 ) self.confusion_matrix cm.reshape(self.n_classes, self.n_classes) def get_results(self): # 逐类 IoU TP / (TP FP FN)加 1e-10 防除零 diag np.diag(self.confusion_matrix).astype(np.float64) row_sum self.confusion_matrix.sum(axis1) # 真实类像素总数 col_sum self.confusion_matrix.sum(axis0) # 预测类像素总数 iou diag / (row_sum col_sum - diag 1e-10) return { mIoU: round(np.nanmean(iou), 4), class_iou: iou, }bincount 那一段是混淆矩阵更新的关键用 target 的行索引乘上类别数再加上 pred 的列索引一次性把所有像素统计进一个一维数组再 reshape 成混淆矩阵。这比两层 for 循环快得多在 Cityscapes 这种单张图一百多万像素的验证集上性能差别肉眼可见。pixAcc 像素准确率的计算同理直接用对角线之和除以总有效像素即可。4.2 predict.py 单图推理与结果文件predict.py 是推理脚本加载训练好的 checkpoint 对单张图片做分割。典型调用方式是python predict.py \ --checkpoint checkpoints/best_model_voc.pth \ --input samples/23_image.png \ --output samples/23_pred.png \ --dataset voc \ --save-overlay输出的 pred 图是每个像素按类别 id 着色的 index 图overlay 则是把半透明的预测结果叠加到原图上便于直接看分割边界是否对齐物体边缘。如果是 VOC 的 checkpoint预测时要注意类别 id 0 是背景如果是 Cityscapes 模型还要注意 train_id 和原始标签 id 的转换否则画出来的图颜色会完全错乱。4.3 samples 目录结果文件对照与目检流程项目 samples 目录里能看到若干组结果样例包括 1、23、114 这几个 VOC 样本和 city_1、city_6 两个 Cityscapes 样本。每组都是几类文件文件后缀含义建议检查点_image.png原始输入图像确认分辨率与训练时一致_target.png人工标注的真值 mask看边界是否有 255 忽略像素_pred.png模型预测的 mask主要关注小物体和边缘_overlay.png预测叠加到原图的效果看轮廓贴合度检查误判区域建议的验证流程是用一个验证集跑完整评估拿到整体 mIoU 后再挑几个典型样本看 overlay 图。比如 114_image.png 这类样本通常包含小物体和遮挡关系光看 mIoU 是 0.78 还是 0.80不如直接看图更直观。samples 里的 visdom-screenshoot.png 就是训练过程中用 Visdom 截下来的训练曲线和分割效果后面的进阶部分会讲怎么自己复现这个监控。5. 避坑记录从 loss 发散、显存溢出到类别对齐失败的经验5.1 训练 loss 不降反升甚至出现 NaN现象训练前几个 epoch 的 loss 非但不降反而从 0.5 慢慢涨到 2 以上再过几轮直接变成 NaN。原因base_lr 设置过大是头号元凶。SGD 在 poly 策略下初始 lr 0.007 是常见值但换到 batch size 较小的数据时梯度更新幅度会相对偏大。另一个常见原因是 backbone 的预训练权重没加载成功BN 层的 running_mean 还在默认值前向输出不稳定反向时梯度爆炸。还有一个容易忽略的情况是数据里有异常标签比如 Cityscapes 的 target 最大值超出类别数CrossEntropy 里出现了 out-of-range 的索引。解决先把初始 lr 降到 0.001 跑 500 步观察 loss 是否平稳打印 load_state_dict 时的 missing key 和 unexpected key确认 backbone 每个卷积层都加载到了权重在 dataset 的__getitem__里加一行assert target.max() n_classes提前暴露标签问题。5.2 CUDA out of memory 在训练刚启动就出现现象训练脚本刚跑几个 iteration立刻报CUDA out of memory退出训练。原因crop size 太大、batch size 太高、backbone 输出 stride 设成 8 导致中间特征图占用显存翻倍。DeepLabv3 的 ResNet 在 stride 8 时最后一层特征图是输入图的 1/8对 512x512 输入就是 64x64ASPP 三个空洞卷积分支加上 concat显存消耗确实不低。解决先以 batch size 2、crop size 320 跑通一个迭代再用 nvidia-smi 观察显存使用量按可用显存估算合理 batch。常见做法是把 batch size 降半或者用梯度累积每两个 batch 累加一次梯度再更新效果等价于跪了一截显存的大 batch。Cityscapes 的 768 裁剪可以暂时降到 640先验证流程再逐步调回去。5.3 切到 Cityscapes 后 mIoU 掉到个位数现象模型在 VOC 上训练正常mIoU 能到 0.7 左右换到 Cityscapes 之后验证 mIoU 只有 1 到 2几乎等于随机猜测。原因class id 映射错了。Cityscapes 原始标签里有三十多个值void 类占掉很大比例如果直接按原始 id 做 loss等于把 void 当成一个正常类别参与训练模型没有能力学习这样混乱的目标。同时 eval 阶段的指标统计也要用同样的映射否则混淆矩阵里的行和列对不上。解决检查 cityscapes.py 里的 id_to_train_id 映射表把 void 统一映射到 255训练类映射到 0-18。同时确认 ignore_index 设置为 255并且验证阶段跑 StreamSegMetrics 时 n_classes 传 19不能传 30。这是切换数据集时最容易被忽视的一环我见过不少人在这一步翻车后重新排查了整整两天。5.4 预训练权重加载报 missing key 与 unexpected key现象加载.pth权重时控制台刷出大段 missing key 和 unexpected key。原因官方发布的 ResNet 权重是 ImageNet 分类格式最后一层是全连接分类头而分割模型的 backbone 截到最后卷积层分类头自然就成了 unexpected key。反过来加载到自己定义的 ResNet 时如果层名里带了 module. 前缀或自定义命名空间就会大量出现 missing key。解决在 network/utils.py 里做一次映射处理加载时用 strictFalse把不是分类头的 key 过滤掉。常见做法是在 load 前先打印两个 key 集合手动对齐名称差异不要直接忽略所有报错。另外 BN 层的 num_batches_tracked 键有时会出现在 missing 列表里这是正常现象不影响加载。5.5 预测可视化全灰看不到分割色块现象predict.py 跑完输出的 pred 图整张灰蒙蒙只有零星看点与人眼看到的物体边界完全对应不上。原因可视化时用了错误的着色表。预测输出是 train_id 索引直接用城市标注原始颜色的 colormap 上色很多索引对应的颜色都是灰色。另一种情况是 overlay 叠加时透明度过高把预测色块全盖没了。解决预测前做 train_id 到原始标签 id 的逆映射或者直接用项目里给定的调色板 dict。叠加时 alpha 取 0.5 左右先看 pred 图再看 overlay 图两个图结合判断。如果用的是别人项目的可视化脚本第一时间检查 colormap 的键是原始 id 还是 train id这是很经典的坑。6. 进阶用 Visdom 实时监控训练把 DeepLabv3 迁移到自己的数据集6.1 Visdom 服务启动与指标监控utils/visualizer.py 封装了 Visdom 可视化启动方式很简单python -m visdom.server -port 8097训练脚本运行后浏览器打开http://localhost:8097在一个 env 里就能看到 loss 曲线、学习率曲线和验证集 mIoU 曲线。我一般会每隔 200 步把当前 batch 的原图、真值 mask 和预测图推到同一个 env这样不用等一个 epoch 结束就能看出模型是否在朝着正确的方向收敛。6.2 自定义数据集迁移的四步把这份代码迁移到自己的数据集大致按四步走先把标注转成 index 图类别从 0 开始连续编号void 用 255再仿照 datasets/data/voc.py 写一个 Dataset 子类替换图片读取路径在 main.py 里注册新的 dataset 名改 n_classes 参数最后灵活决定冻结策略如果数据量小可以冻结 backbone 前几层只让 ASPP 和 decoder 部分更新能明显减少过拟合。6.3 验证与坏例分析模型最后一步的验证我习惯按整体指标加典型样本目检加坏例分析三步走。先跑一遍完整验证集拿 mIoU然后挑最好的和最差的若干样本看 overlay 图和 target 图的差异总结模型对哪一类出错率高再决定是否对困难类别做加权采样。图像分割最忌讳只看一个 mIoU 数字就结束因为它掩盖了类别不均衡的问题。从那以后我每次跑完分割实验都强制做一遍坏例分析尤其是 Cityscapes 里的小目标类别这些类经常被大目标整体吞掉。希望你后续做实验时也能保持这个习惯希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

CNN-LSTM混合网络实现小时级天气预测的原理与PyTorch实践

CNN-LSTM混合网络实现小时级天气预测的原理与PyTorch实践

简介:这是一套面向天气预测与时序建模学习者的完整Python项目,依托CNN-LSTM混合网络实现精细化小时级天气预报。项目将卷积神经网络的局部特征提取能力与长短期记忆网络的时序记忆能力结合,适合有一定深度学习基础、希望快速上手时序预测实战…

📅 2026/10/9 6:17:27
ChatGLM3 Composite Demo 实战指南:基于 Streamlit 的对话、工具与代码解释器一体化演示

ChatGLM3 Composite Demo 实战指南:基于 Streamlit 的对话、工具与代码解释器一体化演示

大模型AI Agent模型推理服务微调对话系统 【免费下载链接】ChatGLM3 ChatGLM3 series: Open Bilingual Chat LLMs | 开源双语对话语言模型 项目地址: https://gitcode.com/zai-org/ChatGLM3 点击查看 免费下载 ChatGLM3 Composite Demo 是 ChatGLM3 系列项目提供的…

📅 2026/10/9 6:17:27
AnyPS5 跨平台图形兼容层:SPIR-V 与 SDL 实战解析

AnyPS5 跨平台图形兼容层:SPIR-V 与 SDL 实战解析

1. 从标题到落地:AnyPS5 到底想解决什么问题第一次看到 AnyPS5 这个名字,很多人会下意识以为它跟某款主机有关。其实从关键词组合(Linux、Windows、SPIR-V、SDL)来看,它更像是一个跨平台的图形/渲染兼容层项目&#xf…

📅 2026/10/9 6:17:27
MORE NEWS

更多资讯

📰

Python入门高频问题全解析:环境配置、导包、语法与并发

刚装好 Python 的新手,大多数会在同一个地方翻车:软件装完了,双击 .py 文件要么闪一下就关掉,要么在终端里跑一行import numpy直接给你一个ModuleNotFoundError,然后就开始在搜索框里疯狂输入“python安装教程”“pyth…

📰

Ubuntu 20.04 WiFi 连接故障排查与 netplan/nmcli 实战配置

简介:本资源是一份面向Ubuntu 20.04初学者与系统运维人员的Wi-Fi连接故障排障指南,聚焦解决“无Wi-Fi图标”“无法识别无线网卡”等典型驱动缺失或配置错误问题。内容系统梳理两种主流解决方案:一是通过有线网络安装Broadcom芯片专用驱动&…

📰

PPT公式导入XHEDITOR图文混排的完整方案:从格式探测到LaTeX渲染全链路实战

1. 从PPT到XHEDITOR,先别急着动手搬做国产化OA系统集成的时候,经常遇到这种需求:业务部门手里有大量历史PPT,里面的内容不是简单的几行文字,而是图文混排的页面——图片、表格、公式、批注揉在一起。现在OA的公文编辑、…

📰

信息管理系统毕设全流程:从需求分析到Spring Boot+Vue项目落地

做计算机毕设这么多年,我见过太多人一上来就问“信息管理系统源码有没有现成的”,但真正把这套东西吃透的人反而很少。信息管理系统这个题目看着烂大街,实际上它是计算机专业本科毕设里性价比非常高的一类——技术栈覆盖全、需求容易理解、可…

📰

档案管理系统建设方案:用Word高效排版与自动化生成实战指南

1. 方案定位与建设背景1.1 这类方案文档是写给谁看的前几天帮客户把一份档案管理系统建设方案从零散的企业资料里整理成正式Word版本,过程中被各种公式、表格和引用折腾得够呛。档案管理系统建设方案这类文档,在很多企业里一直是“立项”和“招标”两个环…

📰

Agent-Reach 实战:用 CLI 和 Python 打通 AI Agent 的触达层

1. 从"Agent-Reach"这个名字说起:它到底想解决什么问题第一次看到 Agent-Reach 这个项目名,我的直觉是:这又是一个给 AI Agent 做"能力延伸"的工具。事实也确实如此,但它的切入点比大多数同类项目要克制得多—…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬