You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LightFM训练集与测试集需同规模吗?纯协同过滤模型报错排查

解决LightFM纯协同过滤中训练/测试用户矩阵维度不匹配的错误

嘿,这个问题我之前踩过坑!咱们来捋清楚到底怎么回事,以及怎么解决它。

错误原因拆解

你碰到的"Incorrect number of features in user_features"错误,本质是纯协同过滤模式下,LightFM把用户ID当作唯一的特征维度——训练时模型会根据训练集的用户总数(也就是训练矩阵的行数)来初始化user_embeddings的维度。当测试矩阵的行数更少时,如果你直接用测试用户生成的特征矩阵,它的列数会等于测试用户的数量,这就和训练好的user_embeddings的行数(训练用户总数)不匹配,触发了lightfm.py第789行的维度检查。

你提到根源在第778行,那行应该是LightFM处理用户特征的逻辑:在纯协同过滤场景下,用户特征默认是一个单位矩阵(identity matrix),行数等于当前输入的用户数量。如果测试时用户数比训练少,这个矩阵的列数就会小于训练时的用户总数,自然过不了维度校验。

解决方案:统一用户特征维度

核心思路是:让测试集的用户特征矩阵的列数,严格等于训练集的用户总数,不管测试集中有多少用户。这里有两种可靠的实现方式:

1. 用LightFM的Dataset类统一管理特征

这是最省心的方法,Dataset会帮你维护全局的用户/物品索引,确保训练和测试的特征维度一致:

from lightfm import LightFM
from lightfm.data import Dataset

# 假设你的训练/测试交互数据是(user_id, item_id)或带评分的三元组
train_interactions = [(u1, i1), (u2, i2), ...]  # 训练集交互
test_interactions = [(u1, i3), (u3, i2), ...]   # 测试集用户都是训练子集

# 初始化Dataset,只基于训练集拟合用户和物品
dataset = Dataset()
dataset.fit(
    (user for user, item in train_interactions),
    (item for user, item in train_interactions)
)

# 构建训练/测试的交互矩阵
train_matrix, _ = dataset.build_interactions(train_interactions)
test_matrix, _ = dataset.build_interactions(test_interactions)

# 生成训练用的用户特征矩阵(纯协同过滤下是单位矩阵)
train_user_features = dataset.build_user_features()

# 训练模型
model = LightFM(loss="warp")
model.fit(train_matrix, user_features=train_user_features, epochs=30)

# 生成测试用的用户特征矩阵——关键!用同一个Dataset生成,维度和训练时一致
test_user_ids = [user for user, item in test_interactions]
test_user_features = dataset.build_user_features(
    ((user_id,) for user_id in test_user_ids)
)

# 现在预测就不会报错了
predictions = model.predict(
    test_user_ids,
    [item for user, item in test_interactions],
    user_features=test_user_features
)

2. 手动维护用户索引映射

如果你不想用Dataset,也可以手动建立训练集用户到索引的映射,确保测试用户的特征向量长度等于训练用户总数:

import numpy as np
from lightfm import LightFM

# 提取训练集所有用户ID并建立映射
train_users = list(set(u for u, i in train_interactions))
user_id_to_idx = {user: idx for idx, user in enumerate(train_users)}
num_train_users = len(train_users)

# 生成训练用户特征矩阵(单位矩阵)
train_user_features = np.eye(num_train_users)

# 训练模型
model = LightFM(loss="warp")
model.fit(train_matrix, user_features=train_user_features, epochs=30)

# 生成测试用户特征矩阵:每个测试用户对应长度为num_train_users的one-hot向量
test_user_features = np.zeros((len(test_interactions), num_train_users))
for idx, (user, _) in enumerate(test_interactions):
    test_user_features[idx, user_id_to_idx[user]] = 1

# 预测
predictions = model.predict(
    [user_id_to_idx[u] for u, i in test_interactions],
    [i for u, i in test_interactions],
    user_features=test_user_features
)

关键提醒

纯协同过滤本身无法处理训练集中没有出现过的新用户——如果你的测试集包含新用户,这个错误本质上是合理的,因为模型没有这些用户的任何历史数据可供学习。这种情况下你可能需要切换到带内容特征的混合模型,或者先处理新用户的冷启动问题。

内容的提问来源于stack exchange,提问作者Chris M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:41:12