优化神经网络:从含高斯噪声数组预测平滑函数数组及解决报错
解决你的神经网络去噪问题:形状兼容与准确率优化
一、先搞定预测时的形状不兼容错误
你碰到的这个形状问题其实很好理解:模型构建时定义的输入形状是(None, 99)(None代表批量大小),但你传入的[noisy_data[0]]实际被解析成了形状为(None, 1)的输入——因为noisy_data[0]是一维数组(99,),直接用列表包裹会让Keras把每个元素当成单独样本,每个样本只有1个特征。
解决方法很简单,只要给输入扩展一个批量维度就行:
# 方法1:用reshape调整形状 model.predict(noisy_data[0].reshape(1, 99)) # 方法2:用np.expand_dims添加维度 model.predict(np.expand_dims(noisy_data[0], axis=0))
这样输入形状就变成了(1,99),和模型期望的输入完全匹配,错误自然就消失了。
二、为什么准确率始终为0?核心问题:任务类型完全匹配错了
你的任务是回归任务(从含噪声的连续值数组预测平滑的连续值数组),但你全程按照分类任务来搭建模型,这是准确率为0的根本原因:
- 损失函数选错:
categorical_crossentropy是给多分类任务用的,回归任务需要用连续值损失,比如mean_squared_error(MSE,均方误差,最常用)或者mean_absolute_error(MAE,平均绝对误差)。 - 最后一层激活函数错误:
softmax会把输出归一化成概率分布(所有输出之和为1),这是分类任务的专属操作,回归任务最后一层应该用线性激活(也就是不指定激活函数,Keras默认就是linear),因为我们要预测的是连续的数值。 - 评估指标选错:
accuracy是分类任务的指标,用来衡量预测类别和真实类别的匹配度,对回归任务完全没用,所以你看到的准确率0是正常现象——这个指标根本不适合你的任务,应该换成mse或者mae这类回归指标。
三、优化后的模型代码
把模型改成适合回归任务的结构,直接替换原来的模型构建代码就行:
model = tf.keras.models.Sequential() model.add(tf.keras.layers.Flatten(input_shape=(99,))) # 输入层没问题,保持99维样本 model.add(tf.keras.layers.Dense(768, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(768, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(99)) # 去掉softmax,用默认的线性激活 model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_squared_error']) # 可以加验证集观察泛化效果 model.fit(x_train, y_train, epochs=20, validation_split=0.1)
四、额外的小优化建议
- 数据生成的小改进:你现在生成的
pure_data所有样本都是完全一样的(每个循环都是生成固定的np.log(j)数组),可以给底层函数加一些随机变化,让模型学习更通用的去噪能力:
for i in tqdm(range(10000)): scale = np.random.uniform(0.8, 1.2) # 随机缩放因子 offset = np.random.uniform(-0.1, 0.1) # 随机偏移 array = scale * np.log(time) + offset noise = np.random.normal(0, 1/10, 99) pure_data.append(array) noisy_data.append(array + noise)
- 模型结构升级:你的数据是按时间步排列的序列,用CNN或LSTM这类适合序列数据的模型,会比全连接网络的去噪效果更好,比如简单的一维CNN结构:
model = tf.keras.models.Sequential() model.add(tf.keras.layers.Reshape((99, 1), input_shape=(99,))) # 转成(99,1)的序列格式 model.add(tf.keras.layers.Conv1D(32, 3, padding='same', activation='relu')) model.add(tf.keras.layers.Conv1D(32, 3, padding='same', activation='relu')) model.add(tf.keras.layers.Conv1D(1, 3, padding='same')) model.add(tf.keras.layers.Flatten()) model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mean_squared_error'])
五、验证优化效果
修改后训练时,你会看到MSE损失逐渐下降(而不是之前的持续上升),这说明模型在真正学习去噪能力。预测时用正确的输入形状,就能得到和pure_data维度一致的平滑输出了。
内容的提问来源于stack exchange,提问作者user142756
相关产品推荐
相关产品推荐

