Utajone funkcje Variational Autoencoder (VAE)

Aug 20 2020

Jestem nowy w DL i pracuję nad VAE dla obrazów biomedycznych. Muszę wyodrębnić odpowiednie funkcje ze skanowania ct. Więc stworzyłem najpierw autoenkoder, a po VAE. Wątpię, że nie wiem, z której warstwy mogę wydobyć właściwości. Moim osobistym pomysłem jest użycie funkcji wyodrębnionych przez warstwy, które obliczają średnią i wariancję (przed trikiem z reparametryzacją), ale myślę, że również warstwa przed nimi nadaje się do tego celu. Zostawiłem tutaj kod części enkodera:

class Sampling(tf.keras.layers.Layer):
    """Uses (z_mean, z_log_var) to sample z, the vector encoding a digit."""
    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon

def Encoder():
    inp = tf.keras.Input(shape=(32,256,256,1)) # prima era 64

    #enc = tf.keras.layers.Conv3D(8, (2,2,2), activation = 'relu', padding = 'same')(inp)
    #enc = tf.keras.layers.MaxPooling3D((2,2,2), padding = 'same')(enc)
 
    enc = tf.keras.layers.Conv3D(16, (2,2,2), activation = 'relu', padding = 'same')(inp)
    enc = tf.keras.layers.MaxPooling3D((2,2,2), padding = 'same')(enc)
 
    enc = tf.keras.layers.Conv3D(32, (2,2,2), activation = 'relu', padding = 'same')(enc)
    enc = tf.keras.layers.MaxPooling3D((2,2,2), padding = 'same')(enc)
 
    enc = tf.keras.layers.Conv3D(64, (2,2,2), activation = 'relu', padding = 'same')(enc)
    enc = tf.keras.layers.MaxPooling3D((2,2,2), padding = 'same') (enc)

    enc = tf.keras.layers.Conv3D(32, (2,2,2), activation = 'relu', padding = 'same')(enc)
    enc = tf.keras.layers.MaxPooling3D((2,2,2), padding = 'same') (enc)
    #enc = tf.keras.layers.Flatten()(enc)
    enc = tf.keras.layers.Conv3D(16, (2,2,2), activation = 'relu', padding = 'same')(enc)
    enc = tf.keras.layers.MaxPooling3D((2,2,2), padding = 'same') (enc)
    '''
    # conv 2D 
    code = tf.keras.layers.Reshape((8,8,96)) (enc)
    code = tf.keras.layers.Conv2D(96,(2,2), activation = 'relu', padding = 'same')(code)
    code = tf.keras.layers.MaxPooling2D((2,2), padding = 'same') (code)
    '''
    
    # latentent code vae
    latent_code = tf.keras.layers.Flatten()(enc)
    latent_code = tf.keras.layers.Dense(256, activation='relu')(latent_code)
    latent_mu = tf.keras.layers.Dense(32, activation='relu')(latent_code) # èprima era 10
    latent_sigma = tf.keras.layers.Dense(32, activation='relu')(latent_code) # prima era 10
    # Reparameterization trick
    #z = tf.keras.layers.Lambda(sample_z, output_shape=(128,), name='z')([latent_mu, latent_sigma])
    z = Sampling()([latent_mu, latent_sigma])
    encoder = tf.keras.Model(inp, [latent_mu, latent_sigma, z ], name = 'encoder')
    
    #encoder = tf.keras.Model(inp, enc)#[latent_mu, latent_sigma, z ], name = 'encoder')
    return encoder
```

Odpowiedzi

4 Tim Aug 20 2020 at 02:47

Wcześniejsze warstwy sieci neuronowej uczą się więcej funkcji niskiego poziomu, podczas gdy głębsze warstwy uczą się bardziej skomplikowanych, abstrakcyjnych funkcji (patrz rysunek z Albawi i in., 2017 ).

Autoenkodery są zbudowane z dwóch koderów sieciowych, które kodują dane w kategoriach niektórych ukrytych zmiennych (zwykle o niższej wymiarowości, stąd mogą być używane do redukcji wymiarów ) i dekodera, który przekształca ukrytą reprezentację z powrotem w początkową reprezentację danych.

W zależności od potrzeb możesz użyć dowolnej warstwy z autoenkodera. Ponieważ autoenkodery są zwykle symetryczne, zwykle do generowania funkcji należy pobierać warstwy z kodera lub z wyjścia. Jeśli chcesz użyć autoenkodera do redukcji wymiarowości, wolałbyś raczej wziąć wyjście kodera, który ma mniejszy wymiar (patrz rysunek poniżej z pracy Windrim et al, 2019 ).

Z drugiej strony, możesz użyć autoenkodera w taki sam sposób, jak każdej innej sieci neuronowej do transferu uczenia się . W takim przypadku należy przeszkolić autoenkodera, a następnie wyodrębnić jego warstwę jako funkcje dla innego algorytmu. W takim przypadku, jeśli potrzebujesz elementów niższego poziomu, weź wcześniejsze warstwy. Gdybyś chciał bardziej abstrakcyjnych funkcji, wziąłbyś wyższe warstwy.

Korzystając z przykładu z pierwszego zdjęcia, weźmiesz pierwszą warstwę sieci wyszkoloną na ludzkich twarzach i użyjesz jej do wyodrębnienia podstawowych kształtów i krawędzi z obrazów innych niż ludzkie twarze. Z drugiej strony, gdybyś musiał wykryć twarze, wziąłbyś głębsze warstwy sieci.

1 partizanos Dec 17 2020 at 12:27

Dodając do rozbudowanej odpowiedzi @Tim:

VAE z latent jest stochastycznym z, co oznacza, że ​​próbki będą różne dla tego samego $x_i$próba. W idealnym przypadku ukryta reprezentacja ($\mu$ lub z) będzie zawierał znaczące informacje, to te, które bym wyodrębnił (przy okazji w tensorflow można wyodrębnić wiele warstw;)). $\sigma$ działa jako składnik hałasu.

Aby upewnić się, że to, co wyodrębniasz, jest przydatne, możesz zrobić test interpretacji.

Funkcje wejściowe skanów Ct to piksele, które masz, ALE czy są jakieś inne informacje, których nie używasz? Na przykład, skoro nie podajesz wyraźnych etykiet, czy masz jakieś zeskanowane zdjęcie chorego pacjenta? A może możesz ręcznie wybrać 10 obrazów z określoną funkcją, aby nieco zinterpretować, jakie neurony są wyzwalane w utajonej przestrzeni? Jeśli tak, to możesz zrobić test korelacji. Może to być tak proste, jak histogram Neymana Pearsona lub histogram 2d pokazujący, jak skorelowane są cechy. To, co chcesz osiągnąć w tym przypadku, to pewne poczucie tego, co jest używane z modelu do podejmowania decyzji.

Niestety jest to łatwe dla kotów / dokumentów i trudniejsze dla bardziej złożonych zestawów danych, ale jest to coś, co musisz zrobić, aby nie mieć maszyny z czarną skrzynką. Powodzenia!