基于同Dir_Id的电影Plot余弦相似度计算异常排查
同导演电影Plot余弦相似度计算问题分析与解决
问题背景
现有电影数据结构如下:
Movie_Id Dir_Id Genre Production_House Plot 1231 14 Drama Columbia Text blob 1232 16 Romance Paramount Text blob 1233 14 Thriller Miramax Text blob 1234 15 Comedy Warner Bros. Text blob 1235 16 Romantic Comedy Paramount Text blob 1236 16 Drama Columbia Text blob . . . . . . . . . .
需求:针对指定Movie_Id,仅计算与同Dir_Id电影在Plot列的余弦相似度,且支持动态切换目标Movie_Id(如查询1234时仅考虑Dir_Id为15的电影)。
现有代码与问题
尝试了以下代码:
index = index_from_movie_id(df, movie_id) # 获取原DataFrame中目标电影的索引 director = dir_from_movie_id(df, movie_id) # 获取目标电影的导演ID in_dir_df = df[df['Dir_Id'] == director] tf_idf_dir = TfidfVectorizer(stop_words='english') tf_idf_dir_matrix = tf_idf_dir.fit_transform(in_dir_df['Plot']) cosine_similarity_dir_matrix = cosine_similarity(tf_idf_dir_matrix, tf_idf_dir_matrix) similarity_scores = list(enumerate(cosine_similarity_dir_matrix[index]))
执行print(similarity_scores)时,得到了其他Dir_Id电影的索引,不符合预期。
问题根源
核心错误是混淆了原DataFrame的行索引和子集的位置索引:
index是原完整DataFrame中目标电影的行索引(比如原DataFrame中Movie_Id=1234的索引可能是3)in_dir_df是原DataFrame的子集,它的行索引继承自原DataFrame,但余弦相似度矩阵cosine_similarity_dir_matrix的维度是子集的行数,其索引是子集内部的0-based位置索引(比如子集只有1部电影时,索引是0)- 用原DataFrame的
index去访问余弦矩阵的行,会取到错误的位置(甚至越界),导致结果包含无关电影的索引。
修正方案
需要先获取目标电影在子集内部的位置索引,再用该索引访问余弦矩阵,最后关联子集的原索引/Movie_Id:
# 获取目标电影的导演ID director = dir_from_movie_id(df, movie_id) # 筛选同导演的电影子集 in_dir_df = df[df['Dir_Id'] == director].copy() # 关键:获取目标电影在子集内部的位置索引(0-based) # 方法1:先找到目标电影在子集的原索引,再转成位置索引 target_original_idx = in_dir_df[in_dir_df['Movie_Id'] == movie_id].index[0] target_subset_idx = in_dir_df.index.get_loc(target_original_idx) # 方法2:更简洁的方式(如果子集内Movie_Id唯一) target_subset_idx = in_dir_df[in_dir_df['Movie_Id'] == movie_id].iloc[0].name target_subset_idx = in_dir_df.index.get_loc(target_subset_idx) # 构建TF-IDF矩阵 tf_idf_dir = TfidfVectorizer(stop_words='english') tf_idf_dir_matrix = tf_idf_dir.fit_transform(in_dir_df['Plot']) # 计算余弦相似度 cosine_sim_matrix = cosine_similarity(tf_idf_dir_matrix, tf_idf_dir_matrix) # 获取同导演电影的相似度分数,关联原DataFrame的索引 similarity_scores = list(zip(in_dir_df.index, cosine_sim_matrix[target_subset_idx])) # 可选:直接关联Movie_Id,更直观 similarity_scores_with_movie_id = [ (in_dir_df.loc[idx, 'Movie_Id'], score) for idx, score in similarity_scores ]
关键说明
- 必须用子集内部的位置索引访问余弦矩阵,才能确保只获取同导演电影的相似度
- 通过
zip(in_dir_df.index, ...)可以把相似度分数和原DataFrame的行索引绑定,进而映射到对应的Movie_Id,得到符合需求的结果
内容的提问来源于stack exchange,提问作者Neo
相关产品推荐
相关产品推荐

