【论文阅读】ToupleGDD: A Fine-Designed Solution of Influence Maximization by Deep Reinforcement Learning

文章提出了一种新的框架ToupleGDD,它整合了耦合的图神经网络(GNN)和双深度Q网络(DQN)来有效解决信息最大化传播问题。通过使用GNN模拟级联效应,该模型能在不同网络上泛化,并通过强化学习策略优化种子节点的选择,以达到最大的影响范围。实验表明,该模型在多个数据集上表现优于现有方法。
摘要由CSDN通过智能技术生成
  1. 它结合了用于网络嵌入的“三个耦合图神经网络(gnn)+用于参数学习的双深度q网络(dqn)”。
  2. 技术一:使用DoubleDQN,近似求解动作状态值函数 Q(s, a)
  3. 除了网络拓扑结构外,DDQN中的函数逼近器还需要捕捉IM中的关键影响级联效应。(级联效应是指一个节点的激活将以连续的方式触发它的邻居,在社交网络上形成扩散级联,这与图神经网络(gnn)中的消息传递效应是一致的。)
  4. 技术二:使用GNN模拟级联效应 我们使用gnn来获取节点嵌入,并利用节点嵌入来构造参数化函数,端到端模型,用DDQN学习所有参数。

痛点:

  1. 以往方法都是在子图上训练,在整个图上测试,导致模型在不同网络间性能不稳定。
    该方法在随机生成的小图上训练,在不同网络上测试,泛化效果好。
  2. 模型可以在无向图和不同的边权上工作
  3. 监督学习,这引入了大量额外的计算开销和手工制作学习管道的努力,而我们的模型可以端到端学习参数。
  4. PIANO方法[11]采用structure2vec学习节点嵌入,而我们设计了三个耦合的gnn来学习网络表示

贡献:

  1. 第一个提出这样一个端到端的框架,ToupleGDD,它结合了耦合gnn和DRL方法来有效地解决IM问题
  2. 一种定制的深度游走(PDW)方法来学习初始节点嵌入作为以下定制GNN层的输入特征,该方法同时考虑了节点的局部和全局影响
  3. 为了捕捉级联效应和网络拓扑,我们设计了3耦合gnn来学习节点嵌入
  4. 在一些数据集上的性能非常接近于IMM,甚至超过了OPIM-C,这证明了我们提出的模型的优越性和有效性。

马尔科夫建模:

• 有向图
• (u,v):u是v的in-neighbor,v是u的out-neighbor
• v有Nin(v)和Nout(v)

IC传播模型:
• puv:u对v的激活概率
• 每个节点有两种可能的状态:活动和不活动
• 初始,种子集S中的所有节点为激活状态,其余节点为非激活状态;
• 如果节点u首先在时间戳t被激活,那么u将尝试在时间戳t + 1激活其未激活的外邻居v,成功率为puv。
• 在时间戳t + 1之后,u不能激活它的任何外部邻居;
• 一旦节点被激活,它在以下时间戳中保持活动状态
IM传播最大化定义
• I(S)扩散过程终止时激活的节点数,σ (S)为S能激活的节点数。σ (S) = E[I(S)]
• b是上限。以S≤b的小节点集S作为种子,其影响范围最大。
• 设St为当前选择的种子集

强化学习过程:

  1. 学习阶段:
    • 给定一组训练图G ={g1, g2,…, Gc}
    • 扩散模型ψ
    • 影响函数σ: S→R+
    • 训练一组参数使得影响函数尽可能准确。
  2. 测试阶段:
    • 给定一个网络G
    • 学习参数
    • 一个整数预算b
    • 在某个扩散模型ψ下求解预算b的IM问题。

GNN框架:

学习拓扑信息,学习级联效应,利用设计的随机游走方式学习节点的局部和全局影响力
1. 给定一组训练图G = {G1, G2,…, Gc},我们首先应用PDW方法得到初始节点嵌入(比随机初始化稳定性强)
2. 然后结合GNN和注意机制学习节点嵌入:
①. 设计3耦合GNN捕捉节点级联效应
3. K回合迭代,使用嵌入构造参数化函数Q(v,S,Θ)
4. 使用强化学习DDQ + ε贪心 获得参数

3耦合GNN:
	目标节点v是否被激活,三方面决定:
		1) In-neighbor:u的状态
		2) u的影响力
		3) v受u影响趋势
	u的嵌入包含三部分:
		1) Xu:节点激活状态 :Xu ∈ R
		2) Su:u影响其他节点的能力:Su ∈ R^l
		3) Tu:被其他节点激活的趋势:Tu ∈ R^l
	一. 初始化:PDW获得节点u对应的Xu、Su、Tu
		PDW方法学习嵌入,作为下一个GNN层的输入特征
			1) 受Inf2vec模型启发
			2) 生成节点上下文(影响)
			3) 利用skip-gram方法预测给定节点的上下文
		1. u的上下文Cu包含两部分,依次获得:
		限制节点上下文的大小,假设节点上下文的长度阈值为L, α∈[0,1]
			· 局部影响Lu:
				可以被u激活的采样集合
				①. 采用重启随机游走(RWR)策略(设置重启概率为0.15)
				②. 到达阈值α·L时停止行走,获得Lu
			· 全局影响Gu:
				从u的out-neighbors的r-hop节点采样,采样集
				①. 随机采样(1-α)·L个节点,Nout^r
		2. 基于u的嵌入,u的影响力Cu(u的级联效应)的概率为:
			1) 给定u的嵌入,任意节点v受u影响的概率用softmax函数表示:
				四部分:Xu节点u的激活状态;Su节点u影响其他节点包括v的能力;Tv节点v被其他节点影响的趋势;Xv节点v的激活状态
				· Pr(v|u) = e^(Xu ·Su ·Tv+Xv) /Z(u)
				· Z(u):归一化项:所有可能的v的e^(Xu ·Su ·Tv+Xv)求和
				· Xv:v的激活状态
				· Tv:v受u激活的趋势
			2) u的影响和Cu:u影响的所有v的概率Pr(v|u)的连乘积
			3) 采样一组u和其级联影响Cu,最大化它们的对数概率log Pr(v|u)
				计算优化:
					(1) 枚举所有v,计算Z(u)费时,使用负采样,近似计算softmax函数
					(2) 采用随机梯度下降法(SGD)学习所有参数,在每一步中,我们通过计算梯度来更新参数
						更新参数: Xu, Su, Xw, Tw
						返回每个节点u对应的Xu、Su、Tu
	二. 3耦合GNN迭代u嵌入
		1. state GNN:建模节点的激活状态:X(k+1)v
		2. Source GNN:建模节点的影响能力:S(k+1)v
		3. Target GNN:建模节点受其他节点影响的趋势:T(k+1)v
	强化学习中,基于当前状态选择的种子集St,需要通过ToupleGNN相应地更新节点表示。
		1) State GNN
			· 建模节点在级联效应过程中的激活状态
			· 节点被in-neighbor中的激活节点激活
			· 节点的激活状态Xv由两部分决定:
									1. 所有in-neighbor的激活状态(节点被激活的可能性)
									2. 所有in-neighbor的影响权重/概率
			· 由于:节点间相互作用强度a(k)v随节点状态改变,所以不能只使用静态边权Puv
				· 两部分组成:所有in-neighbor的puv和动态权重InfluGate()
				优化方法:
					添加:v的in-nighbor的能力嵌入Sv,和v的趋势嵌入Tv
					建立影响注意机制,动态获得节点之间的权值:
							· e(k)uv表示u对v的动态影响
							· 将Sv,Tv使用维度转换矩阵W转换维度后拼接
							· 再作用权重矩阵η
							· 为了使节点间的系数具有可比性,采用了结合LeakyReLU的softmax函数对注意系数进行归一化,获得InfluGate()
			1) 节点被激活的可能性:X(k+1)v
			· 当节点v被选择到当前种子集St中时,节点v的激活状态设置为1
			· 否则,聚合v的in-neighbor的影响来更新:两部分组成:
										w 第k层的X(k)v
										w v的in-neighbor的聚合影响a(k)v
		2) Source GNN
			· 模拟节点影响其他节点的能力:
				(1) 节点的激活状态X(k)v
				(2) 节点向它所有out-neighbor传递的影响:
					(1) 用out-neighbor被激活的趋势之和表示(类似state GNN中的动态影响权重)
					(2) f(k)vw表示,计算方法等同于e(k)uv
					(3) LeakyReLU的softmax函数归一化为a(k)vw
					(4) 用三层MLP(多层感知机)获得每一个out-neighbor的非线性被激活趋势:SourceGate(⋆)
					(5) 聚合所有out-neighbor,获得b(k)v
					(6) 结合:
						} out-neighbor被激活的趋势之和b(k)v
						} k层的S(k)v
						} k层的:节点的激活状态X(k)v
					三个部分,三个参数,获得S(K+1)v
		3) Target GNN
			· 目标GNN用于模拟节点受其他节点影响的倾向:
				(1) 它当前的激活状态X(k)v
				(2) 它的in-neighbor对它的影响扩散决定的:
					(1) 聚合Su和Tv
					(2) LeakyReLU的softmax函数归一化为φ(k)uv
					(3) TargetGate(⋆)用三层MLP(多层感知机)获得每一个in-neighbor的非线性影响力
					(4) 聚合所有in-neighbor,获得c(k)v
					(5) 结合:
						} k层的:T(k)v
						} k层的:c(k)v
						} 当前的激活状态:X(k)v
					三个部分,三个参数,获得T(K+1)v
	三. 强化学习
	拼接三部分获得u的嵌入
	u的嵌入参数化候选节点u的增益函数:Q(u,St,Θ),Θ指代4个参数
	马尔科夫建模:
		A:候选节点u的嵌入
		S:St表示当前的节点序列,是一个| V |维向量
			若u在当前序列,u是1;否则是0
			用Sb代替St,b是当前已选节点数量
		T:选择u为种子时,激活状态Xu从0更改为1
		R:r表示单个节点的增益
		     Sb的影响范围σ等于所有节点增益r之和
		P:映射每个状态下选择每个节点的概率,即如何选择下一个节点
	DDQN训练拟合函数Q(u,St,Θ)的参数:
		采用两个网络:
			· 行为网络:Θ:训练期间,目标网络为行为网络提供未来状态Q的估计值
			· 目标网络:Θ' :Θ更新m回合,更新一次
			1) 为了获得对未来奖励更准确的估计,采用n步q学习更新参数,即等待n步后更新参数。
			2) 采用了带有经验回放的拟合q迭代,以加快学习收敛。
			3) 参数Θ更新是通过最小化损失函数完成
	完整DDQN步骤:
		1. 使用PDW初始化节点嵌入
		2. 每一回合(执行b次):
			1) 初始化空种子集
			2) ε贪心策略选择节点
			3) 若到达n步,存储样本到M,使用经验回放
			4) 利用缓冲区的一批样本更新参数,而非当前损失
			5) b次,每一次:3耦合GNN更新k次嵌入
					      每层聚合一次
	四. 实验
		1. 随机生成20个节点数量15-50不等的ER图用于训练和验证
			· 均匀随机抽取15-50个节点
			· 生成连边概率为0.15的ER图
			· 15张图用于训练
			· 5张和soc-dolphins数据集用于验证
		2. 模型和基线算法在七个真实数据集上进行测试
			· 若为无向图,则改为双向边
			·  Twitter, Wiki-1, caGr, Buzznet
			·  Wiki-2, Epinions, Youtube
		3. 通过修改奖励函数,模型可以很容易地适应不同的扩散模型
			· 使用IC模型:
				® 边传播概率为:1/in-neighbor数量
		4. 为保证公平,进行10000次蒙特卡罗模拟,估计预期的影响范围。
		5. 所有实验运行十次,报告被测量度量的平均值
		6. 基线算法:
			· IMM 
			· OPIM-C 
			· DRL methods 
			· S2V-DQN(修改版)
			· GCOMB
			· PIANO
		7. 训练数据集:
			1) 边权为in-degree
			2) 默认:验证数据集和测试数据集的边权相同
				(1) 三种设置方法:
					①. In-degree
					②. 0.1
					③. 0.5
			3) 预算b为5(测试数据集:人工图:5,soc-dolphins数据集:7)
			4) 测试集:每个测试数据集,我们改变预算b,使b∈{10,20,30,40,50}

项目目录:

  1. test_data:

    1. Wiki-2.txt:
      · 有向图(每对无序节点保存一次)
      · 有向边A->B表示用户A投票支持B成为维基百科管理员
      · 节点:7115
      · 边:103689
  2. train_data:

    1. graph1.txt到graph15.txt:
      · 人工生成的节点数目15-50的15个graph
  3. utils:

    1. init.py:空

    2. graph_utils.py:
      · Graph类:
      (1) 初始化图函数:
      属性
      ①. 节点:
      · set() 类:一个无序不重复元素集
      ②. 边:
      · dict{(src,dst): weight, }
      ③. 孩子(out-neighbor)
      · dict{node: set(), }
      ④. 父母(in-neighbor)
      · dict{node: set(), }
      ⑤. 每个节点的孩子节点集合(有序排列)
      ⑥. 每个节点的父母节点集合(有序排列)
      ⑦. 节点数量
      ⑧. 边数量
      ⑨. 邻接矩阵adj = None
      ⑩. self._from_to_edges = None
      11. self._from_to_edges_weight = None

       (2) get孩子函数(out-neighbor):
       	· 获得节点的out-neighbor节点集合
       (3) get父母函数(in-neighbor):
       	· 获得节点的in-neighbor节点集合
       (4) get概率函数(out-neighbor):
       	· 获得节点的边权节点集合
       (5) get邻接矩阵:
       	· 元素是边权值
       (6) from_to_edge:
       	· 边列表
       (7) from_to_edge_weight:
       	· 边权列表
      

      · 图的功能函数:
      (1) 加载图函数:
      有向图
      · 孩子:dict:包含所有的源节点(key)和对应的目的节点集合(value)
      · 父母:dict:包含所有的目的节点(key)和对应的源节点集合(value)
      · 边:dict:(src, dst) key;边权=0.0(value)
      · 节点:set:所有节点
      无向图
      · 孩子:dict:包含所有的目的节点(key)和对应的源节点集合(value)
      · 父母:dict:包含所有的源节点(key)和对应的目的节点集合(value)
      · 边:dict:(dst, src) key;边权=0.0(value)

       	· 修改边权:1/节点出度
      
  4. val_data:

    1. graph16.txt到graph20.txt
      · 人工生成的节点数目15-50的15个graph
    2. Soc-dolphins.txt
      · 节点:62
      · 边:159
  5. init.py:空

  6. environment.py:
    • Environment类:
    1) 初始化函数:
    属性:
    #图的采样集相关
    ①. 名字:
    ②. 图:
    #IM相关
    ①. 预算:
    ②. 方法:RR或者MC
    #在同一图上运行多次时
    ①. 使用cache:加速
    ②. .method
    ③. .influences
    ④. .RRs_dict
    #训练或测试模式时
    ①. .training=training
    2) 重置批量图函数:
    · 生成新图,默认数量为10个
    3) 重置函数(重新开始):
    (1) 设置.graph
    · 若无图index:环境里随机选择一张图
    · 若有:选择该图
    (2) 设置.state
    · 遍历图中所有节点
    #IM相关
    (3) 设置prev_inf
    · 先前影响得分
    #存储RR集,以防有多个图
    (4) 若使用cache且method是RR
    存储:
    · .RRs
    · .state
    · .actions
    · .rewards
    · .training
    4) 计算奖励函数:
    (1) 并行处理数量为5
    (2) 试验次数为10000
    #获得影响值
    (3) 如果使用cache且method是MC
    5) step函数(改变状态,获得奖励):
    (1) #若节点已经被选择
    如果节点状态是1
    return空
    (2) #若节点没有被选择
    #存储状态和动作
    添加节点状态到状态list中
    添加节点到动作list中
    #更新状态
    将节点状态设置为1
    #计算奖励
    ► 如果.name不是IM
    报错
    如果是IM
    状态S = .actions(节点序列集)
    如果节点数量大于等于预算
    Done
    ► 如果是.training模式
    奖励 = 计算奖励函数返回值(计算奖励)
    如果不是.training模式
    ► 如果done
    ► 如果时间奖励不是0
    开始时间=当前时间(开始计时)
    如果是0
    奖励 = 计算奖励函数返回值(计算奖励)
    如果时间奖励不是0
    时间奖励第一个元素 = 当前时间-开始时间(停止计时)
    如果没done
    奖励=0
    返回(奖励,done)

  7. models.py:
    4个模型类nn.Module:
    ► S2V_DQN
    ► Tripling(3耦合GNN + 强化学习)
    ► DeepWalkNeg
    ► S2V_DUEL
    structure2vector + dueling deep Q network
    Tripling类
    (1) 初始化函数
    参数列表:
    · 嵌入层维度emb_dim
    · stateGNN维度?sourceGNN
    · target GNN维度
    · T:Tripling层数
    · 隐藏层维度
    · w_scale
    #Tripling类继承父类nn.Model的属性,并使用父类的初始化方法初始化继承到的属性。
    #初始化非继承的新属性
    · 设置.emb_dim为传入值
    · 设置.sgate_l1_dim为传入值
    · 设置.tgate_l1_dim为传入值
    · 设置.T为传入值
    · 设置.hidden_dims为传入值
    #初始嵌入维度
    · .hidden_dims.insert(0, embed_dim):插入嵌入维度为索引0
    · 转移权重.trans_weights = nn.ParameterList()
    #stateGNN的参数
    · .influgate_etas = nn.ParameterList()
    · .state_weights_self = nn.ParameterList()
    · .state_weights_neibor = nn.ParameterList()
    #边注意力和边权的参数
    · .state_weights_attention = nn.ParameterList()
    · .state_weights_edge = nn.ParameterList()
    #sourceGNN的参数
    · .source_betas = nn.ParameterList()
    · .sourcegate_layer1s = nn.ModuleList()
    · .sourcegate_layer2s = nn.ModuleList()
    · .source_weights_self = nn.ParameterList()
    · .source_weights_neibor = nn.ParameterList()
    · .source_weights_state = nn.ParameterList()
    #边注意力和边权的参数
    · .source_weights_attention = nn.ParameterList()
    · .source_weights_edge = nn.ParameterList()
    #targetGNN的参数
    · .target_taus = nn.ParameterList()
    · .targetgate_layer1s = nn.ModuleList()
    · .targetgate_layer2s = nn.ModuleList()
    · .target_weights_self = nn.ParameterList()
    · .target_weights_neibor = nn.ParameterList()
    · .target_weights_state = nn.ParameterList()
    #边注意力和边权的参数
    · .target_weights_attention = nn.ParameterList()
    · .target_weights_edge = nn.ParameterList()
    (2) 前向传播(级联效应)
    #输入初始化节点嵌入
    #执行tripling消息传播:
    源节点影响source_influ:S(k)u
    目标节点影响target_influ:T(k)v
    状态
    #遍历tripling所有层
    矩阵乘,矩阵乘,拼接
    influgate_etas[i]:η(k)
    矩阵乘 ,leaky函数,得到e_uv
    state:X(k)v

  8. rl_agents.py:

  9. runner.py:

  10. main.py:
    • 设置logger
    • 参数配置(三步骤):
    1) 创建 .ArgumentParser() 对象
    2) 调用 .add_argument() 方法添加参数
    · 预算–budget:默认6
    · 图路径–graph:默认:soc-dolphins.txt
    · agent类型–agent:默认:Agent
    · 模型名称–model:默认:Tripling
    · 模型文件–model_file:默认:tripling.ckpt
    · 训练回合数–epoch:默认:2000
    · 学习率–lr:默认:1e-3
    · 训练时的批大小–bs:默认:8
    · 强化学习n-step技术的n大小–n_step:默认:2
    · 是否使用cpu–cpu:默认:False
    · 是否测试模型性能–test:默认:False
    · 环境名称–environment_name:默认:IM
    3) 使用 .parse_args() 解析添加的参数
    • main函数:
    #加载参数
    #设置设备
    使用cuda
    #加载图
    ► 如果.graph是目录
    加载多图路径
    如果不是目录
    加载一个图
    ► 获得图路径列表
    遍历多个图,设置.path_graph的路径
    设置.graphs为图路径列表
    设置.double_dqn为True
    ► 如果不是test模式:是tripling模型的训练模式
    时间戳 = 当前时间
    ► 如果时间戳获取失败
    创建目录(以时间戳为路径)
    设置.model_file = 时间戳,模型文件
    设置.T为3
    设置.memory_size = 50000
    设置.reg_hidden为32
    ► 如果模型是Tripling
    嵌入层维度是50
    ► 如果不是
    维度是64
    #加载agant
    使用rl_agent.py文件的.Agent
    #加载环境
    #创建环境
    1) 创建训练环境:
    · 环境名称
    · 图列表graph_lst
    · 预算
    · Method=RR
    · 是否使用cache
    2) 创建测试环境:
    · 环境名称
    · 图列表graph_lst
    · 预算
    · Method=MC
    · 是否使用cache
    #加载runner和开始running
    print:运行单个实例模拟
    设置runner = runner.py的runner:
    · 训练环境
    · 测试环境
    · Agent
    · 不测试
    ► 如果不测试:
    · runner开始训练:
    · .epoch训练回合
    · 模型参数文件
    · 保存计算出的:奖励结果.txt
    如果测试:
    · runner.test():
    · 测试次数默认:10

  11. s2vdqn.ckpt

  12. tripling.ckpt

–graph:提供图的路径。它可以加载单个图形:该图形的路径,或多个图形:包含所有图形的文件夹的路径。
–model:提供模型使用:Tripling是ToupleGDD模型,S2V_DQN是基线S2V-DQN模型。
–model_file:在测试时提供模型的路径,或者在训练时提供模型将保存到的文件名。
–test:需要指定来测试模型。
测试时不需要:–epoch,–lr,–bs,–n_step
图的节点id应为连续整数
main.py第54行:
• 设置图类型:有向或无向
• 设置图的起始节点id: 0-index或1-index
rl_agents.py第143行:
• 设置训练时,生成初始节点嵌入的回合epoch次数9(当前是30)
runner.py第61行:
• 设置test时,生成初始节点嵌入的epoch数(当前是0)
utils/graph_utils.py第 87-97行:
• 设置图边权(有三种方法)
• 边(u, v)的当前设置为:1/in-degree(v) (in-degree设置)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炖鹅小铁锅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值