Descobrindo SOM, uma Rede Neural com aprendizado não supervisionado
Tags: machinelearning, python, neuralnetwork
Published: 2019-10-28 02:11:16


Self Organizing Map (SOM) é uma Rede Neural de aprendizado não supervisionado. SOM é muito utilizada quando se tem datasets com muitos atributos porque é possível que a saída produzida tenha um número muito menor de dimensões, geralmente duas. Essa saída, chamada de map (ou feature map), é uma representação discreta dos dados de entrada.

Um ponto interessante sobre a SOM é que seu sistema é baseado em aprendizado competitivo. Os neurônios (ou nós) competem para decidir quem responderá (será ativado) com um conjunto de entradas e esse neurônio será chamado de winner. SOM pode ser implementada tendo conexões com inibições laterais, ou seja, uma capacidade do neurônio winner de reduzir a atividade dos seus vizinhos dando um feedback negativo a eles. Outro conceito que a SOM trabalha é o chamado mapa topográfico. A informação gerada de um input é representada por alguns neurônios vizinhos e contam com uma interação com conexões curtas. Um neurônio do output de um mapa topográfico é uma característica dos dados de entrada.

![](https://miro.medium.com/max/30/0*4hCbxP1OLCQJDLZs.jpg?q=20)

![](https://miro.medium.com/max/500/0*4hCbxP1OLCQJDLZs.jpg)

Exemplo de inibição lateral dos nossos neurônios produzindo uma ilusão de óptica

# Como a SOM funciona?

Os pontos no espaço dos dados de entrada têm pontos correspondentes no espaço de saída. Na Kohonen Networks, um tipo de SOM, há uma única camada computacional com duas dimensões e os pontos da entrada são totalmente conectados com os neurônios nessa camada.

![](https://miro.medium.com/freeze/max/30/0*tqifhm1yjWLetoTG.gif?q=20)

![](https://miro.medium.com/max/420/0*tqifhm1yjWLetoTG.gif)

No começo do processo de organização os pesos são inicializados com valores aleatórios. Após esse procedimento, para a competição, todos os neurônios calculam a função de discriminação, apresentada abaixo, sobre as características do dataset. O neurônio de menor valor é considerado o campeão (winner).

![](https://miro.medium.com/max/30/1*iqxpENhkzkiLErlqssmIOw.png?q=20)

![](https://miro.medium.com/max/221/1*iqxpENhkzkiLErlqssmIOw.png)

D = dimensão do espaço de entrada; x = as entradas; w = os pesos

Essa função mostra qual neurônio tem mais similaridade com o vetor de entradas.

Quando um neurônio é ativado seus vizinhos ficarão mais excitados comparados com neurônios que estão mais distantes. Esse processo é chamado de vizinhança topológica e é calculada como mostrado abaixo:

![](https://miro.medium.com/max/30/1*-xPWPbYvL3rP7fO_AjfQXA.png?q=20)

![](https://miro.medium.com/max/294/1*-xPWPbYvL3rP7fO_AjfQXA.png)

Onde  _S_  é a distância lateral entre os neurônios, _I(x)_  é o índice do neurônio winner e o  _σ_ é o número de vizinhos que decresce com o tempo. A vizinhança topográfica irá diminuir, tendendo a zero quando um neurônio estiver muito distante do winner.

Com  _t_  sendo a quantidade de épocas e  _η(t)_  o learning rate no tempo, os pesos são atualizados dessa forma:

![](https://miro.medium.com/max/30/1*WVy7thSMQJPmzjdCu-bOPA.png?q=20)

![](https://miro.medium.com/max/352/1*WVy7thSMQJPmzjdCu-bOPA.png)

Como pode-se ver, os pesos são movidos de acordo com a vizinhança tooplógica, fazendo com que os neurônios mais distantes tenham atualizações menores. Isso produz um efeito como se o neurônio winner "puxasse" os outros neurônios.

![](https://miro.medium.com/max/30/0*HOuIfZ3DzWKqAXuq.png?q=20)

![](https://miro.medium.com/max/1280/0*HOuIfZ3DzWKqAXuq.png)

O algoritmo da SOM termina quando a feature map para de mudar.

----------

# Na Prática!

Neste artigo vamos criar uma SOM que aprende cores. Aqui usamos uma biblioteca chamada MiniSom, que contém uma implementação simples do Self Organizing Maps.
```
import sys
sys.path.insert(0, '../')
from minisom import MiniSom
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
%matplotlib inline

# read the image
img = plt.imread('style.jpg')
# reshaping the pixels matrix
pixels = np.reshape(img, (img.shape[0]*img.shape[1], 3))

# SOM initialization and training
print('training...')
som = MiniSom(3, 3, 3, sigma=1.,
learning_rate=0.2, neighborhood_function='bubble') # 3x3 = 9 final colors
som.random_weights_init(pixels)
starting_weights = som.get_weights().copy() # saving the starting weights
som.train_random(pixels, 500)
print('quantization...')
qnt = som.quantization(pixels) # quantize each pixels of the image
print('building new image...')
clustered = np.zeros(img.shape)
for i, q in enumerate(qnt): # place the quantized values into a new image
	clustered[np.unravel_index(i, dims=(img.shape[0], img.shape[1]))] = q
print('done.')

# show the result
plt.figure(figsize=(7, 7))
plt.figure(1)
plt.subplot(221)
plt.title('original')
plt.imshow(img)
plt.subplot(222)
plt.title('result')
plt.imshow(clustered)
plt.subplot(223)
plt.title('initial colors')
plt.imshow(starting_weights, interpolation='none')
plt.subplot(224)
plt.title('learned colors')
plt.imshow(som.get_weights(), interpolation='none')
plt.tight_layout()
plt.show()
```

Treinar uma rede SOM com essa biblioteca é extremamente simples, com apenas 4 linhas foi possível treinar o nosso modelo e produzir as saídas abaixo, mostrando as cores aprendidas pela rede.

![](https://miro.medium.com/max/30/1*6GiM1OY2GKblsLlaJxMGew.png?q=20)

![](https://miro.medium.com/max/503/1*6GiM1OY2GKblsLlaJxMGew.png)

----------

# Referências:

> [Self Organizing Maps: Fundamentals](http://www.cs.bham.ac.uk/~jxb/NN/l16.pdf)
> 
> [Library MiniSom](https://github.com/JustGlowing/minisom)
> 
> [Self Organizing Maps — Towards Data Science](https://towardsdatascience.com/self-organizing-maps-ff5853a118d4)