[ํผ๊ณต๋จธ์ ] 06. ๋น์ง๋ ํ์ต - ๊ตฐ์ง, ์ฃผ์ฑ๋ถ ๋ถ์
๊ณ ๊ฐ ์ฌ๋ฆฐ ์ฌ์ง์ ์ด๋ค ๊ณผ์ผ์ธ์ง ๋ถ๋ฅ
ํ๊น์ ๋ชจ๋ฅด๋ ๋น์ง๋ ํ์ต
ํ๊น์ ๋ชจ๋ฅด๋ ์ฌ์ง์ ์ข ๋ฅ๋ณ๋ก ๋ถ๋ฅ
๋น์ง๋ ํ์ต : ํ๊น์ด ์์ ๋ ์ฌ์ฉํ๋ ์๊ณ ๋ฆฌ์ฆ
์ฌ๋์ด ๊ฐ๋ฅด์ณ ์ฃผ์ง ์์๋ ๋ฐ์ดํฐ์ ์๋ ๋ฌด์ธ๊ฐ๋ฅผ ํ์ต
06-1. ๊ตฐ์ง ์๊ณ ๋ฆฌ์ฆ
๊ณผ์ผ ์ฌ์ง ๋ฐ์ดํฐ ์ค๋น
์ด๋ฏธ์ง ๋ฐ์ดํฐ ๋ํ์ด ๋ฐฐ์ด์ ๊ธฐ๋ณธ ์ ์ฅ ํฌ๋งท์ธ npy ํ์ผ๋ก ์ ์ฅ๋์ด ์์
์ฝ๋ฉ์์ ! ๋ฌธ์๋ก ์์ํ๋ฉด ์ดํ ๋ช ๋ น์ ํ์ด์ฌ ์ฝ๋๊ฐ ์๋๋ผ ๋ฆฌ๋ ์ค ์ ธ ๋ช ๋ น์ด๋ก ์ธ์
wget ์๊ฒฉ ์ฃผ์์์ ๋ฐ์ดํฐ๋ฅผ ๋ค์ด๋ก๋ํ์ฌ ์ ์ฅ
!wget https://bit.ly/fruits_300 -O fruits_300.npy
ํ์ผ๋ก๋
๋ํ์ด์์ npy ํ์ผ์ ๋ก๋ ๋ฐฉ๋ฒ : .load() ๋ฉ์๋์ ํ์ผ ์ด๋ฆ ์ ๋ฌ
import numpy as np
import matplotlib.pyplot as plt
fruits = np.load('fruits_300.npy')
ํฌ๊ธฐ ํ์ธ
print(fruits.shape)
(300, 100, 100)
-> (์ํ ๊ฐ์, ์ด๋ฏธ์ง ๋์ด, ์ด๋ฏธ์ง ๋๋น)
์ด๋ฏธ์ง ํฌ๊ธฐ๋ 100 x 100
์ฒซ ๋ฒ์งธ ์ด๋ฏธ์ง ์ฒซ ํ ์ถ๋ ฅ
3์ฐจ์ ๋ฐฐ์ด์ด๊ธฐ ๋๋ฌธ์ ์ฒ์ 2๊ฐ์ ์ธ๋ฑ์ค๋ฅผ 0์ผ๋ก ์ง์
๋ง์ง๋ง ์ธ๋ฑ์ค ์ง์ ํ์ง ์๊ฑฐ๋ ์ฌ๋ผ์ด์ฑ ์ฐ์ฐ์ -> ์ฒซ ๋ฒ์งธ ์ด๋ฏธ์ง์ ์ฒซ ๋ฒ์งธ ํ ์ถ๋ ฅ
print(fruits[0,0,:])
์ฒซ ๋ฒ์งธ ํ์ ์๋ ํฝ์ 100๊ฐ์ ๋ค์ด ์๋ ๊ฐ ์ถ๋ ฅ
์ด ๋ํ์ด ๋ฐฐ์ด ํ๋ฐฑ ์ฌ์ง ๋ด๊ณ ์์ -> 0~ 255 ์ ์ซ๊ฐ ๊ฐ์ง
์ด๋ฏธ์ง ๊ทธ๋ฆฌ๊ธฐ
๋งทํ๋กฏ๋ฆฝ์ imshow() ๋ํ์ด ๋ฐฐ์ด๋ก ์ ์ฅ๋ ์ด๋ฏธ์ง ๊ทธ๋ฆฌ๊ธฐ
ํ๋ฐฑ์ด๋ฏธ์ง -> cmap ๋งค๊ฐ๋ณ์ 'gray'
plt.imshow(fruits[0], cmap='gray')
plt.show()
0์ ๊ฐ๊น์ธ ์๋ก ๊ฒ๊ฒ ๋ํ๋๊ณ ๋์ ๊ฐ์ ๋ฐ๊ฒ ํ์
์ด ํ๋ฐฑ ์ด๋ฏธ์ง๋ ์ฌ์ง์ผ๋ก ์ฐ์ ์ด๋ฏธ์ง๋ฅผ ๋ํ์ด ๋ฐฐ์ด๋ก ๋ณํํ ๋ ๋ฐ์ ์ํจ ๊ฒ
์ฌ์ง์ ํฐ ๋ฐํ(๋์ ๊ฐ)์ ๊ฒ์์(๋ฎ์ ๊ฐ)์ผ๋ก ๋ง๋ค๊ณ
์ค์ ์ฌ๊ณผ๊ฐ ์์ด ์ง์ ๋ถ๋ถ์(๋ฎ์ ๊ฐ)์ ๋ฐ์ ์(๋์ ๊ฐ)์ผ๋ก ๋ฐ๊ฟ
๊ด์ฌ ๋์์ด ๋ฐํ์ด ์๋ ์ฌ๊ณผ
ํฝ์ ๊ฐ์ด 0์ด๋ฉด ์ถ๋ ฅ๋ 0์ด ๋์ด ์๋ฏธ๊ฐ ์์
ํฝ์ ๊ฐ์ด ๋์ผ๋ฉด ์ถ๋ ฅ๊ฐ๋ ์ปค์ง๊ธฐ ๋๋ฌธ์ ์๋ฏธ ๋ถ์ฌํ๊ธฐ ์ข์
๊ด์ฌ ๋์์ ์ญ์ญ์ ๋์ ๊ฐ์ผ๋ก ๋ฐ๊พธ์์ง๋ง ๋งทํ๋กฏ๋ฆฝ์ผ๋ก ์ถ๋ ฅํ ๋ ๋ฐํ์ด ๊ฒ๊ฒ ๋์ด
gray_r ๋ค์ ๋ฐ์
cmap ๋งค๊ฐ๋ณ์๋ฅผ 'gray_r'๋ก ์ง์ ํ๋ฉด ๋ค์ ๋ฐ์ ํ์ฌ ์ฐ๋ฆฌ ๋์ ๋ณด๊ธฐ ์ข๊ฒ ์ถ๋ ฅ
plt.imshow(fruits[0],cmap='gray_r')
plt.show()
์ด ๊ทธ๋ฆผ์์ ๋ฐ์ ๋ถ๋ถ์ด 0์ ๊ฐ๊น๊ณ ์ง์ ๋ถ๋ถ์ด 255์ ๊ฐ๊น์ด ๊ฐ!
ํ์ธ์ ํ, ๋ฐ๋๋ ์ด๋ฏธ์ง ์ถ๋ ฅ
* subplots() : ์ฌ๋ฌ ๊ฐ์ ๊ทธ๋ํ๋ฅผ ๋ฐฐ์ด์ฒ๋ผ ์์ ์ ์๋๋ก ๋์์ค
๋ ๋งค๊ฐ๋ณ์๋ ๊ทธ๋ํ๋ฅผ ์์ ํ๊ณผ ์ด ์ง์
* axs : ์๋ธ ๊ทธ๋ํ๋ฅผ ๋ด๊ณ ์๋ ๋ฐฐ์ด
fig, axs = plt.subplots(1,2)
axs[0].imshow(fruits[100], cmap='gray_r')
axs[1].imshow(fruits[200], cmap='gray_r')
plt.show()
์ฒ์ 100๊ฐ ์ฌ๊ณผ, ๊ทธ ๋ค์ 100๊ฐ ํ์ธ์ ํ, ๋ง์ง๋ง 100๊ฐ ๋ฐ๋๋
ํฝ์ ๊ฐ ๋ถ์ํ๊ธฐ
๋ํ์ด ๋ฐฐ์ด์ ๋๋ ๋ 100 x 100 ์ด๋ฏธ์ง๋ฅผ ํผ์ณ์ ๊ธธ์ด๊ฐ 10,000์ธ 1์ฐจ์ ๋ฐฐ์ด๋ก ๋ณ๊ฒฝ
-> ์ด๋ฏธ์ง๋ฅผ ์ถ๋ ฅํ๊ธด ์ด๋ ต์ง๋ง ๋ฐฐ์ด์ ๊ณ์ฐํ ๋ ํธ๋ฆฌ
1์ฐจ์ ๋ฐฐ์ด๋ก ๋ณ๊ฒฝ
* .reshape : ์ฐจ์ ํฉ์นจ / ์ฒซ๋ฒ์งธ ์ฐจ์ -1๋ก ์ง์ ์ ์๋์ผ๋ก ๋จ์ ์ฐจ์ ํ ๋น
apple = fruits[0:100].reshape(-1, 100*100)
pineapple = fruits[100:200].reshape(-1, 100*100)
banana = fruits[200:300].reshape(-1, 100*100)
์ด์ ๋ฐฐ์ด ํฌ๊ธฐ๋ (100, 10000)์ผ๋ก ๋ฐ๋
์ํ์ ํฝ์ ํ๊ท ๊ฐ
* .mean() : ํ๊ท ๊ฐ
์ํ๋ง๋ค ํฝ์ ์ ํ๊ท ๊ฐ ๊ณ์ฐ -> ํ๊ท ๊ณ์ฐํ ์ถ ์ง์
* axis = 0 ์ฒซ๋ฒ์งธ ์ถ์ธ ํ์ ๋ฐ๋ผ / axis = 1 ๋๋ฒ์งธ ์ถ์ธ ์ด์ ๋ฐ๋ผ ๊ณ์ฐ
์ฐ๋ฆฌ๊ฐ ํ์ํ ๊ฒ์ ์ํ์ ํ๊ท
์ํ์ ๋ชจ๋ ๊ฐ๋ก๋ก ๊ฐ์ ๋์ดํ์ผ๋, axis = 1๋ก ์ง์ ํ์ฌ ํ๊ท ๊ณ์ฐ
print(apple.mean(axis=1))
์ฌ๊ณผ ์ํ 100๊ฐ์ ๋ํ ํฝ์ ํ๊ท ๊ฐ
ํ์คํ ๊ทธ๋จ ๊ทธ๋ ค ํ๊ท ๊ฐ ๋ถํฌ ํ์ธ
* hist() : ํ์คํ ๊ทธ๋จ ๊ทธ๋ฆฌ๊ธฐ
* alpha : 1๋ณด๋ค ์๊ฒํ๋ฉด ํฌ๋ช ๋
* legend() : ํ์คํ ๊ทธ๋จ ๋ฒ๋ก
plt.hist(np.mean(apple, axis=1), alpha=0.8)
plt.hist(np.mean(pineapple, axis=1), alpha=0.8)
plt.hist(np.mean(banana, axis=1), alpha=0.8)
plt.legend(['apple', 'pineapple', 'banana'])
plt.show()
ํฝ์ ๋ณ ํ๊ท ๊ฐ ๋น๊ต
์ํ์ ํ๊ท ๊ฐ์ด ์๋๋ผ ํฝ์ ๋ณ ํ๊ท ๊ฐ ๋น๊ต
=> ์ ์ฒด ์ํ์ ๋ํด ๊ฐ ํฝ์ ์ ํ๊ท ๊ณ์ฐ
* bar() : ๋ง๋๊ทธ๋ํ
ํฝ์ ์ ํ๊ท ์ด๋ฏ๋ก axis = 0
fig, axs = plt.subplots(1, 3, figsize=(20,5))
axs[0].bar(range(10000), np.mean(apple, axis=0))
axs[1].bar(range(10000), np.mean(pineapple, axis=0))
axs[2].bar(range(10000), np.mean(banana, axis=0))
plt.show()
๊ณผ์ผ๋ง๋ค ๊ฐ์ด ๋์ ๊ตฌ๊ฐ์ด ๋ค๋ฆ
ํฝ์ ํ๊ท ๊ฐ ์ด๋ฏธ์ง ์ถ๋ ฅ
ํฝ์ ํ๊ท ๊ฐ์ 100 x 100 ํฌ๊ธฐ๋ก ๋ฐ๊ฟ์ ์ด๋ฏธ์ฒ๋ผ ์ถ๋ ฅํ์ฌ ์ ๊ทธ๋ํ์ ๋น๊ต
apple_mean = np.mean(apple, axis=0).reshape(100, 100)
pineapple_mean = np.mean(pineapple, axis=0).reshape(100, 100)
banana_mean = np.mean(banana, axis=0).reshape(100, 100)
fig, axs = plt.subplots(1, 3, figsize=(20, 5))
axs[0].imshow(apple_mean, cmap='gray_r')
axs[1].imshow(pineapple_mean, cmap='gray_r')
axs[2].imshow(banana_mean, cmap='gray_r')
plt.show()
ํฝ์ ์์น์ ๋ฐ๋ผ ๊ฐ์ ํฌ๊ธฐ ์ฐจ์ด๋จ
ํ๊ท ๊ฐ๊ณผ ๊ฐ๊น์ด ์ฌ์ง ๊ณ ๋ฅด๊ธฐ
์ฌ๊ณผ ์ฌ์ง์ ํ๊ท ๊ฐ์ธ apple_man๊ณผ ๊ฐ์ฅ ๊ฐ๊น์ด ์ฌ์ง ๊ณ ๋ฅด๊ธฐ
=> ์ ๋๊ฐ ์ค์ฐจ : fruits ๋ฐฐ์ด์ ์๋ ๋ชจ๋ ์ํ์์ apple_mean ๋บธ ์ ๋๊ฐ์ ํ๊ท ๊ณ์ฐ
* abs() : ์ ๋๊ฐ ๊ณ์ฐ / ๋ฐฐ์ด์ ์ ๋ ฅํ๋ฉด ๋ชจ๋ ์์์ ์ ๋๊ฐ์ ๊ณ์ฐํ์ฌ ์ ๋ ฅ๊ณผ ๋์ผํ ํฌ๊ธฐ์ ๋ฐฐ์ด ๋ฐํ
abs_diff =np.abs(fruits - apple_mean)
abs_mean = np.mean(abs_diff, axis=(1,2))
print(abs_mean.shape)
์ค์ฐจ ์์ ์์๋๋ก ๊ณจ๋ผ ๊ทธ๋ํ
* np.argsort() : ์์ ๊ฒ์์ ํฐ ์์๋๋ก ๋์ด
์ฒ์ 100๊ฐ๋ฅผ ์ ํํด 10 x 10 ๊ฒฉ์๋ก ์ด๋ฃจ์ด์ง ๊ทธ๋ํ ๊ทธ๋ฆฌ๊ธฐ
subplots() ํจ์๋ก 10 x 10, ์ด 100๊ฐ์ ์๋ธ ๊ทธ๋ํ ๋ง๋ฆ
๊ทธ๋ํ๊ฐ ๋ง๊ธฐ ๋๋ฌธ์ ์ ์ฒด ๊ทธ๋ํ์ ํฌ๊ธฐ figsize=(10,10) ์ง์ (๊ธฐ๋ณธ๊ฐ (8,6))
for ๋ฐ๋ณต๋ฌธ ์ํํ๋ฉฐ 10๊ฐ์ ํ๊ณผ ์ด์ ์ด๋ฏธ์ง ์ถ๋ ฅ
axis('off') ์ขํ์ถ ๊ทธ๋ฆฌ์ง ์์
apple_index = np.argsort(abs_mean)[:100]
fig, axs = plt.subplots(10, 10, figsize=(10,10))
for i in range(10):
for j in range(10):
axs[i, j].imshow(fruits[apple_index[i*10 + j]], cmap='gray_r')
axs[i, j].axis('off')
plt.show()
ํ๋ฐฑ ์ฌ์ง์ ์๋ ํฝ์ ๊ฐ์ ์ฌ์ฉํด ๊ณผ์ผ ์ฌ์ง ๋ชจ์ผ๋ ์์ ์๋ฃ
๊ตฐ์ง : ๋น์ทํ ์ํ๋ผ๋ฆฌ ๊ทธ๋ฃน์ผ๋ก ๋ชจ์ผ๋ ์์
ํด๋ฌ์คํฐ : ๊ตฐ์ง ์๊ณ ๋ฆฌ์ฆ์์ ๋ง๋ ๊ทธ๋ฃน
06-2. K-ํ๊ท
์ง์ง ๋น์ง๋ ํ์ต์์๋ ์ฌ์ง์ ์ด๋ค ๊ณผ์ผ ๋ค์ด์๋์ง ์์ง ๋ชป ํจ
=> K-ํ๊ท ๊ตฐ์ง ์๊ณ ๋ฆฌ์ฆ์ด ํ๊ท ๊ฐ์ ์๋์ผ๋ก ์ฐพ์์ค
์ด ํ๊ท ๊ฐ์ด ํด๋ฌ์คํฐ์ ์ค์ฌ์ ์์นํ๊ธฐ ๋๋ฌธ์ ํด๋ฌ์คํฐ ์ค์ฌ ๋๋ ์ผํธ๋ก์ด๋๋ผ ๋ถ๋ฆ
K-ํ๊ท ์๊ณ ๋ฆฌ์ฆ ์๋๋ฐฉ์
1. ๋ฌด์์๋ก k๊ฐ์ ํด๋ฌ์คํฐ ์ค์ฌ์ ์ ํจ
2. ๊ฐ ์ํ์์ ๊ฐ์ฅ ๊ฐ๊น์ด ํด๋ฌ์คํฐ ์ค์ฌ์ ์ฐพ์ ํด๋น ํด๋ฌ์คํฐ์ ์ํ๋ก ์ง์
3. ํด๋ฌ์คํฐ์ ์ํ ์ํ์ ํ๊ท ๊ฐ์ผ๋ก ํด๋ฌ์คํฐ ์ค์ฌ ๋ณ๊ฒฝ
4. ํด๋ฌ์คํฐ ์ค์ฌ์ ๋ณํ๊ฐ ์์ ๋๊น์ง 2๋ฒ์ผ๋ก ๋์๊ฐ ๋ฐ๋ณต
K-ํ๊ท ์๊ณ ๋ฆฌ์ฆ์ ์ฒ์์๋ ๋๋คํ๊ฒ ํด๋ฌ์คํฐ ์ค์ฌ์ ์ ํํ๊ณ ์ ์ฐจ ๊ฐ์ฅ ๊ฐ๊น์ด ์ํ์ ์ค์ฌ์ผ๋ก ์ด๋ํ๋ ์๊ณ ๋ฆฌ์ฆ
KMeans ํด๋์ค
!wget https://bit.ly/fruits_300 -O fruits_300.npy
๋ฐฐ์ด ์ค๋น
k-ํ๊ท ๋ชจ๋ธ์ ํ๋ จํ๊ธฐ ์ํด (์ํ ๊ฐ์, ๋๋น, ๋์ด) ํฌ๊ธฐ์ 3์ฐจ์ ๋ฐฐ์ด์
(์ํ ๊ฐ์, ๋๋น x ๋์ด) ํฌ๊ธฐ๋ฅผ ๊ฐ์ง 2์ฐจ์ ๋ฐฐ์ด๋ก ๋ณ๊ฒฝ
import numpy as np
fruits = np.load('fruits_300.npy')
fruits_2d = fruits.reshape(-1, 100*100)
KMeans
k-ํ๊ท ์๊ณ ๋ฆฌ์ฆ์ sklearn.cluster ๋ชจ๋ ์๋ KMeans ํด๋์ค
* n_clusters : ํด๋ฌ์คํฐ ๊ฐ์ ์ง์
๋น์ง๋ ํ์ต์ด๋ฏ๋ก fit() ๋ฉ์๋์์ ํ๊น ๋ฐ์ดํฐ ์ฌ์ฉ x
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=42)
km.fit(fruits_2d)
labels_
๊ตฐ์ง๋ ๊ฒฐ๊ณผ๋ KMeans ํด๋์ค ๊ฐ์ฒด์ labels_ ์์ฑ์ ์ ์ฅ
labels_ ๋ฐฐ์ด์ ๊ธธ์ด๋ ์ํ ๊ฐ์์ ๊ฐ์
n_clusters=3์ผ๋ก ์ง์ ํ๊ธฐ ๋๋ฌธ์ labels_ ๋ฐฐ์ด์ ๊ฐ์ 0,1,2 ์ค ํ๋
print(km.labels_)
๋ ์ด๋ธ๊ฐ 0,1,2์ ๋ ์ด๋ธ ์์์๋ ์ด๋ค ์๋ฏธ๋ ์์
๋ ์ด๋ธ 0,1,2๋ก ๋ชจ์ ์ํ์ ๊ฐ์ ํ์ธ
print(np.unique(km.labels_, return_counts=True))
(array([0, 1, 2], dtype=int32), array([111, 98, 91]))
์ฒซ ๋ฒ์งธ ํด๋ฌ์คํฐ(๋ ์ด๋ธ 0)์ด 91๊ฐ ์ํ
๋ ๋ฒ์งธ ํด๋ฌ์คํฐ(๋ ์ด๋ธ 1)๊ฐ 98๊ฐ ์ํ
์ธ ๋ฒ์งธ ํด๋ฌ์คํฐ(๋ ์ด๋ธ 2)๊ฐ 111๊ฐ ์ํ ๋ชจ์
๊ฐ ํด๋ฌ์คํฐ ์ด๋ฏธ์ง ์ถ๋ ฅ
๊ฐ ํด๋ฌ์คํฐ๊ฐ ์ด๋ค ์ด๋ฏธ์ง๋ฅผ ๋ํ๋๋์ง ์ถ๋ ฅํ๊ธฐ ์ํด ์ ํธ๋ฆฌํฐ ํจ์ ๋ง๋ค๊ธฐ
draw_fruits() ํจ์๋ (์ํ ๊ฐ์, ๋๋น, ๋์ด)์ 3์ฐจ์ ๋ฐฐ์ด์ ์ ๋ ฅ๋ฐ์ ๊ฐ๋ก๋ก 10๊ฐ์ฉ ์ด๋ฏธ์ง๋ฅผ ์ถ๋ ฅfisize๋ ratio ๋งค๊ฐ๋ณ์์ ๋น๋กํ์ฌ ์ปค์ง (ratio ๊ธฐ๋ณธ๊ฐ 1)
import matplotlib.pyplot as plt
def draw_fruits(arr, ratio=1):
n = len(arr) # n์ ์ํ ๊ฐ์
# ํ ์ค์ 10๊ฐ์ฉ ์ด๋ฏธ์ง๋ฅผ ๊ทธ๋ฆฐ๋ค.
# ์ํ ๊ฐ์๋ฅผ 10์ผ๋ก ๋๋์ด ์ ์ฒด ํ ๊ฐ์๋ฅผ ๊ณ์ฐํ๋ค.
rows = int(np.ceil(n/10))
# ํ์ด 1๊ฐ๋ฉด ์ด์ ๊ฐ์๋ ์ํ ๊ฐ์์ด๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด 10๊ฐ์ด๋ค.
cols = n if rows < 2 else 10
fig, axs = plt.subplots(rows, cols, figsize=(cols*ratio,rows*ratio),
squeeze=False)
for i in range(rows):
for j in range(cols):
if i*10 + j < n: # n ๊ฐ๊น์ง๋ง ๊ทธ๋ฆฐ๋ค.
axs[i, j].imshow(arr[i*10 + j], cmap='gray_r')
axs[i, j].axis('off')
plt.show()
๋ถ๋ฆฌ์ธ ์ธ๋ฑ์ฑ
km.labels_==0 -> km.labels_ ๋ฐฐ์ด์์ ๊ฐ์ด 0์ธ ์์น๋ True, ๊ทธ ์ธ ๋ชจ๋ False
๋ถ๋ฆฌ์ธ ์ธ๋ฑ์ฑ : ๋ถ๋ฆฌ์ธ ๋ฐฐ์ด์ ์ฌ์ฉํด ์์ ์ ํ
draw_fruits(fruits[km.labels_==0])
๋ ์ด๋ธ 0์ผ๋ก ํด๋ฌ์คํฐ๋ง๋ 91๊ฐ ์ด๋ฏธ์ง ๋ชจ๋ ์ถ๋ ฅ
draw_fruits(fruits[km.labels_==1])
draw_fruits(fruits[km.labels_==2])
๋ ์ด๋ธ 1์ธ ํด๋ฌ์คํฐ๋ ๋ฐ๋๋๋ง
๋ ์ด๋ธ 2์ธ ํด๋ฌ์คํฐ๋ ํ์ธ์ ํ์ ์ฌ๊ณผ 9๊ฐ ๋ฐ๋๋ 2๊ฐ๊ฐ ์์์
ํด๋ฌ์คํฐ ์ค์ฌ
* cluster_centers_ : KMeans ํด๋์ค๊ฐ ์ต์ข ์ ์ผ๋ก ์ฐพ์ ํด๋ฌ์คํฐ ์ค์ฌ ์ ์ฅ
์ด ๋ฐฐ์ด์ fruits_2d ์ํ์ ํด๋ฌ์คํฐ ์ค์ฌ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง๋ก ์ถ๋ ฅํ๋ ค๋ฉด 100 x 100 ํฌ๊ธฐ์ 2์ฐจ์์ผ๋ก ๋ณ๊ฒฝ
draw_fruits(km.cluster_centers_.reshape(-1,100,100), ratio=3)
* transform() : ํ๋ จ ๋ฐ์ดํฐ ์ํ์์ ํด๋ฌ์คํฐ ์ค์ฌ๊น์ง ๊ฑฐ๋ฆฌ ๋ณํ
StandardScaler ํด๋์ค์ฒ๋ผ ํน์ฑ๊ฐ์ ๋ณํํ๋ ๋๊ตฌ๋ก ์ฌ์ฉํ ์ ์๋ค๋ ์๋ฏธ
.fruits_2d[100]์ฒ๋ผ ์ฐ๋ฉด (10000,) ํฌ๊ธฐ์ ๋ฐฐ์ด์ด ๋๋ฏ๋ก ์๋ฌ
์ฌ๋ผ์ด์ฑ ์ฐ์ฐ์ ์ฌ์ฉํด์ (1, 10000) ํฌ๊ธฐ์ ๋ฐฐ์ด ์ ๋ฌ
print(km.transform(fruits_2d[100:101]))
ํ๋์ ์ํ์ ์ ๋ฌํ๊ธฐ ๋๋ฌธ์ ๋ฐํ๋ ๋ฐฐ์ด์ ํฌ๊ธฐ๊ฐ (1, ํด๋ฌ์คํฐ ๊ฐ์) ์ธ 2์ฐจ์ ๋ฐฐ์ด
์์ธก
print(km.predict(fruits_2d[100:101]))
[2]
-> ๋ ์ด๋ธ 2๋ก ์์ธก -> ํ์ธ์ ํ
draw_fruits(fruits[100:101])
* n_iter_ : ์๊ณ ๋ฆฌ์ฆ์ด ๋ฐ๋ณตํ ํ์ ์ ์ฅ
print(km.n_iter_)
3
์ต์ ์ k ์ฐพ๊ธฐ
k-ํ๊ท ์๊ณ ๋ฆฌ์ฆ ํด๋ฌ์คํฐ ๊ฐ์ ์ฌ์ ์ ์ง์ ํด์ผ ํจ
์ค์ ์๋ ๋ช ๊ฐ์ ํด๋ฌ์คํฐ๊ฐ ์๋์ง ์ ์ ์์ ... ์ ์ ํ k ๊ฐ ?
k-ํ๊ท ์๊ณ ๋ฆฌ์ฆ์ ํด๋ฌ์คํฐ ์ค์ฌ๊ณผ ํด๋ฌ์คํฐ์ ์ํ ์ํ ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ฅผ ์ด ์ ์๋ค
์ด๋์ : ๊ฑฐ๋ฆฌ์ ์ ๊ณฑ ํฉ -> ํด๋ฌ์คํฐ์ ์ํ ์ํ์ด ์ผ๋ง๋ ๊ฐ๊น๊ฒ ๋ชจ์ฌ ์๋์ง๋ฅผ ๋ํ๋ด๋ ๊ฐ
์๋ณด์ฐ : ํด๋ฌ์คํฐ ๊ฐ์๋ฅผ ๋๋ ค๊ฐ๋ฉด์ ์ด๋์ ์ ๋ณํ๋ฅผ ๊ด์ฐฐํ์ฌ ์ต์ ์ ํด๋ฌ์คํฐ ๊ฐ์๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ
ํด๋ฌ์คํฐ ๊ฐ์๋ฅผ ์ฆ์ฌ๊ธฐํค๋ฉด์ ์ด๋์ ๋ฅผ ๊ทธ๋ํ๋ก ๊ทธ๋ฆฌ๋ฉด ๊ฐ์ํ๋ ์๋๊ฐ ๊บพ์ด๋ ์ง์ ์ด ์๋ค
์ด ์ง์ ๋ถํฐ๋ ํด๋ฌ์คํฐ ๊ฐ์๋ฅผ ๋๋ ค๋ ํด๋ฌ์คํฐ์ ์ ๋ฐ์ง๋ ์ ๋๊ฐ ํฌ๊ฒ ๊ฐ์ ๋์ง ์์
์ฆ, ์ด๋์ ๊ฐ ํฌ๊ฒ ์ค์ด๋ค์ง ์๋๋ค. -> ์ด ์ง์ ์ด ํ๊ฟ์น ๋ชจ์ ๊ฐ์์ ์๋ณด์ฐ ๋ฐฉ๋ฒ์ด๋ผ ๋ถ๋ฆ
์ต์ ์ k ๊ฐ - inertia
* inertia_ : ์๋์ผ๋ก ์ด๋์ ๊ณ์ฐํด์ ์ ๊ณต
ํด๋ฌ์คํฐ ๊ฐ์ k๋ฅผ 2~6๊น์ง ๋ฐ๊ฟ๊ฐ๋ฉฐ KMeans ํด๋์ค๋ฅผ 5๋ฒ ํ๋ จ
fit() ๋ฉ์๋๋ก ๋ชจ๋ธ์ ํ๋ จํ ํ inertia_ ์์ฑ์ ์ ์ฅ๋ ์ด๋์ ๊ฐ์ inertia ๋ฆฌ์คํธ์ ์ถ๊ฐ
inertia ๋ฆฌ์คํธ์ ์ ์ฅ๋ ๊ฐ์ ๊ทธ๋ํ๋ก ์ถ๋ ฅ
inertia = []
for k in range(2, 7):
km = KMeans(n_clusters=k, random_state=42)
km.fit(fruits_2d)
inertia.append(km.inertia_)
plt.plot(range(2, 7), inertia)
plt.xlabel('k')
plt.ylabel('inertia')
plt.show()
k = 3์์ ๊ทธ๋ํ์ ๊ธฐ์ธ๊ธฐ๊ฐ ์กฐ๊ธ ๋ฐ๋
06-3. ์ฃผ์ฑ๋ถ ๋ถ์
๊ตฐ์ง์ด๋ ๋ถ๋ฅ์ ์ํฅ์ ๋ผ์น์ง ์์ผ๋ฉด์ ์ ๋ก๋๋ ์ฌ์ง์ ์ฉ๋ ์ค์ด๊ธฐ
์ฐจ์๊ณผ ์ฐจ์ ์ถ์
๋ฐ์ดํฐ๊ฐ ๊ฐ์ง ์์ฑ์ 'ํน์ฑ'์ด๋ผ๊ณ ๋ถ๋ฆ
๊ณผ์ผ ์ฌ์ง์ ๊ฒฝ์ฐ 10000๊ฐ์ ํฝ์ ์ด ์๊ธฐ ๋๋ฌธ์ 10000๊ฐ์ ํน์ฑ์ด ์๋ ์
๋จธ์ ๋ฌ๋์์๋ ์ด๋ฅธ ํน์ฑ์ '์ฐจ์'์ด๋ผ๊ณ ๋ถ๋ฆ
10000๊ฐ ํน์ฑ = 10000๊ฐ ์ฐจ์ -> ์ฐจ์์ ์ค์ด๋ฉด ์ ์ฅ๊ณต๊ฐ ์ ์ฝ!
์ฐจ์์ถ์ : ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฅ ์ ๋ํ๋ด๋ ์ผ๋ถ ํน์ฑ์ ์ ํํ์ฌ ๋ฐ์ดํฐ ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ
์ง๋ ํ์ต ๋ชจ๋ธ์ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ ๋ฐฉ๋ฒ
์ค์ด๋ ์ฐจ์์์ ๋ค์ ์๋ณธ ์ฐจ์์ผ๋ก ์์ค์ ์ต๋ํ ์ค์ด๋ฉด์ ๋ณต์ํ ์๋ ์์
์ฃผ์ฑ๋ถ ๋ถ์(PCA) : ๋ํ์ ์ธ ์ฐจ์ ์ถ์ ์๊ณ ๋ฆฌ์ฆ
์ฃผ์ฑ๋ถ ๋ถ์
์ฃผ์ฑ๋ถ ๋ถ์(PCA)์ ๋ฐ์ดํฐ์ ์๋ ๋ถ์ฐ์ด ํฐ ๋ฐฉํฅ์ ์ฐพ๋ ๊ฒ
๋ถ์ฐ : ๋ฐ์ดํฐ๊ฐ ๋๋ฆฌ ํผ์ ธ์๋ ์ ๋
๋ถ์ฐ์ด ํฐ ๋ฐฉํฅ์ด๋ ๋ฐ์ดํฐ๋ฅผ ์ ํํํ๋ ์ด๋ค ๋ฒกํฐ
์ฃผ์ฑ๋ถ ๋ฒกํฐ : ์๋ณธ ๋ฐ์ดํฐ์ ์๋ ์ด๋ค ๋ฐฉํฅ
์ฃผ์ฑ๋ถ ๋ฒกํฐ์ ์์ ๊ฐ์๋ ์๋ณธ ๋ฐ์ดํฐ์ ์ ์๋ ํน์ฑ ๊ฐ์์ ๊ฐ์
์ฃผ์ฑ๋ถ์ ์๋ณธ ์ฐจ์๊ณผ ๊ฐ๊ณ , ์ฃผ์ฑ๋ถ์ผ๋ก ๋ฐ๊พผ ๋ฐ์ดํฐ๋ ์ฐจ์์ด ์ค์ด๋ฌ!!
์ฒซ ๋ฒ์งธ ์ฃผ์ฑ๋ถ์ ์ฐพ์ ๋ค์ ์ด ๋ฒกํฐ์ ์์ง์ด๊ณ ๋ถ์ฐ์ด ๊ฐ์ฅ ํฐ ๋ค์ ๋ฐฉํฅ์ ์ฐพ์
์ด ๋ฒกํฐ๊ฐ ๋ ๋ฒ์งธ ์ฃผ์ฑ๋ถ
์ฃผ์ฑ๋ถ์ ์๋ณธ ํน์ฑ์ ๊ฐ์๋งํผ ์ฐพ์ ์ ์์
PCA ํด๋์ค
!wget https://bit.ly/fruits_300 -O fruits_300.npy
import numpy as np
fruits = np.load('fruits_300.npy')
fruits_2d = fruits.reshape(-1, 100*100)
์ฌ์ดํท๋ฐ skearn.decomposition ๋ชจ๋ ์๋ pcaํด๋์ค๋ก ์ฃผ์ฑ๋ถ ๋ถ์ ์๊ณ ๋ฆฌ์ฆ ์ ๊ณต
pca ํด๋์ค ๋ง๋ค ๋ n_components ์ง์ ํด์ผ ํจ
* n_components : ์ฃผ์ฑ๋ถ์ ๊ฐ์ ์ง์
๋น์ง๋ ํ์ต์ด๊ธฐ ๋๋ฌธ์ fit() ๋ฉ์๋์ ํ๊น๊ฐ ์ ๊ณต x
from sklearn.decomposition import PCA
pca = PCA(n_components=50)
pca.fit(fruits_2d)
* components_ : PCA ํด๋์ค๊ฐ ์ฐพ์ ์ฃผ์ฑ๋ถ ์ ์ฅ
print(pca.components_.shape)
(50, 10000)
n_components = 50์ผ๋ก ์ง์ ํ๊ธฐ ๋๋ฌธ์ pca.components_ ๋ฐฐ์ด์ ์ฒซ ๋ฒ์งธ ์ฐจ์์ด 500
์ฆ, 50๊ฐ์ ์ฃผ์ฑ๋ถ์ ์ฐพ์
๋๋ฒ์งธ ์ฐจ์์ ํญ์ ์๋ณธ ๋ฐ์ดํฐ์ ํน์ฑ ๊ฐ์์ ๊ฐ์ 10000
draw_fruits() ์ฃผ์ฑ๋ถ ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ
draw_fruits(pca.components_.reshape(-1, 100, 100))
์ฃผ์ฑ๋ถ์ ์๋ณธ ๋ฐ์ดํฐ์์ ๊ฐ์ฅ ๋ถ์ฐ์ด ํฐ ๋ฐฉํฅ์ ์์๋๋ก ๋ํ๋ธ ๊ฒ
๋ฐ์ดํฐ ์ ์ ์๋ ์ด๋ค ํน์ง์ ์ก์๋ธ ๊ฒ์ฒ๋ผ ์๊ฐ
์ฃผ์ฑ๋ถ์ ์ฐพ์์ผ๋ฏ๋ก ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์ฃผ์ฑ๋ถ์ ํฌ์ํ์ฌ ํน์ฑ ๊ฐ์๋ฅผ 10,000๊ฐ์์ 50๊ฐ๋ก ์ค์ผ ์ ์์
์ฃผ์ฑ๋ถ์ผ๋ก ์ฐจ์ ์ค์ด๊ธฐ
* transform() : ์ฐจ์ ์ค์ด๊ธฐ
fruits_pca = pca.transform(fruits_2d)
print(fruits_pca.shape)
(300, 50)
์๋ณธ ๋ฐ์ดํฐ ์ฌ๊ตฌ์ฑ
10000๊ฐ ํน์ฑ์ 50๊ฐ๋ก ์ค์ -> ์ด๋ ์ ๋ ์์ค ๋ฐ์
์ต๋ํ ๋ถ์ฐ์ด ํฐ ๋ฐฉํฅ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ํฌ์ํ๊ธฐ ๋๋ฌธ์, ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์๋น ๋ถ๋ถ ์ฌ๊ตฌ์ฑํ ์ ์์
* inverse_transform() : ์๋ณธ ๋ฐ์ดํฐ ๋ณต์
fruits_inverse = pca.inverse_transform(fruits_pca)
print(fruits_inverse.shape)
(300, 10000)
๋ณต์ํ ๋ฐ์ดํฐ ๊ทธ๋ฆผ์ถ๋ ฅ
fruits_reconstruct = fruits_inverse.reshape(-1, 100, 100)
for start in [0, 100, 200]:
draw_fruits(fruits_reconstruct[start:start+100])
print("\n")
50๊ฐ์ ํน์ฑ์ด ๋ถ์ฐ์ ๊ฐ์ฅ ์ ๋ณด์กดํ๋๋ก ๋ณํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
๊ฑฐ์ ๋ค ์ ๋ณต์ ๋จ
๋ง์ฝ ์ฃผ์ฑ๋ถ์ ์ต๋๋ก ์ฌ์ฉํ๋ค๋ฉด ์๋ฒฝํ๊ฒ ์๋ณธ ๋ฐ์ดํฐ ์ฌ๊ตฌ์ฑ ๊ฐ๋ฅ
์ค๋ช ๋ ๋ถ์ฐ
์ค๋ช ๋ ๋ถ์ฐ : ์ฃผ์ฑ๋ถ์ด ์๋ณธ ๋ฐ์ดํฐ์ ๋ถ์ฐ์ ์ผ๋ง๋ ์ ๋ํ๋ด๋์ง ๊ธฐ๋กํ ๊ฐ
* explained_variance_ratio_ : ์ฃผ์ฑ๋ถ์ ์ค๋ช ๋ ๋ถ์ฐ ๋น์จ
์ฒซ ๋ฒ์งธ ์ฃผ์ฑ๋ถ์ ์ค๋ช ๋ ๋ถ์ฐ์ด ๊ฐ์ฅ ํผ
๋ถ์ฐ ๋น์จ์ ๋ชจ๋ ๋ํ๋ฉด 50๊ฐ์ ์ฃผ์ฑ๋ถ์ผ๋ก ํํํ๊ณ ์๋ ์ด ๋ถ์ฐ ๋น์จ์ ์ป์ ์ ์์
print(np.sum(pca.explained_variance_ratio_))
plt.plot(pca.explained_variance_ratio_)
plt.show()
์ฒ์ 10๊ฐ์ ์ฃผ์ฑ๋ถ์ด ๋๋ถ๋ถ์ ๋ถ์ฐ์ ํํํ๊ณ ์์
๊ทธ ๋ค์๋ถํฐ๋ ๊ฐ ์ฃผ์ฑ๋ถ์ด ์ค๋ช ํ๊ณ ์๋ ๋ถ์ฐ ๋น๊ต์ ์์
๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ๊ณผ ํจ๊ป ์ฌ์ฉ
3๊ฐ์ ๊ณผ์ผ ์ฌ์ง์ ๋ถ๋ฅ -> ๋ก์ง์คํฑ ํ๊ท ๋ชจ๋ธ LogisticRegression
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
์ง๋ ํ์ต ๋ชจ๋ธ ์ฌ์ฉํ๋ ค๋ฉด ํ๊น๊ฐ ์์ด์ผ ํจ
์ฌ๊ธฐ์ ์ฌ๊ณผ 0, ํ์ธ์ ํ 1, ๋ฐ๋๋ 2๋ก ์ง์
ํ์ด์ฌ ๋ฆฌ์คํธ์ ์ ์๋ฅผ ๊ณฑํ๋ฉด ๋ฆฌ์คํธ ์์ ์์๋ฅผ ์ ์๋งํผ ๋ฐ๋ณต
target = np.array([0]*100 + [1]*100 + [2]*100)
๋ก์ง์คํฑ ํ๊ท ๋ชจ๋ธ์์ ์ฑ๋ฅ ๊ฐ๋ ์ํด
* cross_validate() ๊ต์ฐจ๊ฒ์ฆ
from sklearn.model_selection import cross_validate
scores = cross_validate(lr, fruits_2d, target)
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))
0.9966666666666667
0.9233800888061523
๊ต์ฐจ ๊ฒ์ฆ ์ ์ 0.997 ์ ๋๋ก ๋งค์ฐ ๋์
ํน์ฑ 10000๊ฐ๋ ๋๊ธฐ ๋๋ฌธ์ 300๊ฐ ์ํ์์๋ ๊ธ๋ฐฉ ๊ณผ๋์ ํฉ๋ ๋ชจ๋ธ ๋ง๋ค๊ธฐ ์ฌ์
* fit_time : ๊ฐ ๊ต์ฐจ ๊ฒ์ฆ ํด๋์ ํ๋ จ์๊ฐ
0.94์ด ์ ๋ ๊ฑธ๋ฆผ
์ถ์ํ ๊ฐ๊ณผ ๋น๊ต
scores = cross_validate(lr, fruits_pca, target)
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))
1.0
0.02978053092956543
50๊ฐ์ ํน์ฑ๋ง ์ฌ์ฉํ๋๋ฐ๋ ์ ํ๋ 100%
ํ๋ จ์๊ฐ 0.03์ด๋ก ๊ฐ์ํจ
PCA๋ก ํ๋ จ ๋ฐ์ดํฐ์ ์ฐจ์์ ์ถ์ํ๋ฉด ์ ์ฅ ๊ณต๊ฐ๋ฟ๋ง ์๋๋ผ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ํ๋ จ ์๋๋ ๋์ผ ์ ์์
์ค๋ช ๋ ๋ถ์ฐ ๋น์จ ์ ๋ ฅ
* n_components : ์ฃผ์ฑ๋ถ ๊ฐ์ ์ง์
๋์ ์ํ๋ ์ค๋ช ๋ ๋ถ์ฐ์ ๋น์จ ์ ๋ ฅ ๊ฐ๋ฅ, PCA ํด๋์ค ์ง์ ๋ ๋น์จ์ ๋๋ฌํ ๋๊น์ง ์๋์ผ๋ก ์ฃผ์ฑ๋ถ ์ฐพ์
์ฃผ์ฑ๋ถ ๊ฐ์ ๋์ 0~1 ์ฌ์ด์ ๋น์จ์ ์ค์๋ก ์ ๋ ฅ
pca = PCA(n_components=0.5)
pca.fit(fruits_2d)
๋ช ๊ฐ์ ์ฃผ์ฑ๋ถ ์ฐพ์๋์ง
print(pca.n_components_)
2
-> ๋จ 2๊ฐ์ ํน์ฑ๋ง์ผ๋ก ์๋ณธ ๋ฐ์ดํฐ์ ์๋ ๋ถ์ฐ์ 50%๊น์ง ํํํ ์ ์๋ค
์๋ณธ ๋ฐ์ดํฐ ๋ณํ
fruits_pca = pca.transform(fruits_2d)
print(fruits_pca.shape)
(300, 2)
์ฃผ์ฑ๋ถ์ด 2๊ฐ์ด๋ฏ๋ก ๋ณํ๋ ๋ฐ์ดํฐ ํฌ๊ธฐ (300, 2)
๊ต์ฐจ ๊ฒ์ฆ ๊ฒฐ๊ณผ
scores = cross_validate(lr, fruits_pca, target)
print(np.mean(scores['test_score']))
print(np.mean(scores['fit_time']))
0.99
0.03771648406982422
2๊ฐ์ ํน์ฑ์ ์ฌ์ฉํ์ ๋ฟ์ธ๋ฐ 99% ์ ํ๋ ๋ฌ์ฑ
์ฐจ์ ์ถ์๋ ๋ฐ์ดํฐ ์ฌ์ฉ k-ํ๊ท ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํด๋ฌ์คํฐ ์ฐพ๊ธฐ
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=42)
km.fit(fruits_pca)
print(np.unique(km.labels_, return_counts=True))
(array([0, 1, 2], dtype=int32), array([ 91, 99, 110]))
์ฐพ์ ํด๋ฌ์คํฐ๋ ๊ฐ๊ฐ 91, 99, 110๊ฐ์ ์ํ ํฌํจ
KMeans ์ฐพ์ ๋ ์ด๋ธ ์ด๋ฏธ์ง ์ถ๋ ฅ
for label in range(0,3):
draw_fruits(fruits[km.labels_ == label])
print("\n")
ํด๋ฌ์คํฐ๋ณ ์ฐ์ ๋
์ฐจ์ ์ค์ด๋ฉด ์ป๋ ๋ ํ๋์ ์ฅ์ : ์๊ฐํ!
3๊ฐ ์ดํ๋ก ์ฐจ์์ ์ค์ด๋ฉด ํ๋ฉด์ ์ถ๋ ฅํ๊ธฐ ๋น๊ต์ ์ฌ์
km.labels_ ์ฌ์ฉ ํด๋ฌ์คํฐ๋ณ๋ก ๋๋์ด ์ฐ์ ๋ ๊ทธ๋ฆฌ๊ธฐ
for label in range(0, 3):
data = fruits_pca[km.labels_ == label]
plt.scatter(data[:,0], data[:,1])
plt.legend(['apple', 'banana', 'pineapple'])
plt.show()
๊ฐ ํด๋ฌ์คํฐ์ ์ฐ์ ๋๊ฐ ์์ฃผ ์ ๊ตฌ๋ถ๋จ
์ฐธ๊ณ ๋์ : ํผ์๊ณต๋ถํ๋ ๋จธ์ ๋ฌ๋ + ๋ฅ๋ฌ๋, ๋ฐํด์ , ํ๋น๋ฏธ๋์ด, 2020๋
'Ability ๐ฑ > ML' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ํผ๊ณต๋จธ์ ] 06. ์ ๋ฆฌ (1) | 2022.06.23 |
---|---|
[ํผ๊ณต๋จธ์ ] 05. ์ ๋ฆฌ (0) | 2022.06.22 |
[ํผ๊ณต๋จธ์ ] 05. ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ (0) | 2022.06.22 |
[ํผ๊ณต๋จธ์ ] 04. ์ ๋ฆฌ (1) | 2022.06.21 |
[ํผ๊ณต๋จธ์ ] 04. ๋ค์ํ ๋ถ๋ฅ ์๊ณ ๋ฆฌ์ฆ - ๋ก์ง์คํฑ ํ๊ท, ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ (0) | 2022.06.19 |