基于Conv-LSTM的药物对交互分类数据格式及报错求助
药物对交互分类:Conv-LSTM输入格式修正及模型优化
核心错误原因分析
你遇到的ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type float),本质是输入数据的维度、类型不匹配模型要求,同时你的模型定义存在冗余逻辑,导致输入输出不兼容。
一、输入数据(train_x/train_y)的正确处理方式
1. 药物对Embedding的拼接与维度调整
你的数据是药物对形式,每个药物有300维embedding,需将两个药物的embedding拼接成模型可接受的序列输入:
import numpy as np # 假设embedding_df包含drug1_emb和drug2_emb列,每列是300维数组 # 拼接后每个样本形状为(2, 300),代表2个药物(时间步),每个步长300维特征 train_x = np.array([np.stack([d1, d2]) for d1, d2 in zip(embedding_df['drug1_emb'], embedding_df['drug2_emb'])]) # 强制转换为TensorFlow支持的float32类型 train_x = train_x.astype(np.float32)
- 原模型输入定义
(1, 300)不符合药物对场景,需改为(2, 300),对应两个药物的序列输入。
2. 标签(train_y)的格式修正
根据损失函数选择对应标签格式:
- 若用
binary_crossentropy(二分类推荐),直接保留0/1的一维整数数组,转换为float32:train_y = train_y.astype(np.float32) - 若用
categorical_crossentropy,需做one-hot编码:from tensorflow.keras.utils import to_categorical train_y = to_categorical(train_y, num_classes=2).astype(np.float32)
二、Conv-LSTM模型定义修正
原模型存在冗余未使用层,且输入输出维度不匹配,以下是优化后的版本:
from tensorflow.keras.layers import Input, Conv1D, BatchNormalization, MaxPooling1D, LSTM, Dropout, Dense from tensorflow.keras.models import Model from tensorflow.keras.regularizers import L1L2 def Conv_LSTM(num_classes, reg): # 输入形状适配药物对:(样本数, 时间步=2, 特征维度=300) input_layer = Input(shape=(2, 300)) # 卷积层提取序列局部特征(核大小设为1,适配短序列) conv1 = Conv1D(filters=32, kernel_size=1, strides=1, activation='relu', padding='same', kernel_regularizer=reg)(input_layer) bn1 = BatchNormalization()(conv1) pool1 = MaxPooling1D(pool_size=1, strides=1, padding='same')(bn1) conv2 = Conv1D(filters=32, kernel_size=1, strides=1, activation='relu', padding='same', kernel_regularizer=reg)(pool1) bn2 = BatchNormalization()(conv2) # LSTM层捕捉序列依赖关系 lstm1 = LSTM(128, return_sequences=True, kernel_regularizer=reg)(bn2) do3 = Dropout(0.5)(lstm1) lstm2 = LSTM(64, kernel_regularizer=reg)(do3) do4 = Dropout(0.2)(lstm2) # 输出层:二分类用sigmoid,多分类用softmax if num_classes == 2: output_layer = Dense(1, activation='sigmoid')(do4) else: output_layer = Dense(num_classes, activation='softmax')(do4) model = Model(inputs=input_layer, outputs=output_layer) return model
修正要点:
- 删除
fl、rv、flat等未使用的冗余层 - 调整卷积核大小为1,适配仅2个时间步的药物对序列
- 二分类场景用
sigmoid激活更高效,避免softmax的冗余计算 - 将正则化器应用到卷积和LSTM层,抑制过拟合
三、训练函数修正
import tensorflow as tf from tensorflow.keras.callbacks import TensorBoard from time import time def model_train(model, number_epoch, train_x, train_y, sample_weights=None): # 根据输出层自动匹配损失函数 loss_fn = 'binary_crossentropy' if model.output_shape[-1] == 1 else 'categorical_crossentropy' # 降低学习率,避免模型震荡不收敛 optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.001, rho=0.9) model.compile(loss=loss_fn, metrics=['accuracy'], optimizer=optimizer) tensorboardRNN = TensorBoard(log_dir="RNN_logs/{}".format(time())) history1 = model.fit( train_x, train_y, validation_split=0.1, callbacks=[tensorboardRNN], batch_size=32, class_weight=sample_weights, epochs=int(number_epoch), shuffle=True # 训练时打乱数据,避免学习顺序依赖 ) print(model.summary()) return model, history1
修正要点:
- 动态匹配损失函数,适配二分类/多分类场景
- 将学习率从0.01降至0.001,提升模型稳定性
- 给
sample_weights设置默认值,避免未传入时报错 - 开启
shuffle=True,优化训练效果
四、调用代码修正
reg = L1L2(l1=0.01, l2=0.01) model = Conv_LSTM(num_classes=2, reg=reg) model.summary() # 确保train_x和train_y已按上述方式处理完成 convLSTM, history = model_train(model, number_epoch=20, train_x=train_x, train_y=train_y)
额外排查要点
- 检查embedding格式:若
embedding_df中的embedding是字符串类型,需先转换为numpy数组:embedding_df['drug1_emb'] = embedding_df['drug1_emb'].apply(lambda x: np.fromstring(x.strip('[]'), sep=',', dtype=np.float32)) - 验证输入形状:
train_x应为(样本数, 2, 300),train_y应为(样本数, 1)(sigmoid)或(样本数, 2)(softmax) - 强制类型转换:若仍有类型错误,执行
train_x = np.asarray(train_x, dtype=np.float32)
内容的提问来源于stack exchange,提问作者Dalel Rais
相关产品推荐
相关产品推荐

