1. 标签堆到一定量级,画像反而看不清了
做用户画像这件事,很多团队做到最后都会遇到一个很拧巴的阶段:标签系统里躺着几百上千个标签,用户分群报告也出了一摞,但业务方真正问“这批人到底是谁、为什么该推这个品”的时候,数据团队经常答不上来。原因很简单:传统标签画像本质上是把用户拆成一张又一张独立的属性卡片,而人不是属性拼盘,人的决策、偏好、消费行为是被一张巨大的关系网络牵引的。
知识图谱做用户画像,解决的正是这个问题。它不把用户当成孤立的标签集合,而是把用户、设备、商品、内容、品牌、类目这些对象当成实体,把购买、浏览、关注、同址、同设备这些行为当成关系,织成一张网。有了这张网,画像就不只是“知道”用户买了什么,还能“推导”用户接下来可能买什么,并且每一步推导都有路径可查。这也是为什么最近“知识图谱 + 用户画像分析子系统建设”这类词在数据中台和增长团队里越来越热——大家已经意识到,画像的下一站不是多建标签,而是把标签之间的关系建起来。
这篇内容不是教科书式地讲图数据库语法,而是把我实际搭画像知识图谱时踩过的坑、反复调整过的设计,以及最后跑通业务的效果,一起整理出来。适合正在评估要不要上知识图谱的画像负责人,也适合已经决定要做、但卡在实体设计和标签推理阶段的算法工程师。
1.1 标签画像的“孤岛效应”和“解释缺失”
先说标签画像为什么吃力。举一个特别常见的场景:用户在电商平台买了一罐奶粉,又浏览了两篇育儿文章,还加入了一个母婴品牌的会员。传统标签系统会给他打上“母婴人群”“高购买力”“内容偏好”三个标签。这三个标签分别来自交易域、内容域和会员域,彼此之间没有任何连接。
这时候运营想做一个“新生儿妈妈”的精细化人群包,他只能去筛选“近90天购买过奶粉且浏览过育儿内容”的用户。听起来没问题,但实际上会漏掉大量还没开始买奶粉、但已经持续关注孕期知识的用户。因为标签系统没有能力把“浏览育儿文章”和“即将购买奶粉”这两件事关联起来,更没有一个图谱层面的推理机制告诉运营:关注孕期内容三个月后,购买母婴商品的概率会明显上升。
传统画像的另一个硬伤是解释性差。算法模型可以给用户输出一个“高潜母婴”的评分,但业务方追问“凭什么判定他是高潜”,模型只能给出特征权重,给不出业务人员能直接拿去信任的因果路径。标签口径一旦被挑战,数据团队就要反复解释,解释到最后往往只能含糊地说“模型结果是这么算的”。
1.2 知识图谱怎么改变这件事
知识图谱的核心不是“图”这种存储形式,而是“关系即信息”的建模方式。同样一个用户,放回图谱里会变成这样:
- 用户节点usera,属性是性别、年龄、城市
- 他浏览过内容节点article_a,article_a挂了“孕期营养”的类目
- 他购买过商品product_x,product_x属于“孕妇装”类目
- 他使用的设备device_m,和另一个用户user_b的设备是同一台,说明可能是家庭成员
看到区别了吗?传统标签会把“浏览孕期营养”“购买孕妇装”写成两个不相干的事实,图谱则会把这些事实通过“用户-行为-对象-类目”的路径串起来。一旦串起来,就会发现usera和user_b之间存在家庭关系,usera当前阶段大概率是孕中期,母婴商品的推荐时机已经成熟。
这种带路径的画像,最大的价值是“可解释”。运营拿到的不只是一个分数,而是一条完整证据链:因为用户浏览了A文章、购买了B商品、和C用户共用了D设备,所以我们推断他处于某个生命周期阶段,推荐E商品是合理的。业务方认这种逻辑,数据团队也终于能从“黑盒”里走出来。
1.3 一个很小的例子:从“买过”到“为什么买”
我再把粒度放小一点,让还没接触过图谱的人也能快速建立感觉。
假设数据库里只有三件事:用户张三购买过“婴儿纸尿裤”,张三的收货地址和用户李四相同,李四收藏过“儿童安全座椅”。在传统表结构里,这三个事实分散在三张表,关联查询要JOIN三次。在知识图谱里,它们天然形成一条路径:
张三 -[购买]-> 纸尿裤 张三 -[同收货地址]-> 李四 李四 -[收藏]-> 儿童安全座椅
这条路径能告诉我们什么?我们可以推理出:张三很可能有一个婴幼儿阶段的家庭成员(因为纸尿裤通常不是买给自己的),李四和张三住在同一个地址,李四正在关注安全座椅。进一步推测:张三的家庭存在对安全座椅的需求,哪怕张三本人从未搜过安全座椅。这就是从“买过”到“为什么买”的差距,也是知识图谱做画像最核心的竞争力。
2. 画像知识图谱的数据模型:先定义“人”和“事”的关系
很多团队拿到知识图谱这个工具后,第一个反应是“把所有数据都塞进图里”,结果图谱建出来几百种节点、上千种关系,查询慢、维护难、业务看不懂,最后沦为技术团队的自嗨。我自己也干过这种事。后来总结出一个原则:画像图谱不是企业级知识中台,不追求百科全书式的完整,只追求对“用户理解”有直接帮助的那部分关系。
2.1 实体选型:别一上来就建五十类节点
画像知识图谱的实体选型应该围绕一条主线:用户是谁、用户接触了什么、用户和谁在一起。围绕这条主线,我建议第一批实体控制在八类以内。
推荐的基础实体清单是:
| 实体类型 | 含义 | 典型属性 |
|---|---|---|
| User | 注册用户/访客 | user_id、性别、年龄、城市、注册时间 |
| Device | 手机设备/浏览器指纹 | device_id、设备型号、操作系统、首现时间 |
| Product | 商品 | product_id、商品名称、价格、品牌 |
| Content | 文章/视频/直播 | content_id、标题、内容类目、发布时间 |
| Category | 商品/内容的类目体系 | category_id、层级、父类目 |
| Shop | 店铺/品牌方 | shop_id、店铺名称、主营类目 |
| Order | 订单事件 | order_id、下单时间、金额、状态 |
| Coupon/Tag | 营销触点(可选) | 优惠券、会员等级、活动标识 |
不要一上来就把评论、客服工单、物流信息全部实体化。实体越多,实体对齐的复杂度越高,而画像业务初期最关心的往往只是“和什么发生过互动”以及“和谁是同一家人”。先把最小闭环跑通,后续再按需加实体。
2.2 关系怎么命名:边是画像的核心资产
关系边是画像图谱的灵魂。节点之间的边一旦设计歪了,后面所有推理都会跟着歪。
我的建议是,关系的命名必须遵循“动词短语”,并且明确指向一个事实。例如:
- 用户 -[购买]-> 商品
- 用户 -[浏览]-> 内容
- 用户 -[收藏]-> 商品
- 用户 -[关注]-> 店铺
- 设备 -[属于]-> 用户
- 订单 -[包含]-> 商品
- 商品 -[属于]-> 类目
- 商品 -[属于品牌]-> 品牌
- 用户 -[同收货地址]-> 用户
- 用户 -[同设备]-> 用户
这里有个常见误区:把关系名和属性混淆。比如“张三-喜欢->李四”这种边,虽然看起来描述了兴趣,但“喜欢”是一个推断结论,不是一个可以观测的事实。图谱底层应该存事实,推断结果放到上层标签体系里,否则每次修正推断结论的时候,就得改图谱里的边,代价非常高。
2.3 属性设计:保留时间、场景和置信度
图谱里的属性看起来只是键值对,但如果在设计时不考虑时间维度,后面会出大问题。
用户画像不是静态快照。用户三个月前频繁浏览婴儿车,但最近一个月没有相关行为,那么“母婴意向”这个判断的置信度应该衰减。所以我强烈建议,凡是从行为事件提取出来的关系边,至少带上两个属性:发生时间(occur_time)和来源业务域(source)。
例如“购买”这条边可以这样设计:
(u:User {user_id: "U100123"}) -[:PURCHASED { order_id: "O20250615001", amount: 399.00, occur_time: "2025-06-15 14:32:10", source: "trade_order" }]->(p:Product {product_id: "P88231"})这里有个很微妙但重要的点:行为边可以重复。用户买过同一个商品两次,就应该有两条购买边,而不是一条边上的购买次数累加。原因很简单:两条边保留了两笔订单各自的时间、金额和渠道,这些信息在后续做购买生命周期分析时非常有用。聚合统计可以放到上层,不要在底层直接破坏事实粒度。
2.4 Schema 落库示例:Neo4j还是JanusGraph?
选型取决于你的数据规模和使用方式。
如果业务处在千万级用户、亿级关系的规模,团队又希望快速验证,我建议先用Neo4j社区版或者云上的图数据库。它的Cypher查询非常直观,业务方学几个小时就能看懂路径查询,而且社区生态成熟,路径找起来不费劲。
如果已经是大规模、需要对接Hadoop/Spark生态,而且对写入吞吐量要求很高,可以考虑JanusGraph或者 nebula。JanusGraph的存储后端可以挂HBase/Cassandra,能用Spark批量写入,但运维复杂度高,不适合小团队一上来就搞。
有一个建议是,不要一开始就陷入“图数据库 vs 关系型数据库”的争吵。画像知识图谱的项目第一阶段,完全可以用关系型数据库里的一张edge表来模拟图结构,把entity_id、relation_type、target_entity_id、occur_time四个字段建模出来。很多业务逻辑先用这张表验证,跑通了再迁移到专门的图数据库,风险最低。
3. 用户画像分析子系统建设的完整链路
“用户画像分析子系统建设”听起来像是一个架构工程问题,但落到具体执行时,真正的难点不在存储,而在数据接入的脏活。我从零搭过一套完整的子系统,流程大致是:数据接入 -> ID-Mapping -> 事件建模 -> 图谱写入 -> 推理计算 -> 服务化输出。每个环节都有坑。
3.1 ID-Mapping:图谱里的“人”必须先对齐
知识图谱建得再好,如果同一个用户在系统里有五个ID,那画像就是从源头上歪的。
常见的ID包括:注册用户ID、设备ID、手机号码加密串、微信OpenID、UnionID,甚至还有未登录时的游客CookieID。做ID-Mapping时,要先用确定性匹配把强ID对齐:注册登录事件把UserID和DeviceID绑定,订单支付事件把UserID和手机号绑定。设备指纹之间不要轻易做模糊匹配,否则会把完全不相干的人连到一张网上。
我在实际项目里用过一个很蠢但很有效的办法:维护两份表,一份是“ID主从表”,记录每个ID主键对应的master_id;一份是“ID关联证据表”,记录每次关联的来源事件。这样即使后面发现匹配错了,也能回溯到是哪条证据导致的,能及时修正,而不是整个图谱推倒重来。
3.2 行为事件到边:不是所有日志都值得建模
很多团队做这件事时容易走极端。一种是什么事件都建模,用户点了页面上的每个按钮都成为一条边;另一种是只挑最容易的订单数据,结果图谱里只有“购买”一种关系,推理效果很弱。
我的经验是,结合业务目标给事件分类。电商画像至少要覆盖四类关系:
- 交易类:购买、退款、加入购物车、领券
- 互动类:浏览、点击、收藏、分享、评论
- 关注类:关注店铺、关注品牌、订阅内容
- 身份链接类:同设备、同收货地址、同IP、同支付账号
判断一个事件是否值得建模,标准就一条:它是否能帮助推断用户的下一个动作?比如“点击”和“浏览”看起来相似,但“点击”更多反映即时兴趣,“浏览且时长超过阈值”才反映深度兴趣。把两类分开建模,比混成一个“互动”关系更容易做后续推理。
3.3 增量写入与历史归档
图谱的写入不能像数仓一样只做每日全量覆盖。因为边上有时间属性,用户昨天的行为和今天的行为需要同时存在于图中,才能做时间衰减计算。
我的建议是采用“增量实时写 + 离线批量修”的组合:实时行为通过消息队列消费,直接写入当天新增的边;离线任务每天晚上修复当天因数据迟到而遗漏的边,并清理超过生命周期的事件边。比如“浏览”边保留180天,“购买”边保留3年,超过有效期的边归档到冷存储,不再参与实时推理,避免图谱无限膨胀。
这里有个容易忽略的注意点:删除历史边时一定要谨慎,不能物理删,应该逻辑过期。因为用户的某个历史行为可能在未来某个分析场景里被重新捞出来,比如做年度复购分析。我当时的选择是给边加一个is_active标记,查询时默认过滤掉无效边,需要回溯时再放开过滤条件。
3.4 服务化输出:在线接口与离线跑批并行
知识图谱画像子系统不能只活在数据平台上,必须能服务业务。
离线场景:每天定时跑图谱推理任务,产出用户标签和人群包,写入ClickHouse或HBase,供运营后台查询。这个场景对实时性要求不高,但对稳定性要求高。
在线场景:用户访问App或网页时,需要在几百毫秒内返回该用户的高概率偏好。这个场景不能直接查图、跑多跳路径,因为复杂路径遍历的性能很难保证。我建议用图计算的结果反哺特征服务:把离线算好的用户embedding、社区ID、TopN推理标签写入线上KV,线上只做读取和轻量计算。
换句话讲,图谱是“离线算好、在线查结果”,而不是“在线实时遍历图”。这是很多团队把画像子系统做成性能灾难的根源。
4. 图谱上的画像计算:推理、扩散和分群
图谱建好之后,真正的价值来自在图上做计算。这部分我挑三种最常用、也最容易被低估的手段来讲:路径规则推理、图嵌入相似度、社区发现。
4.1 规则推理:用路径生成可解释标签
图谱上最直接的画像计算是路径推理。和机器学习模型不同,规则推理得到的标签天然带有可解释性。
举一个我实际跑过的例子。业务方想圈定“备孕人群”,这类用户往往还没有购买母婴商品,所以光靠交易标签找不到。但图谱上可以设计路径:用户浏览过“备孕”类目下的内容,同时检索过“叶酸”“排卵试纸”等关键词商品,且没有购买过任何母婴大件商品。
对应的Cypher查询大致长这样:
MATCH (u:User)-[:BROWSED {occur_time >= '2025-01-01'}]->(c:Content)-[:belongs_to]->(cat:Category {name: '备孕知识'}) WITH u, count(DISTINCT c) AS cnt WHERE cnt >= 3 MATCH (u)-[:SEARCHED]->(p:Product) WHERE p.title CONTAINS '叶酸' OR p.title CONTAINS '排卵' RETURN u.user_id, cnt这条规则把内容兴趣和商品搜索行为组合起来,效果比单纯用“搜索过备孕关键词”好很多。而且运营能直接看懂,不需要算法工程师解释。
做这类规则时,我给团队立了一个规矩:每一条推理规则都必须注册到规则管理表里,记录规则的输入路径、生效时间、置信度权重。规则不是代码里的临时脚本,而是画像系统的一部分资产,要有版本管理。
4.2 图嵌入与相似度:没有共同行为也能找出“同类”
规则推理的上限受限于人的经验,而图嵌入算法可以把人的经验之外的信息也吸收进来。
比较常用的是Node2Vec和GraphSAGE。把用户、商品、内容、类目都映射成向量之后,用户的画像就不再只是离散标签,而是连续向量。向量和向量之间的余弦相似度,可以用在Lookalike人群扩散上:拿一个种子用户,去图谱中找他“邻居路径相似”的人,哪怕这些人没有共同购买记录,也可能因为“都连接到了相似的类目子图”而被召回。
我在项目里的做法是,每月跑一次GraphSAGE,把所有用户的embedding输出到向量召回服务。做广告投放的时候,选择种子包用户,用embedding做KNN召回,再配合规则过滤。实测下来,向量召回的新客转化率比纯标签圈选高出20%左右,更重要的是把“冷门兴趣”用户也捞出来了——他们有行为,但行为数量少,不足以打上高置信标签,向量仍然能捕捉到他们在图中的位置特征。
4.3 社区发现:从“个人画像”升级到“家庭/群体画像”
个人画像再精确,如果忽略家庭和社交关系,很多业务判断依然是偏的。最典型的就是母婴和家装:决策人和使用者经常不是同一个人。这个时候社群发现算法就派上用场。
图谱里的“同收货地址”“同设备”“同支付账号”这类边,把不同用户连接成一个个家庭或同住关系网络。使用标签传播算法(Label Propagation)在这个子图上做社区划分,就能得到“家庭ID”或者“关系群ID”。
我记得第一次跑出社区结果时,发现一个很有意思的现象:两个用户ID没有任何共同交易行为,但因为长期使用同一台设备、收货地址相同,被划到了同一个家庭社区,最后验证下来确实是夫妻。有了这个社区ID,画像单位就可以从个人升级到家庭。运营可以针对“家庭生命周期”来做策略,比如发现家庭里有新生儿成员时,同步推荐婴童用品和家庭清洁用品,整体客单价明显更高。
5. 一个可复用的实战案例:母婴高潜人群发现
前面讲了不少方法论,这里用一套可以落地的案例串起来,方便你直接对照着搭建自己的第一版知识图谱画像。
5.1 场景设定与业务指标
业务方提出需求:找出未来30天内最可能购买“婴儿推车”的用户。传统做法是用历史购买过母婴商品的用户做定向,但问题在于,很多用户会在购买前2个月开始持续浏览“婴儿推车测评”内容,如果只用交易数据,这部分需求窗口就被错过了。
我们定的核心指标是:推理人群相比随机人群,在30天内的婴儿推车购买转化率提升幅度。
5.2 图谱构建细节
数据范围控制在一个季度,包括:用户基础信息表、订单表、商品浏览日志、内容浏览日志、搜索关键词日志、收货地址表。
实体用前面说的八类。关系侧重以下几条:
- 用户-购买->商品
- 用户-浏览->内容
- 用户-浏览->商品
- 用户-搜索->关键词
- 商品-属于->类目
- 内容-属于->内容类目
- 用户-同收货地址->用户
这里要注意一个细节,把“搜索关键词”作为一种轻量实体建模,而不是直接把关键词作为商品或内容的属性。因为关键词本身带有强意图信号,“用户-搜索->关键词”这条关系在推理婴儿推车需求时比“浏览测评”更强烈。
5.3 推理规则和查询语句
我们设计了三条推理规则,按置信度从高到低排序:
规则一:近30天搜索过“婴儿推车”“遛娃神器”“轻便婴儿车”等关键词,且没有购买过推车类目商品的用户,标记为“近30天强购买意图”。
规则二:近60天购买过“婴儿奶粉”或“纸尿裤”的用户,且家庭社区内没有推车购买记录,标记为“母婴品类活跃但推车未购”。
规则三:近90天浏览“婴儿推车测评”内容超过5次,且浏览过“价格区间1000元以上”推车商品详情页的用户,标记为“高客单推车潜伏人群”。
看一条实际查询:
MATCH (u:User)-[:SEARCHED {occur_time >= '2025-04-01'}]->(kw:Keyword) WHERE kw.word IN ['婴儿推车', '轻便婴儿车', '遛娃神器'] WITH DISTINCT u MATCH (u)-[:PURCHASED]->(p:Product)-[:belongs_to]->(cat:Category {name: '婴儿推车'}) WITH u, count(p) AS buy_count WHERE buy_count = 0 RETURN u.user_id这条规则的业务逻辑很直白:有搜索行为,但没有购买过目标商品,说明需求正在形成,尚未被满足。运营可以直接基于这个结果做定向推送,并且话术可以说“您关注的婴儿推车限时优惠”,因为规则本身就说明了用户关注过,不会显得生硬。
5.4 效果评估:对比规则标签和纯算法召回
最终我们对比了三组用户的30天购买转化率:
| 人群来源 | 用户量级 | 30天购买转化率 | 备注 |
|---|---|---|---|
| 平台随机用户 | 100万 | 0.3% | 基线 |
| 历史购买过母婴商品用户 | 20万 | 1.8% | 传统交易标签 |
| 图谱推理人群(规则一+二+三) | 5万 | 4.6% | 搜索+内容+关系组合 |
图谱推理人群的转化率是历史交易人群的2.5倍多。更关键的是,在这5万人里,有近1.2万人是历史交易标签完全覆盖不到的,属于被图谱规则“新发现”的需求人群。这就是关系带来的增量。
我还尝试把这三条规则的结果作为训练样本喂给排序模型,模型在推理人群内的区分度也更好,因为正样本的纯度提升了,噪音少了。
6. 落地过程中最容易翻车的几个地方
前面把成功的路径写完了,但真实项目里踩坑才是常态。我把经常翻车的几个问题集中说一下,这些教训来自真金白银的线上事故。
6.1 实体对齐的精度会一路传导
知识图谱做画像有个特点:错误会被关系路径放大。传统标签如果给用户打错一个标签,影响的只是这一个标签位;图谱里如果错误地把两个不同的人对齐成同一个用户,错误的标签会通过“同设备”“同地址”等关系蔓延到整个家庭网络。
所以做ID-Mapping时一定要守住底线:强关联用确定性规则,弱关联只做线索不做结论。手机号一致、设备ID一致、支付账号一致属于强关联,可以直接合并;“同一WiFi下出现过”属于弱关联,只能作为候选证据,不能直接合并。
另外一定要保留人工审核的通道。当时我们接了一批线下门店数据,发现同一个会员ID被多个导购重复建档,导致实体对齐率下降,最后是靠运营团队提供的一份手工名单才修正过来。技术再强,业务经验仍然是实体对齐的救命稻草。
6.2 图谱膨胀:不是节点越多越好
图谱最让人兴奋的地方是“什么都能往里塞”,但这恰恰是最大的坑。节点数量上到十亿级之后,任何多跳查询的响应时间都会直线上升,而且数据更新任务会变得异常脆弱。
我建议做两件事控制膨胀。第一,行为边做严格的生命周期管理。浏览、点击这类弱信号边的保留期可以短一些,90天或180天;购买、关注这类强信号边可以保留3年。第二,不做无业务目标的“完整建模”。比如商品评论中的情感标签,如果当前没有分析目标,就不要先建实体,等需求明确时再补数据管道。
每次增加新的实体或关系前,必须回答一个问题:这个实体能参与哪些画像推理,能给业务带来什么新判断?答不上来就不加。
6.3 时序处理:忘记时间线的画像会闹笑话
图谱是状态网络,但业务是在时间线上展开的。如果所有边都放在同一层,不区分布局时间,很容易推出荒谬结论。
举一个真实例子:用户A半年前确实搜索过“婴儿推车”,但孩子已经出生了,推车也早就买了。如果推理规则不看时间窗口,仍然把A标记为“强购买意图”,运营推送婴儿车广告,用户体验会非常差。这就是为什么每条规则都必须约束occur_time,并且让时间衰减机制生效。
我后来把时间处理总结成一句话:图谱负责回答“他和什么有关”,时间负责回答“这个关系现在还有效吗”。两者缺一不可。
6.4 组织协作:先统一口径,再谈技术
最后反而是一个组织问题。图谱画像项目不只是算法团队的事,它需要数仓团队提供干净的数据,需要业务团队定义“用户生命周期”的业务含义,需要运营团队接受新的推理标签并愿意尝试。
我见过很多项目死在不统一的实体定义上。数仓里的“活跃用户”是近30天有登录,业务里的“活跃用户”是近30天有购买,两个口径不打通,图谱里的“活跃”属性出来就是一张废数据。
所以启动时就要拉上各方,把核心实体、核心关系、核心标签的定义全部确认一遍,并且写成数据字典。这个动作虽然枯燥,但它是整个用户画像分析子系统建设的地基。地基稳了,知识图谱这栋楼才盖得高。
做知识图谱用户画像,说到底不是买一个图数据库回来就完事,而是要把团队的认知从“给用户贴标签”升级成“理解用户的关系和处境”。这条路我走下来,最大的感受是:图谱带来的不只是更高的转化率,更是数据团队和业务团队之间终于能用同一种语言对话了。