标签传播算法_基于graphx的标签传播算法实现

上一篇讲了一下spark graphx入门的一些小知识,这周开始做了一下标签传播算法的实现。标签传播算法,即label propagation,是社交网路中用于发现社区结构的一个非常简单高效的算法。时间复杂度低,实现简单。该方法同样能用于标签挖掘场景,通过少量的已标注数据进行指导并预测未标记数据的标签。操作简单,运算量小,适合大规模数据信息的挖掘和处理。

标签传播算法主要包含两个步骤:

第一步: 为所有节点指定一个唯一的标签,可以直接以节点id作为标签;

第二步: 逐轮刷新所有节点的标签, 对于某一个节点,考察其所有邻居节点的标签,并进行统计,将出现个数最多的那个标签赋给当前节点。当个数最多的标签不唯一时,随机选一个。

重复第二步直到达到收敛条件为止,通常会设置一个迭代次数的限制。一般来说,收敛的快慢和图的大小无关,迭代5次基本上95%以上的节点就会收敛。

在大规模图数据集上,并行的图计算是非常必要的。graphx提供了Pregel计算接口。pregel主要包含三个函数:vprog函数、sendMsg函数、mergeMsg函数。其源码如下:

def pregel[A: ClassTag](
initialMsg: A,
maxIterations: Int = Int.MaxValue,
activeDirection: EdgeDirection = EdgeDirection.Either)(
vprog: (VertexId, VD, A) => VD,
sendMsg: EdgeTriplet[VD, ED] => Iterator[(VertexId, A)],
mergeMsg: (A, A) => A)
: Graph[VD, ED] = {
Pregel(graph, initialMsg, maxIterations, activeDirection)(vprog, sendMsg, mergeMsg)
}

代码中A表示消息的类型。从中可以看到,vprog函数是运行在每个节点上的,通过接收信息,更新自身的节点属性值。sendMsg是发送消息的。mergeMsg则是合并消息的。

object LabelPropagation { 
def run[VD, ED: ClassTag](graph: Graph[VD, ED], maxSteps: Int): Graph[VertexId, ED] = { 
//初始化每个定点的社区表示为当前结点的id值 
val lpaGraph = graph.mapVertices { case (vid, _) => vid } 
//定义消息的发送函数,将顶点的社区标识发送到相邻顶点 
def sendMessage(e: EdgeTriplet[VertexId, ED]): Iterator[(VertexId, Map[VertexId, Long])] = { 
Iterator((e.srcId, Map(e.dstAttr -> 1L)), (e.dstId, Map(e.srcAttr -> 1L))) 
} 
//顶点的消息聚合函数 将每个节点消息聚合,做累加;例如一个定点出现了两次,id->2 
def mergeMessage(count1: Map[VertexId, Long], count2: Map[VertexId, Long]) 
: Map[VertexId, Long] = { 
(count1.keySet ++ count2.keySet).map { i => 
val count1Val = count1.getOrElse(i, 0L) 
val count2Val = count2.getOrElse(i, 0L) 
i -> (count1Val + count2Val) 
}.toMap 
} 
//顶点属性更新,如果有消息,取出现次数最大的作为自身的新标记
def vertexProgram(vid: VertexId, attr: Long, message: Map[VertexId, Long]): VertexId = { 
if (message.isEmpty) attr else message.maxBy(_._2)._1 
} 
val initialMessage = Map[VertexId, Long]
Pregel(lpaGraph, initialMessage, maxIterations = maxSteps)( 
vprog = vertexProgram, 
sendMsg = sendMessage, 
mergeMsg = mergeMessage) 
} 
} 

根据LPA算法的原理,可以看到代码中传递的消息类型就是Map[VertexId, Long],即节点所在标签和其出现的次数。

整个的原理和实现差不多就讲完了。在具体的应用过程中,其实还需要考虑很多东西,比如在人群标签扩散中,节点之间的关系紧密程度、关系的类型都会影响标签的传播准确性。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的GAN算法的Python代码示例: ```python import tensorflow as tf import numpy as np import matplotlib.pyplot as plt # 生成器网络模型 def generator(z, output_dim, n_units=128, reuse=False, alpha=0.01): with tf.variable_scope('generator', reuse=reuse): # 隐藏层 h1 = tf.layers.dense(z, n_units, activation=None) # Leaky ReLU激活函数 h1 = tf.maximum(alpha * h1, h1) # 输出层 logits = tf.layers.dense(h1, output_dim, activation=None) out = tf.tanh(logits) return out # 判别器网络模型 def discriminator(x, n_units=128, reuse=False, alpha=0.01): with tf.variable_scope('discriminator', reuse=reuse): # 隐藏层 h1 = tf.layers.dense(x, n_units, activation=None) # Leaky ReLU激活函数 h1 = tf.maximum(alpha * h1, h1) # 输出层 logits = tf.layers.dense(h1, 1, activation=None) out = tf.sigmoid(logits) return out, logits # 定义输入变量 input_dim = 100 output_dim = 28*28 tf.reset_default_graph() X = tf.placeholder(tf.float32, shape=[None, output_dim], name='real_input') Z = tf.placeholder(tf.float32, shape=[None, input_dim], name='input_noise') # 定义超参数 g_units = 128 d_units = 128 alpha = 0.01 learning_rate = 0.001 smooth = 0.1 # 定义生成器 G = generator(Z, output_dim, n_units=g_units, alpha=alpha) # 定义判别器 D_output_real, D_logits_real = discriminator(X, n_units=d_units, alpha=alpha) D_output_fake, D_logits_fake = discriminator(G, n_units=d_units, reuse=True, alpha=alpha) # 定义损失函数 d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logits_real, labels=tf.ones_like(D_output_real) * (1 - smooth))) d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logits_fake, labels=tf.zeros_like(D_output_fake))) d_loss = d_loss_real + d_loss_fake g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_logits_fake, labels=tf.ones_like(D_output_fake))) # 定义优化器 train_vars = tf.trainable_variables() d_vars = [var for var in train_vars if var.name.startswith('discriminator')] g_vars = [var for var in train_vars if var.name.startswith('generator')] d_train_opt = tf.train.AdamOptimizer(learning_rate).minimize(d_loss, var_list=d_vars) g_train_opt = tf.train.AdamOptimizer(learning_rate).minimize(g_loss, var_list=g_vars) # 加载MNIST数据集 from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/") # 训练模型 batch_size = 100 epochs = 100 samples = [] with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for e in range(epochs): for i in range(mnist.train.num_examples // batch_size): batch = mnist.train.next_batch(batch_size) batch_images = batch[0].reshape((batch_size, output_dim)) batch_images = batch_images * 2 - 1 batch_noise = np.random.uniform(-1, 1, size=(batch_size, input_dim)) _ = sess.run(d_train_opt, feed_dict={X: batch_images, Z: batch_noise}) _ = sess.run(g_train_opt, feed_dict={Z: batch_noise}) # 每个epoch结束后输出损失值 train_loss_d = sess.run(d_loss, {Z: batch_noise, X: batch_images}) train_loss_g = g_loss.eval({Z: batch_noise}) print("Epoch {}/{}...".format(e+1, epochs), "Discriminator Loss: {:.4f}...".format(train_loss_d), "Generator Loss: {:.4f}".format(train_loss_g)) # 保存样本 sample_noise = np.random.uniform(-1, 1, size=(16, input_dim)) gen_samples = sess.run(generator(Z, output_dim, n_units=g_units, reuse=True, alpha=alpha), feed_dict={Z: sample_noise}) samples.append(gen_samples) # 显示生成的图像 fig, axes = plt.subplots(figsize=(7,7), nrows=4, ncols=4, sharey=True, sharex=True) for img, ax in zip(samples[-1], axes.flatten()): ax.imshow(img.reshape((28,28)), cmap='Greys_r') ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) plt.show() ``` 以上代码使用TensorFlow实现了一个简单的GAN模型,用于生成MNIST数据集中的手写数字图片。在训练过程中,我们通过反向传播优化生成器和判别器的参数,最终生成了一组手写数字图片。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值