我创建了一个简单的玩具模型来学习在tf.keras
中的确定性嵌入。当训练为keras
模型时,该模型能够完全学习嵌入。使用Estimator
转换为tf.keras.estimator.model_to_estimator
后,模型将无法再学习嵌入权重。 为什么tensorflow Estimator在简单的玩具问题上不能重现keras模型的学习性能?
根据下面的实验结果,我怀疑默认情况下Estimator
中的嵌入权重可能会经过L2规范化,但是在源代码中看不到有任何影响。
1。创建综合数据集
目标是从对Z
和y = Z.dot(b)
馈入网络的线性变换b
的观察中了解y
的值:
import numpy as np
import pandas as pd
np.random.seed(1234)
n_obs = 200
n_sensors = 50
n_sources = 5
Z = np.random.randn(n_obs, n_sources)
b = np.random.randn(n_sources, n_sensors)
y = Z.dot(b)
data = []
for t in range(n_obs):
betas = pd.DataFrame(b).rename(lambda x: 'f_{}'.format(x)).T
data.append(
pd.DataFrame({'target': y[t,:], 't': t}).join(betas)
)
data = pd.concat(data)
2。 Keras模型定义
为betas
创建一个输入层,并通过一个嵌入表查找来学习Z
的值:
import tensorflow as tf
def build_keras_model():
betas = tf.keras.layers.Input(shape=(n_sources,), name='betas')
t = tf.keras.layers.Input(shape=(1,), name='t')
sources = tf.keras.layers.Embedding(
input_dim=n_obs,
output_dim=n_sources,
name='sources')(t)
fitted = tf.keras.layers.Dot(axes=-1)([sources, betas])
net = tf.keras.Model([betas, t], fitted)
net.compile(optimizer='adadelta', loss='mse')
return net
3。 Keras模型训练结果
训练模型可以使收敛到大约。零错误和正确的嵌入权重:
net = build_keras_model()
loss = []
hist = net.fit(
x=[data.filter(like='f_'), data.t],
y=data.target,
batch_size=100,
epochs=200)
loss += hist.history['loss']
Z_hat_keras = net.get_layer('sources').get_weights()
print ((Z_hat_keras - Z) ** 2).mean()
# Out: 8.794945836110652e-05
4。转换为tf.Estimator并进行训练 转换为估计量并使用相同的超参数进行训练会导致无学习且误差大
# convert to estimator
estimator = tf.keras.estimator.model_to_estimator(net)
# slice data so estimator can read it
def input_fn(data, batch_size, num_epochs, shuffle):
ds = tf.data.Dataset.from_tensor_slices((
{'betas': data.filter(like='f_'), 't': data.t}, data.target
))
if shuffle:
ds = ds.shuffle(len(data))
return ds.repeat(num_epochs).batch(batch_size)
train_fn = lambda: input_fn(data, 100, 200, True)
eval_fn = lambda: input_fn(data, 500,1,False)
# run training on estimator
estimator.train(train_fn)
estimator.evaluate(eval_fn)
# Out: {'global_step': 20001, 'loss': 5.0131807}
Z_hat_tensorflow = estimator.get_variable_value('sources/embeddings')
print ((Z_hat_tensorflow - Z) ** 2).mean()
# Out 0.928678746751657
5。学习的嵌入权重似乎很小,但相互关联 tensorflow估计器的嵌入权重与实际值有些相关:
print pd.DataFrame(Z_hat_tensorflow).corrwith(pd.DataFrame(Z))
# 0 0.684187
# 1 0.716039
# 2 0.702139
# 3 0.734620
# 4 0.776179
但是值很小:
print pd.DataFrame(Z_hat_tensorflow).var()
# 0 0.000128
# 1 0.000229
# 2 0.000156
# 3 0.000184
# 4 0.000183
print pd.DataFrame(Z).var()
# 0 0.781733
# 1 0.983512
# 2 0.830148
# 3 1.065107
# 4 1.072370
为什么张量流估计器无法重现keras模型的结果?