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:



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)