Vimos alguns exemplos de aprendizado não supervisionado (ou aprendizado auto-supervisionado, para escolher o termo mais correto, mas menos standard) neste weblog.
Freqüentemente, estes envolvidos AutoEncoders variacionais (VAES)cujo apelo está neles, permitindo modelar um espaço latente de fatores subjacentes e independentes (de preferência) que determinam os recursos visíveis. Uma possível desvantagem pode ser a qualidade inferior das amostras geradas. Redes adversárias generativas (GANs) são outra abordagem standard. Conceitualmente, estes são altamente atraentes devido ao seu enquadramento da teoria dos jogos. No entanto, eles podem ser difíceis de treinar. Pixelcnn As variantes, por outro lado – vamos subspor todas elas aqui sob o Pixelcnn – são geralmente conhecidas por seus bons resultados. Eles parecem envolver um pouco mais de alquimia. Nessas circunstâncias, o que poderia ser mais bem -vindo do que uma maneira fácil de experimentar com elas? Através da probabilidade do TensorFlow (TFP) e seu wrapper R, TFProbabilityagora temos dessa maneira.
Este submit primeiro oferece uma introdução ao Pixelcnn, concentrando-se em conceitos de alto nível (deixando os detalhes para os curiosos procurá-los nos respectivos papéis). Vamos então mostrar um exemplo de usar tfprobability
Para experimentar a implementação do TFP.
Princípios de pixelcnn
Autorregressividade, ou: precisamos (alguns) pedidos
A idéia básica em Pixelcnn é a autorregressividade. Cada pixel é modelado como dependendo de todos os pixels anteriores. Formalmente:
(p ( mathbf {x}) = prod_ {i} p (x_i | x_0, x_1, …, x_ {i-1}) )
Agora espere um segundo – o que mesmo são Pixels anteriores? A última vez que vi uma imagens foi bidimensional. Então isso significa que temos que impor um ordem nos pixels. Geralmente, isso será varredura raster Ordem: Linha após linha, da esquerda para a direita. Mas ao lidar com imagens coloridas, há outra coisa: em cada posição, na verdade temos três Valores de intensidade, um para cada um de vermelho, verde e azul. O papel pixelcnn unique(Oord, Kalchbrenner e Kavukcuoglu 2016) Transportado por autoregressividade aqui também, com a intensidade de um pixel para o vermelho, dependendo de apenas pixels anteriores, os de verde, dependendo desses mesmos pixels anteriores, mas além do valor atual para o vermelho e os de azul, dependendo dos pixels anteriores, bem como do Valores atuais para vermelho e verde.
(p (x_i | mathbf {x}
Aqui, a variante implementada em TFP, Pixelcnn ++(Salimans et al. 2017) apresenta uma simplificação; Ele fatoriza a distribuição conjunta de uma maneira menos intensiva em computação.
Tecnicamente, então, sabemos como a autoregressividade é realizada; Intuitivamente, ainda pode parecer surpreendente que a imposição de uma ordem de varredura raster “apenas funciona” (para mim, pelo menos, é). Talvez este seja um daqueles pontos em que o poder de computação compensa com sucesso a falta de um equivalente a um prior cognitivo.
Mascarar, ou: onde não olhar
Agora, o Pixelcnn termina em “CNN” por um motivo – como de costume no processamento de imagens, estão envolvidas camadas convolucionais (ou blocos). Mas – não é a própria natureza de uma convolução que ele calcula uma média de algum tipo, procurando, para cada pixel de saída, não apenas na entrada correspondente, mas também, em seu ambiente espacial (ou temporal)? Como isso rima com a estratégia de pixels de aparência de apenas prior?
Surpreendentemente, esse problema é mais fácil de resolver do que parece. Ao aplicar o kernel convolucional, apenas se multiplique com uma máscara que zero qualquer “pixels proibido” – como neste exemplo para um kernel de 5×5, onde estamos prestes a calcular o valor convoluído da linha 3, coluna 3:
( esquerda ( Start {Array} {rrr} 1 & 1 & 1 & 1 & 1 1 & 1 & 1 & 1 & 1 1 & 1 & 1 & 0 & 0 0 & 0 & 0 & 0 & 0 0 & 0 & 0 & 0 & 0 finish {Array} Proper) )
Isso torna o algoritmo honesto, mas apresenta um problema diferente: a cada camada convolucional sucessiva consumindo a produção de seu antecessor, há um crescente continuamente ponto cego (o chamado em analogia com o ponto cego na retina, mas localizado no canto superior direito) de pixels que nunca são visto pelo algoritmo. Van den Oord et al. (2016)(Oord et al. 2016) Corrija isso usando duas pilhas convolucionais diferentes, uma de cima para baixo e a outra da esquerda para a direita.

Condicionamento, ou: mostre -me um gatinho
Até agora, sempre conversamos sobre “gerar imagens” de uma maneira puramente genérica. Mas a verdadeira atração está na criação de amostras de algum tipo especificado – uma das lessons em que treinamos ou informações ortogonais alimentadas na rede. É aqui que o pixelcnn se torna Pixelcnn condicional(Oord et al. 2016)e é também onde esse sentimento de mágica ressurge. Novamente, como “matemática geral”, não é difícil de conceber. Aqui, ( mathbf {h} ) é a entrada adicional que estamos condicionando:
(p ( mathbf {x} | mathbf {h}) = prod_ {i} p (x_i | x_0, x_1, …, x_ {i-1}, mathbf {h}) )
Mas como isso se traduz em operações de rede neural? É apenas mais uma multiplicação da matriz ( (V^t mathbf {h} )) adicionado às saídas convolucionais ( (W mathbf {x} )).
( mathbf {y} = tanh (w_ {okay, f} mathbf {x} + v^t_ {okay, f} mathbf {h}) odot sigma (w_ {okay, g} mathbf { x} + v^t_ {okay, g} mathbf {h}) )
(Se você está se perguntando sobre a segunda parte à direita, após o sinal do produto Hadamard – não entraremos em detalhes, mas em poucas palavras, é outra modificação introduzida por (Oord et al. 2016)uma transferência do princípio de “bloqueio” de redes neurais recorrentes, como GRUS e LSTMS, para o cenário convolucional.)
Então, vemos o que entra na decisão de um valor de pixel para amostrar. Mas como essa decisão é realmente feito?
Probabilidade de mistura logística, ou: nenhum pixel é uma ilha
Novamente, é aqui que a implementação do TFP não segue o artigo unique, mas o último pixelcnn ++. Originalmente, os pixels foram modelados como valores discretos, decididos por um softmax acima de 256 (0-255) valores possíveis. (Que isso realmente funcionou parece outro exemplo de mágica de aprendizado profundo. Think about: neste modelo, 254 está tão longe de 255 quanto de 0.)
Por outro lado, o pixelcnn ++ assume uma distribuição contínua subjacente da intensidade da cor e rodadas para o número inteiro mais próximo. Essa distribuição subjacente é uma mistura de distribuições logísticas, permitindo assim a multimodalidade:
( nu sim sum_ {i} pi_i logistic ( mu_i, sigma_i) )
Arquitetura geral e a distribuição pixelcnn
No geral, Pixelcnn ++, conforme descrito em (Salimans et al. 2017)consiste em seis blocos. Os blocos juntos compõem uma estrutura semelhante a não, diminuindo sucessivamente a entrada e depois a amostra novamente:

Na distribuição pixelcnn do TFP, o número de blocos é configurável como num_hierarchies
o padrão é 3.
Cada bloco consiste em um número personalizável de camadas, chamado Camadas de resnet Devido à conexão residual (visível à direita), complementando as operações convolucionais na pilha horizontal:

No TFP, o número dessas camadas por bloco é configurável como num_resnet
.
num_resnet
e num_hierarchies
são os parâmetros que você provavelmente experimentará, mas há mais alguns que você pode conferir no documentação. O número de distribuições logísticas na mistura também é configurável, mas a partir dos meus experimentos é melhor manter esse número bastante baixo para evitar a produção NaN
s durante o treinamento.
Agora vamos ver um exemplo completo.
Exemplo de ponta a ponta
Nosso playground será QuickDrawum conjunto de dados – ainda crescendo – obtido pedindo às pessoas que desenhem algum objeto no máximo vinte segundos, usando o mouse. (Para ver por si mesmo, basta verificar o web site). A partir de hoje, existem mais de cinquenta milhões de instâncias, de 345 lessons diferentes.
Em primeiro lugar, esses dados foram escolhidos para fazer uma pausa no MNIST e suas variantes. Mas, assim como aqueles (e muitos mais!), tfdatasets
-Formulário, through tfdso wrapper R para os conjuntos de dados do TensorFlow. Em contraste com a “família” mnist, as “amostras reais” são elas mesmas altamente irregulares e muitas vezes até perdem partes essenciais. Portanto, para ancorar o julgamento, ao exibir amostras geradas, sempre mostramos oito desenhos reais com eles.
Preparando os dados
O conjunto de dados sendo gigantesco, instruímos tfds
Para carregar os primeiros 500.000 desenhos “somente”.
Para acelerar ainda mais o treinamento, o zoom em vinte aulas. Isso nos deixa efetivamente com ~ 1.100 – 1.500 desenhos por classe.
# bee, bicycle, broccoli, butterfly, cactus,
# frog, guitar, lightning, penguin, pizza,
# rollerskates, sea turtle, sheep, snowflake, solar,
# swan, The Eiffel Tower, tractor, practice, tree
lessons <- c(26, 29, 43, 49, 50,
125, 134, 172, 218, 225,
246, 255, 258, 271, 295,
296, 308, 320, 322, 323
)
classes_tensor <- tf$solid(lessons, tf$int64)
train_ds <- train_ds %>%
dataset_filter(
perform(file) tf$reduce_any(tf$equal(classes_tensor, file$label), -1L)
)
A distribuição Pixelcnn espera valores na faixa de 0 a 255 – não é necessária normalização. O pré -processamento consiste em apenas lançar pixels e etiquetas cada um para float
:
Criando o modelo
Nós agora usamos tfd_pixel_cnn Para definir o que será a loglikeliento usada pelo modelo.
dist <- tfd_pixel_cnn(
image_shape = c(28, 28, 1),
conditional_shape = record(),
num_resnet = 5,
num_hierarchies = 3,
num_filters = 128,
num_logistic_mix = 5,
dropout_p =.5
)
image_input <- layer_input(form = c(28, 28, 1))
label_input <- layer_input(form = record())
log_prob <- dist %>% tfd_log_prob(image_input, conditional_input = label_input)
Essa loglikelização personalizada é adicionada como uma perda ao modelo e, em seguida, o modelo é compilado apenas com apenas uma especificação de otimizador. Durante o treinamento, as perdas diminuíram rapidamente, mas as melhorias das épocas posteriores foram menores.
mannequin <- keras_model(inputs = record(image_input, label_input), outputs = log_prob)
mannequin$add_loss(-tf$reduce_mean(log_prob))
mannequin$compile(optimizer = optimizer_adam(lr = .001))
mannequin %>% match(practice, epochs = 10)
Para exibir em conjunto imagens reais e falsas:
for (i in lessons) {
real_images <- train_ds %>%
dataset_filter(
perform(file) file$label == tf$solid(i, tf$int64)
) %>%
dataset_take(8) %>%
dataset_batch(8)
it <- as_iterator(real_images)
real_images <- iter_next(it)
real_images <- real_images$picture %>% as.array()
real_images <- real_images( , , , 1)/255
generated_images <- dist %>% tfd_sample(8, conditional_input = i)
generated_images <- generated_images %>% as.array()
generated_images <- generated_images( , , , 1)/255
pictures <- abind::abind(real_images, generated_images, alongside = 1)
png(paste0("draw_", i, ".png"), width = 8 * 28 * 10, top = 2 * 28 * 10)
par(mfrow = c(2, 8), mar = c(0, 0, 0, 0))
pictures %>%
purrr::array_tree(1) %>%
purrr::map(as.raster) %>%
purrr::iwalk(plot)
dev.off()
}
Das nossas vinte aulas, aqui está uma escolha de seis, cada uma mostrando desenhos reais na fila superior e falsos abaixo.






Provavelmente não confundimos a primeira e a segunda filas, mas os desenhos humanos reais também exibem enorme variação. E ninguém nunca disse que Pixelcnn period uma arquitetura para o aprendizado de conceitos. Sinta -se à vontade para brincar com outros conjuntos de dados de sua escolha – a distribuição Pixelcnn da TFP facilita.
Embrulhando
Neste submit, tivemos tfprobability
/ O TFP faz todo o trabalho pesado para nós e, portanto, pode se concentrar nos conceitos subjacentes. Dependendo de suas inclinações, essa pode ser uma situação supreme – você não perde de vista a floresta para as árvores. Por outro lado: você descobrir que a alteração dos parâmetros fornecidos não atinge o que deseja, você tem uma implementação de referência para começar. Então, qualquer que seja o resultado, a adição de tal funcionalidade de nível superior ao TFP é uma vitória para os usuários. (Se você é um desenvolvedor de TFP lendo isto: sim, gostaríamos de mais :-)).
Para todos, porém, obrigado por ler!
Oord, Aaron van den, Nal Kalchbrenner e Koray Kavukcuoglu. 2016. “Pixel Redes Neurais recorrentes”. Corr ABS/1601.06759. http://arxiv.org/abs/1601.06759.
Oord, Aaron van den, Nal Kalchbrenner, Oriol Vinyals, Lasse Espeholt, Alex Graves e Koray Kavukcuoglu. 2016. “Geração de imagem condicional com decodificadores de pixelcnn.” Corr ABS/1606.05328. http://arxiv.org/abs/1606.05328.
Salimans, Tim, Andrej Karpathy, Xi Chen e Diederik P. Kingma. 2017. “Pixelcnn ++: uma implementação de pixelcnn com probabilidade de mistura logística discretizada e outras modificações”. Em ICLR.