TensorFlow图神经网络报错:SparseTensor无法转为Tensor求解决
TensorFlow 2.x运行GCN代码时SparseTensor转Tensor报错解决方案
报错信息
TypeError: Failed to convert object of type <class 'TensorFlow.python.framework.sparse_tensor.SparseTensor'> to Tensor. Contents: SparseTensor(indices=Tensor("DeserializeSparse:0", shape=(None, 2), dtype=int64), values=Tensor("DeserializeSparse:1", shape=(None,), dtype=float32), dense_shape=Tensor("stack:0", shape=(2,), dtype=int64)). Consider casting elements to a supported type.
环境信息
- Python 3.6
- TensorFlow 2.6.2
- Keras 2.6.0
运行代码
import numpy as np import tensorflow from tensorflow.python.keras.callbacks import ModelCheckpoint from tensorflow.python.keras.layers import Lambda from tensorflow.python.keras.models import Model from tensorflow.python.keras.optimizer_v1 import adam from tensorflow.python.keras.optimizers import adam_v2 import tensorflow as tf import sklearn from sklearn.feature_extraction.text import CountVectorizer from gcn import GCN from utils import preprocess_adj, plot_embeddings, load_data_v1 if __name__ == "__main__": physical_devices = tf.config.experimental.list_physical_devices('GPU') if len(physical_devices) > 0: for k in range(len(physical_devices)): tf.config.experimental.set_memory_growth(physical_devices[k], True) print('memory growth:', tf.config.experimental.get_memory_growth(physical_devices[k])) else: print("Not enough GPU hardware devices available") FEATURE_LESS = False print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU'))) A, features, y_train, y_val, y_test, train_mask, val_mask, test_mask = load_data_v1( 'cora') A = preprocess_adj(A) features /= features.sum(axis=1, ).reshape(-1, 1) if FEATURE_LESS: X = np.arange(A.shape[-1]) feature_dim = A.shape[-1] else: X = features feature_dim = X.shape[-1] model_input = [X, A] # Compile model model = GCN(A.shape[-1], feature_dim, 16, y_train.shape[1], dropout_rate=0.5, l2_reg=2.5e-4, feature_less=FEATURE_LESS, ) model.compile(optimizer=adam_v2.Adam(0.01), loss='categorical_crossentropy', weighted_metrics=['categorical_crossentropy', 'acc']) NB_EPOCH = 200 PATIENCE = 200 # early stopping patience val_data = (model_input, y_val, val_mask) mc_callback = ModelCheckpoint('./best_model.h5', monitor='val_weighted_categorical_crossentropy', save_best_only=True, save_weights_only=True) # train print("start training") model.fit(model_input, y_train, sample_weight=train_mask, validation_data=val_data, batch_size=A.shape[0], epochs=NB_EPOCH, shuffle=False, verbose=2, callbacks=[mc_callback]) # test model.load_weights('./best_model.h5') eval_results = model.evaluate( model_input, y_test, sample_weight=test_mask, batch_size=A.shape[0]) print('Done.\n' 'Test loss: {}\n' 'Test weighted_loss: {}\n' 'Test accuracy: {}'.format(*eval_results)) embedding_model = Model(model.input, outputs=Lambda(lambda x: model.layers[-1].output)(model.input)) embedding_weights = embedding_model.predict(model_input, batch_size=A.shape[0]) y = np.genfromtxt("{}{}.content".format('../data/cora/', 'cora'), dtype=np.dtype(str))[:, -1] plot_embeddings(embedding_weights, np.arange(A.shape[0]), y)
解决方案
报错核心是preprocess_adj函数返回了SparseTensor,但Keras模型无法直接将其转换为普通Tensor,以下是两种可行解决思路:
思路1:转换为稠密Tensor(小数据集适用)
在预处理邻接矩阵后,添加代码将稀疏矩阵转为稠密矩阵:
A = preprocess_adj(A) # 新增:将SparseTensor转为稠密矩阵 A = tf.sparse.to_dense(A).numpy()
注意:数据集过大时(节点数超10000),稠密矩阵会占用大量内存,不建议使用此方法。
思路2:修改GCN模型适配SparseTensor(大数据集推荐)
保留稀疏矩阵以节省内存,需要调整GCN层实现:
- 前向传播中用
tf.sparse.sparse_dense_matmul()替代普通tf.matmul,处理稀疏邻接矩阵与特征矩阵的乘法 - 模型输入层明确声明支持SparseTensor,用
tf.keras.Input(..., sparse=True)定义输入
额外优化建议
- 检查
load_data_v1和preprocess_adj函数,确保返回格式适配TensorFlow 2.x(很多老GCN代码基于TF1.x编写,需做版本兼容) - 统一使用
tf.keras模块,避免混用tensorflow.python.keras,减少兼容性问题,例如将from tensorflow.python.keras.callbacks import ModelCheckpoint改为from tensorflow.keras.callbacks import ModelCheckpoint
内容的提问来源于stack exchange,提问作者LUKAS
相关产品推荐
相关产品推荐

