自动编码器的二进制激活功能

时间:2019-01-29 21:02:10

标签: python tensorflow keras keras-layer

我有一个自动编码器,它有两个输出(decoded,pred_w),一个输出是重构的输入图像,另一个是重构的二进制图像。我在最后一层使用了S型激活函数,但是输出是浮点数,我需要将每个像素的网络标签标记为0或1。我在此处附加了代码。您能指导我如何解决这个问题吗? 谢谢。

from keras.layers import Input, Concatenate, GaussianNoise,Dropout
from keras.layers import Conv2D
from keras.models import Model
from keras.datasets import mnist
from keras.callbacks import TensorBoard
from keras import backend as K
from keras import layers
import matplotlib.pyplot as plt
import tensorflow as tf
import keras as Kr
import numpy as np
import pylab as pl
import matplotlib.cm as cm
import keract
from tensorflow.python.keras.layers import Lambda;

#-----------------building w train---------------------------------------------
w_main = np.random.randint(2,size=(1,4,4,1))
w_main=w_main.astype(np.float32)
w_expand=np.zeros((1,28,28,1),dtype='float32')
w_expand[:,0:4,0:4]=w_main
w_expand.reshape(1,28,28,1)
w_expand=np.repeat(w_expand,49999,0)

#-----------------building w validation---------------------------------------------
w_valid = np.random.randint(2,size=(1,4,4,1))
w_valid=w_valid.astype(np.float32)
wv_expand=np.zeros((1,28,28,1),dtype='float32')
wv_expand[:,0:4,0:4]=w_valid
wv_expand.reshape(1,28,28,1)
wv_expand=np.repeat(wv_expand,9999,0)

#-----------------building w test---------------------------------------------
w_test = np.random.randint(2,size=(1,4,4,1))
w_test=w_test.astype(np.float32)
wt_expand=np.zeros((1,28,28,1),dtype='float32')
wt_expand[:,0:4,0:4]=w_test
wt_expand.reshape(1,28,28,1)
#wt_expand=np.repeat(wt_expand,10000,0)

#-----------------------encoder------------------------------------------------
#------------------------------------------------------------------------------
wtm=Input((28,28,1))
image = Input((28, 28, 1))
conv1 = Conv2D(16, (3, 3), activation='relu', padding='same', name='convl1e')(image)
conv2 = Conv2D(32, (3, 3), activation='relu', padding='same', name='convl2e')(conv1)
conv3 = Conv2D(8, (3, 3), activation='relu', padding='same', name='convl3e')(conv2)
DrO1=Dropout(0.25)(conv3)
encoded =  Conv2D(1, (3, 3), activation='relu', padding='same',name='reconstructed_I')(DrO1)


#-----------------------adding w---------------------------------------
#add_const = Kr.layers.Lambda(lambda x: x + Kr.backend.constant(w_expand))
#encoded_merged=Kr.layers.Add()([encoded,wtm])

add_const = Kr.layers.Lambda(lambda x: x + wtm)
encoded_merged = add_const(encoded)
encoder=Model(inputs=image, outputs= encoded_merged)
encoder.summary()

#-----------------------decoder------------------------------------------------
#------------------------------------------------------------------------------

#encoded_merged = Input((28, 28, 2))
deconv1 = Conv2D(16, (3, 3), activation='relu', padding='same', name='convl1d')(encoded_merged)
deconv2 = Conv2D(32, (3, 3), activation='relu', padding='same', name='convl2d')(deconv1)
deconv3 = Conv2D(8, (3, 3), activation='relu',padding='same', name='convl3d')(deconv2)
DrO2=Dropout(0.25)(deconv3)
decoded = Conv2D(1, (3, 3), activation='relu', padding='same', name='decoder_output')(DrO2) 

#decoder=Model(inputs=encoded_merged, outputs=decoded)
#decoder.summary()
model=Model(inputs=image,outputs=decoded)
#----------------------w extraction------------------------------------
convw1 = Conv2D(16, (3,3), activation='relu', padding='same', name='conl1w')(decoded)
convw2 = Conv2D(32, (3, 3), activation='relu', padding='same', name='convl2w')(convw1)
convw3 = Conv2D(8, (3, 3), activation='relu', padding='same', name='conl3w')(convw2)
DrO3=Dropout(0.25)(convw3)
pred_w = Conv2D(1, (1, 1), activation='sigmoid', padding='same', name='reconstructed_W')(DrO3)  
# reconsider activation (is W positive?)
# should be filter=1 to match W
w_extraction=Model(inputs=[image,wtm],outputs=[decoded,pred_w])


#----------------------training the model--------------------------------------
#------------------------------------------------------------------------------
#----------------------Data preparesion----------------------------------------

(x_train, _), (x_test, _) = mnist.load_data()
x_validation=x_train[1:10000,:,:]
x_train=x_train[10001:60000,:,:]
#
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_validation = x_validation.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))  # adapt this if using `channels_first` image data format
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))  # adapt this if using `channels_first` image data format
x_validation = np.reshape(x_validation, (len(x_validation), 28, 28, 1))

#---------------------compile and train the model------------------------------
# is accuracy sensible metric for this model?
w_extraction.compile(optimizer='adadelta', loss={'decoder_output':'mse','reconstructed_W':'mse'}, metrics=['mae'])
w_extraction.fit([x_train,w_expand], [x_train,w_expand],
          epochs=100,
          batch_size=128, 
          validation_data=([x_validation,wv_expand], [x_validation,wv_expand]),
          callbacks=[TensorBoard(log_dir='E:/tmp/AutewithW200', histogram_freq=0, write_graph=False)])
model.summary()

2 个答案:

答案 0 :(得分:1)

如果需要在模型内部使用此功能,则可以使用K.round()中的keras.backend。请注意,这将是不可区分的,并且将不能很好地用于培训。

如果只需要结果,则可以简单地定义一个阈值(通常为0.5),然后:

binary_reslts = results > threshold

向模型添加指标

您可以通过添加围绕数据的指标来查看结果。 为此的标准指标可能是"accuracy""categorical_accuracy"。您可以定义自己的指标,例如:

def diceMetric(yTrue, yPred):
    yTrue = K.batch_flatten(yTrue)
    yPred = K.batch_flatten(yPred)

    #round
    yPred = K.greater(yPred, 0.5)
    yPred = K.cast(yPred, K.floatx())

    intersection = yPred * yTrue
    sum = yTrue + yPred

    return (2*intersection + K.epsilon())/(sum + K.epsilon())

指标已添加到compile中:

model.compile(optimizer=..., loss=..., metrics = [diceMetric, 'categorical_accuracy'])

指标不会影响培训,它们只是反馈,让您知道正在发生的事情。

答案 1 :(得分:1)

为什么您需要您的网络精确输出0或1?您可以将网络的输出解释为概率度量,即输入像素对应于类别0或1的可能性有多大。 因此在训练过程中,该模型会尝试近似未知的概率分布。

关于预测,您可以使用.5之类的阈值,也可以使用像otsu之类的阈值。然后,您将获得一个二进制输出。不幸的是,阈值会造成一些缝隙或缩小某些预测形状的面积。

注意: 通常,您需要在自动编码器中进行下采样和上采样,因为否则该模型可能会了解到ididity函数是最佳的。