class KMeans:
def __init__(self, n_clusters, max_iters=100):
self.n_clusters = n_clusters # 군집의 개수 K 지정
self.max_iters = max_iters # 최대 학습 반복횟수 지정
self.centroids = None # 중심점 변수를 설정
def fit(self, X):
n_samples, n_features = X.shape
# 무작위로 중심점 초기화 - 클러스터 개수를 초기 중심점으로 설정
random_indices = np.random.choice(n_samples, self.n_clusters, replace=False)
self.centroids = X[random_indices]
def _euclidean_distances(self, X, Y):
distances = np.sqrt(np.sum((X[:, np.newaxis] - Y)**2, axis=2))
return distances
def _assign_labels(self, X):
distances = self._euclidean_distances(X, self.centroids)
labels = np.argmin(distances, axis=1)
return labels
def _update_centroids(self, X, labels):
new_centroids = np.zeros_like(self.centroids)
for cluster in range(self.n_clusters):
# 특정 클러스터에 해당하는 포인트 모음
cluster_points = X[labels == cluster]
# 특정 클러스터 포인트의 중심점을 찾기 위해 평균을 계산
new_centroid = np.mean(cluster_points, axis=0)
# 새로운 클러스터로 할당
new_centroids[cluster] = new_centroid
return new_centroids
def fit(self, X):
...
for _ in range(self.max_iters):
# 각 샘플에 레이블 할당
labels = self._assign_labels(X)
# 중심점 업데이트
new_centroids = self._update_centroids(X, labels)
# 중심점이 수렴했는지 확인
if np.allclose(self.centroids, new_centroids):
break
# 더 이상 업데이트 되지 않으면 훈련을 중단
self.centroids = new_centroids
import numpy as np
# K-Means 정의
class KMeans:
def __init__(self, n_clusters, max_iters=100):
self.n_clusters = n_clusters
self.max_iters = max_iters
self.centroids = None
# K개의 초기 중심점을 내장되어있는 알고리즘에 따라 지정
def fit(self, X):
n_samples, n_features = X.shape
# 무작위로 중심점 초기화
random_indices = np.random.choice(n_samples, self.n_clusters, replace=False)
self.centroids = X[random_indices]
# 더이상 중심점이 갱신되지 않을때가지 3-4번 방복
for _ in range(self.max_iters):
# 각 샘플에 레이블 할당
labels = self._assign_labels(X)
# 중심점 업데이트
new_centroids = self._update_centroids(X, labels)
# 중심점이 수렴했는지 확인
if np.allclose(self.centroids, new_centroids):
break
# 더이상 업데이트 안되면 훈련 중단
self.centroids = new_centroids
# 유클리디안으로 군집 할당
def _assign_labels(self, X):
distances = self._euclidean_distances(X, self.centroids)
labels = np.argmin(distances, axis=1)
return labels
# 군집 내 데이터들의 평균점을 새로운 중심점으로 갱신
def _update_centroids(self, X, labels):
new_centroids = np.zeros_like(self.centroids)
for cluster in range(self.n_clusters):
# 특정 클러스터에 해당하는 포인트 모음
cluster_points = X[labels == cluster]
# 특정 클러스터 포인트들의 중심점을 찾기위해 평균 계산
new_centroid = np.mean(cluster_points, axis=0)
# new 클러스터로 할당
new_centroids[cluster] = new_centroid
return new_centroids
# 군집 할당을 위한 유클리디안 정의
def _euclidean_distances(self, X, Y):
distances = np.sqrt(np.sum((X[:, np.newaxis] - Y)**2, axis=2))
return distances
def predict(self, X):
labels = self._assign_labels(X)
return labels
# 주어진 거리내에서 포인트들의 이웃을 찾는 함수 정의
def _get_neighbors(self, X, i):
distances = np.linalg.norm(X - X[i], axis=1)
neighbors = np.where(distances <= self.eps)[0]
return neighbors
# 현재 데이터 포인트를 클러스터에 할당
def _expand_cluster(self, X, i, neighbors, cluster_label, visited):
self.labels[i] = cluster_label
# 새로운 이웃들을 현재 이웃들에 추가
j = 0
while j < len(neighbors):
neighbor = neighbors[j]
if not visited[neighbor]:
visited[neighbor] = True
new_neighbors = self._get_neighbors(X, neighbor)
if len(new_neighbors) >= self.min_samples:
neighbors = np.concatenate((neighbors, new_neighbors))
# 이웃을 현재 클러스터에 할당
if self.labels[neighbor] == 0:
self.labels[neighbor] = cluster_label
j += 1
# DBSCAN 정의
class DBSCAN:
def __init__(self, eps=0.5, min_samples=5):
self.eps = eps
self.min_samples = min_samples
self.labels = None
def fit(self, X):
n_samples = X.shape[0]
self.labels = np.zeros(n_samples, dtype=int)
visited = np.zeros(n_samples, dtype=bool)
cluster_label = 0
for i in range(n_samples):
if visited[i]: # 이미 방문한 적이 있다(클러스터가 할당되었다)면 continue
continue
visited[i] = True
neighbors = self._get_neighbors(X, i)
if len(neighbors) < self.min_samples:
self.labels[i] = -1 # Noise point
else:
cluster_label += 1
self._expand_cluster(X, i, neighbors, cluster_label, visited)
import numpy as np
# DBSCAN 정의
class DBSCAN:
def __init__(self, eps=0.5, min_samples=5):
self.eps = eps
self.min_samples = min_samples
self.labels = None
def fit(self, X):
n_samples = X.shape[0]
self.labels = np.zeros(n_samples, dtype=int)
visited = np.zeros(n_samples, dtype=bool)
cluster_label = 0
for i in range(n_samples):
if visited[i]: # 클러스터가 할당되었다면 continue
continue
visited[i] = True
neighbors = self._get_neighbors(X, i)
if len(neighbors) < self.min_samples:
self.labels[i] = -1 # Noise point
else:
cluster_label += 1
self._expand_cluster(X, i, neighbors, cluster_label, visited)
# 주어진 거리범위(Epsilon) 내에서 포인트들의 이웃을 찾음
def _get_neighbors(self, X, i):
distances = np.linalg.norm(X - X[i], axis=1)
neighbors = np.where(distances <= self.eps)[0]
return neighbors
# 도달 가능한 포인트를 추가하며 클러스터를 확장해감
def _expand_cluster(self, X, i, neighbors, cluster_label, visited):
self.labels[i] = cluster_label # 현재 데이터 포인트를 클러스터에 할당
j = 0
while j < len(neighbors):
neighbor = neighbors[j]
if not visited[neighbor]:
visited[neighbor] = True
new_neighbors = self._get_neighbors(X, neighbor)
if len(new_neighbors) >= self.min_samples:
neighbors = np.concatenate((neighbors, new_neighbors))
# 새로운 이웃들을 현재 이웃들에 추가
if self.labels[neighbor] == 0:
self.labels[neighbor] = cluster_label
# 이웃을 현재 클러스터에 할당
j += 1
def predict(self, X):
return self.labels
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.manifold import TSNE
digits = load_digits()
X = digits.data
y = digits.target
tsne = TSNE(n_components=2, random_state=42)
X_tsne = tsne.fit_transform(X)
plt.figure(figsize=(10, 8))
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap=plt.cm.get_cmap("jet", 10))
plt.colorbar(ticks=range(10))
plt.title("t-SNE")
plt.show()
import numpy as np
def pca(X, num_components):
# 데이터 중심화
X_centered = X - np.mean(X, axis=0)
# 공분산 행렬 계산
cov_matrix = np.cov(X_centered.T)
# 공분산 행렬의 고윳값과 고유벡터 계산
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
# 고유값을 내림차순으로 정렬
sorted_indices = np.argsort(eigenvalues)[::-1]
sorted_eigenvalues = eigenvalues[sorted_indices]
sorted_eigenvectors = eigenvectors[:, sorted_indices]
# 상위 k개의 고유벡터 선택 (주성분)
selected_eigenvectors = sorted_eigenvectors[:, :num_components]
# 데이터를 새로운 특징 공간으로 변환
transformed_data = np.dot(X_centered, selected_eigenvectors)
return transformed_data
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
digits = load_digits()
X = digits.data
y = digits.target
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
plt.scatter(X_pca[:,0] , X_pca[:,1], c = y, cmap=plt.cm.get_cmap("jet", 10))
plt.colorbar(ticks=range(10))
plt.title("PCA")
plt.show()
[출처 | 딥다이브 Code.zip 매거진]