segunda-feira, 5 de setembro de 2016

MNIST Para ML Iniciantes

MNIST Para ML Iniciantes

Este tutorial é destinado a leitores que são novos para a aprendizagem de máquina e TensorFlow. Se você já sabe o que é MNIST, eo que é softmax (logística multinomial) regressão, você pode preferir fazer esse tutorial em um ritmo mais rápido. Certifique-se de instalar TensorFlow antes de iniciar o tutorial.
Quando se aprende a programar, há uma tradição que a primeira coisa a fazer é imprimir "Olá mundo". Assim como a programação tem Olá mundo, aprendizado de máquina tem MNIST.

MNIST é uma simples visão de computador dataset(conjunto de dados). Ele consiste em imagens de numeros escritos à mão como estes:


Ele também inclui etiquetas para cada imagem, nos dizendo qual numero é. Por exemplo, as etiquetas para as imagens acima são 5, 0, 4, e 1.

Neste tutorial, vamos treinar(construir) um modelo para olhar as imagens e  prever quais numeros eles são. Nosso objetivo não é treinar um modelo muito elaborado que alcança um desempenho estado-da-arte embora nós vamos dar-lhe o código para fazer isso mais tarde! - Mas sim para mergulhar um dedo do pé usando TensorFlow. Como tal, vamos começar com um modelo muito simples, chamado de Softmax Regressão.

O código real para este tutorial é muito curta, e todo o material interessante acontece em apenas três linhas. No entanto, é muito importante para entender as idéias por trás dele: tanto como TensorFlow funciona e os conceitos de aprendizagem de máquina do núcleo. Devido a isso, estamos indo para o trabalho com muito cuidado através do código.

Sobre este tutorial

Este tutorial é uma explicação, linha por linha, do que está acontecendo no código mnist_softmax.py.

Você pode usar este tutorial em algumas maneiras diferentes, incluindo:

  • Copie e cole cada trecho de código, linha por linha, em um ambiente Python como você lida com as explicações de cada linha. 
  • Execute o arquivo inteiro mnist_softmax.py Python antes ou depois de ler as explicações, e usar este tutorial para entender as linhas de código que não são claros para você.

O que vamos fazer neste tutorial:
Aprender  sobre os dados MNIST e regressões softmax
Criar uma função que é um modelo para reconhecendo de dígitos, 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

O Data MNIST

Os dados MNIST está hospedado no site da Yann LeCun. 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)

Os dados MNIST é dividido em três partes: 55.000 pontos de dados de dados de treinamento (mnist.train), 10.000 pontos de dados de teste (mnist.test), e 5.000 pontos de dados de validação (mnist.validation). Esta divisão é muito importante: é essencial na aprendizagem de máquina que temos dados separado, que nós não aprendemos a partir, para que possamos ter certeza de que o que aprendemos realmente generaliza!

Como mencionado anteriormente, todos os pontos de dados MNIST tem duas partes: uma imagem de um dígito escrita à mão e uma etiqueta correspondente. Vamos chamar a imagens "x" e os rótulos "y". Tanto o conjunto de treinamento e conjunto de teste contêm imagens e seus rótulos correspondentes; por exemplo, as imagens de formação são mnist.train.images e os rótulos de formação são mnist.train.labels.

Cada imagem é de 28 pixels por 28 pixels. Podemos interpretar isso como uma grande variedade de números:



Nós podemos achatar essa matriz em um vetor de 28x28 = 784 números. Não importa como nós achatar a matriz, enquanto estamos consistente entre imagens. A partir dessa perspectiva, as imagens MNIST são apenas um bando de pontos em um espaço vetorial 784-dimensional, com uma estrutura muito rica (aviso: visualizações de computação intensiva).

Achatando os dados joga fora informações sobre a estrutura 2D da imagem. não é tão ruim assim? Bem, os melhores métodos de visão computacional que explorar essa estrutura, e vamos em tutoriais posteriores. Mas o método simples que usaremos aqui, uma regressão softmax (definido abaixo), não vai.

O resultado é que mnist.train.images é um tensor (uma matriz n-dimensional) com uma forma de [55000, 784]. A primeira dimensão é um índice para a lista de imagens e a segunda dimensão é a de índice para cada pixel em cada imagem. entrada no Leste do tensor é uma intensidade de pixel entre 0 e 1, para um elemento de imagem particular numa imagem particular.




Cada imagem em MNIST tem uma etiqueta correspondente, um número entre 0 e 9 que representam o dígito desenhado na imagem.

Para os fins deste tutorial, nós vamos querer nossos rótulos como "vectores de um quentes". Um vector de um-quente é um vector que é 0 na maioria das dimensões, e 1 em uma única dimensão. Neste caso, o dígito enésimo será representada como um vector que é um nth nas dimensões. Por exemplo, seria de 3 [0,0,0,1,0,0,0,0,0,0]. Consequentemente, mnist.train.labels é um [55000, 10] matriz de carros alegóricos.



Agora estamos prontos para realmente fazer o nosso modelo!

Softmax Regressions

Sabemos que cada imagem em MNIST é de um dígito manuscrita entre zero e nove. Portanto, há apenas dez coisas possíveis que uma dada imagem pode ser. Queremos ser capazes de olhar para uma imagem e dar as probabilidades para que seja cada dígito. Por exemplo, o nosso modelo pode olhar para uma foto de um nove e ser 80% de certeza que é um nove, mas dão uma chance de 5% ao facto de ser um oito (por causa do laço superior) e um pouco de probabilidade de todos os outros, porque não é 100% de certeza.

Este é um caso clássico onde uma regressão softmax é um modelo natural, simples. Se você quiser atribuir probabilidades a um objeto sendo uma das várias coisas diferentes, softmax é a coisa a fazer, porque softmax nos dá uma lista de valores entre 0 e 1, que somam 1. Mesmo mais tarde, quando treinamos mais sofisticado modelos, o passo final será uma camada de SoftMax.

Uma regressão softmax tem duas etapas: primeiro somarmos a evidência da nossa entrada estando em certas classes e, em seguida, converter essa evidência em probabilidades.

Coaduna-se com a evidência de que uma determinada imagem está em uma classe particular, fazemos uma soma ponderada das intensidades de pixel. O peso é negativo se o pixel com uma elevada intensidade é evidência contra a imagem estar nessa classe, e positivo se for evidências a favor.

O diagrama a seguir mostra os pesos de um modelo aprendidas para cada uma dessas classes. O vermelho representa pesos negativos, enquanto o azul representa pesos positivos.



Nós também adicionar alguma evidência extra chamado um viés. Basicamente, queremos ser capazes de dizer que algumas coisas são mais propensos independente da entrada. O resultado é que a evidência para uma classe i dada uma entrada x é:

evidence i = ∑ j W i ,   j x j + b i

onde W i é o peso e b i é o viés para a classe i e j é um índice para somar ao longo dos pixels na nossa imagem de entrada x . Em seguida, converter a evidência registra em nossas probabilidades previstas y usando a função "softmax":

y = softmax ( evidence )

Aqui softmax está servindo como uma "activação" ou função de "ligação", moldagem a saída da nossa função linear na forma queremos - neste caso, uma distribuição de probabilidade mais de 10 casos. Você pode pensar nisso como converter contagens de prova em probabilidades do nosso entrada que está sendo em cada classe. É definido como:

softmax ( x ) = normalize ( exp ⁡ ( x ) )

Se você expandir essa equação, você obtém:

softmax ( x ) i = exp ⁡ ( x i ) ∑ j exp ⁡ ( x j )
 
Mas é muitas vezes mais útil pensar em softmax a primeira maneira: exponencializando suas entradas e, em seguida, normalizando-los. A exponenciação significa que mais uma unidade de provas aumenta o peso dado a qualquer hipótese multiplicatively. E por outro lado, ter uma unidade de menos evidência significa que uma hipótese obtém uma fracção do seu peso antes. Nenhuma hipótese alguma vez tem zero ou peso negativo. Softmax, em seguida, normaliza estes pesos, de modo a que eles adiciona-se a uma, formando uma distribuição de probabilidade válido. (Para obter mais intuição sobre a função softmax, confira a seção sobre ele no livro de Michael Nielsen, completo com uma visualização interativa.)

Você pode imaginar a nossa regressão softmax como olhar algo como o seguinte, embora com muito mais x s. Para cada saída, calculamos a soma ponderada dos x s, adicione um viés, e depois aplicar softmax.



Se nós escrevemos isso como equações, obtemos:



Nós podemos "vetorizar" este procedimento, transformando-o em uma multiplicação de matrizes e vector disso. Isto é útil para a eficiência computacional. (É também uma maneira útil de pensar.)



Mais compacta, podemos simplesmente escrever:

y = softmax ( W x + b )

Agora vamos transformar isso em algo que Tensorflow pode usar.

Implementando a Regressão

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. (Abordagens como este pode ser visto em algumas bibliotecas de aprendizagem da máquina).

Para usar TensorFlow, primeiro precisamos importá-lo.

import tensorflow as tf

Descrevemos estas operações que interagem através da manipulação de variáveis ​​simbólicas. Vamos criar um:

x = tf.placeholder(tf.float32, [None, 784])

X não é um valor específico. É um placeholder, um valor que vamos entrada quando pedimos TensorFlow para executar um cálculo. Queremos ser capazes de introduzir qualquer número de imagens MNIST, cada achatados em um vetor 784-dimensional. Nós representamos este como um tensor 2-D de números de ponto flutuante, com uma forma [Nenhum, 784]. (Aqui Nenhum significa que uma dimensão pode ser de qualquer comprimento).

Precisamos também os pesos e preconceitos para o nosso modelo. Podemos imaginar tratar estes como entradas adicionais, mas TensorFlow tem uma maneira ainda melhor para lidar com isso: Variável. Uma variável é um tensor modificável que vive no gráfico de operações interagindo de TensorFlow. Ele pode ser usado e ainda modificado pela computação. Para aplicações de aprendizagem de máquina, um geralmente tem os parâmetros do modelo ser variáveis.

W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

Nós criamos estas variáveis ​​dando tf.Variable o valor inicial da variável: neste caso, nós inicializar ambos W e b como tensores cheios de zeros. Uma vez que estamos indo para aprender W e b, não importa muito o que inicialmente são.

Observe que W tem uma forma de [784, 10] porque queremos multiplicar os vectores de imagem 784-dimensionais por ele para produzir vetores 10-dimensionais de provas para as classes de diferença. b tem uma forma de [10], para que possamos adicioná-lo à saída.

agora podemos implementar nosso modelo. Leva apenas uma linha para defini-lo!

y = tf.nn.softmax(tf.matmul(x, W) + b)

Em primeiro lugar, nós multiplicamos x por W com o tf.matmul expressão (x, W). Este é invertido a partir de quando eu multipliquei-los à nossa equação, onde tivemos W x , como um pequeno truque para lidar com x sendo um tensor 2D com múltiplas entradas. Em seguida, adicione b, e, finalmente, aplicar tf.nn.softmax.

É isso aí. Nos levou apenas uma linha para definir nosso modelo, depois de um par de curtas linhas de configuração. Isso não é porque TensorFlow é projetado para fazer uma regressão softmax particularmente fácil: é só uma forma muito flexível para descrever muitos tipos de cálculos numéricos, a partir de modelos de aprendizado de máquina para simulações de física. E uma vez definido, o nosso modelo pode ser executado em diferentes dispositivos: CPU do seu computador, GPUs e até mesmo telefones!

Treinamento

Para treinar o nosso modelo, precisamos definir o que significa para o modelo a ser bom. Bem, na verdade, no aprendizado de máquina que normalmente definem o que significa para um modelo a ser ruim. Chamamos a isto o custo, ou a perda, e representa quão longe nosso modelo é do nosso resultado desejado. Tentamos minimizar esse erro, e quanto menor a margem de erro, o melhor o nosso modelo é.

Uma função muito comum, muito bom para determinar a perda de um modelo é chamado de "cross-entropia." Cross-entropia surge de pensar sobre informação códigos de compressão na teoria da informação, mas acaba sendo uma ideia importante em lotes de áreas, de jogar a aprendizagem de máquina. É definido como:

H y ′ ( y ) = − ∑ i y i ′ log ⁡ ( y i )

Onde y é a distribuição de probabilidade prevista, e y ′ é a verdadeira distribuição (o vector um-quente com os rótulos de dígitos). Em certo sentido, áspero, o cross-entropia é medir o quão ineficiente nossas previsões são para descrever a verdade. Entrando em mais detalhes sobre cross-entropia está além do escopo deste tutorial, mas vale bem a pena o entendimento.

Para implementar cross-entropia é preciso primeiro adicionar um novo espaço reservado para inserir as respostas corretas:

y_ = tf.placeholder(tf.float32, [None, 10])

Então, podemos implementar a função cross-entropia,  − ∑ y ′ log ⁡ ( y )

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

Em primeiro lugar, calcula tf.log o logaritmo de cada elemento de y. A seguir, multiplicar cada elemento de Y_ com o elemento correspondente de tf.log (y). Em seguida, adiciona tf.reduce_sum os elementos na segunda dimensão de y, devido às reduction_indices = [1] parâmetros. Finalmente, tf.reduce_mean calcula a média sobre todos os exemplos do lote.

Agora que sabemos o que queremos que o nosso modelo de fazer, é muito fácil ter TensorFlow treiná-lo para fazê-lo. Porque TensorFlow sabe todo o gráfico dos seus cálculos, ele pode usar automaticamente o algoritmo de retropropagação para determinar de forma eficiente como suas variáveis ​​afetam a perda você perguntar isso para minimizar. Em seguida, ele pode aplicar a sua escolha de algoritmo de otimização para modificar as variáveis ​​e reduzir a perda.

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

Neste caso, pedir TensorFlow para minimizar cross_entropy usando o algoritmo de gradiente descendente, com uma taxa de aprendizagem de 0,5. gradiente descendente é um procedimento simples, onde TensorFlow simplesmente transfere cada variável de um pouco na direcção em que reduz o custo. Mas TensorFlow também oferece muitos outros algoritmos de otimização: usando um é tão simples como ajustar uma linha.

O que TensorFlow realmente faz aqui, nos bastidores, é adicionar novas operações no seu gráfico que implementar backpropagation e gradiente descendente. Em seguida, ele dá-lhe de volta uma única operação que, quando executado, faz uma etapa de formação gradiente descendente, ajustando ligeiramente suas variáveis ​​para reduzir a perda.

Agora temos o nosso modelo criado para treinar. Uma última coisa antes de iniciá-lo, temos que criar uma operação para inicializar as variáveis ​​que criamos. Note que esta define a operação, mas não executá-lo ainda:

init = tf.initialize_all_variables()

Nós podemos agora lançar o modelo em uma sessão, e agora nós executar a operação que inicializa as variáveis:

sess = tf.Session()
sess.run(init)

Vamos trem - vamos executar o passo de formação 1000 vezes!

for i in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

Cada etapa do circuito, temos um "lote" de cem pontos de dados aleatórios do nosso conjunto de treinamento. Corremos alimentação train_step nos dados de lotes para substituir os espaços reservados.

Usando pequenos lotes de dados aleatório é chamado formação estocástica - neste caso, estocástica gradiente descendente. Idealmente, gostaríamos de usar todos os nossos dados para cada etapa do treinamento porque isso nos daria uma melhor noção do que deveríamos estar fazendo, mas isso é caro. Então, em vez disso, usamos um subconjunto diferente de cada vez. Fazer isso é barato e tem muito do mesmo benefício.

Avaliando Nosso Modelo

Como bem o nosso modelo de fazer?

Bem, 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 tf.argmax (Y_, 1), é a etiqueta correcta. Podemos usar tf.equal para 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, [verdadeiro, falso, verdade, verdade] se tornaria [1,0,1,1], que se tornaria 0,75.

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

Finalmente, pedimos a nossa precisão em nossos dados de teste.

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

Esta deve ser cerca de 92%.

Isso é bom? Bem, na verdade não. Na verdade, é muito ruim. Isto é porque nós estamos usando um modelo muito simples. Com algumas pequenas mudanças, podemos chegar a 97%. Os melhores modelos pode chegar a precisão ao longo de 99,7%! (Para mais informações, ter um olhar para esta lista de resultados.)

O que importa é que nós aprendemos a partir deste modelo. Ainda assim, se você estiver sentindo um pouco para baixo sobre estes resultados, confira a próxima tutorial onde iremos fazer muito melhor e aprender a construir modelos mais sofisticados que usam TensorFlow!

Nenhum comentário:

Postar um comentário