Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Como implementar modelos clássicos de redes neurais usando o Tensor Flow (a nova toolbox do Google de Machine Learning)?

+2 votos
1,753 visitas
perguntada Nov 20, 2015 em Aprendizagem de Máquinas por estudante (431 pontos)  

Tensor Flow

Compartilhe

1 Resposta

+1 voto
respondida Nov 20, 2015 por danielcajueiro (5,261 pontos)  
selecionada Nov 23, 2015 por estudante
 
Melhor resposta

Eu vou discutir a implementação desses modelos clássicos desses modelos de redes neurais usando a interface de Python (é provável que num futuro próximo seja desenvolvida uma interface para R). [Quem não sabe exatamente o que são redes neurais, vale a pena dar uma olhada na pergunta: O que são redes neurais?.]

A idéia por detrás do Tensor Flow é fazer uma computação através da noção de grafos que podem ser usados para representar os "nós" que representam as operações simbólicas usadas em modelos de redes neurais e as "arestas" que representam os tensores (vetores de várias dimensões). Essa concepção justifica o nome do sistema "Tensor Flow" = Fluxo de Vetores = Operações sobre vetores e é fundamental para permitir a computação simbólica do algoritmo de backpropagation (que é a forma de calcular gradientes em redes neurais usados para a otimização dos parâmetros) numa classe bem geral de redes. Ou seja, Tensor Flow internamente define a operação simbólica de backpropagation para operações muito básicas que provavelmente qualquer tipo de rede neural (seja ela clássica=Shalow ou deep) usará. Logo, ao definir um grafo que apresenta uma sequencia de operações, o Tensor Flow automaticamente retorna os gradientes necessários para a "estimação" dos parâmetros da rede. Dessa forma, qualquer implementação de redes neurais no Tensor Flow deve ter como objetivo criar um código que gera esses grafos simbólicos de operações e tensores.

Eu vou apresentar dois exemplos clássicos. Em ambos os casos, existem duas partes relevantes no código:

a) A definição simbólica das variáveis de entrada e saída, que é feita no Tensor Flow através de objetos chamados de "placeholders".

b) A definição do grafo usado no Tensor Flow para especificar o fluxo de operações feita nas implementações abaixo em "model".

Exemplo 1: Modelo Linear

Eu gero um vetor de dados usando o seguinte modelo linear com a seguinte equação:

\[y(x)=\beta_0+\beta_1 x_1+\beta_2 x_2,\]

onde \(\beta_0=1\), \(\beta_1=2\) e \(\beta_3=3\)

Então, eu implemento um modelo de rede neural linear (sem camada escondida) e ele como esperado, após 4 interações, converge para os valores desejados: \(\beta_0=1.0001874\), \(\beta_1=2.00007677\) e \(\beta_2=2.99956393\).

import tensorflow as tf
import numpy as np

def int_bias(shape):
    return tf.Variable(tf.zeros(shape))

def init_weights(shape):
    return tf.Variable(tf.random_uniform(shape, -1.0, 1.0))

def model(x,w,b):
    return tf.matmul(x,w)+b    

def generateData(n):
    theInput = np.float32(np.random.normal(0,1,[n,2])) # Random input            
    theOutput=np.empty([n])
    for i in range(n):
        theOutput[i]=1+2*theInput[i,0]+3*theInput[i,1]
    return theInput,theOutput


if __name__ == '__main__':

# Generate Data
    n=100
    [theInput,theOutput]=generateData(n)


    w = init_weights([2,1])
    b = init_weights([1])

    X=tf.placeholder("float",[None,2])
    Y=tf.placeholder("float",[None,1])    

    y_x = model(X,w,b)

# Minimizing the squared errors.
    loss = tf.square(Y-y_x)
    optimizer = tf.train.GradientDescentOptimizer(0.01)
    train = optimizer.minimize(loss)

# For initializing the variables.
    init = tf.initialize_all_variables()

# Launch the graph
    sess = tf.Session()
    sess.run(init)

# Fit the plane.
    numberEpochs=10
    for step in range(numberEpochs):
        for (x,y) in zip(theInput,theOutput): 
            sess.run(train,feed_dict={X:x.reshape(1,2),Y:y.reshape(1,1)})
            #if step % 20 == 0:
        print step, sess.run(b), sess.run(w)

Exemplo 2: Modelo para aproximar função \(f(x)=sin(x)\)

Nesse exemplo, eu gero dados para a função \(f(x)=sin(x)\) no intervalo \([0,2\pi]\).

Para aproximar a função \(f(x)=sin(x)\) eu uso uma rede neural com uma camada escondida de 5 neurônios com funções tangentes hiperbólicas. De fato, se você desenhar a função seno, você perceberá que você precisa de pelo menos 5 tangentes hiperbólicas.

As três figuras abaixo mostram respectivamente a qualidade da aproximação no (1) início do aprendizado, (2) depois de 50 iterações e (3) depois de 500 iterações:

Neural network tensor flow

Neural network tensor flow

Neural network tensor flow

import tensorflow as tf
import numpy as np
import math
import matplotlib.pyplot as plt

def init_bias(shape):
    return tf.Variable(tf.zeros(shape))

def init_weights(shape):
    return tf.Variable(tf.random_uniform(shape, -1.0, 1.0))

def model(X,w_h,b_h,w_o,b_o):
    h=tf.nn.tanh(tf.matmul(X, w_h)+b_h) 
    return tf.matmul(h, w_o)+b_o


def generateSin(n):
    theInput = np.float32(np.random.uniform(0,6.28,[n,1])) # Random input            
    theOutput=np.empty([n])
    for i in range(n):
        theOutput[i]=np.sin(theInput[i])
    return theInput,theOutput

def generateFigure(theInput,theOutput,weightHidden,weightOutput,biasHidden,biasOutput):
    sizeInput=np.size(theInput)
    nnOutput=np.empty([sizeInput])
    numberHiddenUnits=np.size(weightHidden)

    for k in range(sizeInput):
        nnOutput[k]=biasOutput
        for i in range(numberHiddenUnits):
            nnOutput[k]=nnOutput[k]+weightOutput[i,0]*np.tanh(theInput[k]*weightHidden[0,i]+biasHidden[i])

    fig = plt.figure()
    ax1 = fig.add_subplot(111)  
    ax1.axis([0, 2*math.pi, -1.5, 1.5]) 
    fig.hold()
    ax1.plot(theInput,theOutput,'bo',markersize=7, markeredgewidth=0)
    ax1.plot(theInput,nnOutput,'ro',markersize=7, markeredgewidth=0)

if __name__ == '__main__':

# Generate Data
    n=100
    [theInput,theOutput]=generateSin(n)

    numberInputs=1
    numberHiddenUnits=5
    numberOutputs=1

    w_h = init_weights([numberInputs,numberHiddenUnits])
    b_h = init_bias([numberHiddenUnits])

    w_o=init_weights([numberHiddenUnits,numberOutputs])
    b_o=init_weights([numberOutputs])    

    X=tf.placeholder("float",[None,numberInputs])
    Y=tf.placeholder("float",[None,numberOutputs])    

    y_x = model(X,w_h,b_h,w_o,b_o)

# Minimizing the squared errors.
    loss = tf.square(Y-y_x)
    optimizer = tf.train.GradientDescentOptimizer(0.01)
    train = optimizer.minimize(loss)

# For initializing the variables.
    init = tf.initialize_all_variables()

# Launch the graph
    sess = tf.Session()
    sess.run(init)

    tf.train.write_graph(sess.graph_def, '/home/daniel/Documents/Projetos/Prorum/ProgramasEmPython/ClassicalNeuralNetworksWithTensorFlow/graphOutput', 'graph.pbtxt')

# Fit the plane.
    numberEpochs=1
    for step in range(numberEpochs):
        print step
        for (x,y) in zip(theInput,theOutput): 
            sess.run(train,feed_dict={X:x.reshape(1,1),Y:y.reshape(1,1)})

    weightHidden=sess.run(w_h) 
    weightOutput=sess.run(w_o)
    biasHidden=sess.run(b_h)
    biasOutput=sess.run(b_o)     


generateFigure(theInput,theOutput,weightHidden,weightOutput,biasHidden,biasOutput)
...