segunda-feira, 5 de setembro de 2016

MNIST profunda para Experts

MNIST profunda para Peritos

TensorFlow é uma biblioteca poderosa para fazer em larga escala computação numérica. Uma das tarefas a que se destaca é a implementação e treinamento de redes neurais profundas. Neste tutorial, vamos aprender os blocos de construção básicos de um modelo TensorFlow durante a construção de um classificador MNIST convolutional profundo.
Esta introdução assume familiaridade com redes neurais e o conjunto de dados MNIST. Se você não tem um fundo com eles, veja a introdução para iniciantes . Certifique-se de instalar TensorFlow antes de começar.

Sobre este tutorial

A primeira parte deste tutorial explica o que está acontecendo no mnist_softmax.py código, que é uma implementação básica de um modelo Tensorflow. A segunda parte mostra algumas maneiras de melhorar a precisão.
Você pode copiar e colar cada trecho de código a partir deste tutorial em um ambiente Python, ou você pode optar por apenas ler o código.
O que vamos fazer neste tutorial:
  • Criar uma função de regressão softmax que é um modelo para o reconhecimento de dígitos MNIST, com base na procura em cada pixel da imagem
  • Use Tensorflow para treinar o modelo de reconhecer dígitos por tê-lo "olhar" para milhares de exemplos (e executar nossa primeira sessão Tensorflow a fazê-lo)
  • Verifique a precisão dos modelos com os nossos dados de teste
  • Construir, treinar e testar uma rede neural convolutional multicamadas para melhorar os resultados

Configuração

Antes de criar o nosso modelo, vamos primeiro carregar o conjunto de dados MNIST, e iniciar uma sessão de TensorFlow.

Coloque MNIST Dados

Se você estiver copiando e colando o código a partir deste tutorial, comece aqui com estas duas linhas de código que irá baixar e ler automaticamente os dados:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

Aqui mnisté uma classe leve que armazena o treinamento, validação e conjuntos de testes como arrays numpy.Ele também fornece uma função para iterar minibatches de dados, que usaremos abaixo.

Comece TensorFlow InteractiveSession

TensorFlow depende de uma infra-estrutura altamente eficiente C ++ para fazer seu cálculo. A ligação a este método é chamado de sessão. O uso comum para programas TensorFlow é primeiro criar um gráfico e, em seguida, lançá-lo em uma sessão.
Aqui nós em vez usar o conveniente InteractiveSessionclasse, o que torna TensorFlow mais flexível sobre como você estruturar seu código. Ele permite que você intercalar operações que construir um gráfico de computação com aqueles que correm o gráfico. Isto é particularmente conveniente quando se trabalha em contextos interativos como IPython. Se você não estiver usando um InteractiveSession, então você deve construir o gráfico inteiro de computação antes de iniciar uma sessão e lançar o gráfico .
import tensorflow as tf
sess = tf.InteractiveSession()

computação Graph

Para fazer computação numérica eficiente em Python, que normalmente usam bibliotecas como NumPy que fazem operações caros, como a multiplicação de matrizes fora Python, usando o código altamente eficiente implementada em outro idioma. Infelizmente, ainda pode haver muita sobrecarga de mudar de volta para Python cada operação. Esta sobrecarga é especialmente ruim se você quiser executar cálculos sobre GPUs ou de uma forma distribuída, onde pode haver um custo elevado para a transferência de dados.
TensorFlow também faz o seu trabalho pesado fora Python, mas leva as coisas um passo adiante para evitar essa sobrecarga. Em vez de executar uma única operação cara independentemente do Python, TensorFlow nos permite descrever um gráfico de operações que são executados inteiramente fora Python interagir. Esta abordagem é semelhante ao utilizado na Théano ou tocha.
O papel do código Python é, por conseguinte, para construir este gráfico de cálculo externo, e para ditar que partes do gráfico de cálculo deve ser executado. Veja a Computação Graph secção de Uso Básico para obter mais detalhes.

Construir um modelo de regressão Softmax

Nesta seção vamos construir um modelo de regressão softmax com uma única camada linear. Na próxima seção, vamos estender isso para o caso de regressão softmax com uma rede convolutional multicamadas.

espaços reservados

Nós começar a construir o gráfico computação pela criação de nós para as imagens de entrada e classes de saída de destino.
x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])
Aqui xe y_não são valores específicos. Pelo contrário, são cada um placeholder - um valor que vamos entrada quando pedimos TensorFlow para executar um cálculo.
As imagens de entrada xserá composto por um tensor 2d de números de ponto flutuante. Aqui nós atribuir-lhe umshapede [None, 784], onde 784é a dimensionalidade de um único achatada 28 por imagem MNIST 28 pixels, eNoneindica que a primeira dimensão, correspondente à dimensão do lote, pode ser de qualquer tamanho. As classes de saída de destino y_também será composto por um tensor 2d, onde cada linha é um vetor 10-dimensional de um hot indicando qual classe (zero a nove) dígitos a imagem MNIST correspondente pertence.
O shapeargumento para placeholderé opcional, mas permite TensorFlow para pegar automaticamente erros decorrentes de formas de tensores inconsistentes.

variáveis

Vamos agora definir os pesos We preconceitos bpara o nosso modelo. Podemos imaginar tratar estas entradas adicionais como, mas TensorFlow tem uma maneira ainda melhor para lidar com eles: Variable. Um Variableé um valor que vive no gráfico de computação de TensorFlow. Ele pode ser usado e ainda modificado pela computação. Em aplicações de aprendizagem de máquina, um geralmente tem os parâmetros do modelo serVariables.
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
Passamos o valor inicial para cada parâmetro na chamada para tf.Variable. Neste caso, nós inicializar ambosWe bcomo tensores cheios de zeros. WÉ uma matriz de 784x10 (porque temos 784 recursos de entrada e 10 saídas) e bé um vetor 10-dimensional (porque temos 10 classes).
Antes de Variables pode ser usado dentro de uma sessão, eles devem ser inicializado usando essa sessão. Esta etapa leva os valores iniciais (neste caso, tensores cheios de zeros) que já foram especificados, e os atribui a cada um Variable. Isto pode ser feito por todos Variablesde uma só vez:
sess.run(tf.initialize_all_variables())

Previu classe e função de perda

Agora podemos implementar nosso modelo de regressão. Leva apenas uma linha! Multiplicamos as imagens de entrada vetorizadas xpela matriz de pesos W, adicione o viés b, e calcular as probabilidades softmax que são atribuídos a cada classe.
y = tf.nn.softmax(tf.matmul(x,W) + b)
Podemos especificar uma função de perda com a mesma facilidade. Perda indica o quão ruim a predição do modelo foi em um único exemplo; tentamos minimizar que, enquanto a formação em todos os exemplos. Aqui, a nossa função de perda é o cross-entropia entre o alvo e previsão do modelo:
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
Note-se que tf.reduce_sum resume em todas as classes e tf.reduce_mean leva a média sobre esses montantes.

Treinar o modelo

Agora que definimos a nossa função de modelo e treinamento de perda, é simples para treinar usando TensorFlow.Porque TensorFlow sabe todo o gráfico computação, pode usar diferenciação automática para encontrar os gradientes da perda em relação a cada uma das variáveis. TensorFlow tem uma variedade de algoritmos de optimização embutidos . Para este exemplo, vamos usar mais íngreme gradiente descendente, com um comprimento do passo de 0,5, para descer a entropia cruz.
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
O que TensorFlow realmente fez naquela única linha foi adicionar novas operações para o gráfico de computação.Essas operações incluíram aqueles para calcular gradientes, calcular passos de atualização de parâmetros, e aplicar medidas de actualização para os parâmetros.
A operação retornado train_step, quando executado, irá aplicar as atualizações gradiente descendente aos parâmetros. Treinando o modelo pode, portanto, ser realizado através da execução repetidamente train_step.
for i in range(1000):
  batch = mnist.train.next_batch(100)
  train_step.run(feed_dict={x: batch[0], y_: batch[1]})
Nós carga de 100 exemplos de treinamento em cada iteração de treinamento. Em seguida, executar atrain_stepoperação, usando feed_dictpara substituir os placeholdertensores xe y_com os exemplos de treinamento. Observe que você pode substituir qualquer tensor no seu gráfico de computação usandofeed_dict- não está restrito a apenas placeholders.

Avaliar o Modelo

Quão bem o nosso modelo de fazer?
Primeiro vamos descobrir onde nós previmos o rótulo correto. tf.argmaxÉ uma função extremamente útil que lhe dá o índice da entrada mais alta em um tensor ao longo de alguns eixos. Por exemplo, tf.argmax(y,1)é o nosso modelo de rótulo pensa é mais provável para cada entrada, enquanto que tf.argmax(y_,1)é o verdadeiro rótulo. Podemos usar tf.equalpara verificar se a nossa previsão corresponde à verdade.
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
Isso nos dá uma lista de booleanos. Para determinar que fração estão corretos, nós convertido para números de ponto flutuante e, em seguida, tomar a média. Por exemplo, [True, False, True, True]se tornaria[1,0,1,1]que se tornaria 0.75.
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
Finalmente, podemos avaliar a nossa precisão nos dados de teste. Esta deve ser cerca de 92% correto.
print(accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

Criar uma Convolucional Rede Multilayer

Recebendo 92% de precisão em MNIST é ruim. É quase embaraçosamente ruim. Nesta seção, vamos consertar isso, saltando de um modelo muito simples para algo moderadamente sofisticada: uma rede neural convolutional pequena. Isso vai nos levar a precisão em torno de 99,2% - não estado da arte, mas respeitável.

peso Inicialização

Para criar este modelo, nós estamos indo a necessidade de criar um monte de pesos e preconceitos. Deve-se geralmente pesos inicializar com uma pequena quantidade de ruído para a quebra de simetria, e para evitar gradientes de 0. Desde que nós estamos usando Relu neurônios, também é uma boa prática para inicializar-los com um viés inicial ligeiramente positiva para evitar "neurônios mortos". Em vez de fazer isso várias vezes enquanto nós construir o modelo, vamos criar duas funções úteis para fazer isso por nós.
def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

Convolution e Pooling

TensorFlow também nos dá muita flexibilidade em operações de convolução e agrupamento. Como lidamos com os limites? Qual é o nosso tamanho do passo? Neste exemplo, estamos sempre indo para escolher a versão de baunilha. Os nossos convoluções utiliza um passo de um acolchoado e são zero para que a saída é do mesmo tamanho que a entrada. Nossa pooling é simples max idade pooling sobre blocos 2x2. Para manter o nosso código mais limpo, vamos também abstrair essas operações em funções.
def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

Primeira Camada convolucional

Agora podemos implementar nossa primeira camada. Será composto por convolução, seguido de pooling max. O convolutional irá computar 32 características para cada patch 5x5. O seu peso tensor terá uma forma de [5, 5, 1, 32]. As primeiras duas dimensões são o tamanho do adesivo, o seguinte é o número de canais de entrada, e o último é o número de canais de saída. Nós também terá um vector de polarização com um componente para cada canal de saída.
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
Para aplicar a camada, primeiro remodelar xa um tensor 4d, com a segunda e terceira dimensões correspondente à largura e altura da imagem, e a dimensão final correspondente ao número de canais de cor.
x_image = tf.reshape(x, [-1,28,28,1])
Em seguida, convolve x_imagecom o tensor de peso, adicione o viés, aplicar a função de Relu e piscina, finalmente, max.
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

Segunda camada convolucional

A fim de construir uma rede profunda, empilhar várias camadas deste tipo. A segunda camada terá 64 características para cada patch 5x5.
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

Camada densamente Connected

Agora que o tamanho da imagem foi reduzida para 7x7, que adicionar uma camada completamente ligada com 1024 neurónios para permitir o processamento em toda a imagem. Nós remodelar o tensor da camada de pooling em um lote de vetores, multiplicar por uma matriz de peso, adicione um viés, e aplicar um Relu.
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

Cair fora

Para reduzir overfitting, vamos aplicar abandono antes da camada de leitura. Criamos um placeholderpara a probabilidade de que a saída de um neurônio é mantido durante abandono. Isto permite-nos transformar abandono durante a formação, e desligá-lo durante os testes. De TensorFlow tf.nn.dropoutop trata automaticamente escalar saídas de neurônios, além de mascaramento-las, de modo abandono simplesmente funciona sem qualquer escala adicional. 1
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

Camada de leitura

Por fim, adicione uma camada softmax, assim como para a regressão softmax uma camada acima.
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

Treinar e avaliar o modelo

Até que ponto esse modelo faz? Para treinar e avaliá-lo, vamos utilizar o código que é quase idêntico ao que, para a rede simples SoftMax uma camada acima.
As diferenças são que:
  • Vamos substituir o mais íngreme descida otimizador de gradiente com o otimizador ADAM mais sofisticado.
  • Vamos incluir o parâmetro adicional keep_probno feed_dictpara controlar a taxa de abandono.
  • Nós vamos adicionar o log para cada iteração 100 no processo de formação.
Sinta-se livre para ir em frente e executar este código, mas ele faz 20.000 iterações de formação e pode demorar algum tempo (possivelmente até meia hora), dependendo do seu processador.
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
sess.run(tf.initialize_all_variables())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
    train_accuracy = accuracy.eval(feed_dict={
        x:batch[0], y_: batch[1], keep_prob: 1.0})
    print("step %d, training accuracy %g"%(i, train_accuracy))
  train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print("test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
O final de precisão conjunto de teste depois de executar este código deve ser de aproximadamente 99,2%.
Nós aprendemos como rapidamente e facilmente construir, treinar e avaliar um modelo de aprendizagem profunda bastante sofisticado usando TensorFlow.
1 : Para esta pequena rede convolucional, o desempenho é realmente quase idênticos com e sem abandono.Dropout é frequentemente muito eficaz na redução overfitting, mas é mais útil quando treinando muito grandes redes neurais. ↩