卫星观测数据零值干扰处理:LSTM+MLP模型Masking/Embedding应用咨询
卫星观测数据建模零值处理指导
我使用卫星观测数据集开展建模工作,该数据集包含大量零值,严重影响最终模拟结果。我设置了两类输入数据:
- 动态时序数据(
X_dynamic_LSTM.shape为(95931, 1, 5))采用LSTM处理 - 静态数据(
X_static_MLP.shape为(95931, 10))采用MLP处理
将两者拼接后通过另一MLP输出最终结果。我了解Masking和Embedding技术,但不清楚如何在代码中正确添加以忽略预测数据框中的零值变量,现有代码如下:
from tensorflow.keras.layers import Input, LSTM, Dense, Concatenate from tensorflow.keras.models import Model from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Masking from tensorflow.keras.layers import Dropout from tensorflow.keras.layers import Embedding lstm_input = Input(shape=(X_dynamic_LSTM.shape[1], X_dynamic_LSTM.shape[2])) x = Masking(mask_value=0.)(lstm_input) x = LSTM(70, activation='tanh', return_sequences=True)(x) x = Dropout(0.3)(x) x = LSTM(35)(x) x = Dropout(0.3)(x) x = Dense(1, activation='tanh')(x) #mlp input with additonal 3 variables at t=t mlp_input=Input(shape=(X_static_MLP.shape[1])) mlp = Dense(30, activation='relu')(mlp_input) mlp = Dense(20, activation='relu')(mlp) merge = Concatenate()([x, mlp]) hidden1 = Dense(5, activation='relu')(merge) mlp_out = Dense(1, activation='relu')(hidden1) model = Model(inputs=[lstm_input, mlp_input],outputs=mlp_out) #compile the model model.compile(loss='mae', optimizer='adam') #fit the model model.fit([X_dynamic_LSTM, X_static_MLP], y_train, batch_size=40, epochs=10, validation_split=0.2)
零值处理优化方案
1. LSTM时序数据的Masking(你已实现,补充注意点)
你已经给LSTM输入添加了Masking(mask_value=0.),这部分逻辑是正确的,需要确认两点:
- 这些零值确实是无效缺失值,而非有实际物理意义的数值(比如观测到的0值)
- 由于你的时序长度只有1步(
shape[1]=1),Masking的效果不会太明显,但如果后续扩展时序长度,该层会自动跳过零值对应的时间步计算
2. 静态数据的零值处理(代码缺失部分)
Keras原生Masking层主要针对时序数据,静态数据的零值需要单独处理,提供两种实用方法:
方法一:自定义Lambda层屏蔽零值
通过将零值替换为极小值,利用ReLU激活函数的特性将其置为0,相当于忽略该特征的影响:
from tensorflow.keras.layers import Lambda import tensorflow as tf def mask_static_input(x): # 把零值替换为-1e9,ReLU激活后会被置为0 masked = tf.where(tf.equal(x, 0.), tf.constant(-1e9, dtype=tf.float32), x) return masked
把这段函数加入你的MLP分支:
mlp_input=Input(shape=(X_static_MLP.shape[1])) # 添加静态数据零值屏蔽 masked_mlp_input = Lambda(mask_static_input)(mlp_input) mlp = Dense(30, activation='relu')(masked_mlp_input) mlp = Dense(20, activation='relu')(mlp)
方法二:Embedding层处理类别型静态特征
如果静态数据中的零值是无效类别编码(比如缺失的类别标识),可以用Embedding层的mask_zero=True参数忽略零值:
# 假设静态特征的最大取值为max_val,需包含所有可能类别 max_val = X_static_MLP.max() + 1 mlp_input=Input(shape=(X_static_MLP.shape[1],)) # mask_zero=True表示忽略零值对应的embedding向量 embedding = Embedding(input_dim=max_val, output_dim=8, mask_zero=True)(mlp_input) # 展平embedding后输入MLP flattened = tf.keras.layers.Flatten()(embedding) mlp = Dense(30, activation='relu')(flattened) mlp = Dense(20, activation='relu')(mlp)
整合后的完整代码(以方法一为例)
from tensorflow.keras.layers import Input, LSTM, Dense, Concatenate, Lambda from tensorflow.keras.models import Model from tensorflow.keras.layers import Masking, Dropout import tensorflow as tf # 静态数据零值处理函数 def mask_static_input(x): masked = tf.where(tf.equal(x, 0.), tf.constant(-1e9, dtype=tf.float32), x) return masked # LSTM分支 lstm_input = Input(shape=(X_dynamic_LSTM.shape[1], X_dynamic_LSTM.shape[2])) x = Masking(mask_value=0.)(lstm_input) x = LSTM(70, activation='tanh', return_sequences=True)(x) x = Dropout(0.3)(x) x = LSTM(35)(x) x = Dropout(0.3)(x) x = Dense(1, activation='tanh')(x) # MLP分支(添加零值屏蔽) mlp_input=Input(shape=(X_static_MLP.shape[1])) masked_mlp_input = Lambda(mask_static_input)(mlp_input) mlp = Dense(30, activation='relu')(masked_mlp_input) mlp = Dense(20, activation='relu')(mlp) # 拼接与输出 merge = Concatenate()([x, mlp]) hidden1 = Dense(5, activation='relu')(merge) mlp_out = Dense(1, activation='relu')(hidden1) model = Model(inputs=[lstm_input, mlp_input], outputs=mlp_out) model.compile(loss='mae', optimizer='adam') model.fit([X_dynamic_LSTM, X_static_MLP], y_train, batch_size=40, epochs=10, validation_split=0.2)
额外建议
- 预处理阶段先统计零值分布:如果某些特征全为零,直接删除这些特征更高效
- 若零值是缺失值,也可以先尝试用均值/中位数填充,再结合上述masking方法
- 训练时密切关注验证集loss变化,确认零值处理是否有效
内容的提问来源于stack exchange,提问作者babak asadolah
相关产品推荐
相关产品推荐

