728x90
반응형
2023/09/04
2023.09.01 - [LG 헬로비전 DX DATA SCHOOL/Python] - (Python)군집 분석 및 과일 이미지 군집 분석 실습
(Python)군집 분석 및 과일 이미지 군집 분석 실습
2023-0901 ** Clustering(군집) 1. 군집 비슷한 샘플들을 구별해서 하나의 클러스터로 묶는 작업 비지도 학습 : 레이블이 없는 학습 (정답이 없는 학습) 1.1) 군집이 이용되는 분야 고객 분류 데이터 분석
dxdata.tistory.com
이전 글에 이어 진행하겠습니다!
그 내용이 궁금하신 분들은 위 글을 방문해주세요
6. DBSCAN
6.1) 개요
- 국부적인 밀집도를 추정하는 매우 다른방식을 사용
- 임의의 모양을 가진 클러스터를 식별 가능
- 간단하고 직관적인 알고리즘
- 내부의 원 모양과 외부의 원 모양을 가진 형태의 데이터 분포의 경우 KMeans 나 GMM 또는 계층적 클러스터링으로는 효과적인 군집화가 어려움
- DBSCAN 은 특정 공간 내에 데이터 밀도 차이에 기반한 알고리즘
6.2) 알고리즘
- epsilon : 주변 영역 (공통된 n 개로 구성된 클러스터를 이룸)
- min points : 앱실론 영역에 포함되는 다른 데이터의 개수
- Core Point(핵심 포인트) : 주변 영역 내에 최소 데이터 개수 이상의 다른 데이터를 포함한 포인트
- Neighbor Point(이웃 포인트) : 주변 영역 내에 존재하는 다른 데이터
- Border Point(경계 포인트) : 주변 영역 내에 최소 데이터 개수 이상의 이웃 포인트를 가지고 있지 않지만 핵심 포인트를 이웃으로 가지고 있는 데이터
- Noise Point(잡음 포인트) : 최소 데이터 개수 만큼의 이웃 포인트도 가지지 않고 핵심 포인트도 이웃 포인트로 가지지 않은 데이터
- 작동 방식
알고리즘이 각 샘플에서 엡실론 내에 샘플이 몇 개 놓였는지 세고 이 지역을 샘플의 이웃이라고 불림
이웃 내에 min_samples 개 이상의 데이터가 존재하면 핵심 포인트로 간주
핵심 샘플의 이웃에 있는 모든 샘플은 동일한 클러스터에 속하고 이웃에는 다른 핵심 포인트가 포함될 수 있어서 핵심 포인트의 이웃의 이웃은 계속해서 하나의 클러스터를 형성
핵심 포인트도 아니고 이웃 포인트도 아닌 잡음 포인트는 이상치로 판단
6.3) 클래스
- sklearn 의 DBSCAN 클래스 이용
- 초기화 파라미터
epsilon : 엡실론
min_samples : 최소 이웃의 개수
6.4) DBSCAN을 이용한 반달 모양의 데이터 군집
- eps 을 0.05 그리고 min_samples를 5로 설정해서 DBSCAN을 수행
from sklearn.datasets import make_moons
from sklearn.cluster import DBSCAN
#훈련 데이터 생성
X, y = make_moons(n_samples=1000, noise=0.05, random_state=42)
#훈련
dbscan = DBSCAN(eps=0.05, min_samples=5)
dbscan.fit(X)
#첫번째 10개의 레이블 출력 - -1로 분류된 샘플은 이상치
print(dbscan.labels_[:10])
#핵심 샘플의 인덱스 개수 확인
print(len(dbscan.core_sample_indices_))
#핵심 샘플 확인
#print(dbscan.core_sample_indices_)
#핵심 샘플 자체의 값 출력
print(dbscan.components_)
#클러스터 확인
print(np.unique(dbscan.labels_))
plt.scatter(x=X[:,0], y=X[:,1])
##result
[ 0 2 -1 -1 1 0 0 0 2 5]
808
[[-0.02137124 0.40618608]
[-0.84192557 0.53058695]
[ 0.58930337 -0.32137599]
...
[ 1.66258462 -0.3079193 ]
[-0.94355873 0.3278936 ]
[ 0.79419406 0.60777171]]
[-1 0 1 2 3 4 5 6]
- eps 를 0.2 그리고 min_samples 를 5로 설정해서 DBSCAN을 수행
# eps 을 0.2 그리고 min_samples를 5로 설정해서 DBSCAN을 수행
#훈련
dbscan1 = DBSCAN(eps=0.2, min_samples=5)
dbscan1.fit(X)
#첫번째 10개의 레이블 출력 - -1로 분류된 샘플은 이상치
print(dbscan1.labels_[:10])
#핵심 샘플의 인덱스 개수 확인
print(len(dbscan1.core_sample_indices_))
#핵심 샘플 확인
#print(dbscan.core_sample_indices_)
#핵심 샘플 자체의 값 출력
print(dbscan1.components_)
#클러스터 확인
print(np.unique(dbscan1.labels_))
##result
[0 0 0 0 1 0 0 0 0 1]
1000
[[-0.02137124 0.40618608]
[ 0.97670045 -0.45832306]
[ 0.90405882 -0.37651952]
...
[ 1.66258462 -0.3079193 ]
[-0.94355873 0.3278936 ]
[ 0.79419406 0.60777171]]
[0 1]
DBSCAN 군집 결과 시각화
#DBSCAN 샘플 - 입실론 조정
def plot_dbscan(dbscan, X, size, show_xlabels=True, show_ylabels=True):
core_mask = np.zeros_like(dbscan.labels_, dtype=bool)
core_mask[dbscan.core_sample_indices_] = True
anomalies_mask = dbscan.labels_ == -1
non_core_mask = ~(core_mask | anomalies_mask)
cores = dbscan.components_
anomalies = X[anomalies_mask]
non_cores = X[non_core_mask]
plt.scatter(cores[:, 0], cores[:, 1],
c=dbscan.labels_[core_mask], marker='o', s=size, cmap="Paired")
plt.scatter(cores[:, 0], cores[:, 1], marker='*', s=20, c=dbscan.labels_[core_mask])
plt.scatter(anomalies[:, 0], anomalies[:, 1],
c="r", marker="x", s=100)
plt.scatter(non_cores[:, 0], non_cores[:, 1], c=dbscan.labels_[non_core_mask], marker=".")
if show_xlabels:
plt.xlabel("$x_1$", fontsize=14)
else:
plt.tick_params(labelbottom=False)
if show_ylabels:
plt.ylabel("$x_2$", fontsize=14, rotation=0)
else:
plt.tick_params(labelleft=False)
plt.title("eps={:.2f}, min_samples={}".format(dbscan.eps, dbscan.min_samples), fontsize=14)
#DBSACN 샘플 - 입실론 조정
dbscan2 = DBSCAN(eps=0.2)
dbscan2.fit(X)
plt.figure(figsize=(9, 3.2))
plt.subplot(121)
plot_dbscan(dbscan, X, size=100)
plt.subplot(122)
plot_dbscan(dbscan2, X, size=600, show_ylabels=False)
save_fig("dbscan_plot")
plt.show()
6.5) 예측
- DBSCAN은 predict 와 같은 예측 함수를 제공하지 않음
- 군집 한 후의 예측은 분류나 회귀 알고리즘이 더 잘하기 때문
- 군집한 결과를 가지고 분류나 회귀 알고리즘을 수행한 후 새로운 데이터에 대한 예측을 수행
#새로운 데이터에 대한 예측
dbscan = dbscan2
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=50)
knn.fit(dbscan.components_, dbscan.labels_[dbscan.core_sample_indices_])
X_new = np.array([[-0.5, 0], [0, 0.5], [1, -0.1], [2, 1]])
result = knn.predict(X_new)
#확률
print(result)
print(knn.predict_proba(X_new))
##result
[1 0 1 0]
[[0.18 0.82]
[1. 0. ]
[0.12 0.88]
[1. 0. ]]
6.6) 정리
- 매우 간단하지만 강력한 알고리즘
- 클러스터의 모양과 개수에 상관없이 감지할 수 있는 능력이 있음.
- 이상치에 안정적이고 하이퍼 파라미터가 2개(eps, min_samples)
- 클러스터 간의 밀집도가 다르면 모든 클러스터를 잡아내는 것은 거의 불가능.
- 계산 복잡도는 O(m log m) -> m : 데이터 개수, n : 피처의 수
sklearn 에서는 데이터의 개수에 대해서는 선형으로 증가하지만 eps 에 대해서는 O(m*m) 만큼 메모리가 필요
7. KMeans & GMM(Gausian Mixture) & DBSCAN
7.1) 기본개념
- K-means 는 Centroid 와의 거리를 이용 : 클러스터가 간의 간격이 조금 멀 때 사용 용이
- GMM은 모든 데이터의 분포를 정규 분포라고 가정 : 타원형 데이터
- DBSCAN은 밀집도 기반 : 데이터의 분포가 연속적일 때 - 이상치 탐지
7.2) 3개의 알고리즘
def visualize_cluster_plot(clusterobj, dataframe, label_name, iscenter=True):
if iscenter :
centers = clusterobj.cluster_centers_
unique_labels = np.unique(dataframe[label_name].values)
markers=['o', 's', '^', 'x', '*']
#이상치 여부
isNoise=False
#클러스터 순회
for label in unique_labels:
label_cluster = dataframe[dataframe[label_name]==label]
if label == -1:
cluster_legend = 'Noise'
isNoise=True
else :
cluster_legend = 'Cluster '+str(label)
plt.scatter(x=label_cluster['ftr1'], y=label_cluster['ftr2'], s=70,\
edgecolor='k', marker=markers[label], label=cluster_legend)
if iscenter:
center_x_y = centers[label]
plt.scatter(x=center_x_y[0], y=center_x_y[1], s=250, color='white',
alpha=0.9, edgecolor='k', marker=markers[label])
plt.scatter(x=center_x_y[0], y=center_x_y[1], s=70, color='k',\
edgecolor='k', marker='$%d$' % label)
if isNoise:
legend_loc='upper center'
else: legend_loc='upper right'
plt.legend(loc=legend_loc)
plt.show()
- 샘플데이터 생성 - 동심원 형태의 데이터
from sklearn.datasets import make_circles
X, y = make_circles(n_samples=1000, shuffle=True, noise=0.08,
random_state=42, factor=0.5)
clusterDF = pd.DataFrame(data=X, columns=['ftr1', 'ftr2'])
clusterDF['target'] = y
visualize_cluster_plot(None, clusterDF, 'target', iscenter=False)
- KMeans 적용 - 클러스터의 개수를 2개로 설정
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2, max_iter=1000, random_state=42)
kmeans_labels = kmeans.fit_predict(X)
clusterDF['kmeans_cluster'] = kmeans_labels
visualize_cluster_plot(kmeans, clusterDF, 'kmeans_cluster', iscenter = True)
- GMM 모델 적용 - 클러스터의 개수를 2개로 적용 : 대각선(타원) 방향으로 분할
# GMM으로 make_circles( ) 데이터 세트을 클러스터링 수행.
from sklearn.mixture import GaussianMixture
gmm = GaussianMixture(n_components=2, random_state=0)
gmm_label = gmm.fit(X).predict(X)
clusterDF['gmm_cluster'] = gmm_label
visualize_cluster_plot(gmm, clusterDF, 'gmm_cluster', iscenter=False)
- DBSCAN 적용
# DBSCAN으로 make_circles( ) 데이터 세트을 클러스터링 수행.
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=0.2, min_samples=10, metric='euclidean')
dbscan_labels = dbscan.fit_predict(X)
clusterDF['dbscan_cluster'] = dbscan_labels
visualize_cluster_plot(dbscan, clusterDF, 'dbscan_cluster', iscenter=False)
8. BIRCH
- BIRCH(Balanced Iterative Reducing and Clustering)
- 대규모 데이터 세트를 위해서 개발
- 특성 개수가 많지 않은 경우(20개 이하) K-Means 보다 빠르고 비슷한 결과를 생성
-
훈련 과정에서 새로운 샘플을 클러스터에 빠르게 할당할 수 있는 정보를 담은 트리 구조를 생성
-
트리에 모든 샘플을 저장하지 않음
-
이 방식은 제한된 메모리를 사용해 대용량 데이터 세트를 다룰 수 있음
장점 - 한 번의 스캔으로 clustering 잘할 수 있음
단점 - 숫자 데이터만 다룰 수 있으며 레코드 순서에 민감
#데이터 생성
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
from sklearn.cluster import Birch
brc = Birch(n_clusters=3)
brc.fit(X) #데이터 훈련
assignment = brc.predict(X)
print(assignment)
mglearn.discrete_scatter(X[:, 0], X[:, 1], assignment)
plt.legend(["cluster 0", "cluster 1", "cluster 2"], loc="best")
plt.xlabel("attr 0")
plt.ylabel("attr 1")
plt.show()
9. 유사도 전파
- 투표 방식을 이용함
- 각 데이터는 자신을 대표할 수 있는 비슷한 샘플에 투표
- 알고리즘을 수행하다가 수렴되면 각 대표와 투표한 샘플이 클러스터를 형성
- K-Means 처럼 크기가 다른 여러 개의 클러스터를 감지할 수 있찌만 알고리즘의 계산 복잡도가 O(m * m) 이라서 대규모 데이터 세트에는 적합하지 않음
#유사도 전파
from sklearn.cluster import AffinityPropagation
affinity_propagation = AffinityPropagation(damping=0.9, preference=-200)
affinity_propagation.fit(X)
assignment = affinity_propagation.predict(X)
print(assignment)
mglearn.discrete_scatter(X[:, 0], X[:, 1], assignment)
plt.legend(["cluster 0", "cluster 1", "cluster 2"], loc="best")
plt.xlabel("attr 0")
plt.ylabel("attr 1")
plt.show()
10. 스펙트럼 군집
- 샘플의 유사도 행렬을 받아서 저차원 임베딩을 생성 - 차원을 축소
- 축소된 저차원 공간에서 다른 군집 알고리즘을 수행(sklearn 의 경우는 k-means)
- 복잡한 클러스터 구조를 잘 감지
- 샘플의 개수가 많거나 클러스터의 크기가 너무 다르면 잘 동작하지 않음
11. 이상치 탐지와 특이치 탐지를 위한 다른 형태의 알고리즘
11.1) 군집 알고리즘
- 군집을 했을 때 잘 어울리지 못하는 데이터
11.2)PCA(inverse_ransform() 함수를 가진 다른 차원 축소 기법, 주성분 분석)
- 보통 샘플의 재구성 오차와 이상치의 재구성 오차를 비교하면 일반적으로 후자가 훨씬 큼
- 이는 간단하고 종종 매우 효과적인 이상치 탐지 기법
11.3) Fast-MCD(Minimum Covariance Determinant)
- EllipticEnvelope 클래스에서 구현된 이 알고리즘은 이상치 감지에 유용
- 데이터 세트를 정제 할 때 사용하는데 보통 샘플(정상치)이 하나의 Gaussian 분포에서 생성되었다고 가정하며 이 Gaussian 분포에서 생성되지 않은 데이터는 이상치로 이 데이터 세트가 오염되었다고 가정
- 알고리즘이 Gaussian 분포의 파라미터를(즉 정상치를 둘러싼 타원 도형을) 추정할 때 이상치로 의심되는 샘플을 무시
- 이런 기법은 알고리즘이 타원형을 잘 추정하고 이상치를 잘 구분하도록 도움
11.4) 아이솔레이션 포레스트
- 고차원 데이터 세트에서 이상치 감지를 위한 효율적인 알고리즘
- 무작위로 성장한 결정 트리로 구성된 랜덤 포레스트를 생성하고 각 노드에서 특성을 랜덤하게 선택한 다음(최솟값과 최댓값 사이에서) 랜덤한 임곗값을 골라 데이터 세트를 둘로 나눔
- 이런 식으로 데이터 세트는 점차 분리되어 모든 샘플이 다른 샘플과 격리될 때까지 진행하고 이상치는 일반적으로 다른 샘플과 멀리 떨어져 있으므로(모든 결정 트리에 걸쳐) 평균적으로 정상 샘플과 적은 단계에서 격리됨
11.5) LOF(Local Outlier Factor)
- 이 알고리즘도 이상치 탐지에 좋은 알고리즘인데 주어진 샘플 주위의 밀도와 이웃 주위의 밀도를 비교하고 이상치는 종종 k개의 최근접 이웃보다 더 격리됨
11.6) one -class SVM
- 이 알고리즘은 특이치 탐지에 잘 맞음
- 하나의 평면을 이용해서 이 평면에 놓이지 않은 데이터를 이상치로 간주
- 커널 SVM 분류기가 두 클래스를 분리하는 방법을 이용하는데 먼저 모든 샘플을 고차원 공간에 매핑한 다음 이 고차원 공간에서 선형 SVM 분류기를 사용해 두 클래스를 분리
- 여기서는 샘플의 클래스가 하나이기 때문에 대신 one-class SVM 알고리즘이 원본 공간으로부터 고차원 공간에 있는 샘플을 분리
- 원본 공간에서는 모든 샘플을 둘러싼 작은 영역을 찾는 것에 해당
- 조정할 Hyperparameter가 적음
- 커널 SVM을 위한 Hyperparameter 하나와 마진 Hyperparameter가 있으며 마진은 실제 정상인 새로운 샘플을 실수로 이상치로 판단할 확률에 해당
- 이 알고리즘은 특히 고차원 데이터 세트에 잘 작동하지만 모든 SVM과 마찬가지로 대규모 데이터 세트으로의 확장은 어려움
12. 비지도 학습에서의 전처리
- 비지도 학습에서는 데이터를 적절하게 스케일링을 해야 합니다.
데이터 크기가 조정되지 않으면 PCA, K-Means 등은 큰 값을 갖는 변수들에 의해 결과가 좌우되고 작은 값을 갖는 변수들은 무시되는 경우가 발생
- 범주형 데이터를 사용하게 되면 KNN에서와 유사하게 K-Means 에서는 문제가 발생할 수 있음
순서가 없는 데이터들은 원 핫 인코딩을 하게 되는데 이렇게 되면 다른 피처와 크기가 다를 수 있고 두가지 값만 가질 수 있기 때문에 영향을 많이 미치게 될 수 있음.
반응형
LIST
'LG 헬로비전 DX DATA SCHOOL > Python' 카테고리의 다른 글
NLP(Natural Language Processing) 자연어 처리 (0) | 2023.09.05 |
---|---|
차원 축소 (DimensionalityReduction) (0) | 2023.09.04 |
(Python)군집 분석 및 과일 이미지 군집 분석 실습 (0) | 2023.09.01 |
회귀분석 (0) | 2023.08.30 |
Pandas 의 연산 (0) | 2023.08.16 |