基于知识图谱的Python电影推荐系统毕业设计:从图谱构建到推荐融合
简介这是一套面向计算机相关专业毕业设计场景的Python电影推荐系统源码采用知识图谱架构融合协同过滤算法可有效缓解传统推荐系统的冷启动问题。项目难度中等适合作为课程作业、学期末综合实践或自学训练素材也适合需要实际项目经验的学习者参考。压缩包共67个文件约892KB以43个py脚本为核心辅以zbak备份、txt数据说明、cfg配置文件、md技术文档及sql建库脚本涵盖知识图谱构建、用户行为分析与推荐算法等模块。代码遵循PEP8规范并配有详细注释数据集经多维度清洗构建了导演、演员、类型、题材等实体关系的电影知识网络可实现基于语义相似度的深度推荐。目前已有61人学习读者可从中获得完整项目结构、环境配置指南与部署教程便于快速理解知识图谱推荐系统的实现思路与工程组织方式。1. 从一份「基于知识图谱的Python电影推荐系统毕业设计项目源码」说起很多同学拿到这个题目时第一反应是去搜「电影推荐系统源码」然后找到一堆协同过滤的代码改改数据集就交差了。但答辩老师只要问一句「你的知识图谱在哪、实体关系怎么定义的、图查询怎么落到推荐上」基本就露馅了。这个标题真正的难点不在推荐算法而在于知识图谱构建和推荐逻辑的融合——前者决定你的系统有没有「知识」后者决定这些知识能不能变成推荐理由。这套方案适合三类人一是计算机毕业设计选题卡在推荐系统方向、想做出差异化的同学二是已经会 Python 基础、想找一个能跑通「数据采集→图谱构建→图查询→推荐排序」完整链路的练手项目三是需要一套可讲解、可演示、可写论文的系统而不是一个黑盒模型。下面我按自己带过几届毕设的经验把这条链路拆开讲清楚包括每一步用什么库、参数怎么设、哪里最容易翻车。2. 知识图谱电影推荐系统的技术选型与数据建模2.1 为什么不用纯协同过滤而要引入知识图谱协同过滤的核心问题是冷启动和可解释性。一个用户只看过三部电影ItemCF 算出来的相似度基本是噪声而知识图谱可以把「导演」「演员」「类型」「年份」「地区」这些结构化关系补进来即使交互数据稀疏也能通过实体路径找到候选电影。常见做法是用图谱做召回和可解释路径用协同过滤或矩阵分解做精排两者加权融合。从工程角度看知识图谱推荐系统的数据流是这样的原始电影元数据 → 实体识别与关系抽取 → 三元组存储 → 图查询召回 → 特征拼接 → 排序输出。每一步都有对应的 Python 库不需要从零造轮子。2.2 数据来源与字段设计电影数据一般来自公开数据集或自己爬取。我一般会保留以下字段它们直接决定图谱的节点和边字段用途是否作为图谱节点/边电影ID唯一标识节点属性电影名称展示与检索节点属性导演关系抽取导演节点 执导边演员列表关系抽取演员节点 出演边类型多值分类类型节点 属于边上映年份时间特征节点属性地区分类特征地区节点 产地边评分排序依据节点属性用户评分记录交互数据用户节点 评分边字段设计的原则是能作为推荐理由的才建边。比如「因为你看过这个导演的片子」比「因为评分高」更有说服力所以导演边必须建。2.3 图数据库选型Neo4j 还是 NetworkX毕业设计阶段我建议用 Neo4j 做存储和查询用 NetworkX 做本地分析和可视化。Neo4j 的 Cypher 查询写起来直观答辩演示也好看NetworkX 适合在 Python 里快速算路径和中心度。安装 Neo4j 桌面版后用 Python 驱动连接pip install neo4j networkx pandasfrom neo4j import GraphDatabase # 连接本地 Neo4j默认 bolt 端口 7687 driver GraphDatabase.driver(bolt://localhost:7687, auth(neo4j, 你的密码)) def create_movie_node(tx, movie): # 用 MERGE 避免重复插入ON CREATE 只在新建时设置属性 tx.run( MERGE (m:Movie {movieId: $movieId}) ON CREATE SET m.title $title, m.year $year, m.rating $rating , **movie) with driver.session() as session: session.execute_write(create_movie_node, { movieId: 1, title: 肖申克的救赎, year: 1994, rating: 9.7 })这段代码的关键点是MERGE而不是CREATE否则重复导入会产生大量重复节点。参数movieId是业务主键必须唯一ON CREATE保证已有节点不会被覆盖属性。2.4 三元组抽取与批量导入有了字段设计接下来把 CSV 转成三元组。常见做法是用 pandas 读数据逐行构造(头实体, 关系, 尾实体)再批量写入 Neo4j。import pandas as pd df pd.read_csv(movies.csv) triples [] for _, row in df.iterrows(): movie_id fm_{row[movieId]} triples.append((movie_id, TITLE, row[title])) triples.append((movie_id, YEAR, str(row[year]))) for actor in str(row[actors]).split(|): if actor.strip(): triples.append((movie_id, ACTED_BY, actor.strip())) for genre in str(row[genres]).split(|): if genre.strip(): triples.append((movie_id, BELONGS_TO, genre.strip())) print(f共生成 {len(triples)} 条三元组)逻辑说明电影节点用m_前缀避免和演员节点 ID 冲突演员和类型用|分隔这是常见的数据集格式。参数上split后必须strip()否则会带入空格导致实体对不上。批量写入时建议每 500 条一个事务太大容易内存溢出太小则速度慢。3. 用 Python 构建电影知识图谱的完整步骤3.1 环境准备与依赖安装先确认 Python 版本在 3.8 以上然后安装核心依赖。这里不推荐用最新版因为部分图算法库对 3.12 支持还不稳定。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install neo4j5.14.0 pandas2.1.0 networkx3.1 py2neo2021.2.4py2neo是可选的老牌驱动有些教程用它但官方推荐neo4j驱动。如果安装numpy或cv2报错通常是 Python 版本和 wheel 不匹配换 3.10 最稳。3.2 从 CSV 到 Neo4j批量建节点和边下面这段代码把电影、演员、类型、导演四类节点和对应关系一次性写入。注意先建节点再建边否则关系找不到端点。from neo4j import GraphDatabase import pandas as pd driver GraphDatabase.driver(bolt://localhost:7687, auth(neo4j, 你的密码)) def batch_write(tx, query, rows): tx.run(query, rowsrows) with driver.session() as session: df pd.read_csv(movies.csv) # 建电影节点 movie_rows [{id: fm_{r[movieId]}, title: r[title], year: int(r[year]), rating: float(r[rating])} for _, r in df.iterrows()] session.execute_write(batch_write, UNWIND $rows AS row MERGE (m:Movie {movieId: row.id}) SET m.title row.title, m.year row.year, m.rating row.rating , movie_rows) # 建演员节点并连边 actor_rows [] for _, r in df.iterrows(): for actor in str(r[actors]).split(|): if actor.strip(): actor_rows.append({movieId: fm_{r[movieId]}, actor: actor.strip()}) session.execute_write(batch_write, UNWIND $rows AS row MATCH (m:Movie {movieId: row.movieId}) MERGE (a:Actor {name: row.actor}) MERGE (m)-[:ACTED_BY]-(a) , actor_rows)UNWIND是 Cypher 里处理批量数据的标准写法比循环单条插入快一个数量级。参数$rows是一个字典列表每个字典的键要和row.xxx对应。如果报Expected a map错误检查传入的是不是列表。3.3 用 Cypher 做图查询召回图谱建好后推荐召回就是写查询。比如「找出和用户看过的电影同导演、同类型、但用户没看过的电影」def recommend_by_graph(tx, watched_ids, limit10): query MATCH (m:Movie)-[:DIRECTED_BY]-(d:Director)-[:DIRECTED_BY]-(rec:Movie) WHERE m.movieId IN $watched AND NOT rec.movieId IN $watched RETURN DISTINCT rec.title AS title, rec.rating AS rating ORDER BY rating DESC LIMIT $limit result tx.run(query, watchedwatched_ids, limitlimit) return [record.data() for record in result]这条查询走的是「导演」路径返回结果可以直接作为推荐理由。参数watched_ids是用户已看电影的 ID 列表limit控制召回数量。实际项目中我会把导演、演员、类型三条路径的召回结果合并去重再按评分加权。3.4 图谱可视化与结果验证答辩时一张清晰的图谱截图比十页文字都管用。用 NetworkX 把子图导出import networkx as nx from neo4j import GraphDatabase driver GraphDatabase.driver(bolt://localhost:7687, auth(neo4j, 你的密码)) G nx.DiGraph() with driver.session() as session: result session.run( MATCH (m:Movie)-[r]-(n) WHERE m.movieId IN $ids RETURN m.title AS src, type(r) AS rel, n.name AS dst , ids[m_1, m_2, m_3]) for record in result: G.add_edge(record[src], record[dst], labelrecord[rel]) print(f子图节点数{G.number_of_nodes()}边数{G.number_of_edges()})验证图谱是否建对就看节点数和边数是否符合预期。如果边数远小于预期通常是MERGE时属性名写错导致节点没匹配上。4. 推荐算法与图谱的融合从召回 to 排序4.1 基于图路径的召回策略召回阶段的目标是「不漏」所以我会同时跑三条路径同导演、同演员、同类型。每条路径取 Top 20合并后去重。这里的关键参数是路径深度一般不超过 2 跳3 跳以上噪声会急剧增加。def multi_path_recall(tx, watched_ids): paths { director: MATCH (m:Movie)-[:DIRECTED_BY]-(d)-[:DIRECTED_BY]-(rec:Movie) WHERE m.movieId IN $watched AND NOT rec.movieId IN $watched RETURN DISTINCT rec.movieId AS id, rec.title AS title, 同导演 AS reason LIMIT 20 , actor: MATCH (m:Movie)-[:ACTED_BY]-(a)-[:ACTED_BY]-(rec:Movie) WHERE m.movieId IN $watched AND NOT rec.movieId IN $watched RETURN DISTINCT rec.movieId AS id, rec.title AS title, 同演员 AS reason LIMIT 20 , genre: MATCH (m:Movie)-[:BELONGS_TO]-(g)-[:BELONGS_TO]-(rec:Movie) WHERE m.movieId IN $watched AND NOT rec.movieId IN $watched RETURN DISTINCT rec.movieId AS id, rec.title AS title, 同类型 AS reason LIMIT 20 } candidates {} for name, q in paths.items(): for row in tx.run(q, watchedwatched_ids): candidates.setdefault(row[id], {title: row[title], reasons: []}) candidates[row[id]][reasons].append(row[reason]) return candidates返回的reasons字段就是可解释性来源前端可以直接显示「因为你看过同导演的片子」。4.2 特征拼接与排序模型召回后的候选集需要排序。毕业设计阶段不需要上深度学习用 LightGBM 或逻辑回归就够了。特征包括图谱路径数量、电影评分、年份、类型匹配度、用户历史平均分。import pandas as pd from sklearn.linear_model import LogisticRegression # 构造特征矩阵 rows [] for mid, info in candidates.items(): rows.append({ movieId: mid, path_count: len(info[reasons]), rating: movie_rating[mid], year_gap: abs(2024 - movie_year[mid]), label: 1 if mid in ground_truth else 0 }) X pd.DataFrame(rows) model LogisticRegression() model.fit(X[[path_count, rating, year_gap]], X[label])path_count是最重要的特征它直接反映图谱召回的置信度。year_gap用当前年份减上映年份越小说明越新。训练时注意正负样本比例如果正样本太少用class_weightbalanced。4.3 冷启动用户的处理新用户没有观看记录图谱路径召回会返回空。常见做法是用注册时选择的偏好类型做种子查同类型高分电影或者直接返回全局热门榜。我一般会在代码里加一个兜底分支if not watched_ids: # 冷启动按类型偏好召回 result tx.run( MATCH (m:Movie)-[:BELONGS_TO]-(g:Genre) WHERE g.name IN $preferred RETURN m.title AS title, m.rating AS rating ORDER BY rating DESC LIMIT 10 , preferreduser_preferred_genres)这个分支保证任何用户进来都有推荐结果不会出现空白页。5. 避坑与常见问题排查5.1 现象Neo4j 导入几万条后越来越慢原因每条数据都开一个新事务事务开销累积。解决用UNWIND批量提交每批 500 到 1000 条并且给movieId、name建唯一约束。CREATE CONSTRAINT movie_id IF NOT EXISTS FOR (m:Movie) REQUIRE m.movieId IS UNIQUE; CREATE CONSTRAINT actor_name IF NOT EXISTS FOR (a:Actor) REQUIRE a.name IS UNIQUE;5.2 现象推荐结果全是同一部电影原因某条路径的权重过高或者LIMIT写在了去重之前。解决先合并所有路径结果再去重排序时对同一部电影的多条理由做加权而不是简单取第一条。5.3 现象中文实体写入后查询不到原因Neo4j 默认编码和 Python 字符串编码不一致或者 CSV 读取时没指定encodingutf-8。解决读 CSV 时显式加编码参数写入前用str.strip()清理空格。5.4 现象答辩时被问「图谱和推荐有什么关系」答不上来原因代码里图谱和推荐是两张皮图谱只是存了数据推荐还是纯协同过滤。解决在推荐函数里显式打印每条推荐的理由比如「同导演诺兰」让图谱路径成为推荐逻辑的一部分。5.5 现象pip install某个库报编译错误原因Python 版本太新预编译 wheel 还没发布。解决换 Python 3.10 或 3.11或者用 conda 安装。毕业设计环境稳定比追新重要。6. 让图谱推荐可验证离线评估与一个实用技巧6.1 离线评估指标怎么选推荐系统常用 RecallK、PrecisionK、NDCGK。毕业设计阶段我建议至少跑通 Recall10 和 NDCG10因为这两个指标能同时反映召回覆盖和排序质量。def recall_at_k(recommended, ground_truth, k10): rec_set set(recommended[:k]) gt_set set(ground_truth) return len(rec_set gt_set) / len(gt_set) if gt_set else 0.0 def ndcg_at_k(recommended, ground_truth, k10): dcg sum(1.0 / np.log2(i 2) for i, item in enumerate(recommended[:k]) if item in ground_truth) idcg sum(1.0 / np.log2(i 2) for i in range(min(len(ground_truth), k))) return dcg / idcg if idcg 0 else 0.0评估时把用户行为按时间切分前 80% 做训练后 20% 做测试。注意不要随机切分否则会数据泄露指标虚高。6.2 一个提升可解释性的技巧路径模板化答辩老师最喜欢问「为什么推荐这个」。我一般会把图谱路径转成自然语言模板路径类型模板示例输出同导演因为你喜欢导演{name}因为你喜欢导演克里斯托弗·诺兰同演员因为你关注演员{name}因为你关注演员莱昂纳多同类型因为你常看{genre}类型因为你常看科幻类型组合路径同时满足{reason1}和{reason2}同时满足同导演和同类型这个表可以直接写进论文的「可解释性设计」章节也是系统演示时的加分项。6.3 我踩过的一个坑最早做这套系统时我把所有关系都建成双向边结果图查询出现大量环路召回结果里全是已经看过的电影。后来改成单向边并且在查询里强制加NOT rec.movieId IN $watched问题才解决。图谱建模时边的方向不是随便定的它决定了查询的语义。另一个血泪经验是不要等到最后才做评估每加一条路径就测一次 Recall否则最后指标掉了都不知道是哪一步引入的。如果你正在做这个方向的毕业设计我的建议是先把图谱建对再谈算法融合。图谱是地基推荐是上层建筑地基歪了后面调参都是玄学。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

柑橘病害检测数据集:2814张VOC+YOLO双格式

柑橘病害检测数据集:2814张VOC+YOLO双格式

简介:本资源是面向农业AI与计算机视觉初学者、科研人员及模型训练实践者的橘类果实病害检测专用数据集,聚焦黑斑病、溃疡病、健康果与绿霉病四类典型病症识别任务,适用于目标检测算法(如YOLOv5/v8、Faster R-CNN)的训练…

2026/10/12 0:17:07 阅读更多 →
LangChain 单元测试怎么写:Fake LLM、Mock 与录制回放

LangChain 单元测试怎么写:Fake LLM、Mock 与录制回放

个人主页&#xff1a;> for_ever_love__ <&#xff08;欢迎各位大佬莅临&#x1f60a;&#xff09; 其他栏目: > 大模型开发从0到1 < 其他栏目: > iOS项目总结大全 < 其他栏目: > 我想学python了 < 其他栏目: > iOS UI < 文章目录LangChain 单元…

2026/10/12 0:16:07 阅读更多 →
Kubernetes Python 客户端 V1beta1DeviceAllocationResult 模型详解:DRA v1beta1 设备分配结果字段与序列化指南

Kubernetes Python 客户端 V1beta1DeviceAllocationResult 模型详解:DRA v1beta1 设备分配结果字段与序列化指南

后端云原生容器编排 【免费下载链接】python Official Python client library for kubernetes 项目地址&#xff1a; https://gitcode.com/gh_mirrors/python1/python 点击查看 免费下载 本文围绕 Kubernetes 官方 Python 客户端&#xff08;本仓库&#xff0c;含同步 kuberne…

2026/10/12 0:16:07 阅读更多 →

最新新闻

语言、意境与维度—— 从二维数学看东西方语言的认知分野

语言、意境与维度—— 从二维数学看东西方语言的认知分野

引言&#xff1a;一个翻译中的千古难题“大漠孤烟直&#xff0c;长河落日圆。”这两句诗&#xff0c;无论谁来翻译&#xff0c;都只能无限逼近&#xff0c;而无法真正抵达。英文译本可以告诉你&#xff1a;沙漠里有一道烟直直升起&#xff0c;长河尽头有一轮圆圆的落日。意思似…

2026/10/12 3:33:06 阅读更多 →
CodeIgniter 4 版本解读:4.0.4 的破坏性变更、新命令与增强项全解析

CodeIgniter 4 版本解读:4.0.4 的破坏性变更、新命令与增强项全解析

后端Web框架 【免费下载链接】CodeIgniter4 Open Source PHP Framework (originally from EllisLab) 项目地址&#xff1a; https://gitcode.com/gh_mirrors/co/CodeIgniter4 点击查看 免费下载 本文基于仓库内 v4.0.4 发布记录&#xff08;2020 年 7 月 15 日发布&#xff09…

2026/10/12 3:33:06 阅读更多 →
STM32hal库开发-GPIO

STM32hal库开发-GPIO

1.下载cubeide网址&#xff1a;STM32CubeIDE | 软件 - 意法半导体 2.下载cubemx网址&#xff1a;STM32CubeMX | 软件 - 意法半导体 3.点灯 1.切换为高电平的函数&#xff1a;HAL_GPIO_WritePin(GPIOX,GPIO_Pin,PinState); 4.GPIO模式&#xff1a;浮空输入&#xff0c;上拉输…

2026/10/12 3:33:06 阅读更多 →
semantic-router 的 decision 选择算法:让决策模型为每条请求挑选最合适的模型

semantic-router 的 decision 选择算法:让决策模型为每条请求挑选最合适的模型

后端API网关模型推理服务AI Agent 【免费下载链接】semantic-router An open, programmable decision layer for models and compute. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/sem/semantic-router 点击查看 免费下载 导读 decision 是 vLLM semantic-router 路…

2026/10/12 3:33:06 阅读更多 →
Android学生成绩管理系统开发:数据库设计、接口与避坑指南

Android学生成绩管理系统开发:数据库设计、接口与避坑指南

简介&#xff1a;基于Android的学生成绩管理系统是一套面向移动开发初学者的完整项目资源&#xff0c;覆盖SQLite数据库操作、Java业务逻辑与原生UI设计三大核心模块。系统实现了学生信息及成绩的增删改查、条件查询、排序以及基础异常处理&#xff0c;并针对本地存储和异步加载…

2026/10/12 3:33:06 阅读更多 →
Disconf 安装部署指南:disconf-client 快速集成与 disconf-web 全流程上线实战

Disconf 安装部署指南:disconf-client 快速集成与 disconf-web 全流程上线实战

配置中心后端微服务 【免费下载链接】disconf Distributed Configuration Management Platform(分布式配置管理平台) 项目地址&#xff1a; https://gitcode.com/gh_mirrors/di/disconf 点击查看 免费下载 导读 Disconf&#xff08;Distributed Configuration Management Pla…

2026/10/12 3:32:05 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天&#xff0c;画面可以做到绝对的锐利、平滑与无瑕。然而&#xff0c;当一张秋日手账插画或拍立得照片过于“平整无瑕”时&#xff0c;往往会散发出一种冰冷生硬的“数码塑料感&#xff08;Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中&#xff0c;横排&#xff08;Horizontal Layout&#xff09;早已经成为了绝对的主流。然而&#xff0c;当我们翻开泛黄的线装古籍、宋版木刻诗集&#xff0c;或是欣赏一张茶道雅集的手写便签时&#xff0c;那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点&#xff0c;很多人心里都会悄悄亮起一盏警示灯。 在心理学上&#xff0c;这种现象有一个专门的称谓——“周日夜晚焦虑症&#xff08;Sunday Scaries&#xff09;”。明天又是周一&#xff0c;闹钟又要重新在七点响彻卧房&#xff1b;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →