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

如何从Python字典创建物品-特征稀疏二进制矩阵及索引错误排查

问题解决:创建推荐系统物品-特征稀疏矩阵时的索引越界错误

问题场景

有一个.tsv文件,已生成Python字典movie_features_dict,键为movie_id,值为对应电影的特征列表(每部电影特征数量不同)。目标是构建二进制稀疏矩阵,电影拥有某特征时对应位置为1,但运行代码时报错:

raise IndexError('index (%d) out of range' % max_indx)
IndexError: index (614734) out of range

原代码如下:

创建字典

def Dictionary():
    d={}
    l=[]
    with open(filepath_mapping) as f:
        for line in f.readlines():
            line = line.split()
            key = int(line[0])
            value = [int(el) for el in line[1:]]
            d[key] = value
    return(d)

movie_features_dict = Dictionary()

原矩阵构建代码

n = len(movie_features_dict)
value_lengths = [len(v) for v in movie_features_dict.values()]
d = max(value_lengths)
print(f"ITEM*FEATURES matrix shape: {n,d}\n")

item_feature_matrix = sp.dok_matrix((n,d), dtype=np.int8)

for movie_ids, features in movie_features_dict.items():
    item_feature_matrix[movie_ids, features] = 1

item_feature_matrix = item_feature_matrix.tocsr()
print(item_feature_matrix.shape)

错误原因

  1. 特征索引误用:你把特征的原始ID当成了矩阵的列索引,但特征ID的数值(比如报错里的614734)远大于单部电影的最大特征数量885,矩阵列数只设为885,自然会越界。矩阵列数应该基于所有特征ID的范围,而非单部电影的特征数量最大值。
  2. 行索引问题:原始movie_id可能不是从0开始的连续整数,直接用movie_id作为行索引的话,若movie_id大于矩阵行数22069,也会触发索引越界。

修复方案

步骤1:映射movie_id到连续行索引

创建字典将每个原始movie_id映射到0~n-1的连续索引,避免行索引越界。

步骤2:确定所有特征的范围或映射特征ID到列索引

要么直接用所有特征ID的最大值+1作为列数,要么对特征ID做连续映射(推荐,若特征ID不连续可节省空间)。

步骤3:重构稀疏矩阵

用映射后的索引填充矩阵。

完整修复代码

import numpy as np
import scipy.sparse as sp

def Dictionary():
    d={}
    with open(filepath_mapping) as f:
        for line in f.readlines():
            line = line.split()
            key = int(line[0])
            value = [int(el) for el in line[1:]]
            d[key] = value
    return d

movie_features_dict = Dictionary()

# 映射movie_id到连续行索引
movie_ids = list(movie_features_dict.keys())
movie_to_idx = {mid: idx for idx, mid in enumerate(movie_ids)}
n_rows = len(movie_to_idx)

# 收集所有特征ID并映射到连续列索引
all_features = []
for features in movie_features_dict.values():
    all_features.extend(features)
unique_features = list(set(all_features))
feature_to_idx = {fid: idx for idx, fid in enumerate(unique_features)}
n_cols = len(feature_to_idx)

# 构建稀疏矩阵
item_feature_matrix = sp.dok_matrix((n_rows, n_cols), dtype=np.int8)

for mid, features in movie_features_dict.items():
    row_idx = movie_to_idx[mid]
    for fid in features:
        col_idx = feature_to_idx[fid]
        item_feature_matrix[row_idx, col_idx] = 1

item_feature_matrix = item_feature_matrix.tocsr()
print(f"修复后矩阵形状: {item_feature_matrix.shape}")

补充说明

  • 如果特征ID本身是连续的(从0开始),可以跳过特征映射,直接用max(all_features)+1作为n_cols,简化代码。
  • 使用dok_matrix适合逐元素赋值,最后转成csr_matrix方便后续推荐系统的矩阵运算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:05:26