方差阈值特征选择:原理、实操与Pipeline避坑指南
特征工程里有个挺尴尬的现实很多人花大力气调模型、换算法最后发现真正拖后腿的是那堆几乎不变化的特征列。方差阈值选择就是专门解决这个问题的——它不看你跟标签的关系只看特征自己有没有“波动”。这篇文章我会把方差阈值法的原理、参数计算、实操代码、踩坑经验完整拆一遍适合刚接触特征工程的新手也适合想把这套流程固化进项目Pipeline的老手。1. 方差阈值选择到底在解决什么问题1.1 从“死列”说起为什么低方差特征该被扔掉先想一个场景。你手上有一张用户行为表几百个字段其中有一列叫“是否中国大陆用户”结果采样下来99.9%都是1只有极少数是0。这列特征对模型来说几乎不携带区分信息——因为它几乎不变。类似的还有“app版本号”在某个短周期内全是同一个值、“设备类型”在某个渠道里清一色是安卓。这些列的共同特点就是方差极低。方差衡量的是数据分布的离散程度。一个特征如果所有样本取值都一样方差就是0如果绝大多数样本挤在同一个值附近方差就非常小。从信息论的角度看这类特征对区分类别的贡献微乎其微留着它们只会增加计算量、稀释距离度量、干扰基于分裂的树模型甚至在某些线性模型里引入共线性噪声。方差阈值法Variance Threshold的核心逻辑非常朴素设定一个方差下限低于这个下限的特征直接剔除。它属于过滤式Filter特征选择方法跟卡方检验、互信息、相关系数是一类但它是唯一一个完全不依赖标签的方法。这意味着它可以在无监督场景下使用也可以在拿到标签之前就先把数据瘦身一遍。1.2 它和卡方、互信息、递归消除的本质区别很多人会把方差阈值和卡方检验混为一谈其实它们看问题的维度完全不同。卡方检验、互信息、F检验都是有监督的它们衡量的是“特征和标签之间的关联强度”而方差阈值是无监督的它只问一句“这个特征自己有没有变化”这个区别决定了它们的适用边界方法是否依赖标签衡量对象典型场景方差阈值否特征自身离散度数据清洗、去常量列卡方检验是特征与标签相关性文本分类特征筛选互信息是特征与标签信息增益非线性关系筛选递归特征消除是模型权重贡献小规模高精度筛选方差阈值法的优势在于快、稳、无标签依赖。它的劣势也很明显一个特征方差很大不代表它有用。比如“用户ID”这种列方差巨大但对预测毫无意义。所以方差阈值从来不是终点而是特征选择流水线的第一道粗筛。1.3 什么时候该用它什么时候别碰我个人的经验是下面这几种情况优先上方差阈值数据里有大量常量列或近常量列比如埋点表里某些事件字段在某个时间段内几乎不变做无监督任务聚类、异常检测根本没有标签可用特征维度极高几千上万列需要先快速砍掉一批明显无用的降低后续计算成本构建可复用的预处理Pipeline把去低方差列作为标准步骤固化下来。但下面这些情况要谨慎特征已经做过标准化且你用的是基于距离的模型——标准化后方差被统一到1附近方差阈值几乎筛不掉东西这时候应该用别的标准特征本身是稀疏的one-hot编码大部分取值是0方差天然就低但你并不想删掉它们这时候阈值要设得极低甚至为0你只有几十个精心设计的特征每一列都有业务含义这时候删任何一列都要慎重方差阈值可能过于粗暴。提示方差阈值最适合做“粗筛”不要指望它帮你选出最优特征子集。把它当成数据清洗的一部分而不是特征选择的全部。2. 方差的计算原理与阈值设定逻辑2.1 方差、标准差、量纲为什么阈值不能拍脑袋定方差的计算公式大家都熟对每个样本值减去均值平方后求平均。总体方差除以N样本方差除以N-1。在特征选择场景里我们通常关心的是样本方差因为手里的是抽样数据。这里有个特别容易被忽略的点方差的量纲是原始单位的平方。如果特征是“年龄”单位是岁方差单位就是“岁的平方”如果特征是“收入”单位是元方差单位就是“元的平方”。这两个方差根本没法直接比较阈值也没法统一。所以实践中有一个关键决策要不要先标准化再算方差。标准化Z-score之后每个特征的方差都变成1这时候方差阈值就失去了区分意义——所有特征方差都是1你设0.5的阈值一个都筛不掉。反过来说如果你不标准化方差阈值就高度依赖量纲阈值必须针对每个特征单独考虑或者只用于筛掉那些方差接近0的列。我的建议是方差阈值主要用于筛“近常量列”而不是做精细的方差比较。也就是说阈值通常设得很小比如0到0.01之间目标是干掉那些几乎不变的列而不是在方差0.5和0.8之间做取舍。2.2 阈值设定的三种实用策略阈值到底设多少没有标准答案但有三条可操作的路径策略一设0只删常量列。这是最保守也最安全的做法。方差为0意味着这列所有值完全相同对任何模型都是纯噪声除了可能作为“该特征是否存在”的标记但那是另一回事。VarianceThreshold(threshold0)就是干这个的。策略二基于分位数动态设定。先算出所有特征的方差然后取一个低分位数比如10%分位作为阈值。这样能自适应地砍掉方差最低的那批特征而不是拍一个绝对值。代码上就是threshold np.percentile(variances, 10)。策略三针对稀疏数据设极小值。对于one-hot编码后的稀疏矩阵很多列只有极少数样本为1方差很小但并非无用。这时候阈值要设得极低比如1e-6只删掉真正全0或几乎全0的列。策略阈值适用场景风险设00通用清洗几乎无风险分位数动态高维数据粗筛可能误删有用稀疏特征极小值1e-6稀疏one-hot需配合业务判断2.3 标准化与方差阈值的顺序陷阱这是我在实际项目里踩过的一个坑先标准化再上方差阈值等于白做。因为标准化会把每个特征的方差强行拉到1方差阈值就失效了。正确的顺序应该是先做方差阈值筛选再做标准化。或者如果你确实需要标准化那就不要用方差阈值改用别的筛选标准。还有一种情况是用了MinMaxScaler它把数据缩放到[0,1]区间。这时候方差会变得非常小因为值域被压缩了方差阈值同样会失效。所以记住一句话任何会改变特征方差量纲的变换都要放在方差阈值之后。注意如果你在Pipeline里把Scaler放在VarianceThreshold前面一定要检查一下筛选结果很可能一列都没删掉你还以为代码生效了。3. 完整实操从原始数据到筛选后的特征矩阵3.1 环境准备与数据构造我用一个模拟数据集来演示完整流程。这个数据集模拟的是某类用户行为表包含数值特征、常量列、近常量列和稀疏列方便观察方差阈值的实际效果。import numpy as np import pandas as pd from sklearn.feature_selection import VarianceThreshold np.random.seed(42) # 构造模拟数据200个样本8个特征 data { age: np.random.randint(18, 65, 200), # 正常数值特征 income: np.random.normal(8000, 3000, 200), # 正常数值特征 const_zero: np.zeros(200), # 常量列方差0 const_five: np.full(200, 5), # 常量列方差0 near_const: np.concatenate([np.ones(195), np.zeros(5)]), # 近常量列 sparse_flag: np.random.binomial(1, 0.02, 200), # 稀疏列2%为1 score: np.random.uniform(0, 1, 200), # 正常数值特征 noise: np.random.normal(0, 0.001, 200), # 极小方差噪声列 } df pd.DataFrame(data) print(df.var())跑一下df.var()你会看到类似这样的方差分布const_zero和const_five方差为0near_const方差约0.024sparse_flag方差约0.02noise方差约1e-6而age、income、score方差都在正常量级。3.2 用VarianceThreshold做第一轮筛选先做最保守的筛选阈值设0只删常量列selector VarianceThreshold(threshold0) X_selected selector.fit_transform(df) print(原始特征数:, df.shape[1]) print(筛选后特征数:, X_selected.shape[1]) print(保留的特征:, df.columns[selector.get_support()])结果会删掉const_zero和const_five两列保留6列。这一步几乎没有任何风险任何项目都可以放心做。接下来把阈值提高到0.01看看会删掉什么selector VarianceThreshold(threshold0.01) X_selected selector.fit_transform(df) print(阈值0.01筛选后特征数:, X_selected.shape[1]) print(保留的特征:, df.columns[selector.get_support()])这时候noise列方差1e-6会被删掉near_const方差0.024和sparse_flag方差0.02会被保留因为它们方差大于0.01。这个结果符合预期。3.3 基于分位数动态确定阈值如果特征很多手动试阈值很麻烦可以用分位数自动确定variances df.var() threshold np.percentile(variances, 15) # 取15%分位 print(动态阈值:, threshold) selector VarianceThreshold(thresholdthreshold) X_selected selector.fit_transform(df) print(动态阈值筛选后特征数:, X_selected.shape[1]) print(保留的特征:, df.columns[selector.get_support()])分位数的选择取决于你想砍掉多少。15%分位意味着砍掉方差最低的15%特征。这个比例没有金标准我一般会先看方差分布如果发现有一批特征方差明显低于其他就在那个“断崖”处设阈值。3.4 把方差阈值嵌入Pipeline实际项目里方差阈值应该作为预处理Pipeline的一环而不是单独跑一次。下面是一个完整的Pipeline示例from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression pipe Pipeline([ (variance_filter, VarianceThreshold(threshold0.01)), # 先筛 (scaler, StandardScaler()), # 后标准化 (clf, LogisticRegression(max_iter1000)), ]) # 假设 X_train, y_train 已经准备好 # pipe.fit(X_train, y_train)注意顺序VarianceThreshold必须在StandardScaler之前。如果反过来标准化之后所有特征方差都是1方差阈值就完全失效了。这个顺序问题我在至少两个项目里见过有人搞反排查了半天才发现筛选没生效。3.5 稀疏矩阵场景的特殊处理如果你的特征是one-hot编码后的稀疏矩阵VarianceThreshold默认不支持稀疏输入需要设置threshold0并且数据要是密集的或者用支持稀疏的写法。实际上sklearn的VarianceThreshold对稀疏矩阵的支持有限处理稀疏数据时更推荐先转成密集再筛或者用SelectKBest配合其他标准。对于稀疏场景我的经验是不要用方差阈值去筛one-hot列。因为one-hot列的方差天然就低大部分是0但它们往往是有意义的。这时候应该用卡方检验或互信息来筛而不是方差。4. 常见问题与排查技巧实录4.1 筛选后特征数没变是哪里出了问题这是最高频的问题。原因通常有三个原因一阈值设得太低。如果所有特征方差都大于阈值自然一列都不删。先打印df.var()看看方差分布再决定阈值。原因二标准化放在了前面。前面强调过标准化后方差全为1阈值只要小于1就筛不掉任何东西。检查Pipeline顺序。原因三数据里确实没有低方差列。有些数据集本身就很干净每列都有变化这时候方差阈值确实筛不掉东西属于正常现象不用怀疑代码。排查方法很简单先算方差再对比阈值最后看get_support()返回的布尔数组。4.2 误删了有用特征怎么办方差阈值最大的风险就是误删。比如某个特征在训练集里几乎不变但在测试集或未来数据里会变化这时候删掉它就损失了信息。还有一种情况是稀疏特征方差低但业务含义强。应对策略阈值从0开始逐步提高观察每次筛选后模型效果的变化而不是一步到位设个大阈值保留筛选前后的特征列表方便回溯对稀疏特征单独处理不要和普通数值特征混在一起筛在交叉验证里评估筛选效果而不是只看一次训练结果。我个人的习惯是方差阈值只用来删方差严格为0的列以及方差小于1e-6的列。再往上就要结合业务判断了不会盲目用分位数一刀切。4.3 方差阈值和后续模型效果的联动观察方差阈值本身不保证提升模型效果它的主要价值是降低计算成本、减少噪声。所以评估它的时候不要只看准确率有没有涨还要看训练时间有没有缩短模型稳定性有没有提升比如交叉验证方差变小特征重要性排序有没有变得更清晰。如果筛完之后模型效果明显下降说明阈值设高了误删了有用特征需要回调。4.4 常见问题速查表问题现象可能原因排查方法解决方式筛选后特征数不变阈值过低或已标准化打印方差分布提高阈值或调整顺序模型效果下降误删有用特征对比筛选前后特征列表降低阈值稀疏特征被删阈值对稀疏列过高单独查看稀疏列方差对稀疏列设极低阈值Pipeline报错稀疏矩阵不支持检查输入类型转密集或换筛选方法结果不可复现未固定随机种子检查数据生成设置random_state4.5 几个我踩过的坑第一个坑是在标准化之后做方差阈值筛了半天发现一列没删还以为是数据太干净。后来打印方差才发现全是1白白浪费半小时。第二个坑是对one-hot矩阵用方差阈值结果把一些低频但重要的类别特征删了模型效果反而下降。后来改成只删全0列问题解决。第三个坑是阈值设了0.1在某个数据集上效果不错换到另一个数据集直接把一半特征删了因为两个数据集的特征量纲完全不同。这让我意识到方差阈值高度依赖数据分布不能跨数据集复用阈值。提示方差阈值是一个“数据相关”的操作阈值没有通用值。每次换数据集都要重新看方差分布重新定阈值。5. 进阶用法结合其他筛选方法构建特征选择流水线5.1 方差阈值 卡方检验的两级筛选方差阈值做粗筛卡方检验做精筛这是我用得最多的组合。流程是先用方差阈值删掉常量列和近常量列再用卡方检验选出与标签最相关的K个特征。from sklearn.feature_selection import SelectKBest, chi2 pipe Pipeline([ (variance_filter, VarianceThreshold(threshold0)), (chi2_select, SelectKBest(chi2, k50)), (clf, LogisticRegression(max_iter1000)), ])这样既保证了去掉无变化列又保证了保留与标签相关的特征。注意卡方检验要求特征非负如果数据有负值需要先做适当变换。5.2 方差阈值 递归特征消除的精度路线如果追求精度而不是速度可以在方差阈值之后接递归特征消除RFE。RFE会用模型权重反复训练、逐步删特征计算量大但筛选精度高。方差阈值在这里的作用是先把明显无用的列砍掉减少RFE的搜索空间。from sklearn.feature_selection import RFE pipe Pipeline([ (variance_filter, VarianceThreshold(threshold0)), (rfe, RFE(estimatorLogisticRegression(max_iter1000), n_features_to_select20)), (clf, LogisticRegression(max_iter1000)), ])这个组合适合特征数在几百到几千、且对精度要求较高的场景。如果特征上万RFE会非常慢这时候更适合用方差阈值加卡方或互信息。5.3 在无监督场景下的独立价值方差阈值最独特的价值在于无监督可用。聚类、异常检测、降维这些任务没有标签卡方和互信息都用不了但方差阈值可以用。比如在做用户分群之前先用方差阈值删掉那些在所有用户上取值都一样的字段能让聚类结果更聚焦于真正有差异的维度。我在一个无监督异常检测项目里原始特征有300多列其中近一半是各种配置项在很多样本上取值相同。用方差阈值删掉这些列之后特征降到150列左右孤立森林的训练时间缩短了将近一半检测效果基本持平。这就是方差阈值的典型价值不提升效果但显著降低成本。5.4 阈值选择的自动化尝试如果你想让阈值选择更自动化可以写一个简单的循环遍历一组候选阈值观察筛选后特征数和模型交叉验证分数的变化from sklearn.model_selection import cross_val_score thresholds [0, 1e-6, 1e-4, 1e-3, 1e-2, 0.05, 0.1] for t in thresholds: pipe Pipeline([ (vf, VarianceThreshold(thresholdt)), (scaler, StandardScaler()), (clf, LogisticRegression(max_iter1000)), ]) scores cross_val_score(pipe, X_train, y_train, cv5) print(fthreshold{t}, features{pipe.named_steps[vf].fit(X_train).get_support().sum()}, cv_score{scores.mean():.4f})跑完这个循环你就能看到阈值和特征数、模型分数之间的关系从而选一个平衡点。注意这个循环里每次都要重新fit因为不同阈值下保留的特征不同。我个人在实际操作中的体会是方差阈值这个工具看起来简单但真正用好需要理解它的边界它只负责删“没变化”的列不负责选“有用”的列。把它放在流水线的最前面做粗筛配合后面的有监督筛选方法才能发挥最大价值。阈值不要拍脑袋定先看方差分布再从0开始逐步提高观察特征数和模型效果的变化。最后再分享一个小技巧如果你的数据里有很多稀疏的one-hot列方差阈值只用来删全0列就够了不要用分位数去筛否则很容易误删低频但重要的类别特征。

相关新闻

Cesium 自主漫游实战:路径插值、姿态控制与时间轴完整实现

Cesium 自主漫游实战:路径插值、姿态控制与时间轴完整实现

简介:这是一份面向具备一定GIS开发基础读者的Cesium三维开发实战源码包,聚焦于在三维地球场景中实现键盘驱动的自主漫游功能。资源通过监听WASD或方向键事件,结合CallbackProperty逐帧更新小车实体的位置与朝向,并将整套逻辑封装为…

2026/10/18 14:40:42 阅读更多 →
SGK字典学习算法:半正交约束与分块SVD的工程化实现

SGK字典学习算法:半正交约束与分块SVD的工程化实现

简介:本资源为面向图像处理与计算机视觉方向研究者及算法工程师的字典学习核心算法实现包,聚焦SGK(Semi-Orthogonal Generalized K-SVD)这一高效改进型字典学习方法,解决传统K-SVD在大规模数据下计算慢、收敛低的问题&…

2026/10/18 14:40:42 阅读更多 →
MS-GARCH模型详解:MATLAB代码包实现与状态划分避坑指南

MS-GARCH模型详解:MATLAB代码包实现与状态划分避坑指南

简介:马尔科夫转换GARCH(MS-GARCH)模型是融合GARCH与马尔科夫链的金融波动率分析工具,这套MATLAB实现包恰好为研究者与量化学习者提供了可直接运行的代码基础。压缩包共14个文件、约1.34MB,其中12个M文件覆盖主程序、似…

2026/10/18 14:40:42 阅读更多 →

最新新闻

HWFW_GUI华为ONT固件逆向工具环境配置指南

HWFW_GUI华为ONT固件逆向工具环境配置指南

简介:HWFW_GUI是一款面向通信设备开发与逆向分析工程师的华为ONT固件可视化编辑工具,基于C开发,专用于解析、浏览、修改及导出华为光猫(ONT)固件镜像中的子项目(如uboot、kernel、rootfs等)&…

2026/10/18 15:25:02 阅读更多 →
SwiftUI macOS开发:单选组实现、美化与流式布局实践

SwiftUI macOS开发:单选组实现、美化与流式布局实践

把iOS的SwiftUI代码直接搬到macOS上跑,第一个让我愣住的就是Picker。同一个控件,在iOS上默认是滚动选择或跳转列表,到了macOS里却变成一个干干净净的下拉框;改成Segment分段样式之后,iOS上白白胖胖的控件到了macOS上立…

2026/10/18 15:25:02 阅读更多 →
cy163客服系统22.0.0全开源版:生产级实时会话路由与三端接入底座

cy163客服系统22.0.0全开源版:生产级实时会话路由与三端接入底座

简介:聚合客服(万能客服)cy163_customerservice 22.0.0 全开源版安装更新一体包,是一款面向中小企业、开发者及技术团队的轻量级多渠道客服系统解决方案,聚焦解决客户咨询分散、响应滞后、知识复用率低等典型服务痛点。…

2026/10/18 15:25:02 阅读更多 →
Unity UI核心RectTransform详解:锚点、Pivot与屏幕适配实战

Unity UI核心RectTransform详解:锚点、Pivot与屏幕适配实战

做Unity UI开发,绕不开RectTransform。无论是摆一张图片、做按钮、搭Panel,还是处理不同分辨率下的适配,本质上都是在跟RectTransform打交道。很多初学者一上来就被Inspector里的Position(Pos X、Pos Y、Pos Z)、Width…

2026/10/18 15:25:02 阅读更多 →
老照片上色全攻略:三种实用方法一次掌握

老照片上色全攻略:三种实用方法一次掌握

黑白老照片上色这事,我做了不少年,从最早的画笔一点一点涂,到后来用图层混合模式偷懒,再到现在AI一键生成打底稿,整套流程算是踩过不少坑也攒了不少心得。这个标题其实点得很准——上色本身不难,难的是“简…

2026/10/18 15:25:02 阅读更多 →
MATLAB脑电信号预处理实战:避开基线漂移与眼电伪迹的5大深坑

MATLAB脑电信号预处理实战:避开基线漂移与眼电伪迹的5大深坑

简介:本资源是一套基于MATLAB实现脑电信号情绪分类的完整分析方案,面向生物医学工程、神经科学及人工智能交叉领域的初学者与进阶学习者,聚焦EEG信号预处理、特征提取与多情绪状态(愤怒、平静、悲伤)分类建模。压缩包共…

2026/10/18 15:24:02 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →