python - 混合密度网络 (MDN) 仅返回概率 1.0 和 0.0
问题描述
我正在构建一个混合密度网络,试图预测一个变量在两个协变量上的分布。其中一个协变量具有每小时数据,而另一个在白天没有变化(即每日数据)。先前的工作表明 2 个分布应该会产生好的结果,所以我也使用 2 个分布。
对于损失函数,我使用了一个定制的负对数似然来进行正态分布,并应用了 log-sum-exp 技术。
我正在使用两个具有 relu 激活函数和 60 个神经元的隐藏层,一批 60 个和 e-4 学习率。
但是,结果显示其中一种分布的概率始终为 1,而另一种分布的概率始终为 0。我是否增加 epoch 的数量没有区别。请注意,概率为 1.0 的分布的结果是完全合理的,但考虑到该主题的先前工作,我很难相信在 60K+ 小时内,没有一个混合了 2 个不同的分布。
任何有关如何更正概率或可能是仅 0-1 概率的原因的建议都将受到高度赞赏。
from tensorflow.keras import backend as bk
# reading inputs, etc.
components = 2 # Number of normal distributions in mixture
no_parameters = 3 # Number of parameters of the mixtures (weight, mean, std. dev)
neurons = 60 # Number of neurons per layer
SB = 1 # Number of outputs we want to predict
# Make the input tensor: two covariates-- quantity & price.
inputs = ks.Input(shape=(X_train.shape[1],))
h1 = ks.layers.Dense(neurons, activation="relu",
kernel_initializer='ones', bias_initializer='ones')(inputs)
h2 = ks.layers.Dense(neurons, activation="relu",
kernel_initializer='ones', bias_initializer='ones')(h1)
alphas = ks.layers.Dense(components, activation="softmax", name="alphas",
kernel_initializer='ones', bias_initializer='ones')(h2)
mus = ks.layers.Dense(components, name="mus")(h2)
sigmas = ks.layers.Dense(components, activation="relu", name="sigmas",
kernel_initializer='ones', bias_initializer='ones')(h2)
outputVector = ks.layers.Concatenate(name="output")([alphas, mus, sigmas])
model = ks.Model(inputs=inputs, outputs=outputVector)
def slice_parameter_vectors(parameter_vector):
""" Returns an unpacked list of parameter vectors. """
return [parameter_vector[:, i * components:(i + 1) * components] for i in range(no_parameters)]
def log_sum_exp(x, axis=None):
"""Log-sum-exp trick implementation"""
x_max = bk.max(x, axis=axis, keepdims=True)
return bk.log(bk.sum(bk.exp(x - x_max),
axis=axis, keepdims=True)) + x_max
def mean_log_Gaussian_like2(y, parameter_vector):
""" Computes the mean negative log-likelihood loss of the observed price given the mixture parameters. """
alpha, mu, sigma = slice_parameter_vectors(parameter_vector) # Unpack parameter vectors
mu = tf.keras.backend.reshape(mu, [-1, SB, 2])
alpha = bk.softmax(bk.clip(alpha, 1e-8, 1.))
exponent = bk.log(alpha) - .5 * float(SB) * bk.log(2 * np.pi) \
- float(SB) * bk.log(sigma) \
- bk.sum((bk.expand_dims(y, 2) - mu) ** 2, axis=1) / (2 * (sigma) ** 2)
log_likelihood = log_sum_exp(exponent, axis=1)
return -bk.mean(log_likelihood)
model.compile(optimizer=ks.optimizers.Adam(learning_rate=1e-4, clipvalue=1.0), # , clipvalue=0.5
loss= mean_log_Gaussian_like2,
metrics=['accuracy'])
model.fit(X_train, y_train, batch_size=60, epochs=500)
y_pred = model.predict(X_test)
解决方案
我解决了这个问题。解决方案是从重新定义 alpha 中去掉 softmax 函数。也就是说 alpha = bk.softmax(bk.clip(alpha, 1e-8, 1.)) 应该是 alpha = bk.clip(alpha, 1e-8, 1.)。谢谢大家。
推荐阅读
- wordpress - 如何忽略对带有链接标签的古腾堡块的点击?
- reactjs - React-Devtools 停产了还是刚搬家?(React Native 调试)
- ckeditor5 - 如何让 CKEditor 5“链接”对话框固定到自定义 DOM 元素而不是“document.body”
- php - 如何编写一个 PHP 程序来显示所有 $_SERVER 元素
- api - 如何通过 Gitlab 的 API 执行 PUT 操作?
- ios - 防止AVPlayer进入后台时暂停?
- c# - CultureInfo("ar") 在服务器上返回英文
- powerbi - How to find day over day change in summarize table taking two columns into account
- python - return a list as a unique list using tuples
- asp.net-core - X.PagedList, manual Paging and a pre-existing webapi for data only advance 1 record at a time