You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
279 KiB
Markdown

1 year ago
03\. SOM pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: var(--jp-cell-editor-active-background) } .highlight { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) } .highlight .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /\* Comment \*/ .highlight .err { color: var(--jp-mirror-editor-error-color) } /\* Error \*/ .highlight .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /\* Keyword \*/ .highlight .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /\* Operator \*/ .highlight .p { color: var(--jp-mirror-editor-punctuation-color) } /\* Punctuation \*/ .highlight .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /\* Comment.Hashbang \*/ .highlight .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /\* Comment.Multiline \*/ .highlight .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /\* Comment.Preproc \*/ .highlight .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /\* Comment.PreprocFile \*/ .highlight .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /\* Comment.Single \*/ .highlight .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /\* Comment.Special \*/ .highlight .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /\* Keyword.Constant \*/ .highlight .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /\* Keyword.Declaration \*/ .highlight .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /\* Keyword.Namespace \*/ .highlight .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /\* Keyword.Pseudo \*/ .highlight .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /\* Keyword.Reserved \*/ .highlight .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /\* Keyword.Type \*/ .highlight .m { color: var(--jp-mirror-editor-number-color) } /\* Literal.Number \*/ .highlight .s { color: var(--jp-mirror-editor-string-color) } /\* Literal.String \*/ .highlight .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /\* Operator.Word \*/ .highlight .pm { color: var(--jp-mirror-editor-punctuation-color) } /\* Punctuation.Marker \*/ .highlight .w { color: var(--jp-mirror-editor-variable-color) } /\* Text.Whitespace \*/ .highlight .mb { color: var(--jp-mirror-editor-number-color) } /\* Literal.Number.Bin \*/ .highlight .mf { color: var(--jp-mirror-editor-number-color) } /\* Literal.Number.Float \*/ .highlight .mh { color: var(--jp-mirror-editor-number-color) } /\* Literal.Number.Hex \*/ .highlight .mi { color: var(--jp-mirror-editor-number-color) } /\* Literal.Number.Integer \*/ .highlight .mo { color: var(--jp-mirror-editor-number-color) } /\* Literal.Number.Oct \*/ .highlight .sa { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Affix \*/ .highlight .sb { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Backtick \*/ .highlight .sc { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Char \*/ .highlight .dl { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Delimiter \*/ .highlight .sd { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Doc \*/ .highlight .s2 { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Double \*/ .highlight .se { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Escape \*/ .highlight .sh { color: var(--jp-mirror-editor-string-color) } /\* Literal.String.Heredoc \*/ .highlight .si { color: va
SOM (Self Organizing Map, 자기조직화지도)[¶](#SOM-(Self-Organizing-Map,-%EC%9E%90%EA%B8%B0%EC%A1%B0%EC%A7%81%ED%99%94%EC%A7%80%EB%8F%84))
==================================================================================================================================
### 개요[¶](#%EA%B0%9C%EC%9A%94)
* 비지도학습 중 하나로, 대뇌피질의 시각피질의 학습 과정을 모델화한 인공신경망으로써 자율 학습에 의한 클러스터링을 수행하는 알고리즘
### 역사[¶](#%EC%97%AD%EC%82%AC)
* 1980년대 후반에 핀란드의 컴퓨터 과학자 Teuvo Kohonen에 의해 개발
* SOM은 분류, 군집화, 데이터 시각화 등 다양한 분야에서 사용되며, 인공신경망 분야에서 가장 성공적인 알고리즘 중 하나로 평가됨
* 초기에는 이미지 인식과 음성 인식 분야에서 주로 사용되었으나 현재는 데이터 분석 등의 다양한 분야에서도 사용됨
### 특징[¶](#%ED%8A%B9%EC%A7%95)
* 인간의 뇌에서 발견된 "자기 조직화" 원리를 모델링하여 입력 데이터의 유사성을 기반으로 뉴런들을 2D 혹은 3D 지도상에 배치함
* Topological Ordering (위상적 순서)에 따라 지도상에서 인접한 뉴런들이 입력 데이터의 유사성을 반영하여 군집화(Clusturing)함 입력 데이터에 대한 어떤 사전 정보나 라벨이 없이도, 데이터가 가지고 있는 패턴과 특성을 스스로 학습하고 이를 지도상으로 표현함
* 주로 데이터의 시각화 및 차원 축소에 사용되며, 입력 데이터의 분포를 파악하여 그룹화하여 시각적으로 표현하므로, 복잡한 데이터를 시각적으로 이해하고 분석하는 데 도움을 줌
### 주요 용어[¶](#%EC%A3%BC%EC%9A%94-%EC%9A%A9%EC%96%B4)
* 클러스터링(clustering): 데이터의 유사성에 기초하여 데이터를 몇몇의 그룹으로 분류하는 기법
* 입력층(input layer): 입력 벡터를 입력받는 층
* 경쟁층(competitive layer): 입력 벡터의 특성에 따라 입력 벡터가 한 점으로 클러스터링 되는 층
* 가중치(weight): 인공신경망에서 가중치는 각 입력 값에 대한 입력 값의 중요도를 값을 말함
* 노드(node): 경쟁층에서 입력 벡터들이 서로의 유사성에 의해 모이는 하나의 영역
![SOM Layer Structure](./images/SOM1.png)
### 알고리즘[¶](#%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98)
1-1) 가중치 행렬 각 원소의 값을 임의의 0보다 크고 1보다 작은 값으로 초기화
2-1) 입력 벡터와 경쟁층에 존재하는 j 개의 노드에 대해 입력 벡터와 노드 간의 거리 Dij 를 계산
2-2) 현재 입력 벡터와 Dij 값이 가장 작은 경쟁층의 노드를 선택
2-3) 해당 노드의 가중치와 이웃 노드의 가중치를 수정
5-1) 현재 입력 벡터가 마지막 입력 벡터라면 다음 과정으로 이동하고, 그렇지 않다면 과정 2로 돌아간다
6-1) 현재 반복 횟수가 최대 반복 횟수라면 알고리즘을 종료
6-2) 현재 반복 횟수가 최대 반복 횟수가 아니면 현재 입력 벡터를 처음 입력 벡터로 설정하고 과정 2로 돌아간다
![SOM Algorithm](./images/SOM2.png)
### 참고[¶](#%EC%B0%B8%EA%B3%A0)
[https://untitledtblog.tistory.com/5](https://untitledtblog.tistory.com/5)
### SOM 예제 코드[¶](#SOM-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C)
In \[ \]:
import numpy as np
import matplotlib.pyplot as plt
In \[ \]:
\# 입력 데이터 생성
data \= np.random.rand(100, 2)
\# data = np.array(\[\[0.8, 0.0064\],
\# \[0.12, 0.2848\],
\# \[0.24, 0.7472\],
\# \[0.68, 0.3488\]\])
data
Out\[ \]:
array(\[\[0.76959259, 0.03105338\],
\[0.91933906, 0.8980492 \],
\[0.74919767, 0.46775453\],
\[0.66010482, 0.70532455\],
\[0.07347433, 0.31437638\],
\[0.52162755, 0.75475037\],
\[0.07618824, 0.5595569 \],
\[0.37694104, 0.88389 \],
\[0.59261356, 0.49140373\],
\[0.11567152, 0.32084966\],
\[0.81627506, 0.7724125 \],
\[0.7708446 , 0.98667885\],
\[0.57884267, 0.92658698\],
\[0.48815338, 0.04666865\],
\[0.07971729, 0.56926156\],
\[0.93371788, 0.20473364\],
\[0.71241481, 0.68994675\],
\[0.69855141, 0.55690579\],
\[0.87081581, 0.48218263\],
\[0.73239668, 0.47015934\],
\[0.48234206, 0.38374233\],
\[0.51407113, 0.3925697 \],
\[0.97608349, 0.58044996\],
\[0.67676596, 0.51393561\],
\[0.37059459, 0.99168193\],
\[0.17015263, 0.17250751\],
\[0.6980668 , 0.47156525\],
\[0.9674704 , 0.29847506\],
\[0.85297608, 0.15389296\],
\[0.99135256, 0.95353731\],
\[0.75749781, 0.05744834\],
\[0.5850026 , 0.69425312\],
\[0.35572734, 0.77261987\],
\[0.96259553, 0.10738437\],
\[0.0178066 , 0.68856146\],
\[0.78219693, 0.6523648 \],
\[0.18744908, 0.73438952\],
\[0.19713904, 0.56662014\],
\[0.11656314, 0.50708698\],
\[0.33800968, 0.03634445\],
\[0.64802194, 0.90416709\],
\[0.7668028 , 0.7619133 \],
\[0.55338936, 0.78892134\],
\[0.20716839, 0.95280491\],
\[0.47688275, 0.30063862\],
\[0.22233577, 0.02612442\],
\[0.21021643, 0.66526042\],
\[0.87039248, 0.75634555\],
\[0.91421121, 0.60350262\],
\[0.32014712, 0.61909491\],
\[0.03320721, 0.69900356\],
\[0.0806021 , 0.68826953\],
\[0.52828811, 0.78636528\],
\[0.49048742, 0.60616199\],
\[0.07021355, 0.64982408\],
\[0.21773879, 0.55571391\],
\[0.02119119, 0.62099936\],
\[0.75589808, 0.88236869\],
\[0.99479197, 0.98599938\],
\[0.35444256, 0.84292181\],
\[0.90941177, 0.30758414\],
\[0.87616741, 0.18060184\],
\[0.22973575, 0.50353087\],
\[0.33569227, 0.82710827\],
\[0.03575231, 0.86915894\],
\[0.59710596, 0.91274408\],
\[0.61854338, 0.06007 \],
\[0.69497861, 0.26505075\],
\[0.80347052, 0.93909288\],
\[0.8998602 , 0.34498986\],
\[0.96359265, 0.66780466\],
\[0.6180583 , 0.36145526\],
\[0.22507441, 0.24977 \],
\[0.82067222, 0.65858647\],
\[0.26533719, 0.50457457\],
\[0.20615695, 0.52028333\],
\[0.78530409, 0.23287443\],
\[0.81894409, 0.32542015\],
\[0.66607148, 0.0717416 \],
\[0.15435642, 0.57144805\],
\[0.60568206, 0.62824524\],
\[0.40981871, 0.51319754\],
\[0.14660118, 0.14759826\],
\[0.89091339, 0.12148139\],
\[0.48159329, 0.76667587\],
\[0.73766975, 0.76237422\],
\[0.32449576, 0.11193535\],
\[0.05351455, 0.37051478\],
\[0.15487227, 0.0884276 \],
\[0.40902546, 0.73216362\],
\[0.6227993 , 0.54298886\],
\[0.70489165, 0.60729615\],
\[0.43506953, 0.26510733\],
\[0.17818975, 0.41551925\],
\[0.07820619, 0.31987945\],
\[0.27646196, 0.00825832\],
\[0.30999502, 0.67284126\],
\[0.6372436 , 0.48780002\],
\[0.66962877, 0.44225145\],
\[0.48185839, 0.17663244\]\])
In \[ \]:
\# SOM 파라미터 설정
map\_width \= 10
map\_height \= 10
lr \= 0.1
num\_iterations \= 1000
\# map\_width = 2
\# map\_height = 2
\# lr = 0.1
\# num\_iterations = 1000
In \[ \]:
\# SOM 초기화
som\_map \= np.random.rand(map\_width, map\_height, 2)
print(som\_map.shape)
fig, (ax1, ax2) \= plt.subplots(1, 2)
ax1.imshow(som\_map\[:,:,0\])
ax2.imshow(som\_map\[:,:,1\])
plt.show()
(10, 10, 2)
![No description has been provided for this image](data:image/png;base64,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
In \[ \]:
\# SOM 학습
for i in range(num\_iterations):
\# 랜덤한 입력 데이터 선택
input\_data \= data\[np.random.choice(data.shape\[0\])\]
\# 가장 유사한 뉴런 찾기
\# 3D som\_map과 input\_data의 차이^2를 구하여 z축으로 모두 합한 거리
distances \= np.sum((som\_map \- input\_data) \*\* 2, axis\=2)
\# 위에서 구한 z축의 거리들 중 가장 작은 뉴런
winner \= np.argmin(distances)
\# 3D z축에서 선택된 가장 작은 뉴런을 2D map으로 맵핑한 좌표
x, y \= np.unravel\_index(winner, (map\_width, map\_height))
\# 학습률 계산
learning\_rate \= lr \* (1 \- i/num\_iterations)
\# 뉴런 가중치 업데이트
for j in range(map\_width):
for k in range(map\_height):
dist \= np.sqrt((x\-j)\*\*2 + (y\-k)\*\*2)
if dist < 3:
som\_map\[j, k\] += learning\_rate \* (input\_data \- som\_map\[j, k\])
In \[ \]:
\# SOM 시각화
print(som\_map.shape)
fig, (ax1, ax2) \= plt.subplots(1, 2)
ax1.imshow(som\_map\[:,:,0\])
ax2.imshow(som\_map\[:,:,1\])
plt.show()
(10, 10, 2)
![No description has been provided for this image](data:image/png;base64,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
### 참고[¶](#%EC%B0%B8%EA%B3%A0)
ChatGPT