3

使用神经网络进行分布变换

 2 years ago
source link: https://allenwind.github.io/blog/12982/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Mr.Feng Blog

NLP、深度学习、机器学习、Python、Go

使用神经网络进行分布变换

使用神经网络进行分布变换

过去的文章采样:从均匀分布采样、正太分布采样到MCMC提及过分布变换,即从一个分布变换到另外一个分布,例如从均匀分布变换到正太分布。不过还真没有尝试过直接使用神经网络进行分布变换机器应用。今天这里进行一个简单的尝试和实践。

假设有神经网络ff,分布变换要做的事情是把从满足某一分布的数据XX,变换为数据YY,

Y=f(X)Y=f(X)

使其满足目标分布。

一个具体的例子,假如有数据[X1,X2,…,Xn][X1,X2,…,Xn]独立地采样字均匀分布,神经网络ff负责变换为[Y1,Y2,…,Yn][Y1,Y2,…,Yn]使其满足正太分布。

均值估计,

μ=1nn∑i=1Yiμ=1n∑i=1nYi

方差的无偏估计,

σ2=1n−1n∑i=1(Yi−μ)2σ2=1n−1∑i=1n(Yi−μ)2

通过KL散度来评估与标准正太分布的差距,计算KL散度,

KL(N(μ,σ2)∥∥N(0,1))=∫1√2πσ2e−(x−μ)2/2σ2(loge−(x−μ)2/2σ2/√2πσ2e−x2/2/√2π)dx=∫1√2πσ2e−(x−μ)2/2σ2log{1√σ2exp{12[x2−(x−μ)2/σ2]}}dx=12∫1√2πσ2e−(x−μ)2/2σ2[−logσ2+x2−(x−μ)2/σ2]dx=12[−logσ2+μ2+σ2−1]KL⁡(N(μ,σ2)‖N(0,1))=∫12πσ2e−(x−μ)2/2σ2(log⁡e−(x−μ)2/2σ2/2πσ2e−x2/2/2π)dx=∫12πσ2e−(x−μ)2/2σ2log⁡{1σ2exp⁡{12[x2−(x−μ)2/σ2]}}dx=12∫12πσ2e−(x−μ)2/2σ2[−log⁡σ2+x2−(x−μ)2/σ2]dx=12[−log⁡σ2+μ2+σ2−1] KL(N(μi,σ2i)∥∥N(0,1))=12(−logσ2i+μ2i+σ2i−1)KL⁡(N(μi,σi2)‖N(0,1))=12(−log⁡σi2+μi2+σi2−1)

上式作为loss参与神经网络的训练,主导参数的优化方向。

更一般的形式,

KL(N(μ1,σ21)∥N(μ2,σ22))=12(−logσ21σ22+(μ1−μ2)2σ22+σ21σ22−1)KL⁡(N(μ1,σ12)‖N(μ2,σ22))=12(−log⁡σ12σ22+(μ1−μ2)2σ22+σ12σ22−1)

可以用来控制生成的正太分布的形状。

拉普拉斯分布的概率密度,

f(x∣μ,b)=12bexp(−|x−μ|b)f(x∣μ,b)=12bexp⁡(−|x−μ|b)

均值和方差分别为μ,2b2μ,2b2。

上述方法最关键是的KL散度这一层的实现,

class KLLossLayer(tf.keras.layers.Layer):

def __init__(self, **kwargs):
super(KLLossLayer, self).__init__(**kwargs)

def call(self, inputs):
hdims = tf.cast(tf.shape(inputs)[-1], tf.float32)
mu = tf.reduce_mean(inputs, axis=1, keepdims=True)
var = tf.reduce_sum(tf.square(inputs - mu), axis=1) / (hdims-1)
kl_loss = 0.5 * tf.reduce_mean(-tf.math.log(var) + tf.square(mu) + var - 1)
self.add_loss(kl_loss)
return inputs

模型十分简单,

inputs = tf.keras.layers.Input(shape=(hdims,))
x = inputs
x = tf.keras.layers.Dense(hdims, activation="tanh")(x)
x = tf.keras.layers.Dense(hdims)(x)
outputs = KLLossLayer()(x)
model = tf.keras.Model(inputs, outputs)
model.compile(optimizer="adam")

变换结果,

上图红线是正太分布概率密度曲线,蓝色部分是变换结果。可以看到效果还是不错的。

实现代码见Github

[1] http://www.allisons.org/ll/MML/KL/Normal/

[2] https://en.wikipedia.org/wiki/Normal_distribution

转载请包括本文地址:https://allenwind.github.io/blog/12982
更多文章请参考:https://allenwind.github.io/blog/archives/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK