\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[brazil]{babel}
\usepackage{graphicx}
\usepackage[colorlinks, urlcolor=blue]{hyperref}
\include{pythonlisting}

\renewcommand{\familydefault}{\sfdefault}
\title{Relatório do trabalho 4 \\ Rede neural para reconhecimento ótico de caracteres}
\author{João Paulo Pizani Flor \\ Mauricio Oliveira Haensch}
\date{\today}


%------------------------------------------------------------------------------------------------
% Achei na net esse comando, serve para mudar temporariamente as margens
% Precisei usar para inserir o codigo em python, tava muito grande para caber nas margens usadas
\newenvironment{changemargin}[2]{
\begin{list}{}{
  \setlength{\topsep}{0pt}
  \setlength{\leftmargin}{#1} 
  \setlength{\rightmargin}{#2}
  \setlength{\listparindent}{\parindent}
  \setlength{\itemindent}{\parindent}
  \setlength{\parsep}{\parskip}
}
\item[]}{\end{list}}
% -------- Utilizacao: --------------------------------------------------------------------------
%\begin{changemargin}{margem esquerda}{margem direita}
%  stuff
%\end{changemargin}
%------------------------------------------------------------------------------------------------



\begin{document}

    \maketitle
    \thispagestyle{empty}
    \pagebreak

    \section{Introdução}
        \paragraph{}
        O objetivo deste trabalho é criar uma rede neural capaz de identificar dígitos de 0 a 9, não
        sendo necessário implementar uma rede, apenas utilizar um simulador. Para isso, dois simuladores
        foram sugeridos: SNNS (Stuttgart Neural Network Simulator) e JNNS (Java Neural Network Simulator).
        A descrição	do trabalho disponibilizada aos alunos pode ser vista abaixo:

        \paragraph{}
        Criar uma rede neural capaz de reconhecer dígitos (0-9). Detalhes:

        \begin{itemize}
            \item Não é preciso implementar, basta utilizar um simulador pronto. Sugiro usar o SNNS ou
                JNNS.
            \item A camada de entrada deve ter um grid de entrada de tamanho 10x15 (15 de altura e 10
                de largura; tamanho das imagens do conjunto de treinamento)
            \item Como resposta a rede deve identificar qual dos possíveis dígitos tenta-se identificar.
            \item Entregar implementação ou arquivo de configuração da rede, caso tenham utilizado o SNNS.
            \item Entregar relatório.
            \item Sugestão: utilizar os valores normalizados dos pixels, ou seja, os mesmos devem ficar
                entre 0 e 1.
        \end{itemize}

        \paragraph{}
        O trabalho consistia em criar uma rede neural artificial \emph{feed-forward} com uma camada intermediária
        (\emph{hidden}), utilizando um simulador de escolha livre do grupo. A rede deveria ser treinada
        utilizando-se o algoritmo \emph{Backpropagation}.


    \pagebreak
    \section{Ferramentas utilizadas}

        \paragraph{}
        Nosso grupo escolheu o simulador JavaNNS para a implementação do trabalho, devido ao fato de que o
        mesmo possui versões mais atuais e principalmente por ser multiplataforma (roda na máquina virtual
        Java\textregistered).

        \paragraph{}
        Além do simulador propriamente dito, utilizamos mais duas ferramentas para fazer um pré-processamento
        das imagens de entrada antes do treinamento:

        \begin{description}
            \item[ImageMagick] O comando ``convert'' do pacote ImageMagick foi utilizado em um script que
                converteu todas as imagens de entrada fornecidas para o \emph{espaço de cores
                monocromático}, onde cada pixel contém apenas um valor de 8 bits, representando o brilho
                daquele ponto.
            \item[Python] Escrevemos um script em Python para ler cada uma das imagens de treinamento de um
                diretório e produzir um arquivo de texto no formato aceito pelo JavaNNS.
        \end{description}

        \paragraph{}
        Abaixo está o código desse script de geração de padrões de treinamento. Todos os padrões são
        consolidados em um único arquivo, ``ocrTraining.pat''.

        \begin{changemargin}{-3cm}{-3cm}
            \begin{python}
#!/usr/bin/env python
#-*- coding: utf8 -*-

import Image
import sys
import os

header = """SNNS pattern definition file V3.2
generated at Mon Mai 02 10:00:00 2011

No. of patterns : 70
No. of input units : 150
No. of output units : 10"""

imgWidth = 10
imgHeight = 15

if __name__ == "__main__":
    directory = sys.argv[1]
    imageFiles = os.listdir(directory)
    os.chdir(directory)

    trainingFileContents = ""
    trainingFileContents += header + os.linesep + os.linesep

    counter = 0
    for fname in imageFiles:
        if (fname[-3:] != "png"):
            continue

        handle = Image.open(fname)
        trainingFileContents += os.linesep + "#Input case " + str(counter)
        for pixY in range(imgHeight):
            trainingFileContents += os.linesep
            for pixX in range(imgWidth):
                trainingFileContents += str(1 - handle.getpixel((pixX, pixY)) / 255.0) + " "

        trainingFileContents += os.linesep
        patternNameIndex = int(fname.split(".")[0][-1])
        outputs = " ".join([("1" if i == patternNameIndex else "0") for i in xrange(10)])

        trainingFileContents += "#Output case " + str(counter) + os.linesep
        trainingFileContents += outputs
        counter += 1

    outputFile = open("../ocr.pat", "w")
    outputFile.write(trainingFileContents)
    outputFile.close()
            \end{python}
        \end{changemargin}


    \section{Implementação}

        \subsection{Parâmetros}
            \paragraph{}
            Abaixo estão os parâmetros de configuração de nossa rede neural. O arquivo de configuração
            ``ocr.net'', no diretório raiz do trabalho, contém toda a especificação da rede e deve ser 
            aberto no JavaNNS.

            \begin{description}
                \item[Tipo de rede] Utilizamos uma rede do tipo feed-forward, com uma camada intermediária e
                    totalmente conectada.
                \item[Regra de aprendizado] A regra de aprendizado utilizada foi a \emph{Backpropagation}
                \item[Quantidade de neurônios] De acordo com os requisitos, a rede possui 150 neurônios de
                    entrada, um para cada pixel da imagem. A camada intermediária possui 15 neurônios e a camada
                    de saída possui 10 neurônios (um correspondente a cada classe possível no reconhecimento).
                \item[Funções de ativação] A função de ativação escolhida para a camada de entrada foi a
                    identidade. Já para as camadas intermediária e de saída foi utilizada a função logística.
            \end{description}

            \paragraph{}
            Na fase de pré-processamento das imagens fazemos também a normalização do valor de brilho dos pixels
            de uma imagem, de maneira que os valores apresentados a cada neurônio da camada de entrada da rede
            sempre estão no intervalo [0,1] (0 é branco e 1 é preto).

            \paragraph{}
            Na figura \ref{fig:uninitialized} pode-se observar uma captura de tela mostrando a rede com suas
            três camadas, e já inicializada com pesos aleatórios, porém ainda não treinada.
            \begin{figure}[h!]
                \begin{center}
                    \includegraphics[width=1.0\textwidth]{imgs/uninitialized.png}
                \end{center}
                \caption{Nossa rede neural artificial: Feed-Forward de 3 camadas}
                \label{fig:uninitialized}
            \end{figure}

        \subsection{Inicialização e treinamento}
            \paragraph{}
            Os pesos de nossa rede são inicializados aleatoriamente, no intervalo [0,1]. O treinamento é
            realizado apresentando-se todos os 70 padrões do conjunto de treinamento, em 100 ciclos.

            Cada um dos 10 dígitos está presente no conjunto de treinamento em 7 fontes diferentes,
            totalizando os 70 padrões apresentados. Em cada um dos ciclos de treinamento o conjunto é
            embaralhado antes dos padrões serem apresentados à redes. Outro fator interessante a notar é que
            há uma condição de parada no treinamento: Assim que o erro da rede atinja um valor mínimo
            estipulado, o treinamento é finalizado, mesmo que os 100 ciclos não tenham sido realizados. Isso
            evita o \emph{sobretreinamento} da rede.


    \section{Resultados e conclusões}
        Abaixo, nas figuras \ref{fig:rec1}, \ref{fig:rec2} e \ref{fig:rec3} são mostrados alguns exemplos de
        reconhecimento de dígitos, utilizando a rede já treinada com o procedimento da seção anterior.
        \begin{figure}
            \begin{center}
                \includegraphics[width=0.7\textwidth]{imgs/rec1.png}
            \end{center}
            \caption{Exemplo de reconhecimento 1}
            \label{fig:rec1}
        \end{figure}

        \begin{figure}
            \begin{center}
                \includegraphics[width=0.7\textwidth]{imgs/rec2.png}
            \end{center}
            \caption{Exemplo de reconhecimento 2}
            \label{fig:rec2}
        \end{figure}

        \begin{figure}
            \begin{center}
                \includegraphics[width=0.7\textwidth]{imgs/rec3.png}
            \end{center}
            \caption{Exemplo de reconhecimento 3}
            \label{fig:rec3}
        \end{figure}

        Através do uso da rede para reconhecer algumas entradas com leves alterações em relação aos padrões
        apresentados foi possível comprovar a utilidade do modelo de redes neurais artificiais no
        reconhecimento de padrões. Esse tipo de problema teria solução muito mais complexa caso fossem
        utilizados métodos simbólicos.
        

    \section{Referências}
        \begin{itemize}
            \item Python Programming Language - \url{http://www.python.org}
            \item Python Imaging Library - \url{http://www.pythonware.com/products/pil}
            \item SNNS - Stuttgart Neural Network Simulator - \url{http://www.ra.cs.uni-tuebingen.de/SNNS}
            \item JavaNNS - Java version of SNNS - \url{http://www.ra.cs.uni-tuebingen.de/downloads/JavaNNS}
        \end{itemize}

\end{document}
