Recursos latentes do Autoencoder variacional (VAE)
Sou novo no DL e estou trabalhando em VAE para imagens biomédicas. Preciso extrair recursos relevantes da tomografia computadorizada. Então criei primeiro um autoencoder e depois um VAE. Minha dúvida é que não sei de qual camada posso extrair feautures. Minha ideia pessoal é usar recursos extraídos por camadas que calculam a média e a variância (antes do truque de reparametrização), mas acho que também a camada anterior a essas é adequada para o propósito. Deixei aqui código da parte do encoder:
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
```
Respostas
As camadas anteriores da rede neural aprendem mais recursos de baixo nível, enquanto as camadas mais profundas aprendem recursos abstratos mais complicados (consulte a figura de Albawi et al, 2017 ).
Autoencoders são construídos de duas redes codificador que codifica os dados em termos de algumas variáveis latentes (geralmente de menor dimensionalidade, portanto, eles podem ser usados para redução de dimensionalidade ) e decodificador que transforma a representação latente de volta na representação inicial dos dados.
Você pode usar qualquer camada do autoencoder, dependendo de suas necessidades. Como os autoencoders geralmente são simétricos, geralmente para geração de recursos, você tiraria camadas do codificador ou de sua saída. Se você deseja usar o codificador automático para redução de dimensionalidade, prefere obter a saída do codificador com dimensão menor (consulte a figura abaixo do artigo de Windrim et al, 2019 ).
Por outro lado, você pode usar o autoencoder da mesma forma que qualquer outra rede neural para aprendizado de transferência . Nesse caso, você treinaria o autoencoder e extrairia alguma camada dele como recursos para outro algoritmo. Nesse caso, se você desejasse recursos de nível inferior, usaria as camadas anteriores. Se você quisesse recursos mais abstratos, usaria camadas mais altas.
Usando o exemplo da primeira imagem, você pegaria a primeira camada da rede treinada em rostos humanos e a usaria para extrair algumas formas e arestas básicas de imagens que não fossem rostos humanos. Por outro lado, se você precisasse detectar rostos, usaria camadas mais profundas da rede.
Adicionando à resposta elaborada de @Tim:
VAE z latente é estocástico z, o que significa que as amostras serão diferentes para um mesmo$x_i$amostra. No caso ideal, sua representação latente ($\mu$ou z) conterá informações significativas, essas são as que eu extrairia (aliás, no tensorflow, você pode extrair várias camadas;)).$\sigma$é estabelecido para atuar como um componente de ruído.
Para ter certeza de que o que você extrai é útil, o que você pode fazer é um teste de interpretabilidade.
Os recursos de entrada do Ct-scans são os pixels que você tem, MAS há alguma outra informação que você não está usando? Por exemplo, já que você não dá rótulos explícitos, você tem alguma imagem digitalizada de um paciente doente? Ou você poderia selecionar 10 imagens à mão com alguma característica específica para interpretar um pouco quais neurônios são acionados no espaço latente? Nesse caso, o que você pode fazer é um teste de correlação. Isso pode ser tão simples quanto neyman pearson ou um histograma 2D mostrando como os recursos são correlacionados. O que você deseja obter neste caso é alguma noção do que está sendo usado no modelo para decidir.
Infelizmente, isso é fácil para gatos/documentos e mais difícil para conjuntos de dados mais complexos, mas é algo que você precisa fazer para não ter uma máquina de caixa preta. Boa sorte!