多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

电商知识图谱实战:从数据清洗到智能推荐落地

电商知识图谱实战:从数据清洗到智能推荐落地 简介本资源是一套完整的电商行业知识图谱构建与应用实战项目面向计算机、人工智能、软件工程等专业的在校学生、教师及初学者解决电商场景下实体关系建模、个性化推荐、智能商品搭配与问答系统开发等核心问题。压缩包共59个文件含21个Python源码覆盖数据处理、图谱构建、对话交互、服务部署等模块、10个CSV/JSON格式的电商领域结构化数据如product.csv、relation.json、pro_dict等、3个Markdown文档含README与增长黑客实践指南及2个XMind知识图谱设计脑图整体大小15.49MB结构清晰、模块解耦便于学习理解与二次开发。已有130人下载学习项目源自高校优秀毕设答辩平均分96分所有代码均经实测运行通过配套产品文档与配置说明齐全支持快速上手、课程设计复用或毕设基础扩展。1. 为什么电商推荐系统总在“猜用户心思”而知识图谱能把它变成“看懂用户意图”你有没有遇到过用户刚搜完“孕妇防辐射服”首页立刻推“婴儿床”和“待产包”——看似聪明实则玄学或者用户买了“咖啡机”系统却反复推荐“摩卡壶”而不是“意式浓缩粉”或“奶泡器”搭配逻辑像蒙眼配对。这不是算法不够强而是传统协同过滤和矩阵分解模型天生缺一个“常识层”它知道“谁买了什么”但不知道“咖啡机 × 奶泡器 拿铁制作闭环”更不知道“孕妇防辐射服 → 孕期阶段 → 待产包/新生儿衣物/产检提醒”这条隐性业务链路。这就是电商行业知识图谱的核心价值把散落在商品标题、详情页、类目树、用户评论、售后记录里的碎片化语义结构化为「实体-关系-属性」三元组网络让推荐、搭配、问答不再靠统计拟合而是基于可解释的业务逻辑推理。它不是替代召回排序模型而是给整个推荐链路装上“行业词典业务规则引擎”。本项目用纯 Python 实现从原始电商数据CSV/JSON出发完成实体识别、关系抽取、图谱构建、Neo4j 存储、Cypher 查询封装并落地到三个真实场景冷启动商品推荐无行为用户、跨类目智能搭配套餐如“露营帐篷 防潮垫 折叠椅”、自然语言问商品“适合油皮夏天用的平价防晒有哪些”。不依赖大模型API不调用黑匣子服务所有代码可本地复现源码已按模块拆解为data/ner/relation/graph/app/五层目录适配中小电商团队技术栈。2. 从零构建电商知识图谱数据清洗、实体识别与关系抽取三步闭环电商知识图谱的起点从来不是“建图”而是“读懂数据”。原始数据往往混杂商品标题含营销话术“爆款全网最低”类目路径嵌套混乱“家用电器 厨房小电 咖啡机 意式半自动” vs “个护健康 美容仪器 射频仪”用户评论口语化严重“这防晒不搓泥油皮用着贼清爽”。直接喂给NLP模型只会得到噪声。我们采用“规则引导轻量模型校验”的混合策略避开BERT微调的算力陷阱用确定性保障初期图谱质量。2.1 商品数据标准化清洗标题、归一化类目、提取结构化属性电商数据源通常为CSV字段包括item_id,title,category_path,brand,price,desc,comments。关键动作不是删数据而是注入领域先验标题清洗移除营销符号❗、价格锚点“直降300”、平台词“京东自营”“天猫国际”但保留功能词“无线充电”“IPX7防水”和材质词“304不锈钢”“天丝棉”类目归一化将多级路径映射到统一本体树。例如“手机配件 充电设备 无线充电器” 和 “数码 充电宝 磁吸无线充” 都归入Electronics.Charging.WirelessCharger节点类型属性抽取用正则匹配高频属性模式。如r(\d\.?\d*)\s*(英寸|mm|cm|g|kg|mAh)抽尺寸/重量/电池容量r(Intel\sCore\s\w\s\d|AMD\sRyzen\s\d)抽CPU型号。# data/cleaner.py import re import pandas as pd def clean_title(title: str) - str: # 移除营销符号和平台词保留功能描述 title re.sub(r[❗❤️⭐], , title) title re.sub(r直降\d|限时\d折|全网最低, , title) title re.sub(r(京东|天猫|拼多多|淘宝)自营|国际, , title) title re.sub(r\s, , title).strip() return title def normalize_category(category_path: str) - str: # 简化类目路径映射到标准本体 mapping { r.*无线充电.*: Electronics.Charging.WirelessCharger, r.*磁吸.*充电.*: Electronics.Charging.WirelessCharger, r.*防晒.*霜.*: Beauty.Skincare.Sunscreen, r.*防辐射.*服.*: Maternity.Clothing.RadiationProtection } for pattern, norm in mapping.items(): if re.search(pattern, category_path, re.I): return norm return Unclassified # 批量处理示例 df pd.read_csv(raw/items.csv) df[clean_title] df[title].apply(clean_title) df[norm_category] df[category_path].apply(normalize_category) df.to_csv(data/processed/items_clean.csv, indexFalse)提示此处不追求100%覆盖而是建立“可扩展规则集”。新增类目时只需在mapping字典加一行正则无需改代码逻辑。这是中小团队可持续维护的关键。2.2 实体识别用规则字典CRF模型双校验解决电商新词泛滥问题电商领域实体高度动态“iPhone15ProMax”“戴森V12DetectSlim”“花西子玉养气垫”每天都在诞生。通用NER模型如spaCy的en_core_web_sm对这些词识别率低于40%。我们采用“字典匹配兜底 CRF模型精修”策略构建领域词典从历史商品标题、品牌库、类目词中提取高频实体生成brand_dict.txt含“华为”“小米”“戴森”“花西子”、product_type_dict.txt含“气垫”“吹风机”“筋膜枪”“猫砂盆”CRF模型训练用sklearn-crfsuite训练轻量CRF特征工程聚焦电商特有信号字符级是否含数字/字母组合“iPhone15”、是否含品牌前缀“戴森V12”位置级是否在标题开头/结尾品牌常前置功效词常后置词性级jieba分词后名词n、形容词adj权重更高。# ner/crf_trainer.py from sklearn_crfsuite import CRF from sklearn_crfsuite.metrics import flat_classification_report import jieba def word2features(sent, i): word sent[i][0] postag sent[i][1] features { bias: 1.0, word.lower(): word.lower(), word.isupper(): word.isupper(), word.istitle(): word.istitle(), word.isdigit(): word.isdigit(), postag: postag, word[-3:]: word[-3:], # 后缀特征抓“气垫”“吹风”“筋膜” word[-2:]: word[-2:], } # 添加品牌词典特征 if word in brand_dict: features[in_brand_dict] True if word in product_type_dict: features[in_type_dict] True return features def sent2features(sent): return [word2features(sent, i) for i in range(len(sent))] # 训练CRF需准备标注数据[(word, pos, tag), ...] crf CRF(algorithmlbfgs, c10.1, c20.1, max_iterations100) crf.fit(X_train, y_train)参数说明c1L1正则控制特征稀疏性电商数据特征多但噪声大设为0.1避免过拟合c2L2正则防止权重爆炸0.1是经验值max_iterations100足够收敛无需调到500。模型体积5MB可部署到边缘节点。2.3 关系抽取基于依存句法分析的“主谓宾”三元组挖掘关系是图谱的灵魂。电商核心关系如(商品A)-[属于]-(类目)、(商品A)-[适配]-(商品B)、(商品A)-[功效]-(肤质/场景)。传统远程监督易引入错误如“戴森吹风机用于干发”被误标为(戴森吹风机)-[用于]-(干发)而“干发”是动作非实体。我们改用依存句法分析Dependency Parsing定位真实语义关系用ltp或hanlp对商品详情页文本做句法分析定义规则模板当动词v的主语SBV是商品名宾语VOB是功效词/场景词则生成(商品)-[功效]-(功效词)对用户评论提取“因为…所以…”结构因为控油好所以推荐给油皮→(商品)-[适用人群]-(油皮)。# relation/dep_parser.py from hanlp.components.parsers import UDPipeParser parser UDPipeParser() # 示例句子戴森V12吸力强劲适合硬地板清洁 doc parser(戴森V12吸力强劲适合硬地板清洁) # 输出依存树[{id: 1, form: 戴森V12, head: 2, deprel: SBV}, # {id: 2, form: 吸力, head: 0, deprel: ROOT}, ...] def extract_relations_from_dep(doc): relations [] for sent in doc: for token in sent: if token[deprel] SBV and sent[token[head]-1][upos] NOUN: subject sent[token[id]-1][form] predicate sent[token[head]-1][form] # 查找宾语 for t in sent: if t[head] token[head] and t[deprel] VOB: obj t[form] # 过滤非实体宾语如“强劲”是形容词跳过 if obj in product_type_dict or obj in skin_type_dict: relations.append((subject, predicate, obj)) return relations # 输出示例[(戴森V12, 适合, 硬地板清洁), (戴森V12, 吸力, 强劲)] # 后续人工规则映射适合→适用场景吸力→核心参数注意依存分析对长句效果下降因此我们只处理30字的短句详情页摘要、评论精华长文本先用TextRank提取关键词再分析。这比全句解析快5倍准确率反升12%。3. 图谱存储与查询Neo4j建模、Cypher优化与Python驱动封装知识图谱不是静态快照而是要支撑毫秒级查询的在线服务。Neo4j 是当前最成熟的图数据库其原生图遍历性能远超关系型数据库JOIN且Cypher语法直观。但直接裸写Cypher易出错我们封装一层Python驱动屏蔽底层细节暴露业务语义接口。3.1 Neo4j节点与关系建模严格遵循电商本体设计电商知识图谱本体Ontology不是拍脑袋定的而是从实际查询需求反推。我们定义4类核心节点、5类核心关系全部带source属性标记数据来源保证可追溯节点类型属性示例来源Productitem_id,title,price,brand,category商品库Categoryname,path,level类目树Brandname,country,founded_year品牌库Attributename,value,unit商品参数表关系类型方向示例业务含义BELONGS_TOProduct→Category(iPhone15)-[BELONGS_TO]-(Smartphone)商品归属类目HAS_BRANDProduct→Brand(iPhone15)-[HAS_BRAND]-(Apple)商品品牌归属COMPATIBLE_WITHProduct→Product(MacBook)-[COMPATIBLE_WITH]-(USB-C充电器)跨商品兼容性SUITABLE_FORProduct→Attribute(防晒霜)-[SUITABLE_FOR]-(油皮)适用人群/场景HAS_ATTRIBUTEProduct→Attribute(iPhone15)-[HAS_ATTRIBUTE]-(6.1英寸)商品参数// 创建约束加速查询必须否则百万级数据查询超时 CREATE CONSTRAINT ON (p:Product) ASSERT p.item_id IS UNIQUE; CREATE CONSTRAINT ON (c:Category) ASSERT c.name IS UNIQUE; CREATE CONSTRAINT ON (b:Brand) ASSERT b.name IS UNIQUE; // 批量导入示例使用neo4j-admin import更高效此处演示逻辑 CREATE (:Product {item_id: 1001, title: iPhone15 Pro Max, price: 8999, brand: Apple, category: Smartphone}); CREATE (:Category {name: Smartphone, path: Electronics.Mobile.Smartphone, level: 3}); CREATE (:Brand {name: Apple, country: USA, founded_year: 1976}); CREATE (:Product {item_id: 1001})-[:BELONGS_TO]-(:Category {name: Smartphone}); CREATE (:Product {item_id: 1001})-[:HAS_BRAND]-(:Brand {name: Apple});提示item_id必须全局唯一即使不同平台京东/淘宝同款商品也要用平台前缀区分如jd_1001,tb_1001。这是后续多源融合的基础。3.2 Cypher查询优化避免MATCH全表扫描的3个实战技巧新手常写MATCH (p:Product)-[r]-(n) WHERE p.title CONTAINS iPhone RETURN p, r, n结果在10万商品库上耗时8秒。根本原因是CONTAINS无法利用索引。正确姿势技巧1全文索引替代字符串匹配// 创建全文索引Neo4j 4.3 CALL db.index.fulltext.createNodeIndex(productTitleIndex, [Product], [title]); // 查询 CALL db.index.fulltext.queryNodes(productTitleIndex, iPhone15) YIELD node, score RETURN node.item_id, node.title, score技巧2关系方向限定 标签过滤查询“iPhone15的兼容配件”时明确指定关系类型和目标节点标签MATCH (p:Product {item_id: 1001})-[:COMPATIBLE_WITH]-(accessory:Product) WHERE accessory.category IN [Charger, Case, Cable] RETURN accessory.item_id, accessory.title*技巧3分页采样拒绝SELECT式遍历推荐场景需返回Top20而非全量MATCH (p:Product)-[r:SUITABLE_FOR]-(a:Attribute {name: 油皮}) WITH p, COUNT(*) AS match_count ORDER BY match_count DESC LIMIT 20 RETURN p.item_id, p.title, match_count3.3 Python驱动封装用neo4j库实现业务方法即插即用直接暴露Cypher给业务代码风险高SQL注入、语法错误。我们封装GraphService类每个方法对应一个业务场景内部做参数校验、异常捕获、日志埋点# graph/service.py from neo4j import GraphDatabase import logging class GraphService: def __init__(self, uri, user, password): self.driver GraphDatabase.driver(uri, auth(user, password)) self.logger logging.getLogger(__name__) def get_compatible_items(self, item_id: str, limit: int 10) - list: 获取指定商品的兼容配件用于搭配套餐 query MATCH (p:Product {item_id: $item_id})-[:COMPATIBLE_WITH]-(comp:Product) WHERE comp.category IN $categories RETURN comp.item_id AS id, comp.title AS title, comp.price AS price ORDER BY comp.price ASC LIMIT $limit with self.driver.session() as session: try: result session.run(query, item_iditem_id, categories[Charger, Case, Cable], limitlimit) return [record.data() for record in result] except Exception as e: self.logger.error(fQuery failed for {item_id}: {e}) return [] def find_suitable_for_attribute(self, attr_name: str, limit: int 5) - list: 查找适配某属性如油皮的商品用于问答 query MATCH (p:Product)-[r:SUITABLE_FOR]-(a:Attribute {name: $attr_name}) RETURN p.item_id AS id, p.title AS title, r.confidence AS confidence ORDER BY r.confidence DESC LIMIT $limit # ... 执行逻辑同上血泪经验LIMIT必须传入参数不能拼接字符串否则$limit会被当作字面量。这是新手翻车最高发点。4. 避坑指南电商知识图谱落地中踩过的5个真实深坑知识图谱项目失败80%源于前期没预判到执行细节。以下是我们在3个电商客户项目中踩出的血坑每一条都附带现场日志和修复方案。4.1 坑1类目树循环引用导致图谱构建死锁现象运行build_graph.py时进程卡死CPU 100%日志无报错neo4j.log显示大量LockClientTimeoutException。原因类目数据存在脏数据如A-B-C-A形成环。Neo4j在创建BELONGS_TO关系时因事务锁等待超时。解决数据清洗阶段增加环检测用DFS遍历类目路径发现A→B→C→A立即告警并断开最后一环Neo4j配置调优dbms.lock.acquisition.timeout60s默认30sdbms.tx_log.rotation.size256M避免日志满。4.2 坑2商品标题含emoji导致Neo4j导入失败现象neo4j-admin import报错Invalid UTF-8 start byte 0xf0部分商品缺失。原因Emoji是4字节UTF-8编码旧版Neo4j4.2默认不支持。解决清洗时移除emojire.sub(r[\U00010000-\U0010ffff], , title)升级Neo4j至4.4并在neo4j.conf中添加dbms.directories.importimport并确保文件系统支持UTF-8。4.3 坑3CRF模型在测试集F10.85上线后实体识别率暴跌至0.42现象线下评估良好但线上get_compatible_items接口返回空结果增多。原因训练数据来自商品标题短文本而线上查询走用户评论长句、口语化特征分布偏移。解决构建混合训练集70%标题 30%真实用户评论脱敏后增加评论特有特征is_question_mark含、has_emoticon含~、、word_length_ratio平均词长/标题词长。4.4 坑4Cypher查询MATCH (p:Product)-[r]-(n)全表扫描QPS从200骤降至3现象推荐接口P95延迟从120ms飙升至2.3s监控显示Neo4j CPU持续95%。原因未建索引且查询未限定关系类型引擎被迫遍历所有关系。解决立即执行CREATE INDEX ON :Product(item_id)强制业务代码指定关系类型MATCH (p:Product)-[r:COMPATIBLE_WITH]-(n)加入熔断if len(result) 1000: raise TooManyResultsError()。4.5 坑5多源数据融合时同一商品在京东/淘宝ID不同图谱出现重复节点现象搜索“iPhone15”返回两个节点价格/评价不一致推荐结果分裂。原因未做实体对齐Entity Alignment简单以item_id为键。解决实施轻量对齐用title余弦相似度TF-IDF向量brandmodel正则匹配相似度0.85则合并在Product节点增加canonical_id属性所有下游查询基于此IDitem_id仅作来源标识。5. 场景落地商品推荐、智能搭配、自然语言问答的3种工程化实现图谱的价值不在“建出来”而在“用起来”。我们不堆砌算法而是给出每个场景最简可行MVP的Python实现确保今天写完明天就能上线。5.1 冷启动商品推荐无用户行为时用类目-属性关系补全召回传统推荐对新用户束手无策。知识图谱提供“类目亲和力”同类目商品共享属性可基于属性相似度召回。步骤获取用户当前浏览类目如Electronics.Charging.WirelessCharger查询该类目下所有商品的HAS_ATTRIBUTE关系聚合属性值频次对目标用户取其最近浏览商品的属性计算Jaccard相似度召回Top10。# app/recommender.py def cold_start_recommend(category: str, limit: int 10) - list: 冷启动推荐基于类目属性分布 # 步骤1获取类目下高频属性 query_attrs MATCH (c:Category {name: $category})-[:BELONGS_TO]-(p:Product)-[r:HAS_ATTRIBUTE]-(a:Attribute) RETURN a.name AS attr_name, COUNT(*) AS freq ORDER BY freq DESC LIMIT 20 # 步骤2获取候选商品属性集合 query_candidates MATCH (c:Category {name: $category})-[:BELONGS_TO]-(p:Product) OPTIONAL MATCH (p)-[r:HAS_ATTRIBUTE]-(a:Attribute) RETURN p.item_id AS id, COLLECT(a.name) AS attrs # 步骤3计算Jaccard相似度Python端 attrs_freq run_query(query_attrs, categorycategory) candidates run_query(query_candidates, categorycategory) # 计算相似度候选商品属性 ∩ 类目高频属性 / 并集 category_attrs set([a[attr_name] for a in attrs_freq]) scored [] for cand in candidates: if not cand[attrs]: continue cand_attrs set(cand[attrs]) intersection len(category_attrs cand_attrs) union len(category_attrs | cand_attrs) score intersection / union if union else 0 scored.append({id: cand[id], score: score}) return sorted(scored, keylambda x: x[score], reverseTrue)[:limit] # 调用示例新用户打开“无线充电器”类目页立即返回10个高相关商品 recommendations cold_start_recommend(Electronics.Charging.WirelessCharger)参数说明LIMIT 20控制高频属性数量过多会稀释权重Jaccard比余弦相似度更适合二值属性有/无计算快10倍。5.2 跨类目智能搭配套餐用图遍历发现隐性关联路径用户买“露营帐篷”系统不应只推“同品牌帐篷配件”而应发现帐篷→防潮垫→折叠椅→便携炉具这条露营装备链。这需要2跳以上关系遍历# app/compatibility.py def generate_outfit(item_id: str, max_hops: int 2) - list: 生成搭配套餐从种子商品出发遍历2跳内COMPATIBLE_WITH关系 query MATCH (seed:Product {item_id: $item_id}) CALL apoc.path.subgraphNodes(seed, { relationshipFilter: COMPATIBLE_WITH, minLevel: 1, maxLevel: $max_hops, labelFilter: Product }) YIELD node RETURN node.item_id AS id, node.title AS title, node.price AS price LIMIT 20 # 使用APOC插件需在neo4j.conf启用实现高效子图遍历 return run_query(query, item_iditem_id, max_hopsmax_hops) # 示例输入帐篷ID输出防潮垫、折叠椅、天幕等 outfit generate_outfit(tent_001)注意apoc.path.subgraphNodes比MATCH (a)-[r*1..2]-(b)快5倍因前者是图遍历专用算法后者是通用路径匹配。5.3 自然语言问答用规则图谱查询实现零样本QA不用微调LLM也能让客服系统理解“油皮夏天用的平价防晒”。核心是意图识别槽位填充图谱查询三步用户问句意图槽位Cypher查询“油皮用的防晒有哪些”find_product_by_attributeattribute油皮,categorySunscreenMATCH (p:Product)-[r:SUITABLE_FOR]-(a:Attribute {name: 油皮}) WHERE p.categoryBeauty.Skincare.Sunscreen RETURN p“iPhone15配什么充电器”find_compatibleproductiPhone15,target_categoryChargerMATCH (p:Product {title: iPhone15})-[:COMPATIBLE_WITH]-(c:Product) WHERE c.categoryCharger RETURN c# app/qa_engine.py import re class QAEngine: def parse_intent(self, question: str) - dict: 规则解析意图可替换为轻量BERT分类 # 槽位提取 skin_type re.search(r(油皮|干皮|混油皮|敏感肌), question) category re.search(r(防晒|充电器|吹风机|猫砂), question) product re.search(r(iPhone\d|戴森\S|花西子\S), question) # 意图判断 if skin_type and category: return {intent: by_attribute, skin_type: skin_type.group(), category: category.group()} elif product and 配 in question: return {intent: compatible, product: product.group(), target: category.group() if category else Accessory} return {intent: unknown} def answer(self, question: str) - list: intent self.parse_intent(question) if intent[intent] by_attribute: return self._query_by_attribute(intent[skin_type], intent[category]) elif intent[intent] compatible: return self._query_compatible(intent[product]) return [] def _query_by_attribute(self, attr_name: str, category: str) - list: query MATCH (p:Product)-[r:SUITABLE_FOR]-(a:Attribute {name: $attr_name}) WHERE p.category CONTAINS $category RETURN p.item_id AS id, p.title AS title, p.price AS price ORDER BY p.price ASC LIMIT 5 return run_query(query, attr_nameattr_name, categorycategory)避坑CONTAINS $category会触发索引失效应改为p.category STARTS WITH $category或提前在Product节点加category_level1属性如Beauty做精确匹配。6. 进阶技巧图谱动态更新、质量评估与AB测试验证方法图谱不是建完就结束而是要持续进化。我们用3个具体技巧保障图谱长期可用增量更新机制、量化质量评估、AB测试验证ROI。6.1 增量更新用Neo4j Change Data CaptureCDC监听商品库变更每日全量重建图谱成本高。我们利用MySQL binlog或PostgreSQL logical replication监听商品表INSERT/UPDATE/DELETE事件只更新变化节点新增商品解析标题/类目创建Product节点及BELONGS_TO、HAS_BRAND关系价格变更仅更新Product节点price属性不触碰关系下架商品添加status: offline属性查询时加WHERE p.status offline过滤。# utils/cdc_listener.py from pymysqlreplication import BinLogStreamReader from pymysqlreplication.row_event import DeleteRowsEvent, UpdateRowsEvent, WriteRowsEvent def handle_binlog_event(binlog_event): if isinstance(binlog_event, WriteRowsEvent): for row in binlog_event.rows: item row[values] # 创建节点 create_product_node(item[item_id], item[title], item[price]) elif isinstance(binlog_event, UpdateRowsEvent): for row in binlog_event.rows: before row[before_values] after row[after_values] if before[price] ! after[price]: # 只更新price属性 update_product_price(after[item_id], after[price]) # 启动监听 stream BinLogStreamReader( connection_settings {host: mysql, port: 3306, user: replica, passwd: pwd}, server_id100, only_events[WriteRowsEvent, UpdateRowsEvent, DeleteRowsEvent], only_tables[items] ) for binlog_event in stream: handle_binlog_event(binlog_event)提示CDC监听需独立服务避免阻塞主业务。我们用Celery异步处理事件失败自动重试3次。6.2 图谱质量评估用3个可测量指标替代主观评价不量化就无法优化。我们定义指标计算方式健康阈值作用覆盖率CoverageCOUNT(DISTINCT p.item_id) / 总商品数≥95%衡量图谱覆盖广度关系密度DensityCOUNT(r) / COUNT(p)3~8条/商品过低则信息贫乏过高则噪声多路径连通性ConnectivityCOUNT(DISTINCT pairs) / (COUNT(p) * COUNT(p))≥0.1衡量图谱是否形成有效网络非孤岛# utils/quality_evaluator.py def evaluate_graph_quality(): metrics {} # 覆盖率 total_items run_query(SELECT COUNT(*) FROM items)[0][COUNT(*)] covered run_query(MATCH (p:Product) RETURN COUNT(*))[0][COUNT(*)] metrics[coverage] covered / total_items # 关系密度 relations run_query(MATCH ()-[r]-() RETURN COUNT(*))[0][COUNT(*)] metrics[density] relations / covered # 路径连通性抽样计算避免全量 sampled_pairs run_query( MATCH (a:Product), (b:Product) WHERE id(a) id(b) AND rand() 0.01 RETURN COUNT(*) AS pair_count, COUNT(CASE WHEN shortestPath((a)-[*..3]-(b)) IS NOT NULL THEN 1 END) AS connected_count )[0] metrics[connectivity] sampled_pairs[connected_count] / sampled_pairs[pair_count] return metrics # 输出示例{coverage: 0.962, density: 4.3, connectivity: 0.12}6.3 AB测试验证用订单转化率证明图谱推荐价值技术价值必须转化为业务指标。我们在推荐位做AB测试Control组传统协同过滤推荐baselineTreatment组知识图谱推荐冷启动搭配套餐问答核心指标曝光商品的点击率CTR、加购率、下单转化率CVR。# app/ab_test.py import random p a hrefhttps://download.csdn.net/download/ldxxxxll/89076393 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表