在tensorflow框架下,模型为GNN模型,要解决图着色(图论)问题,中间大致过程经过编码输入,RNN循环,聚合更新节点,颜色的嵌入,经固定次数嵌入更新,得到最后的节点和颜色的特征,输入MLP,进行预测任务:该图是否接受C中颜色着色?(二分类问题)
其中,负责聚合更新的RNN循环次数设为32时,loss在迭代过程会由很大的值(超过百万以上)逐渐变为lan,循环次数为8,最后loss由50左右经100epoch后会稳定在0.69和acc稳定在0.5左右是什么原因呢?
除此之外,我想在最后一层激活函数sigmoid之前加入BN层应该怎么编写呢,部分段代码如下:
......
# Get the last embeddings
last_states = gnn(
{ "M": M_matrix, "VC": VC_matrix, 'chrom_number': chrom_number },
{ "V": vertex_initial_embeddings, "C": colors_initial_embeddings },
time_steps = time_steps
)
GNN["last_states"] = last_states
V_n = last_states['V'].h
C_n = last_states['C'].h
# Compute a vote for each embedding
V_vote = tf.reshape(V_vote_MLP(V_n), [-1])
# Compute the number of problems in the batch
num_problems = tf.shape(n_vertices)[0]
# Compute a logit probability for each problem
pred_logits = tf.while_loop(
lambda i, pred_logits: tf.less(i, num_problems),
lambda i, pred_logits:
(
(i+1),
pred_logits.write(
i,
tf.reduce_mean(V_vote[tf.reduce_sum(n_vertices[0:i]):tf.reduce_sum(n_vertices[0:i])+n_vertices[i]])
)
),
[0, tf.TensorArray(size=num_problems, dtype=tf.float32)]
)[1].stack()
# Convert logits into probabilities
GNN['predictions'] = tf.sigmoid(pred_logits)
或者BN层应该加到其他什么地方呢,希望有详细代码指导?期望得到详细咨询指导,想具体了解代码的可以私信
关于loss变化的问题,可能是因为RNN循环的次数较多(32),导致模型训练较慢,需要更多的迭代才能收敛。此外,模型可能存在梯度爆炸或消失问题,可以尝试加入梯度裁剪或使用其他的优化器和学习率调整策略。
而最后loss和准确率稳定在一个相对较高的数值(0.69和0.5)可能是因为该问题本身就比较困难,即使是一个随机猜测的准确率也是0.5左右。
至于在最后一层激活函数sigmoid之前加入BN层,可以按照以下方式修改代码:
from tensorflow.keras.layers import BatchNormalization
# Get the last embeddings
last_states = gnn(
{ "M": M_matrix, "VC": VC_matrix, 'chrom_number': chrom_number },
{ "V": vertex_initial_embeddings, "C": colors_initial_embeddings },
time_steps = time_steps
)
GNN["last_states"] = last_states
V_n = last_states['V'].h
C_n = last_states['C'].h
# Compute a vote for each embedding
V_vote = tf.reshape(V_vote_MLP(V_n), [-1])
# Add a Batch Normalization layer before the final output
V_vote = BatchNormalization()(V_vote)
# Compute the number of problems in the batch
num_problems = tf.shape(n_vertices)[0]
# Compute a logit probability for each problem
pred_logits = tf.while_loop(
lambda i, pred_logits: tf.less(i, num_problems),
lambda i, pred_logits:
(
(i+1),
pred_logits.write(
i,
tf.reduce_mean(V_vote[tf.reduce_sum(n_vertices[0:i]):tf.reduce_sum(n_vertices[0:i])+n_vertices[i]])
)
),
[0, tf.TensorArray(size=num_problems, dtype=tf.float32)]
)[1].stack()
# Convert logits into probabilities
GNN['predictions'] = tf.sigmoid(pred_logits)
在最后一层激活函数sigmoid之前,使用Batch Normalization层进行归一化,可以加速模型收敛,提高模型的精度。
图神经网络(GNN)简介
可以借鉴下
https://blog.csdn.net/qq_28368377/article/details/108936199
引用new bing部分指引作答:
首先,关于你的第一个问题,RNN循环次数从32减少到8后,loss值和acc稳定在0.69和0.5左右,这很可能是由于过多的循环次数导致了梯度消失或梯度爆炸的问题。这可能是由于RNN的循环结构以及激活函数的非线性性质导致的,因此减少循环次数是一个解决方法。你可以尝试使用其他的循环结构,比如LSTM或GRU,来避免梯度消失和爆炸问题。
其次,关于在最后一层添加Batch Normalization层,你可以这样实现:
# Get the last embeddings
last_states = gnn(
{ "M": M_matrix, "VC": VC_matrix, 'chrom_number': chrom_number },
{ "V": vertex_initial_embeddings, "C": colors_initial_embeddings },
time_steps = time_steps
)
GNN["last_states"] = last_states
V_n = last_states['V'].h
C_n = last_states['C'].h
# Compute a vote for each embedding
V_vote = tf.reshape(V_vote_MLP(V_n), [-1])
# Add Batch Normalization layer before activation function
V_vote = tf.keras.layers.BatchNormalization()(V_vote)
# Compute the number of problems in the batch
num_problems = tf.shape(n_vertices)[0]
# Compute a logit probability for each problem
pred_logits = tf.while_loop(
lambda i, pred_logits: tf.less(i, num_problems),
lambda i, pred_logits:
(
(i+1),
pred_logits.write(
i,
tf.reduce_mean(V_vote[tf.reduce_sum(n_vertices[0:i]):tf.reduce_sum(n_vertices[0:i])+n_vertices[i]])
)
),
[0, tf.TensorArray(size=num_problems, dtype=tf.float32)]
)[1].stack()
# Add sigmoid activation function
pred_logits = tf.keras.activations.sigmoid(pred_logits)
# Assign predictions to dictionary
GNN['predictions'] = pred_logits
在添加Batch Normalization层之后,需要在它之前应用激活函数之前。这是因为Batch Normalization层的设计是在激活函数之前应用,以确保激活函数输入的值的均值和方差都接近于1和0。在你的代码中,你需要将GNN['predictions']从sigmoid函数改为pred_logits,因为sigmoid函数已经添加到了while循环体内。
至于你遇到的ValueError: ('Input has undefined axis dimension. Input shape: ', TensorShape([None]))问题,
这个错误通常出现在在输入张量的形状中有一个轴的维度为None,这会导致TensorFlow无法推断张量的形状。通常这个问题可以通过在定义输入张量时明确指定维度大小来解决。下面是一些可能导致这个错误的情况:
1 数据的维度不匹配。例如,如果您的代码需要输入一批图像,但是在输入中有一些图像大小不同,就会导致这个错误。
2 在代码的某个位置,您可能没有正确处理输入张量的形状,导致某个维度的大小变为None。
1、我印象这个在Gpt可以找到回答;
2、有其他的关于这个问题的回答问题可以参考
该回答引用chatgpt:
首先,关于模型训练过程中loss变化的问题,这可能是由于使用的RNN循环次数过多,导致模型在训练初期无法正确地更新参数。这种现象称为“梯度消失”或“梯度爆炸”。您可以尝试减少RNN循环次数或使用更先进的优化器来缓解这个问题。
其次,如果您想在最后一层激活函数sigmoid之前添加批量归一化(Batch Normalization,BN)层,可以使用TensorFlow提供的BatchNormalization函数。您可以将BN层添加到最后一层的输出之前,并将激活函数放在BN层之后。例如:
# Add a Batch Normalization layer
bn_layer = tf.keras.layers.BatchNormalization()(output_of_last_layer)
# Add the activation function after the BN layer
output = tf.keras.activations.sigmoid(bn_layer)
注意,添加BN层后,您需要重新训练模型以使其适应新的层结构。
引用chatGPT作答,对于第一个问题,由于在循环次数为32时,loss会由很大的值逐渐变为较小的值,这表明模型可能存在梯度爆炸的问题,即在反向传播过程中,梯度可能变得非常大,导致无法稳定地更新模型的参数。因此,您可以尝试使用梯度裁剪来限制梯度大小,或者尝试减小循环次数。
对于第二个问题,您可以在最后一层激活函数sigmoid之前添加BN层,如下所示:
# Define the BN layer
bn_layer = tf.keras.layers.BatchNormalization()
# Get the last embeddings
last_states = gnn(
{ "M": M_matrix, "VC": VC_matrix, 'chrom_number': chrom_number },
{ "V": vertex_initial_embeddings, "C": colors_initial_embeddings },
time_steps = time_steps
)
GNN["last_states"] = last_states
V_n = last_states['V'].h
C_n = last_states['C'].h
# Compute a vote for each embedding
V_vote = tf.reshape(V_vote_MLP(V_n), [-1])
# Add BN layer before the final sigmoid activation function
V_vote = bn_layer(V_vote)
V_vote = tf.keras.activations.sigmoid(V_vote)
# Compute the number of problems in the batch
num_problems = tf.shape(n_vertices)[0]
# Compute a logit probability for each problem
pred_logits = tf.while_loop(
lambda i, pred_logits: tf.less(i, num_problems),
lambda i, pred_logits:
(
(i+1),
pred_logits.write(
i,
tf.reduce_mean(V_vote[tf.reduce_sum(n_vertices[0:i]):tf.reduce_sum(n_vertices[0:i])+n_vertices[i]])
)
),
[0, tf.TensorArray(size=num_problems, dtype=tf.float32)]
)[1].stack()
# Convert logits into probabilities
GNN['predictions'] = tf.sigmoid(pred_logits)
在代码中添加了一个BatchNormalization层,然后使用sigmoid激活函数对其进行了激活,以生成最终的预测。请注意,BatchNormalization层应该在激活函数之前添加。