SQLFlow 自定义模型指南:用 Python 定义可被 SQL 调用的深度学习模型
人工智能机器学习后端编译器【免费下载链接】sqlflowBrings SQL and AI together.项目地址https://gitcode.com/gh_mirrors/sq/sqlflow点击查看免费下载导读SQLFlow 的核心能力是让 SQL 程序直接调用用 Python 定义的深度学习模型——用户只需在 SQL 中书写TO TRAIN语句指定模型名称与超参数即可触发一次完整的模型训练、评估与预测流程。本文以 SQLFlow 官方设计文档《Define Models for SQLFlow》为基础讲解如何在 SQLFlow 中定义自定义模型为什么选择 Keras 而非 TensorFlow Estimator、Keras 三种建模 API 的取舍、tf.keras.Model子类化与 Functional API 的完整代码示例并结合仓库源码剖析 SQLFlow 运行时runtime如何加载、编译、训练、保存与预测这些自定义模型。读完本文你将掌握编写可直接被 SQL 语句调用的 Keras 自定义模型的全部规范与底层原理。为什么 SQLFlow 首选 Keras 而非 EstimatorSQLFlow 需要 SQL 程序能够调用定义在 Python 中的深度学习模型。在 TensorFlow 生态中模型通常有两种定义方式Keras API或继承tf.estimator.Estimator的自定义类。SQLFlow 明确优先选择 Keras理由有三TensorFlow 2.x 将与 Keras 深度集成官方在 TensorFlow Dev Summit 2019 上宣布了这一方向Keras 的文档资料比 Estimator 更丰富学习与排查成本更低社区中用 Keras 定义的模型数量远多于 Estimator。这一取向在仓库源码中得到了印证运行时在加载模型后会通过 is_tf_estimator 判断模型是否为 Estimator仅当模型是tf.estimator.Estimator、BoostedTreesClassifier或BoostedTreesRegressor的子类时返回 True其余一律按 Keras 模型走训练/预测分支而 SQL 侧的代码生成模板 template_train.go 默认导入的是tensorflow.estimator中预置的分类器/回归器与 Keras 优化器、损失函数供两类模型共同使用。Keras 三种建模 API 及其代码形态Keras 提供了三种定义模型的方式SQLFlow 文档逐一给出了最小可运行的代码骨架1. 子类化tf.keras.Model通过继承tf.keras.Model并重写__init__与call方法构建模型class DNNClassifier(tf.keras.Model): def __init__(self, feature_columns, hidden_units, n_classes): super(DNNClassifier, self).__init__() self.feature_layer tf.keras.layers.DenseFeatures(feature_columns) self.hidden_layers [] for hidden_unit in hidden_units: self.hidden_layers.append(tf.keras.layers.Dense(hidden_unit)) self.prediction_layer tf.keras.layers.Dense(n_classes, activationsoftmax) def call(self, inputs): x self.feature_layer(inputs) for hidden_layer in self.hidden_layers: x hidden_layer(x) return self.prediction_layer(x) model DNNClassifier(feature_columns, hidden_units, n_classes)注意tf.keras.Model提供的save_weights/load_weights只保存和恢复模型参数weights不保存网络拓扑结构topology。这一限制对子类化模型尤其明显——由于拓扑结构在 Python 代码中定义反序列化时必须重新实例化模型对象再加载权重。SQLFlow 正是按这一思路处理预测阶段先用同样的模型类与参数重建对象再加载权重详见下文保存与加载一节。2. Functional API函数式 APIx tf.feature_column.input_layer(shape(5,)) for n in hidden_units: x tf.keras.layers.Dense(n, activationrelu)(x) pred tf.keras.layers.Dense(n_classes, activationsoftmax)(x) model tf.keras.models.Model(inputsfeature_columns, outputspred)函数式 API 可以与 feature column API 协作但需要为每个原始特征列手工分配一个tf.keras.Input作为输入占位。3.keras.Sequential顺序模型model tf.keras.Sequential() model.add(tf.keras.layers.DenseFeatures(feature_columns)) for n in hidden_units: model.add(tf.keras.layers.Dense(n, activationrelu)) model.add(tf.keras.layers.Dense(n_classes, activationsoftmax))需要特别说明的是Sequential只能覆盖少量简单模型无法表达 ResNet、Transformer、WideAndDeep 等主流结构因此覆盖面有限。SQLFlow 的最终选择子类化tf.keras.Model三种 API 的对比如下表Keras API兼容 feature column API保存/加载模型模型覆盖面tf.keras.Model子类化☑️仅权重无拓扑高Functional API☑️☑️高Sequential 模型☑️☑️低综合与 feature column 的协作能力、模型的保存加载便利性、结构覆盖面三个维度SQLFlow 选定子类化tf.keras.Model作为首选建模方式。值得注意的是子类化模型只保存权重、不保存拓扑的局限并不会妨碍 SQLFlow 的使用因为 SQLFlow 的 SQL 语句本身完整记录着模型类名estimator与全部模型参数model.*运行时可以在训练、预测、评估阶段随时用这些信息重建模型对象——拓扑信息其实隐含在 SQL 中。实战示例一子类化tf.keras.Model的完整写法SQLFlow 文档给出了一个可在 SQL 中直接调用的完整模型类DNNClassifier要求 TensorFlow 2.0 alpha 及以上版本class DNNClassifier(tf.keras.Model): def __init__(self, feature_columns, hidden_units, n_classes): DNNClassifier :param feature_columns: feature columns. :type feature_columns: list[tf.feature_column]. :param hidden_units: number of hidden units. :type hidden_units: list[int]. :param n_classes: List of hidden units per layer. :type n_classes: int. super(DNNClassifier, self).__init__() # combines all the data as a dense tensor self.feature_layer tf.keras.layers.DenseFeatures(feature_columns) self.hidden_layers [] for hidden_unit in hidden_units: self.hidden_layers.append(tf.keras.layers.Dense(hidden_unit)) self.prediction_layer tf.keras.layers.Dense(n_classes, activationsoftmax) def call(self, inputs): x self.feature_layer(inputs) for hidden_layer in self.hidden_layers: x hidden_layer(x) return self.prediction_layer(x) def default_optimizer(self): Default optimizer name. Used in model.compile. return adam def default_loss(self): Default loss function. Used in model.compile. return categorical_crossentropy def default_training_epochs(self): Default training epochs. Used in model.fit. return 5 def prepare_prediction_column(self, prediction): Return the class label of highest probability. return prediction.argmax(axis-1)除了__init__与call这两个 Keras 强制要求的方法外SQLFlow 约定模型类还可以可选地提供四个默认值方法用于在 SQL 未显式指定对应超参数时兜底default_optimizer()默认优化器示例返回adam用于model.compiledefault_loss()默认损失函数示例返回categorical_crossentropy用于model.compiledefault_training_epochs()默认训练轮数示例返回5用于model.fitprepare_prediction_column(prediction)将模型输出转换为可写入结果表的预测值示例对分类输出做argmax(axis-1)取概率最大的类别。仓库 python/runtime/models/example.py 中保存着与文档完全一致的DNNClassifier实现并展示了纯 Python 侧的调用方式训练时执行model.compile(optimizermodel.default_optimizer(), lossmodel.default_loss())与model.fit(..., epochsmodel.default_training_epochs())预测时执行model.prepare_prediction_column(prediction)可作为脱离 SQLFlow、独立验证模型逻辑的参考脚本。实战示例二Functional API 的完整写法对于偏好函数式风格的开发者SQLFlow 文档也给出了一个可直接使用的MyExampleModel工厂函数其关键点在于为每个特征字段显式创建tf.keras.Inputdef MyExampleModel(feature_columns, field_metas, learning_rate0.01): feature_layer_inputs dict() for fm in field_metas: feature_layer_inputs[fm.name] tf.keras.Input(shape(fm.shape), namefm.name, dtypefm.dtype) feature_layer tf.keras.layers.DenseFeatures(feature_columns) feature_layer_outputs feature_layer(feature_layer_inputs) x layers.Dense(128, activationrelu)(feature_layer_outputs) x layers.Dense(64, activationrelu)(x) pred layers.Dense(1, activationsigmoid)(x) return keras.Model(inputs[v for v in feature_layer_inputs.values()], outputspred) def loss(output, labels): labels tf.reshape(labels, [-1]) return tf.reduce_mean( input_tensortf.nn.sparse_softmax_cross_entropy_with_logits( logitsoutput, labelslabels ) ) def optimizer(lr0.1): return tf.optimizers.SGD(lr) def prepare_prediction_column(self, prediction): Return the class label of highest probability. return prediction.argmax(axis-1)这里field_metas参数携带每个字段的name、shape、dtype信息用于构造输入占位。这一点与运行时的实现严格对应在 train.py 中SQLFlow 会判断模型是否是一个函数isinstance(estimator, types.FunctionType)如果是则自动把 SQL 侧推导出的feature_metas注入到model_params[field_metas]从而满足函数式模型的构造签名要求predict.py 的预测路径也做了同样的处理。在 SQL 中调用自定义模型参数从 SQL 到 Python 的传递链路模型定义好之后即可在 SQL 中通过TO TRAIN 模型名直接引用。SQLFlow 文档配套示例见 docgen.go如下SELECT * FROM iris.train TO TRAIN DNNClassifier WITH model.n_classes 3, model.hidden_units [10, 20], validation.select SELECT * FROM iris.test LABEL class INTO sqlflow_models.my_dnn_model;这条 SQL 的语义分解如下TO TRAIN DNNClassifier指定要训练的模型类。模型名既可以是 TensorFlow 预置的 Estimator也可以是sqlflow_models.DNNClassifier这类自定义包中的模型详见下文WITH model.n_classes 3, model.hidden_units [10, 20]model.前缀下的键值对会被收集为模型构造参数LABEL class指定标签列INTO sqlflow_models.my_dnn_model指定模型保存位置可理解为模型仓库中的命名空间.模型名。参数的分类与传递由 Go 侧的 codegen.go 完成CategorizeAttributescodegen.go按前缀把WITH子句属性拆分为三组model.*→ 模型参数modelParams、train.*→ 训练参数trainParams、validation.*→ 验证参数validateParamsInitializeAttributescodegen.go会调用attribute.ExtractSQLFlowModelsSymbolOnce()通过 Python 的symbol_extractor解析sqlflow_models包内各模型 docstring 中的参数说明实现见 attribute.go从而对自定义模型的model.*参数做类型检查与默认值补全如果模型不在sqlflow_models前缀下即完全未知的自定义模型则会放开为任意model.*参数见 codegen.go特殊地constructOptimizers与constructLossescodegen.go会把model.optimizer、model.loss及其loss.xxx参数拼装成合法的 Python 调用表达式如SGD(lr0.1)最终代码生成模板 template_train.go 会把model_params序列化进生成的 Python 脚本并对optimizer、dnn_optimizer、linear_optimizer、loss等字符串参数执行eval将其还原为真实的 TensorFlow 优化器/损失对象后再传给训练入口。生成的 Python 脚本会尝试import sqlflow_modelstemplate_train.go失败时打印告警但不中断——这保证了内置模型在未安装自定义包时依然可用。运行时如何识别、加载并编译自定义模型SQL 语句经代码生成后最终调用的是 runtime/tensorflow/train.py 中的train()入口。其加载与分发的关键步骤如下加载模型类import_model(estimator_string)实现见 import_model.py直接对模型名字符串执行eval取回类或函数对象若模型名形如my_pkg.MyModel两段式且包名不是xgboost、sqlflow_models还会先尝试__import__导入对应包import_model.py判别模型类型is_tf_estimator(estimator)判断是 Estimator 还是 Keras 模型从而分流到 train_estimator.py 或 train_keras.py 两条训练管线编译 Keras 模型keras_compile()train_keras.py负责组装compile参数若WITH子句未显式给出optimizer则优先调用模型模块中定义的optimizer()函数若模块中没有该函数则回退到tf.keras.optimizers.Adagrad(lr0.001)默认优化器若未给出loss优先取模块级变量loss否则使用默认值sparse_categorical_crossentropy指标metrics则通过eval_metrics_fn()或 SQL 的validation.metrics指定包装特征输入init_model_with_feature_column()见 keras_with_feature_column_input.py通过inspect.getargspec检查模型构造函数是否接受feature_columns参数如果不接受例如纯函数式模型就把它包装进WrappedKerasModel由包装类先经过tf.keras.layers.DenseFeatures层把 SQL 侧 COLUMN 子句生成的 feature column 组装成稠密张量再喂给用户子模型训练keras_train_compiled()train_keras.py执行classifier.fit(...)其中epochs优先取 SQL 的train.epoch未指定时调用模型的default_training_epochs()。保存与加载子类化模型的权重恢复机制子类化 Keras 模型只保存权重、不保存拓扑SQLFlow 的处理方式是用 SQL 中的信息重建拓扑再恢复权重保存训练结束后train_keras.py 调用classifier.save(save, save_formattf)保存模型TensorFlow SavedModel 格式。源码注释特别指出若模型定义了sqlflow_train_loop且不含 Keras 层save可能失败因此会先写model_meta.json元数据再尝试保存加载预测时predict.py 先用相同的模型类与model_params重新实例化模型执行一次predict_on_batch以初始化参数再调用load_keras_model_weights()load_model.py从保存目录的variables/variablesTensorFlow checkpoint 格式恢复权重。model.save与model.save_weights的产物在 checkpoint 层面是兼容的因此可以互相加载。这一机制意味着自定义模型的类定义必须始终可用例如通过 pip 安装的sqlflow_models包或随模型仓库镜像分发因为模型的结构只存在于 Python 代码中。预测时的输出处理SQLFlow 的keras_predict()predict.py负责把模型输出写回数据库结果表其处理逻辑与文档中prepare_prediction_column的语义一致对单输出回归len(result[0]) 1直接取标量对多分类输出各输出概率之和约等于 1.0通过np.isclose(sum, 1.0)判定后执行result[0].argmax(axis-1)取概率最大的类别索引对多输出回归则原样保留向量若 SQL 指定了predict.extra_outputs模型可返回元组前一个元素为主预测结果其余元素按顺序写入附加结果列predict.py。文档示例中的prepare_prediction_column正是这一取 argmax约定的模型侧显式版本二者在语义上互为印证。补充阅读与进一步探索文档末尾建议进一步阅读 Keras 的三个核心源码文件models.py、engine/network.py与engine/training.py以深入理解模型的构造、层连接与训练循环。本仓库中与自定义模型主题强相关的可继续探索路径doc/design/customized_model.md本文所依据的官方设计文档原文python/runtime/models/example.py与文档一致的DNNClassifier参考实现及独立运行脚本python/runtime/tensorflow/train_keras.pyKeras 模型编译、训练、保存的完整运行时实现python/runtime/tensorflow/keras_with_feature_column_input.pyWrappedKerasModel特征包装机制go/codegen/tensorflow/codegen.go 与 go/codegen/tensorflow/template_train.goSQL 到 Python 训练脚本的代码生成链路python/runtime/tensorflow/keras_example.py 与 python/runtime/tensorflow/keras_example_reg.py分别演示自定义分类/回归 Keras 模型在训练-预测全流程中的真实调用参数。此外SQLFlow 的模型参数文档可通过go/cmd/docgen命令生成 Markdown 表格见 docgen.go 中的DocGenInMarkdown其中TO TRAIN DNNClassifier WITH model.n_classes3, ...的写法是各类模型参数在 SQL 中的统一表达范式可作为编写自定义模型文档时的参考模板。赞分享人工智能机器学习后端编译器【免费下载链接】sqlflowBrings SQL and AI together.项目地址https://gitcode.com/gh_mirrors/sq/sqlflow点击查看免费下载相关推荐TDgpt 自定义机器学习模型接入指南将 Keras/Torch 模型注册为 SQL 可调用的时间序列分析算法TDgpt 自定义机器学习模型接入指南将 Keras/Torch 模型注册为 SQL 可调用的时间序列分析算法 TDgpt 是 TDengine 内置的时间序数据库时序数据库物联网大数据实时分析云原生5步构建专业级金融数据系统Python量化分析实战指南5步构建专业级金融数据系统Python量化分析实战指南 在金融科技快速发展的今天高效处理通达信数据已成为量化交易和数据分析师的核心需求。mootdx作为一款金融科技数据分析终极Flash游戏收藏方案Flash Collector完整实战指南终极Flash游戏收藏方案Flash Collector完整实战指南 Flash Collector是一款专为保存和运行经典Flash小游戏设计的开源工具能桌面应用网页爬虫上一篇如何快速为Honey Select 2安装完整汉化去码补丁新手友好终极指南下一篇FPM 打包 CPAN Perl 模块实战指南cpan 输入类型与命令行参数全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

5分钟搞定B站API:开发者必备的实战指南

5分钟搞定B站API:开发者必备的实战指南

5分钟搞定B站API:开发者必备的实战指南 B站作为中国最大的弹幕视频网站,拥有海量的内容和活跃的社区,其API为开发者提供了丰富的开发可能性。无论你是想分析视频数据、获取弹幕信息,还是构建自动化工具,掌握B站API都能…

2026/10/13 6:27:47 阅读更多 →
AnyPS5是什么?破解、越狱与免费游戏的误区

AnyPS5是什么?破解、越狱与免费游戏的误区

1. 先说清楚AnyPS5到底是什么玩意儿1.5 先泼一盆冷水:AnyPS5不是破解,不是越狱,更不是让你免费玩游戏的神器

2026/10/13 6:26:47 阅读更多 →
VS2005 编译 FFmpeg 实战:从工程配置到 RTMP 推流避坑指南

VS2005 编译 FFmpeg 实战:从工程配置到 RTMP 推流避坑指南

简介:这份ffmpeg_vs2005工程资源面向需要在Windows平台、以Visual Studio 2005为开发环境编译FFmpeg的C/C开发者与音视频学习者,重点解决旧版IDE下配置libavcodec、libavformat、libavfilter、libavutil等组件时遇到的工程设置与依赖链接问题。压缩包为r…

2026/10/13 6:26:46 阅读更多 →

最新新闻

Win7离线OCR工具:PaddleOCR-json免Python部署实战

Win7离线OCR工具:PaddleOCR-json免Python部署实战

简介:win7-x64-PaddleOCR-json.zip是面向Windows 7 64位系统的PaddleOCR部署压缩包,适用于需要在旧版平台快速搭建文字识别能力、并通过JSON格式获取结构化结果的开发者和运维人员。包内共64个文件,总体积约126.19MB。其中dll动态库用于支撑推…

2026/10/13 7:13:58 阅读更多 →
AI应用上下文管理实战:分层压缩方案详解

AI应用上下文管理实战:分层压缩方案详解

我做过一个内部的智能客服项目,上线三个月后收到最多的用户反馈不是"回答不准",而是"它怎么又把我说过的话忘了"。用户在第十分钟重新提起自己五分钟前强调过的产品型号时,模型一本正经地给出了另一款产品的介绍。查日志…

2026/10/13 7:13:58 阅读更多 →
LSTM+Attention时序预测实战:从原理到PyTorch落地

LSTM+Attention时序预测实战:从原理到PyTorch落地

1. 从"预测"这个词说起:为什么LSTM加Attention成了时序任务里的常驻组合做时序预测的人大概都有过这样的经历:拿到一批带时间戳的数据,第一反应是上ARIMA或者简单移动平均,跑出来的结果在平稳段看着还行,一到…

2026/10/13 7:13:58 阅读更多 →
扣子3.0零代码搭建AI智能体:工作流与多Agent协作实战

扣子3.0零代码搭建AI智能体:工作流与多Agent协作实战

扣子 3.0 这个版本,最核心的变化就是把“搭建 AI 智能体”这件事,从写代码变成了搭积木。你不需要懂 Python,不需要本地显卡,打开浏览器登录就能开始做。这篇文章会带你从零开始,走完一个完整的智能体搭建流程&#xf…

2026/10/13 7:13:58 阅读更多 →
HuggingFace英译中模型迁移ONNX:导出、推理与量化部署全攻略

HuggingFace英译中模型迁移ONNX:导出、推理与量化部署全攻略

最近把一个托管在 HuggingFace 上的英译中模型真正搬进了生产环境,折腾了一阵子之后,总算把完整的导出、推理、优化流程打通了。这篇内容就是从那个项目里整理出来的,全程聚焦一件事:如何把一个 HuggingFace 上的英译中模型迁移到…

2026/10/13 7:13:58 阅读更多 →
零基础AI漫剧量产:12模块工业化流水线实战

零基础AI漫剧量产:12模块工业化流水线实战

1. 这不是“AI绘画课”,而是一套可批量交付的漫剧工业化流水线“零基础 AI 漫剧智能量产创作营”——光看标题,很多人第一反应是:又一个教Stable Diffusion换脸、用Runway生成动图的速成班?我最初也这么想。直到去年参与某高校数字…

2026/10/13 7:12:57 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →