Я построил автоматический кодировщик в Keras, который принимает несколько входов и один и тот же набор выходов, которые я хотел бы преобразовать в вариационный автоматический кодировщик. У меня возникли проблемы при объединении потери разницы между входом и выходом и потери вариационной части.
Чего я хочу достичь:
Для данных должен использоваться автоматический кодировщикнабор, содержащий как числовые, так и категориальные данные. Для этого я нормализую числовые столбцы и кодирую в горячем виде категориальные столбцы. Поскольку результирующие категориальные векторы и числовые векторы требуют различных функций потерь (среднеквадратичная ошибка для числовой и категориальной кросс-энтропии для категориальных столбцов) и очень большие векторы горячего кодирования 1-hot будут доминировать над потерями по сравнению смаленькие числовые столбцы, я решил поместить каждый столбец как свой собственный входной вектор. Таким образом, мой автоматический кодер принимает набор входных векторов, генерирует выходные векторы одинакового числа и форм.
Что я сделал до сих пор:
Это настройка для двух числовых входов и двух категориальныхс кодированием 20 и 30 в 1-горячем коде:
encWidth = 3
## Encoder
x = Concatenate(axis=1)([ Input(1,),Input(1,),Input(20,),Input(30,) ]) #<-configurable
x = Dense( 32, activation="relu")(x)
layEncOut = Dense( encWidth, activation="linear")(x)
layDecIn = Input( encWidth, name="In_Encoder" )
x = Dense( 32, activation="relu")(layDecIn)
layDecOut = [ outLayer(x) for outLayer in C.layOutputs ]
encoder = Model(C.layInputs, layEncOut, name="encoder")
decoder = Model( layDecIn, layDecOut, name="decoder" )
AE = Model(C.layInputs, decoder(encoder(C.layInputs)), name="autoencoder")
AE.compile(optimizer="adam",
loss=['mean_squared_error', 'mean_squared_error',
'categorical_crossentropy', 'categorical_crossentropy',], #<-configurable
loss_weights=[1.0, 1.0, 1.0, 1.0] #<-configurable
)
Этот пример статичен, но в моей реализации числовые и категориальные поля являются настраиваемыми, поэтому входы, вид функций потерь и веса потерьдолжен конфигурироваться из объекта, в котором хранятся исходные столбцы из набора данных.
....
## Encoder
x = Concatenate(axis=1)( C.layInputs )
...
AE.compile(optimizer="adam",
loss=C.losses
loss_weights=C.lossWeights
)
Здесь C - это экземпляр класса, который имеет входной слой и функции / веса потерь в зависимости от того, какие столбцыЯ хочу иметь в авто кодировщике.
Моя проблема:
Теперь я расширил набор до вариационного авто кодировщика со скрытым слоем среднего и стандартного отклонения.
encWidth = 2
## Encoder
x = Concatenate(axis=1)(C.layInputs)
x = Dense( 32, activation="relu")(x)
### variational part
z_mean = Dense(encWidth, name='z_mean', activation=lrelu)(x)
z_log_var = Dense(encWidth, name='z_log_var', activation=lrelu)(x)
z = Lambda(sampling, name='z')([z_mean, z_log_var])
## Decoder
layDecodeInput = Input( encWidth, name="In_Encoder" )
x = Dense( 32, activation="relu")(layDecodeInput)
layOutDecoder = [ outLayer(x) for outLayer in C.layOutputs ]
### build the encoder model
vEncoder = Model(C.layInputs, [z_mean, z_log_var, z], name='v_encoder')
### build the decoder model
vDecoder = Model( layDecodeInput, layOutDecoder, name="v_decoder" )
## Autoencoder
vAE = Model(C.layInputs, vDecoder(vEncoder(C.layInputs)[2]))
vae_loss = variational_loss(z_mean, z_log_var)
vAE.compile(optimizer="adam",
loss=vae_loss)
Теперь мне нужна пользовательская функция ошибок, которая сочетает в себе потерю разницы между входом и выходом (как в предыдущемпример) с потерей в вариационной части;это то, что я придумал до сих пор:
def variational_loss(z_mean, z_log_var, varLossWeight=1.):
def lossFct(yTrue, yPred):
var_loss = -0.5 * K.mean(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var))
lossFunctions = [getattr(losses, "mean_squared_error") for losses in C.losses]
ac_loss = [
lossFkt(yTrue, yPred) * lossWeigt for
yt, yp, lossFkt, lossWeigt in zip(yTrue, yPred, lossFunctions, C.lossWeights) ]
loss = K.mean( ac_loss + [ kl_loss * varLossWeight ] )
return loss
return lossFct
Так что это функция генератора, которая возвращает функцию, принимающую yTrue и yPredicted, но работает в вариационной части. Цикл for должен зациклить все входы и соответствующие выходы и сравнить их, используя соответствующую функцию потерь (либо среднеквадратичная ошибка для числового значения, либо категориальная перекрестная энтропия для категориальных признаков)
Но, очевидно, цикл for длязацикливание набора входных векторов и сравнение их с набором выходных векторов не допускается;Я получаю сообщение об ошибке
Tensor objects are only iterable when eager execution is enabled. To iterate over this tensor use tf.map_fn.
Как мне получить удобное поведение функции Model.compile()
, где я могу просто сказать использовать разные функции потерь на разных входах и выходах в сочетании с вариационными потерями?