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

如何计算多对多依赖图模型的特征向量?

好问题!要计算这个依赖图的特征向量(通常我们指的是主特征向量,用来衡量节点的重要性,类似PageRank的逻辑),我们可以分步骤来实现,结合你的Rails模型结构,具体如下:

第一步:明确图的节点与边

你的模型里,每个Article是图的节点,Relation代表一条边:dependent(依赖方)指向dependency(被依赖方)——也就是说,如果文章A依赖文章B,那么A会给B的“重要性”投票,我们的特征向量会反映这种投票后的权重分布。

如果你的业务逻辑需要反过来(比如被依赖方指向依赖方),只需要后续代码中调换dependency_id和dependent_id的角色即可。

第二步:构建转移矩阵

首先我们需要把所有文章映射到矩阵的索引,然后构建转移矩阵(矩阵中的元素M[i][j]表示从节点i跳转到节点j的概率):

# 获取所有文章,建立ID到矩阵索引的映射
articles = Article.all
id_to_index = articles.each_with_index.to_h { |article, idx| [article.id, idx] }
total_nodes = articles.size

# 初始化全0的转移矩阵
transition_matrix = Array.new(total_nodes) { Array.new(total_nodes, 0.0) }

# 先统计每个节点的出度(即该节点依赖了多少其他文章)
out_degree = Hash.new(0)
Relation.find_each do |rel|
  from_idx = id_to_index[rel.dependent_id]
  next unless from_idx # 跳过已删除的文章(如果存在的话)
  out_degree[from_idx] += 1
end

# 填充转移矩阵:如果节点i有出度d,每条出边的概率是1/d
Relation.find_each do |rel|
  from_idx = id_to_index[rel.dependent_id]
  to_idx = id_to_index[rel.dependency_id]
  next unless from_idx && to_idx
  
  if out_degree[from_idx] > 0
    transition_matrix[from_idx][to_idx] = 1.0 / out_degree[from_idx]
  end
end
第三步:用幂迭代法计算主特征向量

主特征向量对应图的最大特征值,最适合用幂迭代法计算(简单易实现,适合大规模图)。我们还可以加入阻尼因子(模拟用户随机跳转的行为,通常设为0.85):

def power_iteration(transition_matrix, damping_factor = 0.85, max_iterations = 100, tolerance = 1e-6)
  total_nodes = transition_matrix.size
  # 初始化权重向量:每个节点初始权重相等
  current_vector = Array.new(total_nodes, 1.0 / total_nodes)
  
  max_iterations.times do
    new_vector = Array.new(total_nodes, (1 - damping_factor) / total_nodes)
    
    # 计算新的权重向量
    total_nodes.times do |i|
      total_nodes.times do |j|
        new_vector[j] += damping_factor * transition_matrix[i][j] * current_vector[i]
      end
    end
    
    # 判断是否收敛:向量变化量小于阈值就停止迭代
    diff = new_vector.each_with_index.sum { |val, idx| (val - current_vector[idx]).abs }
    current_vector = new_vector
    break if diff < tolerance
  end
  
  current_vector
end

# 计算特征向量(即各文章的重要性权重)
feature_vector = power_iteration(transition_matrix)

# 把结果映射回文章对象,按权重降序排序
article_scores = articles.each_with_index.to_h { |article, idx| [article, feature_vector[idx]] }
sorted_articles = article_scores.sort_by { |_article, score| -score }
关键注意事项
  • 边方向调整:如果你的业务逻辑中,被依赖的文章需要指向依赖它的文章(比如想衡量“被多少文章依赖”的反向权重),只需要在构建矩阵时把from_idx设为id_to_index[rel.dependency_id],to_idx设为id_to_index[rel.dependent_id]。
  • 孤立节点处理:没有任何依赖或被依赖的文章,我们通过阻尼因子的均匀分布项处理,确保它们也能获得基础权重。
  • 性能优化:如果你的文章数量很大(比如上万级),纯Ruby的矩阵操作会比较慢。可以考虑用NMatrix(Ruby的线性代数库)来加速,或者把数据导出到Python用numpy/scipy计算后再导回Rails。
  • 按用户过滤:如果需要计算某个特定用户的依赖图特征向量,只需要在查询Relation时加上where(user_id: target_user_id)即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:17:50