|
|
|
@ -50,9 +50,10 @@
|
|
|
|
|
|
|
|
|
|
[https://untitledtblog.tistory.com/5](https://untitledtblog.tistory.com/5)
|
|
|
|
|
|
|
|
|
|
### SOM 예제 코드[¶]()
|
|
|
|
|
### SOM 예제 코드 1[¶]()
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Code View</summary>
|
|
|
|
|
<summary>입력 데이터 생성</summary>
|
|
|
|
|
<div markdown="1">
|
|
|
|
|
|
|
|
|
@ -258,21 +259,154 @@ array(\[\[0.76959259, 0.03105338\],
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 참고[¶]()
|
|
|
|
|
|
|
|
|
|
- ChatGPT
|
|
|
|
|
### SOM 예제 코드 2[¶]()
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Code View</summary>
|
|
|
|
|
<summary>Randomize 함수</summary>
|
|
|
|
|
<div markdown="1">
|
|
|
|
|
|
|
|
|
|
````python
|
|
|
|
|
def randomize(A, rowcol=0):
|
|
|
|
|
"""
|
|
|
|
|
행렬 A를 행 혹은 열을 랜덤하게 섞기
|
|
|
|
|
rowcol: 0 혹은 없으면 행을 랜덤하게 섞기 (default)
|
|
|
|
|
1 이면, 열을 랜덤하게 섞기
|
|
|
|
|
"""
|
|
|
|
|
np.random.seed(int(sum([int(x) for x in str(time.time()) if x.isdigit()])))
|
|
|
|
|
|
|
|
|
|
if rowcol == 0:
|
|
|
|
|
m, n = A.shape
|
|
|
|
|
p = np.random.rand(m, 1)
|
|
|
|
|
p1, I = np.sort(p, axis=0), np.argsort(p, axis=0)
|
|
|
|
|
B = A[I, :]
|
|
|
|
|
return B.reshape(A.shape)
|
|
|
|
|
elif rowcol == 1:
|
|
|
|
|
Ap = A.T
|
|
|
|
|
m, n = Ap.shape
|
|
|
|
|
p = np.random.rand(m, 1)
|
|
|
|
|
p1, I = np.sort(p, axis=0), np.argsort(p, axis=0)
|
|
|
|
|
B = Ap[I, :]
|
|
|
|
|
return B.reshape(Ap.shape).T
|
|
|
|
|
````
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<summary>Data Generator 함수</summary>
|
|
|
|
|
<div markdown="1">
|
|
|
|
|
|
|
|
|
|
````python
|
|
|
|
|
def datagen(Nvec, mean_var):
|
|
|
|
|
m, c = mean_var.shape
|
|
|
|
|
if m != 3 or c != len(Nvec):
|
|
|
|
|
print("dimension not match, break")
|
|
|
|
|
return None
|
|
|
|
|
X = np.empty((0, 2))
|
|
|
|
|
for i in range(c):
|
|
|
|
|
np.random.seed(int(sum([int(x) for x in str(time.time()) if x.isdigit()])))
|
|
|
|
|
tmp = np.sqrt(mean_var[2, i]) * np.random.randn(Nvec[i], 2) # scaled by variance
|
|
|
|
|
mean = mean_var[0:2, i] # mean is a 2 by 1 vector
|
|
|
|
|
X = np.vstack((X, tmp + np.ones((Nvec[i], 2)) * mean))
|
|
|
|
|
return X
|
|
|
|
|
````
|
|
|
|
|
|
|
|
|
|
### SOM [¶]()
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<details>
|
|
|
|
|
<summary>Code View</summary>
|
|
|
|
|
<summary>SOM 구현</summary>
|
|
|
|
|
<div markdown="1">
|
|
|
|
|
|
|
|
|
|
````python
|
|
|
|
|
import os
|
|
|
|
|
import logging
|
|
|
|
|
import time
|
|
|
|
|
import numpy as np
|
|
|
|
|
import matplotlib.pyplot as plt
|
|
|
|
|
import matplotlib.font_manager as fm
|
|
|
|
|
import matplotlib as mpl
|
|
|
|
|
|
|
|
|
|
# 마이너스 기호 표시 설정
|
|
|
|
|
mpl.rcParams['axes.unicode_minus'] = False
|
|
|
|
|
|
|
|
|
|
# 한글 폰트 설정 - Windows
|
|
|
|
|
# font_location = fm.findfont(fm.FontProperties(family='Malgun Gothic'))
|
|
|
|
|
# fm.FontProperties(fname=font_location)
|
|
|
|
|
# plt.rcParams['font.family'] = 'Malgun Gothic'
|
|
|
|
|
|
|
|
|
|
# 로거 수준을 ERROR로 설정하여 경고 메시지를 제거
|
|
|
|
|
matplotlib_logger = logging.getLogger("matplotlib")
|
|
|
|
|
matplotlib_logger.setLevel(logging.ERROR)
|
|
|
|
|
# 한글 폰트 설정 - Linux
|
|
|
|
|
font_dir = "/usr/share/fonts/truetype/nanum"
|
|
|
|
|
nanum_gothic_ttf = os.path.join(font_dir, "NanumGothic.ttf")
|
|
|
|
|
nanum_gothic = fm.FontProperties(fname=nanum_gothic_ttf)
|
|
|
|
|
# plt.rcParams["font.family"] = nanum_gothic.get_name()
|
|
|
|
|
plt.rcParams["axes.unicode_minus"] = False
|
|
|
|
|
|
|
|
|
|
def onces(rows, cols):
|
|
|
|
|
return np.ones((rows, cols))
|
|
|
|
|
|
|
|
|
|
# Parameters
|
|
|
|
|
N = 100 # 각 클러스터의 표본의 개수
|
|
|
|
|
N2 = N + N
|
|
|
|
|
eta = 0.2
|
|
|
|
|
means = np.array([[0.7, -0.8],
|
|
|
|
|
[0.7, -0.8]])
|
|
|
|
|
var = np.array([0.2, 0.2])
|
|
|
|
|
|
|
|
|
|
x = datagen([N, N], np.vstack((means, var))) # x: N2 by 2
|
|
|
|
|
x = randomize(x) # 행의 값을 랜덤하게 섞기
|
|
|
|
|
ncenter = 11 # 사용할 클러스터 뉴런의 개수
|
|
|
|
|
w = np.random.rand(ncenter, 2) - 0.5 * onces(ncenter, 2) # 초기 뉴런은 특징 공간상에 임의로 위치시킴
|
|
|
|
|
|
|
|
|
|
plt.figure()
|
|
|
|
|
plt.subplot(121)
|
|
|
|
|
plt.plot(x[:, 0], x[:, 1], 'r.', w[:, 0], w[:, 1], '*-')
|
|
|
|
|
plt.axis([-2, 2, -2, 2])
|
|
|
|
|
plt.title('초기화', fontproperties=nanum_gothic)
|
|
|
|
|
|
|
|
|
|
i = 1
|
|
|
|
|
iter = 1
|
|
|
|
|
converge = 0
|
|
|
|
|
|
|
|
|
|
while converge == 0:
|
|
|
|
|
dn = np.ones((ncenter, 1)) * x[i, :] - w
|
|
|
|
|
ddn = np.sum((dn * dn), axis=1) # ddn: ncenter by 1
|
|
|
|
|
istar = np.argmin(ddn)
|
|
|
|
|
|
|
|
|
|
if istar == 0:
|
|
|
|
|
w[[istar, istar + 1], :] = w[[istar, istar + 1], :] + eta * (np.ones((2, 1)) * x[i, :] - w[[istar, istar + 1], :])
|
|
|
|
|
elif istar == ncenter - 1:
|
|
|
|
|
w[[istar - 1, istar], :] = w[[istar - 1, istar], :] + eta * (np.ones((2, 1)) * x[i, :] - w[[istar - 1, istar], :])
|
|
|
|
|
else:
|
|
|
|
|
w[[istar - 1, istar, istar + 1], :] = w[[istar - 1, istar, istar + 1], :] + eta * (np.ones((3, 1)) * x[i, :] - w[[istar - 1, istar, istar + 1], :])
|
|
|
|
|
|
|
|
|
|
plt.subplot(122)
|
|
|
|
|
plt.plot(x[:, 0], x[:, 1], 'r.', x[i, 0], x[i, 1], 'o', w[:, 0], w[:, 1], '*-')
|
|
|
|
|
plt.title(f'Iteration = {iter}')
|
|
|
|
|
plt.pause(0.01)
|
|
|
|
|
|
|
|
|
|
i = (i + 1) % N2
|
|
|
|
|
iter += 1
|
|
|
|
|
|
|
|
|
|
if i == 0:
|
|
|
|
|
x = randomize(x) # 클러스터의 순서를 랜덤하게 섞는다.
|
|
|
|
|
i = 1 # 재배치된 입력으로 시작
|
|
|
|
|
|
|
|
|
|
if iter % 50 == 0:
|
|
|
|
|
eta *= 0.9
|
|
|
|
|
if iter >= 200:
|
|
|
|
|
converge = 1
|
|
|
|
|
|
|
|
|
|
plt
|
|
|
|
|
|
|
|
|
|
````
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 참고[¶]()
|
|
|
|
|
|
|
|
|
|
- ChatGPT
|