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

创建TensorFlow TimeDistributed层时触发floating point exception报错求解

问题情况
  • 报错类型:floating point exception,无堆栈追踪
  • 崩溃触发点:执行distributed_cnn = tf.keras.layers.TimeDistributed(cnn_model)(input_layer)时,模型call函数运行两次后程序崩溃
  • 完整代码如下:
import os
import sys
from typing import Counter
import tensorflow as tf
import numpy as np
from tensorflow.keras import models, layers, callbacks
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.datasets import mnist
from matplotlib import pyplot as plt

# Change this to the location of the database directories
DB_DIR = os.path.dirname(os.path.realpath(__file__))

# Import databases
sys.path.insert(1, DB_DIR)
from db_utils import get_imdb_dataset, get_speech_dataset, get_single_digit_dataset

def Secure_Voice_Channel(func):
    """Define Secure_Voice_Channel decorator."""
    def execute_func(*args, **kwargs):
        print('Established Secure Connection.')
        returned_value = func(*args, **kwargs)
        print("Ended Secure Connection.")

        return returned_value

    return execute_func

@Secure_Voice_Channel
class generic_vns_function(tf.keras.Model):
    def __init__(self, input_shape, layers, layer_units): 
        super().__init__() 
        self.convolutions = []

        # Dynamically create Convolutional layers and MaxPools
        for layer in range(len(layers)):
            self.convolutions.append(tf.keras.layers.Conv2D(layer, 3, padding="same", input_shape=input_shape, activation="relu"))

        # Add MaxPooling layer
        self.convolutions.append(tf.keras.layers.MaxPooling2D((2,2)))
        
        # Flatten 
        self.flatten = tf.keras.layers.Flatten()
        
        # Dense layer 
        self.dense1 = tf.keras.layers.Dense(1024, activation="relu")

        
    def call(self, input):
        x = input

        for layer in self.convolutions:
            x = layer(x)

        x = self.flatten(x)
        x = self.dense1(x)

        return x

def train_model(model, epochs, batch_size, X_train, y_train, X_test, y_test):
    """Generic Deep Learning Model training function."""
    cb = [callbacks.EarlyStopping(monitor='val_loss', patience=3)]
    model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs,
              batch_size=batch_size, verbose=1, callbacks=cb)
    scores = model.evaluate(X_test, y_test, verbose=2)

    print("Baseline Error: %.2f%%" % (100-scores[1]*100))

    return model

def choose_dataset(dataset_type):
    """Select dataset based on string variable."""
    if dataset_type == "nlp":
        return get_imdb_dataset(dir=DB_DIR)
    elif dataset_type == "computer_vision":
        (X_train, y_train), (X_test, y_test) = mnist.load_data()
    elif dataset_type == "speech_recognition":
        # (X_train, y_train), (X_test, y_test), (_, _) = get_speech_dataset()
        (X_train, y_train), (X_test, y_test), (_, _) = get_single_digit_dataset(0)        

    else:
        raise ValueError("Couldn't find dataset.")

    (X_train, X_test) = normalize_dataset(dataset_type, X_train, X_test)

    (X_train, y_train), (X_test, y_test) = reshape_dataset(X_train, y_train, X_test, y_test)

    return (X_train, y_train), (X_test, y_test)

def normalize_dataset(string, X_train, X_test):
    """Normalize speech recognition and computer vision datasets."""
    if string == "computer vision":
        X_train = X_train / 255
        X_test = X_test / 255
    else:
        mean = np.mean(X_train)
        std = np.std(X_train)
        X_train = (X_train-std)/mean
        X_test = (X_test-std)/mean

    return (X_train, X_test)

def reshape_dataset(X_train, y_train, X_test, y_test):
    """Reshape Computer Vision and Speech datasets."""

    y_train = to_categorical(y_train)
    y_test = to_categorical(y_test)

    return (X_train, y_train), (X_test, y_test)

def create_LSTM(cnn_model, input_shape, num_classes):
    input_layer = layers.Input(shape=input_shape)
    distributed_cnn = tf.keras.layers.TimeDistributed(cnn_model)(input_layer)

    x, state_a, state_b = layers.LSTM(distributed_cnn)
    output = layers.Dense(num_classes, activation="softmax")(x)

    model = models.Model(inputs=input_layer, outputs=output)

    opt = Adam()
    model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])

    return model

def main():

    # Hyperparameters
    layers = [64, 32]
    layer_units = 1000
    epochs = 10
    batch_size = 200
    lr = 0.001
    filter = 64
    kernal_size = 3
    window = 3

    dataset = "speech_recognition"

    # Import Datasets
    (X_train, y_train), (X_test, y_test) = choose_dataset(dataset)

    num_classes = y_train.shape[1]

    # Reshape both the train and test dataset
    X_train = X_train.reshape(X_train.shape[0], window, int(X_train.shape[1]/window), X_train.shape[2], 1)
    X_test = X_test.reshape(X_test.shape[0], window, int(X_test.shape[1]/window), X_test.shape[2], 1)

    # Generate CNN model
    cnn_model = generic_vns_function(X_train.shape[1:], layers, layer_units)
    print("Created generic CNN model")

    # Create the LSTM CNN with time distributed layer
    model = create_LSTM(cnn_model, X_train.shape[1:], num_classes)
    print("Created LST model")

    trained_model = train_model(model, epochs, batch_size, X_train, y_train, X_test, y_test)

    save_format="tf"
    # # Save model to h5 file
    trained_model.save(save_format, 'models/model_%s_a3.h5' % dataset)

    return None
问题根因分析
  1. 卷积层参数配置错误(核心触发浮点异常的原因)
    generic_vns_function类初始化时,循环创建卷积层的参数写错:原代码循环用for layer in range(len(layers)):,传入Conv2D的第一个参数是循环变量layer,也就是当layers为[64,32]时,两次循环传入的滤波器数量是0、1,第一层卷积输出通道数为0,后续计算涉及除以通道数、矩阵维度匹配时直接触发除以0的浮点异常。
  2. LSTM层调用不符合API规范
    layers.LSTM的第一个参数是隐藏层单元数(整数),原代码直接传入张量distributed_cnn作为初始化参数,属于API使用错误,会触发张量维度、参数类型异常。
  3. 数据归一化逻辑双重错误
  • 字符串匹配错误:choose_dataset传入的分类标识是computer_vision(下划线分隔),normalize_dataset中判断条件是computer vision(空格分隔),导致所有数据集都走标准差归一化逻辑
  • 归一化公式错误:正确的Z-score标准化公式为(样本值-均值)/标准差,原代码写为(样本值-标准差)/均值,同时未做标准差为0的防护,容易出现除0异常
  1. Keras模型子类被错误装饰
    自定义模型类generic_vns_function被普通函数装饰器@Secure_Voice_Channel修饰,破坏了Keras Model类的继承链和内部初始化逻辑,导致张量追踪、前向传播调用出现未知异常。
  2. 模型保存API使用错误
    model.save的第一个参数为保存路径,原代码将save_format="tf"作为第一个参数传入,参数顺序完全错误。
修复方案
  • 修正卷积层参数:将卷积层创建代码改为
for i in range(len(layers)):
    self.convolutions.append(tf.keras.layers.Conv2D(layers[i], 3, padding="same", activation="relu"))

input_shape不需要给卷积层单独传,子类模型会自动推断输入形状。

  • 修正LSTM层调用:将create_LSTM中的LSTM部分改为
# 可根据需求调整units的数值
x = layers.LSTM(units=256)(distributed_cnn)
# 若需返回状态则开启return_state参数
# x, state_a, state_b = layers.LSTM(units=256, return_state=True)(distributed_cnn)
  • 修正归一化逻辑:
def normalize_dataset(string, X_train, X_test):
    """Normalize speech recognition and computer vision datasets."""
    if string == "computer_vision":
        X_train = X_train / 255.0
        X_test = X_test / 255.0
    else:
        mean = np.mean(X_train)
        std = np.std(X_train) + 1e-8 # 加极小值避免除0
        X_train = (X_train - mean) / std
        X_test = (X_test - mean) / std
    return (X_train, X_test)
  • 移除模型类上的@Secure_Voice_Channel装饰器,若需要安全日志可以在call方法首尾加打印语句,或者在模型训练/推理的调用外层加装饰器。
  • 修正模型保存代码:
# 保存为h5格式
trained_model.save('models/model_%s_a3.h5' % dataset, save_format='h5')
# 若保存为tf SavedModel格式
# trained_model.save('models/model_%s_a3_tf' % dataset, save_format='tf')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:24:08