Pages

Redes Neurais Auto-Organizáveis - SOM

Tuesday, April 21, 2009

Nest post, irei discutir um pouco sobre as redes neurais auto-organizáveis (Self-Organized-Maps -SOM), também conhecidas como Mapas de Kohonen ou mapas topográficos.

Até agora, meus artigos sobre redes neurais focaram no campo de aprendizado supervisionado, isto é, o aprendizado pelo qual apresentamos um conjunto de padrões a uma rede neural em conjunto com as saídas desejadas. A rede então ajusta os pesos visando obter as saídas corretas em função das entradas. Entretanto, vamos supor que não temos de antemão o conjunto de saídas desejadas. E agora ? Como podemos fazer com que a rede neural nos traga alguma informação útil ? Isto se chama o aprendizado não supervisionado. A tarefa agora é explorar as semelhanças entre os exemplos de entrada e agrupar padrões parecidos sem conhecer as classes de antemão. Algumas razões pelo qual escolhemos este método são:
  • Agrupamento de padrões (Clusters)
  • Redução de dimensionalidade
  • Descoberta de correlações escondidas entre os dados (mineração de dados)
  • Compressão de dados (Extração de características)
  • Classificação

A rede SOM é uma rede neural de 2 camadas que aceita padrões de N-dimensões como entrada e os mapeia para um conjunto de neurônios de saída, o qual representa o espaço dos dados a serem agrupados. O mapa (camada) de saída, que é tipicamente bi-dimensional, representa as posições dos neurônios em relação aos seus vizinhos. A idéia é que neurônios topologicamente próximos respondam de maneira semelhante a entradas semelhantes. Para isso todos neurônios da camada de entrada são todos conectados aos neurônios de saída.



Modelo de uma rede SOM
Os passos do algoritmo de treinamento do SOM é simples:


  1. Inicialize os pesos com valores aleatórios.
  2. Apresente o padrão de entrada à rede.
  3. Escolha o neurônio de saída com maior estado de ativação (Neurôno "vencedor").
  4. Atualize os pesos dos neurônios vizinhos ao neurônio vencedor, usando um fator de aprendizado (Geralmente baseado no raio de vizinhança e taxa de aprendizado).
  5. Reduza o fator de aprendizado monotonicamente (linearmente).
  6. Reduza o raio de vizinhaça monotonicamente (linearmente).
  7. Repita os passos a partir do passo 2 até que a atualização dos pesos sejam bem poucas.


O tamanho de vizinhaça irá inicialmente incluir todos neurônios da camada, e sendo reduzindo progressivamente durante a execução do treinamento, até incluir apenas o próprio neurônio vencedor.


Para descrever o treinamento acima, apresentarei um exemplo de uma solução de um problema com a rede SOM. O exemplo consiste de um conjunto de 25 alimentos, onde a rede SOM irá tentar agrupá-los em regiões de similaridade, baseado em três parâmetros, que são as informações nutricionais do alimento: Proteínas, carboidratos e gordura.

Logo, o desafio para esta rede SOM é reduzir os dados contendo três dimensões para apenas 2 dimensões, sem perda de informação. As redes SOM fazem isso automaticamente identificando as características diferenciais que terão maior efeito no resultado final do treinamento da rede.

O conjunto de exemplos de entrada segue abaixo:


Após executada a rede SOM com este conjunto de dados, os alimentos são posicionados em um plano de 10 x 10 agrupados em regiões de acordo com suas semelhanças. Uma representação gráfica do resultado é apresentado abaixo:


Agrupamento de regiões

Como o mapa de características agrupou os itens, reduzindo as três dimensões para apenas 2 dimensões ? Bem, um número de regiões foram geradas. Por exemplo, água, que não contém nenhuma proteína, carboidratos ou gordura foi empurrado para o canto direito superior. Seguindo para o canto superior esquerdo, o açúcar que é formado praticamente de carboidratos, foi posicionado. No canto inferior direito, manteiga reina soberana, sendo composta inteiramente por gordura. Finalmente, o canto esquerdo inferior é ocupado por filé de atum e frango assado, que contêm a maior concentração de proteína em relação aos alimentos apresentados. Os alimentos restantes são distribuídos entre esses extremos, onde os alimentos "fast food" ocupam a zona do centro.


Podemos observar que a rede SOM conseguiu agrupar em regiões os alimentos de acordo com as informações nutricionais. Podemos inferir 4 tipos de grupos: O grupo formado pelos padrões onde a proteína foi a característica determinante, outro pela gordura como característica predominante, e carboidratos como determinante. Por fim o último grupo seriam os alimentos na região central formados por alimentos formados por quantidades balanceadas dos 3 componentes acimas demonstrados. Isso que acabamos de fazer foi uma análise de dados e extração de informações úteis de um conjunto de dados brutos: Mineração de dados.


Abaixo disponibilizo o código em Python da rede SOM, o qual você poderá modificar ou alterar o conjunto de entradas. Tente adicionar mais dimensões no conjunto de entradas (novas infomações nutricionais) e observe os resultados. É claro que não é sempre óbvio ver o que está acontecendo, especialmente com um grande número de dimensões. Entretanto, eventualmente você poderá concluir, e até as vezes inesperadamente, alguma correlação entre os dados. Isso é a magia da mineração de dados!


Não irei exibir o código aqui no site, pois é um pouco grande, mas deixarei o link para download. Espero que usufruam bem e ajudem no seu aprendizado de redes neurais!


Até a próxima,


Marcel Pinheiro Caraciolo

10 comments:

  1. Interessante. Só não gostei do passo 6:
    # Reduza o raio de vizinhaça monotonicamente (linearmente).
    Isso me faz chorar ao lembrar que errei isso na prova. Mas tudo bem, já atualizei os pesos dos meus neurônios e acredito que o poder de gereralização aumentou!!

    ReplyDelete
  2. Cara, o difícil pra mim é entender essas fórmulas de RNA. É cálculo demais pra mim. Aquele livro do Haykin é um terror. Já implementei hopfield e perceptron multicamadas e achei fácil. O grande problema é entender na forma que é explicado na literatura. Mas quando ao SOM, vc poderia me esclarecer umas dúvidas? Como defino dimensão do meu mapa. Em alguns exemplos todos usavam 10x10, mas qual a lógica disso?
    Cada neurônio nessa matriz vai ter um vetor de pesos w?

    ReplyDelete
  3. Quando eu rodei o script deu a mensagem de current erro, o que poderá ter sido?

    ReplyDelete
  4. O script está funcionando normalmente quando executei aqui novamente. Você poderia dar mais detalhes do possível erro ?

    Em relação ao tamanho do número de neurônios da camada de saída do SOM, isso depende do problema a ser solucionado. Isso nao significa que sempre tem que ser 10 x 10, a idéia é que à medida que você aumente o tamanho do mapa (reticulado) mais dispersos os dados ficarão sobre o mapa, porém isso pode acarretar em perda de informações, os dados ficam bastante dispersos no mapa (modelar precisamente os dados) de maneira que não possa inferir agrupamentos e consequentemente informações úteis sobre os clusters formados. Muito pequeno, posso dizer que o mapa de tamanho reduzido é incapaz de detectar agrupamentos, visto que poucos neurônios na camada de saída geram fronteiras de decisão em que as fronteiras cruzam umas comas outras, causando o problema de overlapping (dados acabam se agrupando de forma incorreta).
    Existem alguns trabalhos na literatura que tentar superar essas limitações (técnicas híbridas). Uma delas é a construção do reticulado de saída durante a fase de treinamento. Procure sobre GCS, GNG (link: http://www.cin.ufpe.br/~aluizioa/redes-neurais/RN-16-SOM-topologia-dinamica.pdf)
    Sim. Cada neurônio dessa matriz vai ter um vetor de pesos w que o número é número de conexões de entrada.

    ReplyDelete
  5. Tentei mudar no txt os valores em float (proteina, carboidrato, gordura) para valores em string e float(tipo, endereço, faixa de preço), mas deu o seguinte erro:

    Traceback (most recent call last):
    File "SOM.py", line 197, in
    map = Map(3,10,"dataset.txt")
    File "SOM.py", line 40, in __init__
    self.normalisePatterns()
    File "SOM.py", line 75, in normalisePatterns
    sum += self.patterns[key][j]
    TypeError: unsupported operand type(s) for +=: 'float' and 'str'

    Como devo prosseguir? Preciso mto modificar as entradas para outro proposito, se possivel para hj.

    Grato

    ReplyDelete
  6. André, suas entradas contêm dados categóricos, correto ? (Pelo que percebi endereço e tipo).
    Vale salientar que o algoritmo de treinamento convencional da rede SOM (apresentada neste artigo) apenas trata de dados numéricos.
    Se seus dados contêm dados categóricos, há algumas opções:
    Converter estes dados em um conjunto de dados numéricos antes de o treinamento da rede SOM começar.
    Para cada tipo ou endereço vc pode incluir uma faixa de números 1, 100, 200, 300, 400, etc.
    Dê uma olhada neste livro que pode te ajudar:

    http://books.google.com.br/books?id=BtdLOv0K4GUC&printsec=frontcover&dq=Data+Preparation+for+Data+Mining&source=bl&ots=zLj1XLenMt&sig=Lwbb16dAaOc3ikzMpLAVq-Gh-cE&hl=pt-BR&ei=z1IJTK-AKoOdlge828mjDg&sa=X&oi=book_result&ct=result&resnum=3&ved=0CCsQ6AEwAg#v=onepage&q=categorical&f=false

    Ou você pode tentar outras abordagens de treinamento de SOM. Pela urgência faria uma transformação dos dados categóricos em numéricos.

    Bom trabalho e boa sorte! Espero ter ajudado!

    ReplyDelete
  7. Entendi, tipo se eu colocar apenas valores numericos como no seu exemplo e por uma legenda ele funcionará nornalmente n é? Em relação aos resultados eu não conseguir entender como pelos valores mostrados o gráfico que foi mostrado fico daquela forma. No meu programa eu quero dividir os grupos de restaurantes em faixa de preço, tipo de comida, localização. Atribuirei a faixa de preço e localização a numeros pra que rode certinho, mais os resultados sairao no grafico da mesma forma que o seu? Como ficaria mais ou menos o gráfico? Estou com grande dúvida em como mostrarei os resultados!

    ReplyDelete
  8. Entendi, tipo se eu colocar apenas valores numericos como no seu exemplo e por uma legenda ele funcionará nornalmente n é? Em relação aos resultados eu não conseguir entender como pelos valores mostrados o gráfico que foi mostrado fico daquela forma. No meu programa eu quero dividir os grupos de restaurantes em faixa de preço, tipo de comida, localização. Atribuirei a faixa de preço e localização a numeros pra que rode certinho, mais os resultados sairao no grafico da mesma forma que o seu?

    ReplyDelete
  9. Olá André , não esqueça de usar faixas bem distintas para seus dados categóricos. COmida A = 1 , Comida B = 100, Comida C = 1000 , etc.
    O meu gráfico eu construí usando excel, pois mapeei os resultados em uma grade bi-dimensional 10 x 10. os resultados serão pares (X,Y) o qual você pode plotar num gráfico de pontos (Scatter graph) e aí inferir conclusões sobre os dados agrupados.

    ReplyDelete
  10. Opá
    Com esse resultado, teria alguma forma de saber quais alimentos pertence a cada grupo?

    ReplyDelete