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

Keras SimpleRNNCell状态权重未参与训练问题排查

TensorFlow中SimpleRNNCell状态权重不更新问题

问题描述

在TensorFlow的Keras框架中使用SimpleRNNCell实现基础循环神经网络时,出现了状态权重始终保持初始值1.0未更新的异常情况:仅包含一个RNN单元和Dense层的极简模型训练后,输入权重、偏置、Dense层权重均正常变化,唯独状态权重无更新,导致循环机制失效。

复现代码

import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import RNN
from tensorflow.keras.layers import SimpleRNN, SimpleRNNCell
from sklearn.preprocessing import MinMaxScaler
from tensorflow import random as rnd

# 固定随机种子
rnd.set_seed(0)

# 数据集为MackeyGlass_t17.txt
data = np.loadtxt('MackeyGlass_t17.txt')

# 归一化处理
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(data.reshape(-1, 1))

# 划分训练集与测试集
train, test = scaled[0:-100], scaled[-100:]

# 划分输入与输出
train_X, train_y = train[:-1], train[1:]
test_X, test_y = test[:-1], test[1:] 

# 调整输入形状
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))

# 训练参数
batch_size = 20
epochs = 2

# 构建并训练模型
model = Sequential()
model.add(RNN(SimpleRNNCell(1)))
# model.add(SimpleRNN(1))) # 与上面一行效果一致
model.add(Dense(train_y.shape[1]))
model.compile(loss='huber', optimizer='adam')
model.fit(train_X, train_y, epochs=epochs, batch_size=batch_size, validation_data=(test_X, test_y), verbose=0, shuffle=False)

# 打印各层权重
for layer in model.layers: print(layer.get_weights())

初始运行结果

运行2个epoch的输出:

[array([[-0.8942287]], dtype=float32), array([[1.]], dtype=float32), array([0.05435111], dtype=float32)]
[array([[-1.272426]], dtype=float32), array([0.04711587], dtype=float32)]

运行3个epoch的输出:

[array([[-0.89395165]], dtype=float32), array([[1.]], dtype=float32), array([0.06734365], dtype=float32)]
[array([[-1.2927996]], dtype=float32), array([0.05247825], dtype=float32)]

注:由于是标量序列且仅一个RNN单元,权重矩阵/向量简化为单个元素,共5个权重:输入权重、状态权重、输入偏置、Dense层权重、Dense层偏置,仅状态权重未更新。

环境信息

Ubuntu 20.04, Python 3.9.15, Tensorflow 2.7.0, 无GPU加速

修正后的代码与结果

将原数据处理部分替换为以下代码:

def get_XY(dat, time_steps):
    # 目标数组索引
    Y_ind = np.arange(time_steps, len(dat), time_steps)
    Y = dat[Y_ind]
    # 准备输入数据X
    rows_x = len(Y)
    X = dat[range(time_steps*rows_x)]
    X = np.reshape(X, (rows_x, time_steps, 1))    
    return X, Y
 
time_steps = 12
train_X, train_y = get_XY(train, time_steps)
test_X, test_y = get_XY(train, time_steps)

运行3个epoch后的输出:

[array([[-0.63304466]], dtype=float32), array([[0.9038045]], dtype=float32), array([0.06537308], dtype=float32)]
[array([[-0.97942555]], dtype=float32), array([-0.07855547], dtype=float32)]

问题

为何初始实现中训练过程未影响状态权重?代码是否存在明显错误?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:03:36