PyTorch从零构建CNN图像分类器:数据到评估全流程实战
1. 从一个实际需求说起为什么要手写一个CNN图像分类器搞深度学习这几年我越来越觉得框架用得再溜如果没亲手从零搭过一个完整的图像分类器很多细节永远是模糊的。你可能看过无数篇教程知道卷积、池化、全连接这些名词但真让你从数据加载一路写到模型评估中间那些坑——通道数对不上、维度爆炸、过拟合、学习率设错——照样一个不落地踩一遍。这个项目就是干这件事的用PyTorch从零构建一个卷积神经网络CNN图像分类器覆盖数据准备、模型定义、训练循环、评估验证、调参优化这一整条链路。它解决的核心问题是——把看懂CNN变成能跑通CNN并且跑出来的结果是可以复现、可以解释、可以继续优化的。适合谁来参考如果你已经会一点Python知道张量是什么但还没独立完成过一个端到端的深度学习项目那这篇内容就是给你写的。如果你已经做过几个项目但每次都是复制粘贴别人的代码不清楚每一行为什么这么写那也能从里面的参数计算和踩坑记录里捞到东西。我尽量不写成教科书而是按一个从业者实际动手的顺序来讲把为什么这么选讲透。2. 整体设计思路与方案选型2.1 为什么选CNN而不是全连接网络图像分类这个任务最朴素的做法是把图片拉平成一维向量喂给全连接网络。我早期就这么干过结果很惨一张32x32的彩色图拉平就是3072维第一层全连接直接上万个参数训练慢不说准确率还上不去。根本原因在于全连接网络丢掉了图像的空间结构——它不知道相邻像素之间的关系也不知道一个图案平移之后还是同一个图案。CNN的两个核心机制正好解决这个问题。局部连接让每个神经元只看一小块区域参数量骤降权值共享让同一个卷积核在整张图上滑动于是平移不变性天然就有了。这两个特性不是锦上添花而是CNN能在图像任务上碾压全连接的根本原因。所以这个项目选CNN不是跟风是任务性质决定的。2.2 数据集的选择与考量我选了一个经典的小尺寸彩色图像数据集来做演示类别数适中、单张图片分辨率不高32x32这个量级这样在普通显卡甚至CPU上都能跑完方便你快速验证代码正确性。为什么不直接上大分辨率数据集因为调试阶段最重要的是快速迭代——你改一行代码几分钟就能看到结果而不是等几个小时。等这套流程跑通了换成自己的数据集只是改数据加载部分的事。这里有个经验新手最容易犯的错是一上来就用超大数据集结果训练一次要半天调参根本没法进行。先用小数据集把管线跑通确认每个环节都对再放大规模这是我一直推荐的做法。2.3 整体架构的分层设计整个项目我分成四层来组织这样职责清晰改哪块都不影响其他部分数据层负责数据集的下载、预处理、增强、分批加载模型层定义CNN的网络结构包括卷积块、池化、全连接训练层损失函数、优化器、训练循环、验证逻辑评估层测试集评估、混淆矩阵、错误案例分析这么分层的好处是当你想换数据集时只动数据层想换网络结构时只动模型层互不干扰。很多教程把所有代码堆在一个文件里看着省事实际维护起来是灾难。3. 核心细节解析与实操要点3.1 数据预处理归一化到底在做什么数据预处理里最关键的一步是归一化。原始像素值是0到255的整数直接喂给网络会有问题数值范围太大梯度更新不稳定收敛慢。常见的做法是减均值、除标准差把数据拉到均值0、方差1附近。具体到实现我一般先算整个训练集的均值和标准差然后用这两个值去归一化训练集、验证集、测试集。注意必须用训练集的统计量去归一化验证集和测试集不能各自算各自的。为什么因为验证集和测试集在真实场景里是没见过的数据你不能假设提前知道它们的分布。用训练集统计量模拟的就是真实推理时的情形。import torch from torchvision import transforms # 训练集的预处理包含数据增强 train_transform transforms.Compose([ transforms.RandomCrop(32, padding4), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean[0.4914, 0.4822, 0.4465], std[0.2470, 0.2435, 0.2616]) ]) # 验证/测试集只做归一化不做增强 val_transform transforms.Compose([ transforms.ToTensor(), transforms.Normalize(mean[0.4914, 0.4822, 0.4465], std[0.2470, 0.2435, 0.2616]) ])上面那组均值和标准差是这类数据集上被广泛验证过的经验值你可以直接抄。如果换成自己的数据集记得重新算一遍。3.2 数据增强为什么训练集和验证集处理方式不同数据增强是防止过拟合的利器但有个铁律只在训练集上做增强验证集和测试集绝对不做。原因很简单增强是为了让模型见到更多变形的样本提升泛化能力而验证和测试是为了评估模型在真实数据上的表现如果你对测试集也做随机裁剪、翻转那评估结果就带了随机性没法反映真实水平。常用的增强手段有随机裁剪、随机水平翻转、颜色抖动、随机旋转等。但要注意增强方式要和任务匹配。比如做数字识别水平翻转就可能把6变成不合理的形状这时候翻转反而有害。我一般从随机裁剪加水平翻转这个最安全的组合开始效果不够再加别的。3.3 卷积层的参数计算通道数怎么定这是新手最容易懵的地方。一个卷积层的输出通道数到底设多少我的经验是从小到大递增比如32、64、128这样翻倍。为什么递增因为浅层提取的是边缘、纹理这类低级特征数量需求少深层提取的是语义特征组合方式多需要更多通道来表达。卷积核大小一般用3x3这是被大量实验验证过的性价比之选。两个3x3卷积堆叠的感受野等于一个5x5但参数更少、非线性更强。padding设为1stride设为1这样3x3卷积不改变特征图的空间尺寸方便堆叠。输出尺寸的计算公式要记牢输出尺寸 (输入尺寸 2 × padding - 卷积核大小) / stride 1拿32x32输入、3x3卷积、padding1、stride1来算(32 2 - 3) / 1 1 32尺寸不变。如果stride改成2就是(32 2 - 3) / 2 1 16尺寸减半。这个公式我在设计网络时几乎每层都要算一遍算错一步后面全乱。3.4 池化层的作用与选择池化层我一般用最大池化2x2窗口、stride为2效果是把特征图尺寸减半。它的作用有两个一是降低计算量二是提供一定的平移不变性。为什么不平均池化因为最大池化保留了最显著的特征响应在分类任务上通常表现更好。不过现在有个趋势是用stride为2的卷积代替池化让网络自己学下采样方式。这两种做法我都试过在小数据集上差别不大池化更简单直接我倾向于先用池化把流程跑通。4. 实操过程与核心环节实现4.1 搭建CNN网络结构下面是我常用的一个基础CNN结构适合32x32这类小图。它由三个卷积块加一个分类头组成结构清晰方便你在此基础上改。import torch.nn as nn import torch.nn.functional as F class SimpleCNN(nn.Module): def __init__(self, num_classes10): super(SimpleCNN, self).__init__() # 第一个卷积块3 - 32 self.conv1 nn.Conv2d(3, 32, kernel_size3, padding1) self.bn1 nn.BatchNorm2d(32) # 第二个卷积块32 - 64 self.conv2 nn.Conv2d(32, 64, kernel_size3, padding1) self.bn2 nn.BatchNorm2d(64) # 第三个卷积块64 - 128 self.conv3 nn.Conv2d(64, 128, kernel_size3, padding1) self.bn3 nn.BatchNorm2d(128) self.pool nn.MaxPool2d(2, 2) self.dropout nn.Dropout(0.5) # 经过三次池化32 - 16 - 8 - 4 self.fc nn.Linear(128 * 4 * 4, num_classes) def forward(self, x): x self.pool(F.relu(self.bn1(self.conv1(x)))) # 32x32 - 16x16 x self.pool(F.relu(self.bn2(self.conv2(x)))) # 16x16 - 8x8 x self.pool(F.relu(self.bn3(self.conv3(x)))) # 8x8 - 4x4 x x.view(x.size(0), -1) # 展平 x self.dropout(x) x self.fc(x) return x这里有几个设计点值得说。BatchNorm加在卷积之后、激活之前能加速收敛、稳定训练几乎是标配。Dropout放在全连接层之前比例0.5防止过拟合。展平那一步的维度128×4×4是三次池化把32降到4算出来的这个数字必须和前面的结构严格对应写错了运行时报维度错误。4.2 训练循环的完整实现训练循环是整个项目的核心我把它拆成几个关键部分前向传播、计算损失、反向传播、参数更新、记录指标。import torch.optim as optim def train_one_epoch(model, loader, criterion, optimizer, device): model.train() running_loss 0.0 correct 0 total 0 for inputs, labels in loader: inputs, labels inputs.to(device), labels.to(device) optimizer.zero_grad() # 清空梯度 outputs model(inputs) # 前向传播 loss criterion(outputs, labels) # 计算损失 loss.backward() # 反向传播 optimizer.step() # 更新参数 running_loss loss.item() * inputs.size(0) _, predicted outputs.max(1) total labels.size(0) correct predicted.eq(labels).sum().item() epoch_loss running_loss / total epoch_acc correct / total return epoch_loss, epoch_accoptimizer.zero_grad()这一步千万别忘PyTorch的梯度是累加的不清零的话梯度会越滚越大训练直接崩。损失函数用交叉熵优化器我一般用Adam学习率从1e-3开始这个组合在大多数任务上都能work不用一上来就调。4.3 验证与模型保存策略验证集的作用是监控过拟合。每个epoch训练完跑一遍验证集记录验证损失和准确率。如果训练准确率还在涨、验证准确率开始跌那就是过拟合了该加正则化或者早停。def evaluate(model, loader, criterion, device): model.eval() running_loss 0.0 correct 0 total 0 with torch.no_grad(): # 验证不需要梯度省显存 for inputs, labels in loader: inputs, labels inputs.to(device), labels.to(device) outputs model(inputs) loss criterion(outputs, labels) running_loss loss.item() * inputs.size(0) _, predicted outputs.max(1) total labels.size(0) correct predicted.eq(labels).sum().item() return running_loss / total, correct / total模型保存我推荐保存验证准确率最高的那个而不是最后一个epoch的。因为最后一个epoch很可能已经过拟合了验证集上表现最好的才是泛化能力最强的。best_acc 0.0 for epoch in range(num_epochs): train_loss, train_acc train_one_epoch(model, train_loader, criterion, optimizer, device) val_loss, val_acc evaluate(model, val_loader, criterion, device) print(fEpoch {epoch1}: train_acc{train_acc:.4f}, val_acc{val_acc:.4f}) if val_acc best_acc: best_acc val_acc torch.save(model.state_dict(), best_model.pth)4.4 学习率调度与训练稳定性学习率设大了震荡不收敛设小了收敛慢。我的做法是用一个初始学习率配合调度器训练过程中动态降低。最常用的是余弦退火或者阶梯下降。scheduler optim.lr_scheduler.CosineAnnealingLR(optimizer, T_maxnum_epochs) # 每个epoch结束后调用 scheduler.step()余弦退火的好处是前期学习率大、快速下降后期学习率小、精细调整整个训练过程比较平滑。我实测下来同样的网络加了调度器比固定学习率能高出一两个百分点的准确率。5. 常见问题与排查技巧实录5.1 维度不匹配最常见的报错维度错误是新手遇到最多的报错没有之一。典型信息是size mismatch或者mat1 and mat2 shapes cannot be multiplied。根源通常是全连接层的输入维度算错了。排查方法在展平那一步之前打印一下张量的shape看看实际是多少再和全连接层定义的输入维度对比。我习惯在x.view(x.size(0), -1)之前加一句print(x.shape)确认无误后再删掉。这个习惯帮我省了无数时间。5.2 损失不下降的几种可能训练时损失一直不降或者降得很慢原因可能有好几个我按排查优先级列一下现象可能原因排查方法损失完全不动学习率太小或梯度消失调大学习率检查激活函数损失震荡剧烈学习率太大降低学习率加梯度裁剪损失降但准确率不涨标签错位或数据问题检查标签和数据的对应关系训练准确率高验证低过拟合加Dropout、数据增强、权重衰减我踩过最坑的一次是标签和数据没对齐损失看着在降但准确率一直在随机水平。后来发现是自定义数据集时__getitem__返回的标签索引错了。所以自定义数据集一定要先可视化几张图确认图和标签对得上。5.3 显存不够怎么办显存不足报CUDA out of memory解决办法按代价从低到高排减小batch size这是最快的用torch.no_grad()包住验证部分省显存用混合精度训练torch.cuda.amp能省将近一半显存减小模型规模比如减少通道数我一般先降batch size如果还不行再考虑混合精度。混合精度稍微复杂一点但收益明显值得学。5.4 过拟合的识别与应对过拟合的典型信号是训练准确率远高于验证准确率比如训练95%、验证70%。应对手段我按效果排序数据增强最有效其次是加Dropout和权重衰减再不行就减小模型容量或者早停。注意不要一看到过拟合就猛加正则化先确认训练集和验证集的分布是不是一致的。如果验证集本身有问题加再多正则化也没用。5.5 一个容易被忽略的坑随机种子深度学习有大量随机性——权重初始化、数据打乱、Dropout。如果不固定随机种子每次跑的结果都不一样你根本没法判断是改动起了作用还是随机波动。我的做法是在代码开头固定所有随机种子import random import numpy as np def set_seed(seed42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.deterministic True固定种子后同样的代码跑出来结果可复现调参才有意义。不过要注意完全确定性会稍微牺牲一点速度调试阶段值得最终训练可以放开。6. 从跑通到跑好几个提升准确率的实操技巧6.1 迁移学习小数据集的救命稻草如果你的数据集不大从零训练CNN很难达到理想效果。这时候迁移学习是最优解——用一个在大数据集上预训练好的模型把最后的分类层换成你自己的类别数然后微调。import torchvision.models as models model models.resnet18(pretrainedTrue) # 替换最后的全连接层 num_features model.fc.in_features model.fc nn.Linear(num_features, num_classes)微调时有个技巧前面的层用较小的学习率新加的分类层用较大的学习率。因为前面的层已经学到了通用特征不需要大改分类层是全新的需要快速学习。这个做法叫判别式微调实测比统一学习率效果好。6.2 学习率预热稳定训练前期训练刚开始时权重是随机的梯度可能很大直接上大学习率容易震荡。学习率预热就是前几个epoch用很小的学习率慢慢升到设定值让训练平稳起步。def warmup_lr(epoch, warmup_epochs, base_lr): if epoch warmup_epochs: return base_lr * (epoch 1) / warmup_epochs return base_lr这个技巧在训练大模型时几乎是必备的小模型上也能带来稳定性提升。6.3 测试时增强免费的准确率提升测试时增强TTA是个很划算的技巧对同一张测试图做多种变换比如原图、水平翻转分别预测然后把结果平均。这样相当于让多个视角投票通常能提升零点几个百分点而且不需要重新训练。def predict_with_tta(model, image, device): model.eval() with torch.no_grad(): # 原图预测 out1 F.softmax(model(image.to(device)), dim1) # 水平翻转预测 flipped torch.flip(image, dims[3]) out2 F.softmax(model(flipped.to(device)), dim1) # 平均 return (out1 out2) / 2代价是推理时间翻倍如果对延迟不敏感这个技巧值得加上。6.4 错误分析找到模型的盲区模型训完之后别只看一个准确率数字就完事。把预测错的样本挑出来看看往往能发现规律。比如是不是某一类总是被错分成另一类是不是某些角度的图片识别不了。这些信息比准确率有用得多能指导你下一步是补数据还是改结构。我一般会画一个混淆矩阵横轴是真实标签纵轴是预测标签对角线越深越好非对角线的亮点就是问题所在。这个分析做完往往能发现数据标注的问题或者类别不平衡的问题。7. 我在这类项目里踩过的几个真实坑第一个坑是忘了切换train和eval模式。PyTorch里Dropout和BatchNorm在训练和推理时行为不同如果验证时忘了model.eval()Dropout还在随机丢弃神经元BatchNorm还在用当前batch的统计量验证结果会偏低且不稳定。这个错误很隐蔽因为代码不报错只是结果不对。我现在养成的习惯是训练循环里model.train()和model.eval()成对出现绝不遗漏。第二个坑是数据加载的num_workers设置。在Windows上设成大于0有时会出问题在Linux上设成0又太慢。我的经验是Linux下设成4到8Windows下先用0跑通再说。这个参数不影响正确性但影响效率值得根据平台调一下。第三个坑是学习率设得想当然。我早期总觉得学习率越小越稳结果设成1e-5训练一百个epoch损失才降一点点。后来才明白学习率要和batch size、优化器配合着看。Adam配1e-3是个稳妥的起点SGD的话要配0.01到0.1再加动量。没有万能值但有个合理的起点能省很多试错时间。第四个坑是过早追求复杂模型。刚开始做项目时我总想直接上ResNet、上注意力机制结果调不通连baseline都没有。后来学乖了先用最简单的三层CNN跑出一个能接受的baseline再逐步加东西每加一个都验证有没有提升。这个思路让我少走了太多弯路。这套流程跑下来一个基础CNN图像分类器从数据到评估就完整了。后续想扩展的话可以换更深的网络、加注意力模块、试不同的数据增强策略或者把分类头换成多标签输出。基础打牢了往上加东西就是顺理成章的事。

相关新闻

基于Chat2DB、DB-GPT与Gonavi构建AI多模态数据洞察平台实战

基于Chat2DB、DB-GPT与Gonavi构建AI多模态数据洞察平台实战

1. 数据洞察平台的整体架构设计思路1.1 为什么要把三个开源项目揉进一个平台先说清楚这个项目到底在干什么。标题里提到的 AllData 是一个数据洞察平台,核心目标是把企业内部散落的数据源统一管起来,同时叠加 AI 能力,让不懂 SQL 的业务人员也…

2026/10/14 7:33:40 阅读更多 →
从零手搓CNN图像分类器:PyTorch实战与核心细节拆解

从零手搓CNN图像分类器:PyTorch实战与核心细节拆解

1. 从零手搓CNN图像分类器:为什么选PyTorch,以及这个实战到底练什么搞深度学习这几年,我越来越觉得,图像分类是每个想入门计算机视觉的人绕不开的第一道坎。你可能会问,现在大模型满天飞,目标检测、语义分割…

2026/10/14 7:33:40 阅读更多 →
数据库客户端绿色部署与授权合规:免安装方案与开源替代实践

数据库客户端绿色部署与授权合规:免安装方案与开源替代实践

简介:NavicatPremium11破解免安装版面向数据库开发、运维及数据分析人员,解决正式版授权成本高、安装配置繁琐的问题,解压后即可直接运行,无需注册与安装流程,适合需要快速搭建本地数据库管理环境的初、中级使用者。压…

2026/10/14 7:32:39 阅读更多 →

最新新闻

视频补帧提速:超帧HyperFrame原理与工程实践指南

视频补帧提速:超帧HyperFrame原理与工程实践指南

前阵子帮朋友处理一段 4K 30fps 的航拍素材,要补到 60fps 做慢动作。我把视频丢进 RIFE 模型,一帧一帧等它跑。两个小时过去,才处理了不到两分钟素材,盯着显卡的显存占用一直在 60% 上下跳,我意识到问题不是算力不够&a…

2026/10/14 8:32:03 阅读更多 →
.NET 8 Blazor WASM + Azure AD + Ant Design 权限集成实战

.NET 8 Blazor WASM + Azure AD + Ant Design 权限集成实战

简介:这是一套基于 .NET 8 构建的 Azure 单点登录后台管理框架,面向 Blazor Server 开发者及企业级 Web 应用初学者,解决快速搭建安全、规范、UI 统一的管理后台问题。项目采用 Ant Design Blazor 组件库实现现代化前端界面,后端以…

2026/10/14 8:32:03 阅读更多 →
Agent技能包机制:告别冗长提示词,构建可维护AI能力模块

Agent技能包机制:告别冗长提示词,构建可维护AI能力模块

最近在调一个Agent项目时我踩了个大坑。任务本身不复杂——让AI助手根据用户手头的食材推荐三道菜。我一开始图省事,把所有逻辑全写进系统提示词里,结果提示词超过三千字之后,模型开始"精神分裂":有时候忘了查库存&…

2026/10/14 8:32:03 阅读更多 →
hyperframes:列式存储与惰性求值,让DataFrame内存计算性能提升10倍

hyperframes:列式存储与惰性求值,让DataFrame内存计算性能提升10倍

hyperframes 这个项目名字,我第一次接触到的时候以为是某个算法框架的命名,后来才发现它其实是一个针对数据密集型任务的高性能内存计算库。简单说,它把 DataFrame 的易用性和底层向量化执行引擎结合到一起,目标是解决大数据场景下…

2026/10/14 8:32:03 阅读更多 →
大学物理波动复习指南:从波函数到多普勒效应的三层框架与避坑路线

大学物理波动复习指南:从波函数到多普勒效应的三层框架与避坑路线

1. 波动复习框架的底层逻辑重构1.1 为什么波动章节总让人“一听就会,一考就废”大学物理里的波动章节,几乎是我见过挂科率最稳定的模块之一。很多同学把原因归结为“公式太多”,但实际带过几轮复习之后我发现,真正的问题出在思维方…

2026/10/14 8:32:03 阅读更多 →
MongoDB 6.0特性与Java开发实战指南

MongoDB 6.0特性与Java开发实战指南

1. MongoDB 6.0 核心特性解析 2022年发布的MongoDB 6.0版本带来了多项重要改进,这些特性对Java开发者而言意味着更高效的开发体验和更强大的数据处理能力。时间序列集合(Time Series Collections)经过深度优化后,写入性能提升达40…

2026/10/14 8:31:02 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →