实现《A Three-Layered Mutually Reinforced Model》中B矩阵时得向量而非方阵
排查个性化引文推荐模型中B矩阵变为向量的问题
嘿,我来帮你搞定这个问题!你要实现《A Three-Layered Mutually Reinforced Model for Personalized Citation Recommendation》第4页的B方阵,但代码跑出来是向量,核心问题出在逻辑误解和代码错误上,咱们一步步拆解:
1. 最明显的错误:嵌套调用余弦距离完全不符合逻辑
你代码里的这行是硬伤:
spatial.distance.cosine(spatial.distance.cosine(query, model.docvecs[i]), model.docvecs[i])
spatial.distance.cosine(a, b)要求输入的a和b是同维度的向量,但第一层cosine返回的是一个标量(比如0.3这样的单个数值),你把标量和多维的文档向量传进去,numpy会自动广播标量成和向量同长度的数组,但这完全不是论文公式要计算的内容!
你应该是想计算query和每个文档向量的余弦相似度(或距离),所以直接改成单层调用就行:
# 余弦距离(范围0-2) spatial.distance.cosine(query, model.docvecs[i]) # 如果论文用的是相似度(范围0-1),就转一下: 1 - spatial.distance.cosine(query, model.docvecs[i])
2. 误解了B矩阵的结构:为什么你得到的是向量?
你当前的代码是循环每个文档i,计算一个值,最终得到长度为Docs_len的向量,但论文里的B是方阵(假设维度是N×N,N=Docs_len)。根据论文的“三层互增强”定位,B的结构通常有两种可能,对应不同的实现方式:
情况一:B是文档-文档的个性化相似性矩阵
如果B的元素B_ij表示结合query个性化信息后,文档i和文档j的相关性,那需要双重循环遍历所有文档对:
def eq_b(query_vec): # 初始化N×N的零矩阵 b_matrix = np.zeros((Docs_len, Docs_len)) for i in range(Docs_len): doc_i = model.docvecs[i] # 先计算query与文档i的个性化相似度 sim_q_i = 1 - spatial.distance.cosine(query_vec, doc_i) for j in range(Docs_len): doc_j = model.docvecs[j] # 计算文档i与文档j的基础相似度 sim_i_j = 1 - spatial.distance.cosine(doc_i, doc_j) # 按照论文公式结合两个相似度(这里是示例,要严格匹配论文定义) b_matrix[i][j] = sim_q_i * sim_i_j # 按行归一化(匹配论文的归一化要求) row_sums = b_matrix.sum(axis=1, keepdims=True) return b_matrix / row_sums
情况二:B是query-文档相似度构成的对角矩阵
如果B是对角矩阵(仅对角线元素有值,B_ii表示query与文档i的相似度,其余为0),那代码可以简化为:
def eq_b(query_vec): # 计算query与每个文档的余弦相似度 sim_scores = np.array([1 - spatial.distance.cosine(query_vec, model.docvecs[i]) for i in range(Docs_len)]) # 归一化后构造对角矩阵 normalized_sim = sim_scores / sim_scores.sum() b_matrix = np.diag(normalized_sim) return b_matrix
3. 验证归一化方式
你当前的代码是把整个向量的总和作为分母归一化,但如果是方阵,通常是按行/按列归一化,这要严格对应论文里的公式说明,别搞错了!
修正后的完整示例代码
假设B是对角矩阵的情况,完整代码如下:
querySplit = query.split(',') queryText = querySplit[0] qt_tag = word_tokenize(queryText.rstrip().lower().translate(translator)) qt_vector = model.infer_vector(qt_tag) def eq_b(query_vec): # 计算query与每个文档的余弦相似度(转换为0-1范围) sim_scores = np.array([1 - spatial.distance.cosine(query_vec, model.docvecs[i]) for i in range(Docs_len)]) # 归一化后构造对角矩阵 normalized_sim = sim_scores / sim_scores.sum() b_matrix = np.diag(normalized_sim) return b_matrix b = eq_b(qt_vector) print("B矩阵的形状:", b.shape) # 应该输出 (Docs_len, Docs_len) print("B矩阵:", b)
内容的提问来源于stack exchange,提问作者BiSarfraz
相关产品推荐
相关产品推荐

