You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Keras转ONNX时的'NoneType' object is not subscriptable错误

Keras含LSTM模型转ONNX报错解决方案

环境信息

  • Python 3.8
  • TensorFlow==2.2.0
  • Keras==2.4.0
  • 问题:使用keras2onnx转换含LSTM节点的Keras模型时触发TypeError: 'NoneType' object is not subscriptable,手动指定input_shape无效

模型构建代码

import keras
from keras import models 
import numpy as np
from keras import layers
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Dense, Dropout, LSTM, BatchNormalization, Activation, Embedding
from keras import callbacks

tf.keras.backend.set_floatx('float64')
# 读取打乱后的数据
dataread = DataReader()
data_array, fin_risk = dataread.get_shuffle_data()

batchsz = 1024  # 批次大小
val_size = 1800  # 验证集大小

train_db = tf.data.Dataset.from_tensor_slices((data_array[val_size:, :, :], fin_risk[val_size:]))   # 划分训练集
val_db = tf.data.Dataset.from_tensor_slices((data_array[:val_size, :, :], fin_risk[:val_size]))    # 划分验证集
train_db = train_db.batch(batchsz)
val_db = val_db.batch(batchsz)
print(train_db)  # 输出:((None, 23, 102), (None,)), types: (tf.float64, tf.float64)
print(val_db)

model = Sequential()
model.add(Dense(10))
#model.add(BatchNormalization())
model.add(LSTM(units, input_shape=(None,3,6), return_sequences=True, activation="tanh"))
#model.add(LSTM(units, dropout=0.2, return_sequences=True, unroll=True))
model.add(LSTM(units, activation="tanh"))
#model.add(BatchNormalization())
model.add(Dense(10, activation='tanh'))
model.add(Dense(1))

ONNX转换代码

import onnx
import keras2onnx
from keras import backend as K
from keras.models import load_model

onnx_model_name = 'N_256_T3.onnx'
model = load_model('logs/last3.h5')
onnx_model = keras2onnx.convert_keras(model, model.name)
onnx.save_model(onnx_model, onnx_model_name)

错误信息

tf executing eager_mode: True
tf.keras model eager_mode: False
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [1], line 11
      8 onnx_model_name = 'N_256_T3.onnx'
     10 model = load_model('logs/last3.h5')
---> 11 onnx_model = keras2onnx.convert_keras(model, model.name)
     12 onnx.save_model(onnx_model, onnx_model_name)

File ~\Anaconda3\envs\python_3_8_backup\lib\site-packages\keras2onnx\main.py:62, in convert_keras(model, name, doc_string, target_opset, channel_first_inputs, debug_mode, custom_op_conversions)
     60 output_dict = {}
     61 if is_tf2 and is_tf_keras:
---> 62     tf_graph = build_layer_output_from_model(model, output_dict, input_names, output_names)
     63 else:
     64     tf_graph = model.outputs[0].graph if is_tf2 else keras.backend.get_session().graph

File ~\Anaconda3\envs\python_3_8_backup\lib\site-packages\keras2onnx\_parser_tf.py:304, in build_layer_output_from_model(model, output_dict, input_names, output_names)
    302     return extract_outputs_from_subclassing_model(model, output_dict, input_names, output_names)
    303 else:
--> 304     graph = model.outputs[0].graph
    305     output_names.extend([n.name for n in model.outputs])
    306     output_dict.update(extract_outputs_from_inbound_nodes(model))

TypeError: 'NoneType' object is not subscriptable

解决方案

核心原因

报错是因为模型加载后model.outputs为空——Keras模型需要至少完成一次前向传播(即输入数据跑一次预测/推理),才能确定输入输出节点的形状和图结构,否则保存的模型缺少必要的图信息,导致转换工具无法解析。

具体修复步骤

1. 训练阶段确保模型完成前向传播再保存

在训练代码中,添加示例输入执行一次预测,再保存模型:

# 生成符合输入形状的示例数据(对应你的输入(23,102))
dummy_input = np.random.randn(1, 23, 102).astype(np.float64)
# 执行一次前向传播,让Keras确定模型的输入输出结构
model.predict(dummy_input)
# 之后再保存模型
model.save('logs/last3.h5')

2. 修正模型定义的input_shape错误

原模型中第一层Dense未指定input_shape,且LSTM的input_shape(None,3,6)与实际输入(23,102)不匹配,修正如下:

model = Sequential()
# 第一层指定正确的输入形状:(时间步长, 特征数),对应你的数据(23,102)
model.add(Dense(10, input_shape=(23, 102)))
model.add(LSTM(units, return_sequences=True, activation="tanh"))
model.add(LSTM(units, activation="tanh"))
model.add(Dense(10, activation='tanh'))
model.add(Dense(1))

注意:LSTM层不需要手动指定batch维度,只需要传入(时间步长, 特征数)即可。

3. 已保存模型的补救方法

如果不想重新训练,加载模型后手动执行一次前向传播再转换:

import onnx
import keras2onnx
from keras.models import load_model
import tensorflow as tf

onnx_model_name = 'N_256_T3.onnx'
model = load_model('logs/last3.h5')
# 传入符合形状的示例输入,触发模型构建
dummy_input = tf.random.uniform((1, 23, 102), dtype=tf.float64)
model(dummy_input)
# 再执行转换
onnx_model = keras2onnx.convert_keras(model, model.name)
onnx.save_model(onnx_model, onnx_model_name)

4. 替换转换工具(推荐)

keras2onnx对TensorFlow 2.x早期版本兼容性一般,建议使用tf2onnx替代,对TF2.x的支持更完善:

import tf2onnx
import tensorflow as tf
from keras.models import load_model

model = load_model('logs/last3.h5')
# 定义输入签名,指定形状和数据类型
spec = (tf.TensorSpec((None, 23, 102), tf.float64, name="input"),)
output_path = "N_256_T3.onnx"
# 执行转换
tf2onnx.convert.from_keras(model, input_signature=spec, output_path=output_path)

内容的提问来源于stack exchange,提问作者ELI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:50:46