Получение входов нейронной сети от выходов - PullRequest
0 голосов
/ 24 февраля 2019

Я строю нейронную сеть, используя керасы с одинаковым номером нейронов в каждом слое и одинаковой функцией активации (LeakyReLU), чтобы получить входные данные от выходов.Я знаю, что это математически возможно, и я могу найти, что здесь также.

Это работает с 1 или 2 слоистыми нейронными сетями, но в более глубоких есть большая разница между данным входом и темрассчитывается на основе выходных данных.

Это моя реализация нейронной сети:

input_dim = 256
LR = 0.25
# create encoder model

input_plain = Input(shape=(input_dim,))

encoded = Dense(input_dim, use_bias=False)(input_plain)
encoded = LeakyReLU(LR)(encoded)
encoded = Dense(input_dim, use_bias=False)(encoded)
encoded = LeakyReLU(LR)(encoded)
encoded = Dense(input_dim, use_bias=False)(encoded)
encoded = LeakyReLU(LR)(encoded)
encoded = Dense(input_dim, use_bias=False)(encoded)
encoded = LeakyReLU(LR)(encoded)
encoded = Dense(input_dim, use_bias=False)(encoded)
encoded = LeakyReLU(LR)(encoded)
encoded = Dense(input_dim, use_bias=False)(encoded)
encoded = LeakyReLU(LR)(encoded)

encoder = Model(input_plain, encoded)

encoded = encoder.predict(x_test)

И эта обратная функция с запаздыванием:

def LeakyReLU_inv(alpha,x):
  output = np.copy(x)
  output[ output < 0 ] /= alpha
  return output

И вот как я получаюисходные входы от выходов:

encoder_weights= encoder.get_weights()
decoder_weights = []

for w in encoder_weights:
  decoder_weights.append((np.linalg.inv(w)))

decoder_weights.reverse()

x = encoded
for w in decoder_weights:
  x = LeakyReLU_inv(LR,x) 
  x = np.dot(x,w) 

Я построил нейронную сеть меньшего размера с двумя слоями и реализовал ту же логику, и она работала:

input_plain = Input(shape=(3,))

encoded = Dense(3, use_bias=False)(input_plain)
encoded = LeakyReLU(0.25)(encoded)
encoded = Dense(3, use_bias=False)(encoded)
encoded = LeakyReLU(0.25)(encoded)
encoder = Model(input_plain, encoded)

W1 = encoder.get_weights()[0]
W2 = encoder.get_weights()[1]
Z1 = np.dot(X,W1)
Y_calc1 = LeakyReLU_(0.25,Z1)
Z2 = np.dot(Y_calc1,W2)
Y_calc2 = LeakyReLU_(0.25,Z2)
Y_calc2_inv = LeakyReLU_inv(0.25,Y)
Z_inv2 = np.dot(Y_calc2_inv,np.linalg.inv(W2))
Y_calc1_inv = LeakyReLU_inv(0.25,Z_inv2)
x= np.dot(Y_calc1_inv,np.linalg.inv(W1))

Обратите внимание, что я реализовал LeakyReLU_, как показано:

def LeakyReLU_(alpha,x):
  output = np.copy(x)Y_calc1
  output[ output < 0 ] *= alpha
  return output 

Что я делаю неправильно в первой более глубокой нейронной сети, в которой неверный расчетный ввод неверен, как в двухслойной нейронной сети?

Заранее спасибо!

1 Ответ

0 голосов
/ 26 февраля 2019

Это слишком много работы, чтобы достичь того, чего вы хотите.Могу поспорить, что вы ищете, это Autoencoder.Автоэнкодеры используются для генерации точно такого же ввода на выходном слое при обработке ввода через набор уровней кодирования и декодирования.

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

Ниже приведен автокодер, который я построил для восстановления входного изображения на выходном слое.

def autoencoder(inputs):
    # encoder
    # 32 x 32 x 1   ->  16 x 16 x 64
    # 16 x 16 x 64  ->  8 x 8 x 32
    # 8 x 8 x 32  ->  4 x 4 x 16
    # 4  x 4  x 16  ->  1 x 1 x 100
    conv1 = lays.conv2d(inputs, 64, [5, 5], stride=2, padding='SAME')
    conv2 = lays.conv2d(conv1, 32, [5, 5], stride=2, padding='SAME')
    conv3 = lays.conv2d(conv2, 16, [5, 5], stride=2, padding='SAME')
    conv4 = lays.conv2d(conv3, 100, [5, 5], stride=4, padding='SAME')
    # decoder
    # 1 x 1 x 100   ->  4 x 4 x 16 
    # 4 x 4 x 16    ->  16 x 16 x 32
    # 16 x 16 x 32   ->  32 x 32 x 64
    # 32 x 32 x 64  ->  64 x 64 x 1
    # dconv1 = lays.conv2d_transpose(conv4, 16, [5, 5], stride=4, padding='SAME')
    latent_ph = tf.placeholder_with_default(conv4, [None, 1, 1, 100], name="latent_ph")
    dconv1 = lays.conv2d_transpose(latent_ph, 16, [5, 5], stride=4, padding='SAME')
    dconv2 = lays.conv2d_transpose(dconv1, 32, [5, 5], stride=2, padding='SAME')
    dconv3 = lays.conv2d_transpose(dconv2, 64, [5, 5], stride=2, padding='SAME')
    dconv4 = lays.conv2d_transpose(dconv3, 1, [5, 5], stride=2, padding='SAME', activation_fn=tf.nn.relu)
    # W_conv1 = weights([5, 5, 1, 64])
    # conv1 = conv2d(inputs, W_conv1, stride=(2,2))


    return dconv4, latent_ph, conv4

tf.placeholder_with_default() позволяет вам подавать тензор извне во время тестирования.Поэтому, если у вас сокращенный формат ввода, вы можете скорректировать приведенный тензор до tf.placeholder_with_default() тензор и наблюдать за выводом.

Возвращаясь к вашему вопросу, не имеет значения, является ли это глубокая сеть,мелкая сеть, CNN, полностью подключенный NN, он должен работать при реализации одного из этих автоэнкодеров.Единственное изменение, которое вам нужно будет сделать, - это сделать labels = inputs.

...