бинарная функция активации для автоэнкодера - PullRequest
0 голосов
/ 30 января 2019

У меня есть авто-кодер, который имеет два выхода (декодированный, pred_w), один выход - восстановленное входное изображение, а другой - восстановленное двоичное изображение.Я использовал функцию активации сигмоида в последнем слое, но выходные данные имеют число с плавающей запятой, и мне нужно, чтобы каждый пиксель сети обозначался как 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 голосов
/ 30 января 2019

Зачем вам нужна ваша сеть для вывода ровно 0 или 1?Вы можете интерпретировать выходные данные своей сети как меру вероятности того, насколько вероятно, что входной пиксель соответствует классу 0 или 1. Поэтому во время обучения модель пытается аппроксимировать неизвестное распределение вероятностей.

Когда это происходитдля прогнозов вы можете использовать порог, как .5, или вы можете использовать что-то вроде порога отсу.Тогда вы получите двоичный вывод.К сожалению, пороги создадут некоторые пропуски или уменьшат область некоторых предсказанных форм.

Примечание: обычно вы хотите уменьшить и увеличить частоту в автоэнкодере, потому что в противном случае модель могла бы узнать, что функция идентности оптимальна.

0 голосов
/ 30 января 2019

Если вам нужно это внутри модели, вы можете использовать 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'])

Метрики не влияют на обучение, они просто обратная связь, чтобы вы зналичто происходит.

...