基于内容的图书推荐系统分块处理遇Shape不匹配ValueError求助
问题分析
报错ValueError: Shape of passed values is (2, 5000), indices imply (2, 1)的核心原因是数据中存在重复的书名:
- 当
chunk_df里有重复的Title时,indices = pd.Series(chunk_df.index, index=chunk_df["Title"])会让相同书名对应多个行索引。 - 调用
indices[title]会返回包含多个索引的Series,而非单个整数索引,此时cosine_sim[book_index]会提取多行相似度数据(形状为[n, 5000],n是重复书名的数量)。 - 用这个二维数组创建DataFrame并指定单列
["score"]时,就会出现形状不匹配的错误。
另外还有一个潜在问题:每个chunk单独调用tfidf.fit_transform会重新构建词汇表,导致不同chunk的TF-IDF向量维度不一致,跨chunk的推荐逻辑不成立(当前报错是单chunk内的问题,先优先解决)。
解决方案
1. 处理重复书名
方案A:修改推荐函数,兼容重复书名
直接在推荐函数中判断并取第一个匹配的索引:
def content_based_recommender(title, cosine_sim, chunk_df): indices = pd.Series(chunk_df.index, index=chunk_df["Title"]) # 处理重复书名:若返回多个索引则取第一个 book_index = indices[title].iloc[0] if isinstance(indices[title], pd.Series) else indices[title] similarity_scores = pd.DataFrame(cosine_sim[book_index], columns=["score"]) book_indices = similarity_scores.sort_values("score", ascending=False)[1:11].index return chunk_df['Title'].iloc[book_indices].tolist()
方案B:提前去重或标记重复书名
在读取chunk时先处理重复数据,避免后续逻辑出错:
for chunk_number, data_chunk in enumerate(data_chunks, start=1): print(f"Processing Chunk {chunk_number}") # 方案1:保留每个书名的第一条数据 data_chunk = data_chunk.drop_duplicates(subset="Title", keep="first") # 方案2:给重复书名加序号区分(如"书名 (1)") # data_chunk["Title"] = data_chunk["Title"] + " (" + data_chunk.groupby("Title").cumcount().astype(str) + ")" # 后续代码不变 tfidf_matrix = tfidf.fit_transform(data_chunk['Blurb'].fillna('')) cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix) for title in data_chunk['Title']: recommendations = content_based_recommender(title, cosine_sim, data_chunk) recommendations_dict['Title'].append(title) recommendations_dict['Recommendations'].append(recommendations)
2. 修复TF-IDF词汇表一致性(可选但重要)
如果希望跨chunk的推荐有意义,不能每个chunk都重新训练TF-IDF,应该先全局构建词汇表,再转换每个chunk的数据:
# 第一步:遍历所有chunk,收集文本并训练TF-IDF词汇表 all_blurbs = [] for data_chunk in pd.read_csv("books_with_blurbs.csv", chunksize=chunk_size): all_blurbs.extend(data_chunk['Blurb'].fillna('').tolist()) tfidf = TfidfVectorizer(stop_words='english') tfidf.fit(all_blurbs) # 第二步:重新读取chunk,用已训练好的TF-IDF转换数据 data_chunks = pd.read_csv("books_with_blurbs.csv", chunksize=chunk_size) recommendations_dict = {'Title': [], 'Recommendations': []} for chunk_number, data_chunk in enumerate(data_chunks, start=1): print(f"Processing Chunk {chunk_number}") # 先处理重复书名(可选) data_chunk = data_chunk.drop_duplicates(subset="Title", keep="first") # 使用transform而非fit_transform,复用全局词汇表 tfidf_matrix = tfidf.transform(data_chunk['Blurb'].fillna('')) cosine_sim = cosine_similarity(tfidf_matrix, tfidf_matrix) for title in data_chunk['Title']: recommendations = content_based_recommender(title, cosine_sim, data_chunk) recommendations_dict['Title'].append(title) recommendations_dict['Recommendations'].append(recommendations)
验证
修改后运行代码,先确认重复书名的情况是否被处理,再检查TF-IDF词汇表是否全局一致,即可解决报错并优化推荐逻辑的合理性。
内容的提问来源于stack exchange,提问作者notorious
相关产品推荐
相关产品推荐

