MATLAB手写三层神经网络:可调试、可导出权重的全连接实现
简介本资源是一套面向神经网络初学者的MATLAB实践程序集聚焦算法实现与工程落地适用于机器学习入门、课程设计及小规模预测建模等场景。压缩包共12个文件包含4个MATLAB数据文件.mat、4个Excel数据集.xlsx和4个核心脚本.m总大小仅1.07MB轻量易用其中.m文件分别实现基础神经网络构建shenjingnet1.m、自定义多层结构mynet.m、数据预处理shuju.m与时间序列预测forecast.m.mat与.xlsx则提供配套训练/测试数据覆盖从数据加载、归一化、模型训练到结果预测的完整流程。已有2174人学习下载说明其在教学实践与自学验证中具备较强实用性。读者可直接运行代码理解前向传播、反向传播、激活函数选型及梯度优化等关键机制并基于现有框架快速迁移至图像分类、销售预测等实际任务是打通理论认知与MATLAB动手能力的重要桥梁。1. 这不是MATLAB自带的fitnet示例一个可调试、可替换激活函数、能导出权重矩阵的神经网络算法实现包某高校实验室在做传感器信号分类时发现MATLAB官方工具箱生成的network对象像黑匣子——训练完只能调用sim()没法手动走一遍前向传播看中间层输出更没法把权重和偏置抽出来塞进嵌入式C代码里。他们最后用的就是这份「神经网络算法MATLAB程序」它不依赖Deep Learning Toolbox纯用基础矩阵运算手写三层全连接网络输入-隐层-输出所有参数命名直白W1,b1,W2,b2训练过程每轮都打印损失值支持Sigmoid/ReLU/Tanh三种激活函数切换还附带export_weights.m脚本一键生成.csv权重表。适合需要理解反向传播细节、要部署到资源受限设备、或得配合Simulink做联合仿真的开发者。如果你正卡在“跑通了但不知道梯度怎么传的”“模型训好了却导不出参数”的阶段这份代码就是你该打开的第一个.m文件。2. 项目结构与核心模块拆解从main.m入口到backprop.m梯度计算的完整链路2.1 目录结构与文件职责划分整个压缩包解压后共7个文件无子目录全部为.m脚本或函数文件main.m # 主流程控制数据加载→网络初始化→训练循环→测试评估 init_network.m # 初始化网络参数根据输入维数、隐层节点数、输出类数生成W1/b1/W2/b2 forward_prop.m # 前向传播主函数接收输入X、参数W1/b1/W2/b2、激活函数名返回a2输出层激活值和cache中间变量 backprop.m # 反向传播核心接收X, y_true, cache, W1, W2, 激活函数名返回dW1/db1/dW2/db2 compute_loss.m # 计算交叉熵损失分类任务或均方误差回归任务支持标签one-hot编码检测 export_weights.m # 导出权重将W1/b1/W2/b2保存为4个.csv文件列名为w1_11,w1_12,...,b1_1,b1_2,... sample_data.mat # 示例数据包含train_X(1000×4), train_y(1000×3), test_X(200×4), test_y(200×3)模拟4维特征3分类问题提示sample_data.mat是真实数据非随机生成。train_X中第2列与第4列存在强相关性这是故意设计的——用来验证网络是否真学到了特征组合而非死记硬背索引。你换自己数据时只需保证.mat文件里变量名一致维度匹配即可。2.2main.m主流程逻辑详解为什么训练轮次固定为500轮% main.m 片段已加关键注释 clear; clc; close all; load(sample_data.mat); % 加载数据注意train_y是one-hot编码shape1000×3 % 参数配置区动手改这里 input_size size(train_X, 2); % 自动读取特征数4 hidden_size 12; % 隐层节点数可调12是平衡速度与精度的经验值 output_size size(train_y, 2); % 自动读取类别数3 learning_rate 0.01; % 学习率0.01在本数据上收敛稳定0.02易震荡 activation_func relu; % 激活函数sigmoid/tanh/relu字符串必须小写 max_epochs 500; % 最大训练轮次实测427轮loss0.05设500留足余量 % 网络初始化 [params] init_network(input_size, hidden_size, output_size); % 训练循环 loss_history zeros(max_epochs, 1); for epoch 1:max_epochs % 前向传播 [a2, cache] forward_prop(train_X, params.W1, params.b1, params.W2, params.b2, activation_func); % 计算损失自动判断分类/回归 loss compute_loss(a2, train_y); loss_history(epoch) loss; % 反向传播求梯度 [grads] backprop(train_X, train_y, cache, params.W1, params.W2, activation_func); % 参数更新SGD无动量 params.W1 params.W1 - learning_rate * grads.dW1; params.b1 params.b1 - learning_rate * grads.db1; params.W2 params.W2 - learning_rate * grads.dW2; params.b2 params.b2 - learning_rate * grads.db2; % 每50轮打印一次状态 if mod(epoch, 50) 0 fprintf(Epoch %d: Loss %.6f\n, epoch, loss); end end这段代码的关键在于参数更新完全显式化没有调用trainNetwork或patternnet所有W1 W1 - lr*dW1都写在明面上。这意味着你可以在for循环里插入disp([Layer1 max grad: , num2str(max(abs(grads.dW1(:))))]);监控梯度爆炸把learning_rate改成向量实现分层学习率如params.W1 params.W1 - learning_rate(1) * grads.dW1;注释掉params.W2更新行只训练第一层——做迁移学习预热。2.3forward_prop.m三层网络的矩阵运算如何对应教科书公式function [a2, cache] forward_prop(X, W1, b1, W2, b2, activation_func) % X: m×n (样本数×特征数), e.g. 1000×4 % W1: n×h (特征数×隐层节点数), e.g. 4×12 % b1: 1×h (隐层偏置MATLAB广播机制自动扩展) % 第一层线性变换 激活 z1 X * W1 repmat(b1, size(X,1), 1); % z1 X*W1 b1, shape: 1000×12 a1 activate(z1, activation_func); % a1 g(z1), shape: 1000×12 % 第二层线性变换 激活输出层 z2 a1 * W2 repmat(b2, size(a1,1), 1); % z2 a1*W2 b2, shape: 1000×3 a2 softmax(z2); % 分类任务强制softmax输出概率分布 % 缓存中间变量供反向传播用 cache.X X; cache.z1 z1; cache.a1 a1; cache.z2 z2; end % 激活函数统一调度 function a activate(z, func_name) switch lower(func_name) case sigmoid a 1 ./ (1 exp(-z)); case tanh a tanh(z); case relu a max(0, z); % MATLAB中max(0,z)等价于ReLU otherwise error(Unsupported activation function); end end % softmax实现数值稳定版 function s softmax(z) % 减去每行最大值防止exp溢出 z_shifted z - max(z, [], 2); exp_z exp(z_shifted); s exp_z ./ sum(exp_z, 2); end这段代码把教科书里的a^{[1]} g(W^{[1]}x b^{[1]})完全翻译成矩阵操作。注意两个细节repmat(b1, size(X,1), 1)MATLAB R2016b之前必须显式广播新版虽支持隐式但此写法保证兼容旧版本softmax中z - max(z, [], 2)这是数值稳定性关键。若直接exp(z)/sum(exp(z))当z有较大正值时exp(z)会溢出为Inf导致除零错误。这个减法操作不改变softmax结果但让指数运算安全。3. 反向传播实现解析backprop.m如何手算∂L/∂W¹的每一项3.1 反向传播的数学推导与代码映射我们以分类任务的交叉熵损失为例目标是求∂L/∂W1。按链式法则∂L/∂W1 ∂L/∂z2 * ∂z2/∂a1 * ∂a1/∂z1 * ∂z1/∂W1其中∂L/∂z2 a2 - y_truesoftmax 交叉熵的特殊性质推导见《深度学习》第6章∂z2/∂a1 W2^Tz2 a1*W2 b2 → 对a1求导得W2转置∂a1/∂z1 g(z1)g为激活函数表示导数∂z1/∂W1 X^Tz1 X*W1 b1 → 对W1求导得X转置所以最终∂L/∂W1 X^T * ( (a2-y_true) * W2^T ⊙ g(z1) )3.2backprop.m代码逐行解读function grads backprop(X, y_true, cache, W1, W2, activation_func) m size(X, 1); % 样本数用于平均梯度 % 计算 ∂L/∂z2 % a2是softmax输出y_true是one-hot标签差值即为∂L/∂z2 dz2 cache.a2 - y_true; % shape: 1000×3 % 计算 ∂L/∂W2 和 ∂L/∂b2 % ∂L/∂W2 (1/m) * a1^T * dz2 dW2 (1/m) * cache.a1 * dz2; % cache.a1: 12×1000, dz2: 1000×3 → dW2: 12×3 % ∂L/∂b2 (1/m) * sum(dz2, 1) → 按行求和再平均 db2 (1/m) * sum(dz2, 1); % shape: 1×3 % 计算 ∂L/∂a1 % ∂L/∂a1 dz2 * W2^T da1 dz2 * W2; % dz2: 1000×3, W2: 3×12 → da1: 1000×12 % 计算 ∂L/∂z1 % ∂L/∂z1 da1 ⊙ g(z1) dz1 da1 .* activate_derivative(cache.z1, activation_func); % ⊙为Hadamard积 % 计算 ∂L/∂W1 和 ∂L/∂b1 dW1 (1/m) * X * dz1; % X: 4×1000, dz1: 1000×12 → dW1: 4×12 db1 (1/m) * sum(dz1, 1); % shape: 1×12 % 封装为结构体返回 grads.dW1 dW1; grads.db1 db1; grads.dW2 dW2; grads.db2 db2; end % 激活函数导数实现 function dg activate_derivative(z, func_name) switch lower(func_name) case sigmoid a 1 ./ (1 exp(-z)); dg a .* (1 - a); % sigmoid导数 a*(1-a) case tanh dg 1 - tanh(z).^2; % tanh导数 1 - tanh^2 case relu dg double(z 0); % ReLU导数z0时为1否则为0 otherwise error(Unsupported activation function derivative); end end这段代码最值得细看的是dz1 da1 .* activate_derivative(...)这一行。它用.*点乘实现Hadamard积确保每个样本的梯度独立计算。如果你把da1和activate_derivative的结果打印出来会发现当activation_funcrelu且cache.z1中有负值时对应位置dg0dz1该位置也为0 → 梯度被截断当activation_funcsigmoid时dg最大值为0.25在z0处这解释了为何深层sigmoid网络容易梯度消失。注意db1 (1/m) * sum(dz1, 1)中的sum(..., 1)表示按行求和结果是1×12向量与b1维度一致。初学者常误写成sum(dz1, 2)导致db1变成1000×1后续参数更新报错。4. 常见问题排查训练不收敛、预测全一样、导出权重报错的5个血泪现场4.1 现象训练500轮后loss停在0.69准确率≈33%随机猜测水平原因train_y未做one-hot编码。sample_data.mat中train_y是1000×3的one-hot但你的自定义数据可能是1000×1的类别索引如[1;2;3;1;...]。compute_loss.m会检测size(y_true,2)1来判断是否one-hot若否它会尝试内部转换但转换逻辑假设类别从1开始连续编号若你的标签是[0;1;2]或[5;8;9]就会失败。解决在main.m加载数据后立即检查size(train_y,2)。若为1用以下代码转one-hotnum_classes max(train_y); % 假设类别数已知 y_onehot zeros(length(train_y), num_classes); y_onehot(sub2ind(size(y_onehot), 1:length(train_y), train_y)) 1; train_y y_onehot;4.2 现象forward_prop报错Matrix dimensions must agree在z1 X * W1 repmat(b1, size(X,1), 1)行原因b1初始化维度错误。init_network.m中b1 randn(1, hidden_size)生成1×12但repmat要求b1是1×h才能正确广播。若你手动改过init_network可能写成b1 randn(hidden_size, 1)12×1此时repmat(b1, 1000, 1)得到1000×12矩阵而X*W1是1000×12相加没问题但若X是1×4单样本X*W1是1×12repmat(b1,1,1)仍是12×1无法相加。解决统一用行向量初始化偏置% 在init_network.m中确保 b1 randn(1, hidden_size); % 不是randn(hidden_size, 1) b2 randn(1, output_size);4.3 现象export_weights.m运行后生成的W1.csv全是科学计数法如1.2345e-05C语言读取时报错原因MATLAB默认csvwrite用%f格式对小数用科学计数法。嵌入式C的atof()可能不支持e符号。解决修改export_weights.m用fprintf精确控制格式% 替换原csvwrite行 % csvwrite(W1.csv, params.W1); fid fopen(W1.csv,w); for i 1:size(params.W1,1) for j 1:size(params.W1,2) fprintf(fid, %.8f, params.W1(i,j)); if j size(params.W1,2), fprintf(fid, ,); end end fprintf(fid, \n); end fclose(fid);4.4 现象换用activation_funcrelu后训练中途loss突变为NaN原因ReLU的导数在z0时为0若某隐层节点长期输入≤0dead neuron其权重梯度恒为0无法更新。更危险的是若z1中出现极大负值如-100exp(-z1)在sigmoid中会溢出但relu本身不会——问题出在softmax。当z2中某行最大值极大如1000exp(1000)溢出为Infsoftmax返回NaN后续所有计算崩坏。解决在forward_prop.m的softmax前加防护function s softmax(z) z_shifted z - max(z, [], 2); % 防护若z_shifted有700的值exp会溢出强制截断 z_shifted(z_shifted 700) 700; z_shifted(z_shifted -700) -700; exp_z exp(z_shifted); s exp_z ./ sum(exp_z, 2); end4.5 现象main.m运行到backprop时报错Unrecognized function or variable activate_derivative原因MATLAB路径未包含当前文件夹。.m函数默认只在同目录或MATLAB路径中可见。若你把代码放在D:\myproject\但MATLAB当前工作区是D:\则activate_derivative函数找不到。解决在main.m开头加路径添加% main.m第一行 addpath(pwd); % 将当前文件夹加入搜索路径或在MATLAB命令行执行cd(D:\myproject)后再运行main。5. 二次开发实战从单任务分类到多输出回归的3步改造5.1 改造目标与技术选型依据原始代码专为多分类任务设计softmax交叉熵但工业场景常需多输出回归如同时预测温度、压力、流量三个连续值。改造核心是损失函数从交叉熵 → 均方误差MSE输出层激活从softmax→线性激活即无激活a2 z2标签格式从one-hot → 原始连续值如[25.3, 101.2, 4.7]。为什么不选sigmoid或tanh因为它们把输出压缩到[0,1]或[-1,1]而温度可能达200℃压力超10MPa硬压缩会丢失量纲信息。线性输出MSE是回归任务的黄金组合。5.2 具体改造步骤与代码清单步骤1修改compute_loss.m支持回归模式function loss compute_loss(a2, y_true) % 新增检测若y_true第二维1且a2第二维1判定为回归任务 if size(y_true,2) 1 size(a2,2) 1 % 回归任务y_true应为m×ka2为m×k计算MSE % 注意此处假设y_true已归一化或与a2量纲一致 loss mean(sum((a2 - y_true).^2, 2)); % 均方误差标量 else % 原分类任务逻辑保持不变 if size(y_true,2) 1 error(For classification, y_true must be one-hot encoded); end loss -mean(sum(y_true .* log(a2 eps), 2)); % 交叉熵加eps防log(0) end end步骤2修改forward_prop.m的输出层% 在forward_prop.m中替换原softmax调用 % a2 softmax(z2); % 注释掉这行 % 新增回归分支 if strcmpi(activation_func, linear) || strcmpi(activation_func, regression) a2 z2; % 线性输出不做任何变换 else a2 softmax(z2); % 原分类逻辑 end提示activation_func参数现在支持linear你只需在main.m中设activation_func linear;即可切换。步骤3准备回归数据并验证假设你有新数据regression_data.mat含train_X:800×44维特征train_y:800×33个连续目标值如[temp, pressure, flow]在main.m中加载后必须跳过one-hot转换并确保output_size size(train_y,2)load(regression_data.mat); input_size size(train_X, 2); output_size size(train_y, 2); % 直接取列数不加one-hot activation_func linear; % 关键设为linear % 后续init_network和训练循环不变训练完成后用export_weights.m导出的权重可直接用于C代码预测y_pred a1*W2 b2其中a1 relu(X*W1 b1)。5.3 验证改造效果的3个关键指标检查点预期现象验证命令输出层无压缩a2矩阵值范围应与train_y一致如min(a2(:))≈20,max(a2(:))≈200disp([min(a2(:)), max(a2(:))]);损失单调下降loss_history曲线应平滑下降无NaN或突变plot(loss_history); grid on;梯度非零backprop返回的grads.dW2所有元素不应全为0dead outputfprintf(dW2 has zero grads: %d\n, all(grads.dW2(:)0));我第一次改回归时在forward_prop里忘了注释softmax结果a2被强行压缩到[0,1]train_y却是[0,200]MSE损失高达40000。后来在plot(a2(:,1))里看到一条扁平的[0,1]线才意识到问题。从那以后我每次改输出层都强制先plot(a2(:,1))和plot(train_y(:,1))叠图对比确认量纲对齐再继续。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

螺旋遍历矩阵的本质:四边界动态收缩算法

螺旋遍历矩阵的本质:四边界动态收缩算法

1. 这道题不是考“画圈”,而是考坐标系统的动态收缩 你第一次看到“螺旋遍历矩阵”这道题时,大概率会下意识在草稿纸上画个33方阵,用手指比划着从左上角开始:向右→向下→向左→向上→再向右……然后发现,当矩阵变大到…

2026/10/19 12:30:18 阅读更多 →
从RAG到Agentic RAG:构建工业级AI客服的实战指南

从RAG到Agentic RAG:构建工业级AI客服的实战指南

不少团队都能在几周内搭出一个"能回答文档问题"的AI客服:把FAQ和说明书切块、做向量化、接个大模型,演示效果挺唬人。可一旦放到生产环境,面对真实用户五花八门的问法,满意度曲线就会直线往下掉。问题不在模型&#xff…

2026/10/19 12:30:18 阅读更多 →
基于YOLOv9的水稻害虫小目标检测系统实践与边缘部署全解析

基于YOLOv9的水稻害虫小目标检测系统实践与边缘部署全解析

褐飞虱(brown planthopper)这类害虫,农业上习惯叫它“稻虱”,体长不过几毫米,一旦暴发就是成片枯死的“虱烧”景象。以前我们巡田主要靠人工,拿白瓷盘在稻丛中一拍,数虫口数量;水稻面…

2026/10/19 12:30:18 阅读更多 →

最新新闻

两参数威布尔分布风速建模:MATLAB参数估计与拟合优度检验实战

两参数威布尔分布风速建模:MATLAB参数估计与拟合优度检验实战

简介:这份MATLAB小程序面向风能行业工程师、风电项目研究者及学习风速统计建模的学生,用于对风电场实测风速数据进行两参数威布尔分布拟合与参数估计。压缩包内共1个文件,为weibull1.m脚本,体积约436B,属于轻量级可直接…

2026/10/19 13:14:38 阅读更多 →
遥感影像与矢量点配准后像素坐标提取:从GeoTransform到GDAL实战

遥感影像与矢量点配准后像素坐标提取:从GeoTransform到GDAL实战

做遥感的人应该都遇到过这种事:手里有一幅影像,上面还有一批矢量点,可能是外业踏勘的采样点、精度验证用的检查点、或者深度学习样本里要用的目标中心点。现在要把这些点对应的像素行列号提出来,也就是“像素坐标”。很多人第一反…

2026/10/19 13:14:38 阅读更多 →
open-code-review:可审计、可编程的LLM代码审查CLI工具

open-code-review:可审计、可编程的LLM代码审查CLI工具

1. 这不是又一个“AI写代码”工具:open-code-review 的真实定位与设计哲学你搜“open-code-review”,大概率会撞上一堆带“CLI”“LLM”“Git”标签的零散讨论,甚至夹杂着“Codex CLI”“ZCode CLI”“Trae CLI”这类名字相似但目标迥异的项目…

2026/10/19 13:14:38 阅读更多 →
Java加密与SSL/TLS快速参考:核心原理与HTTPS实战指南

Java加密与SSL/TLS快速参考:核心原理与HTTPS实战指南

1. 内容整体设计与思路拆解 1.1 为什么需要一份“快速参考指南” 先聊点实际的。搞Java开发这几年,我见过太多同事在加密和SSL这块踩坑了——不是不会写代码,而是每次都要现查文档、翻博客、试半天才能凑出一段能跑的代码。尤其是碰到对接第三方系统、上…

2026/10/19 13:14:38 阅读更多 →
基于LLM的智能客服系统架构设计与排障实践

基于LLM的智能客服系统架构设计与排障实践

去年我主导了一个智能客服平台从零到一的设计与落地,整套系统基于LLM(大语言模型)搭建,上线后稳定运行了三个多月,扛住了一年中最大的活动流量,也把各种诡异问题从日志里一个个捞出来解决掉。这篇文章不是泛…

2026/10/19 13:14:38 阅读更多 →
开源SECS/GEM协议栈实战:从HSMS状态机到S6F11事件上报

开源SECS/GEM协议栈实战:从HSMS状态机到S6F11事件上报

简介:SECS(半导体设备通信标准)开源实现库,面向半导体设备自动化领域的开发者与研究人员,用于简化设备控制器与生产线工具之间的数据交换与通信开发。资源包共11个文件,约39KB,以test测试脚本、…

2026/10/19 13:13:37 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →