반응형

 

비지도 학습

  • 지도학습에 많은 발전이 이루어졌지만 가장 잠재력이 큰 분야
  • 군집
    • 비슷한 샘플을 클러스터로 모음, 군집은 데이터 분석, 고객 분류, 추천 시스템, 검색 엔진, 이미지 분할, 준지도 학습, 차원 축소 등에 사용할 수 있는 도구
  • 이상치 탐지
    • 정상 데이터가 어떻게 보이는지를 학습, 그다음 비정상 샘플을 감지하는 데 사용
    • 제조 라인에서 결함 제품을 감지하거나 시계열 데이터에서 새로운 트렌드를 찾음
  • 밀도 추정
    • 데이터셋 생성 확률 과정의 확률 밀도 함수(PDF)를 추정
    • 밀도 추정은 이상치 탐지에 널리 사용
    • 밀도가 매우 낮은 영역에 놓인 샘플이 이상치일 가능성이 높음, 데이터 분석과 시각화에도 유용

 

군집

  • 비슷한 샘플을 구별해 하나의 클러스터 또는 비슷한 샘플의 그룹으로 할당하는 작업
  • 분류와 같이 각 샘플은 하나의 그룹에 할당됨, 분류와 다르게 군집은 비지도 학습방법
    • 왼쪽은 iris 데이터셋, 클래스 구분이 잘 되어있음
    • 오른쪽은 같은 데이터 셋이지만 구분이 없는 상태
  • 군집이 사용되는 예시
    • 고객 분류
      • 고객을 구매 이력이나 웹사이트 내 행동 기반으로 클러스터로 모을 수 있음
      • 이는 고객이 누구인지, 고객이 무엇을 원하는지 이해하는 데 도움이 됨
      • 고객 그룹 각각에 제품 추천, 마케팅 전략을 다르게 적용할 수 있음
    • 데이터 분석
      • 새로운 데이터셋을 분석할 때 군집 알고리즘을 실행하고 각 클러스터를 따로 분석하면 도움이 됨
    • 차원 축소 기법
      • 한 데이터셋에 군집 알고리즘을 적용하면 각 클러스터에 대한 샘플의 친화성을 측정할 수 있음
      • 각 샘플의 특성 벡터 x는 클러스터 친화성의 벡터로 바꿀 수 있음
      • k개의 클러스터가 있다면 이 벡터는 k차원이 됨
      • 일반적으로 벡터는 원본 특성 벡터보다 훨씬 저차원이지만 이후의 분석을 위한 충분한 정보를 가질 수 있음
    • 이상치 탐지
      • 모든 클러스터에 친화성이 낮음 샘플은 이상치일 가능성이 큼
      • 제조 분야의 결함을 감지, 부정 거래 감지 등에 활용 됨
    • 준지도 학습
      • 레이블된 샘플이 적다면 군집을 수행하고 동일한 클러스터에 있는 모든 샘플에 레이블을 생성할수 있음
      • 이 방법을 통해 지도 학습 알고리즘에 필요한 레이블을 생성하여 성능 향상 가능
    • 검색 엔진
      • 제시된 이미지와 비슷한 이미지를 찾아줌, 이런 시스템을 구축하려면 먼저 데이터 베이스에 있는 모든 이미지에 군집 알고리즘을 적용
      • 사용자가 찾으려는 이미지를 제공하면 훈련된 군집 모델을 사용해 이미지의 클러스터를 찾음, 이후에 이 클러스터의 모든 이미지를 반환
    • 이미지 분할
      • 색을 기반으로 픽셀을 클러스터, 그다음 각 픽셀의 색을 해당 클러스터의 평균 색으로 변경
      • 이미지에 있는 색상의 종류를 크게 줄이고 물체의 윤곽을 감지하기 쉬워져 물체 탐지 및 추적 시스템에서 이미지 분할을 많이 활용

 

k-mean

  • 각 클러스터의 중심을 찾고 가장 가까운 클러스터에 샘플을 할당
  • 찾을 클러스터 개수 k를 지정해야 함
  • 예제
    • 위 center을 기반으로 그린 보로노이 다이어그램
  • from sklearn.cluster import KMeans k = 5 kmeans = KMeans(n_clusters=k, random_state=42) y_pred = kmeans.fit_predict(X) ## label 확인 kmeans.labels_ >> array([4, 0, 1, ..., 2, 1, 0], dtype=int32) ## k=5 의 중심좌표 kmeans.cluster_centers_ >> array([[-2.80389616, 1.80117999], [ 0.20876306, 2.25551336], [-2.79290307, 2.79641063], [-1.46679593, 2.28585348], [-2.80037642, 1.30082566]])
  • 샘플은 대부분 적절한 클러스터에 잘 할당됨, 하지만 몇몇 샘플은 레이블이 잘못 부여
  • 실제 k-평균 알고리즘은 클러스터의 크기가 많이 다르면 잘 작동하지 않음
  • 샘플을 클러스터에 할당할때 센트로이드까지 거리를 고려하는 것이 전부이기 때문
  • 하드군집 샘플을 클러스터에 할당하는 것보다 클러스터마다 샘플에 점수를 부여하는 것이 유용할 수 있음 이를 소프트 군집 이라고 함
    • 하드 군집은 각 샘플에 대해 가장 가까운 것을 선택
kmeans.transform(X_new)
array([[2.81093633, 0.32995317, 2.9042344 , 1.49439034, 2.88633901],
       [5.80730058, 2.80290755, 5.84739223, 4.4759332 , 5.84236351],
       [1.21475352, 3.29399768, 0.29040966, 1.69136631, 1.71086031],
       [0.72581411, 3.21806371, 0.36159148, 1.54808703, 1.21567622]])
  • kmeans는 transform 매서드 샘플과 각 센트로이드 사이의 거리를 반환
  • 이런 방식으로 고차원 데이터셋을 변환하면 k-차원 데이터셋 생성, 효율적인 비선형 차원 축소 방법이 될수 있음

 

k-mean 알고리즘

  • KMeans 클래스는 기본적으로 최적화된 알고리즘을 적용, 아래에서 설명하는 내용은 init='random', n_init=1, algorithm='full'로 선택한 경우 원래의 k-means 설명
  • 처음에는 센트로이드를 랜덤하게 선정, 그다음 샘플에 레이블을 할당하고 센트로이드를 업데이트
  • 샘플에 레이블을 할당하고 센트로이드를 업데이트하는 식으로 센트로이드에 변화가 없을 때까지 계속 수행
  • 제한된 횟수 안에 수렴하는 것으 보장, 무한 반복하지 않음

해당 알고리즘 계산 복잡도 : 샘플 개수(m), 클러스터 개수(k), 차원 개수(n)에 선형적이지만 군집할 수 있는 구조를 가질 경우에 해당

그렇지 않는 최악의 경우 계산 복잡도는 샘플 개수가 지수적으로 급증할수 있음, 일반적으로 k-means는 빠른 군집 알고리즘

 

센트로이드 초기화 방법

  • 센트로이드 위치를 근사하게 알 수 있다면 (다른 군집 알고리즘을 먼저 실행하여 어느정도 센트로이드를 알고 있을 경우) init 매개변수에 센트로이드 리스트를 담은 넘파이 배열을 지정하고 n_init을 1로 설정 할 수 있음
    • 예시
    • good_init = np.array([[-3, 3], [-3, 2], [-3, 1], [-1, 2], [0, 2]]) kmeans = KMeans(n_clusters=5, init=good_init, n_init=1, random_state=42) kmeans.fit(X) kmeans.inertia_ >> 211.598537258168
  • 랜덤 초기화를 다르게 하여 여러 번 알고리즘을 실행하고 가장 좋은 솔루션을 선택하는 것
  • 랜덤 초기화 횟수는 n_init 매개변수로 조절 가능, 기본값은 10
  • 이너셔를 통해 가장 최적의 솔루션을 찾는 지표로 활용
  • k-means는 현재는 k-means++ 초기화 방법을 기본으로 사용

 

k-means 속도 개선과 미니배치 k-means

  • 불필요한 거리 계산을 많이 피함으로서 알고리즘의 속도를 상당히 높일 수 있음
  • 현재는 k-means에서 기본적으로 사용됨
  • 전체 데이터셋을 사용해 반복하지 않고 각 반복마다 미니배치를 사용해 센트로이드를 조금씩 이동 시키는 방식이 제안됨
    • 일반적으로 알고리즘 속도를 3배에서 4배 정도 높임
    • 메모리에 들어가지 않는 대량의 데이터셋에 군집 알고리즘을 적용
    • sklearn에서 minibatchkmeans 클래스에 구현함
    • 예제
    • from sklearn.cluster import MiniBatchKMeans minibatch_kmeans = MiniBatchKMeans(n_clusters=5, random_state=42) minibatch_kmeans.fit(X) minibatch_kmeans.inertia_ >> 211.652398504332
  • 미니배치 k-means가 일반 k-means 보다 훨씬 빠름 하지만 이너셔는 일반적으로 안좋음
  • 특히 클러스터의 개수가 증가할 때 더욱 안좋아지는 경향을 보임
  • 데이터 셋이 크다면 일반적인 k-means보다는 minibatchkmeans가 더 좋을수 있음

 

최적의 클러스터 개수 찾기

      • 이녀셔가 급격히 작아지는 elbow 지점 선택
      • 정확한 방법은 아님
    • 실루엣 스코어 비교
      • 실루엣 스코어는 모든 샘플에 대한 실루엣 계수의 평균
      • (b-a)/max(a,b)로 계산
        • a : 동일한 클러스터에 있는 다른 샘플까지의 평균 거리
        • b : 가장 가까운 클러스터까지 평균 거리
      • -1 ~ +1 범위
        • +1 에 가까우면 잘 분리된 결과
        • 0 에 가까우면 클러스터의 경계에 위치
        • -1에 가까우면 잘못된 클러스터에 할당
      • from sklearn.metrics import silhouette_score
        silhouette_score(X, kmeans.labels_)
        >> 0.655517642572828
        • 이니셔 보다 k에 대한 다양한 정보를 볼수 있음
        • 모든 샘플의 실루엣 계수를 할당된 클러스터와 실루엣 값으로 정렬하여 그리면 훨씬 많은 정보를 얻을 수 있습니다. 이를 실루엣 다이어그램이라고 함
          • 높이 : 클러스터가 포함한 샘플의 수, 너비 : 이 클러스터에 포함된 샘플의 정렬된 실루엣 계수
          • 수직 점선 : 클러스터 개수에 해당하는 실루엣 점수

실제로 좋은 클러스터를 선택할때 실루엣에서 유심히 봐야하는 것은 3개

        1. 그래프에 음수값이 없어야 함
        2. 너비가 각 클러스터 마다 비슷해야 함
        3. 모든 클러스터가 수직점선을 넘어야 함

 

k-평균의 한계

    • 속도가 빠르고 확장이 용이
    • 최적이 아닌 솔루션을 피하기 위해 알고리즘 여러 번 실행해야 함
    • 클러스터 개수도 사전에 지정해야 함
    • 원형 모양의 데이터가 아닌경우 잘 작동하지 않음
        • 두 솔루션 모두 좋지않음, 데이터에 따라 잘 수행할수 있는 군집 알고리즘이 다름
        • 타원형 클러스터에서는 가우시안 혼합 모델이 잘 작동

k-mean 실행하기 전에 입력 특성의 스케일을 맞추는 것이 중요, 그렇지 않으면 클러스터가 길쭉해짐

      •  

일반적으로 특성의 스케일을 맞추면 잘 구분됨

    •  

 

군집을 사용한 이미지 분할

  • 이미지 분할은 이미지를 세그먼트 여러 개로 분할하는 작업
  • 시멘틱 분할에서는 동일한 종류의 물체에 속한 모든 픽셀은 같은 세그먼트에 할당
  • 색상분할 예제
  • from matplotlib.image import imread image = imread(os.path.join(images_path, filename)) image.shape >> (533, 800, 3) X = image.reshape(-1, 3) kmeans = KMeans(n_clusters=8, random_state=42).fit(X) segmented_img = kmeans.cluster_centers_[kmeans.labels_] segmented_img = segmented_img.reshape(image.shape) segmented_imgs = [] n_colors = (10, 8, 6, 4, 2) for n_clusters in n_colors: kmeans = KMeans(n_clusters=n_clusters, random_state=42).fit(X) segmented_img = kmeans.cluster_centers_[kmeans.labels_] segmented_imgs.append(segmented_img.reshape(image.shape))

 

군집을 사용한 전처리

  • 지도 학습 알고리즘 적용하기 전에 전처리 단계로 사용하기 좋음
  • 예제
    • 훈련셋과 테스트 세트로 분할
    from sklearn.linear_model import LogisticRegression
    
    log_reg = LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)
    log_reg.fit(X_train, y_train)
    
    log_reg_score = log_reg.score(X_test, y_test)
    log_reg_score
    >> 0.9688888888888889
    • 로지스틱 회귀 모델 훈련, 테스트 세트의 정확도 평가
  • from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X_digits, y_digits, random_state=42)
  • 클러스터를 전처리에 사용하는 예제
  • from sklearn.pipeline import Pipeline

pipeline = Pipeline([
("kmeans", KMeans(n_clusters=50, random_state=42)),
("log_reg", LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)),
])
pipeline.fit(X_train, y_train)

pipeline_score = pipeline.score(X_test, y_test)
pipeline_score

0.9777777777777777


  - 훈련 세트를 50개의 클러스터로 모음, 그 후에 이미지를 50개 클러스터까지 거리로 변경, 마지막에 로지스틱 회귀 모델 적용

- grid search를 통해 최적의 parameter 찾기

  ```python
  from sklearn.model_selection import GridSearchCV

  param_grid = dict(kmeans__n_clusters=range(2, 100))
  grid_clf = GridSearchCV(pipeline, param_grid, cv=3, verbose=2)
  grid_clf.fit(X_train, y_train)

 

군집을 사용한 준지도 학습

  • 레이블이 없는 데이터가 많고 레이블이 있는 데이터가 적을 때 사용
  • 예제
    • 훈련 세트를 50개의 클러스터로 모으고 그다음 각 클러스터에서 센트로이드에 가장 가까운 이미지를 찾음, 이런 이미지를 대표 이미지 라고 함
    k = 50
    
    kmeans = KMeans(n_clusters=k, random_state=42)
    X_digits_dist = kmeans.fit_transform(X_train)
    representative_digit_idx = np.argmin(X_digits_dist, axis=0)
    X_representative_digits = X_train[representative_digit_idx]
    
    y_train[representative_digit_idx]
    y_representative_digits = np.array([
        0, 1, 3, 2, 7, 6, 4, 6, 9, 5,
        1, 2, 9, 5, 2, 7, 8, 1, 8, 6,
        3, 1, 5, 4, 5, 4, 0, 3, 2, 6,
        1, 7, 7, 9, 1, 8, 6, 5, 4, 8,
        5, 3, 3, 6, 7, 9, 7, 8, 4, 9])
    • 대표 이미지를 출력하고 수동으로 레이블 생성
    • 각 클러스터를 대표하는 이미지를 통해 학습
    log_reg = LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)
    log_reg.fit(X_representative_digits, y_representative_digits)
    log_reg.score(X_test, y_test)
    >> 0.09555555555555556
    • 셈플에 레이블을 부여하는 것은 비용이 많이 소요, 무작위 샘플 대신 대표 샘플에 레이블을 할당하는 것이 좋음
    • 레이블을 동일한 클러스터에 있는 모든 샘플로 전파하는 방법을 레이블 전파라고 함
      • 아래 방법은 전체가 아닌 75번째 백분위수까지만 전파하는 코드
      • 전체 전파시 이상치 생성 됨
    percentile_closest = 75
    
    X_cluster_dist = X_digits_dist[np.arange(len(X_train)), kmeans.labels_]
    for i in range(k):
        in_cluster = (kmeans.labels_ == i)
        cluster_dist = X_cluster_dist[in_cluster]
        cutoff_distance = np.percentile(cluster_dist, percentile_closest)
        above_cutoff = (X_cluster_dist > cutoff_distance)
        X_cluster_dist[in_cluster & above_cutoff] = -1
    
    partially_propagated = (X_cluster_dist != -1)
    X_train_partially_propagated = X_train[partially_propagated]
    y_train_partially_propagated = y_train_propagated[partially_propagated]
    
    
  • n_labeled = 50 log_reg = LogisticRegression(multi_class="ovr", solver="lbfgs", random_state=42) log_reg.fit(X_train[:n_labeled], y_train[:n_labeled]) log_reg.score(X_test, y_test) >> 0.83333333334

훈련

log_reg = LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)
log_reg.fit(X_train_partially_propagated, y_train_partially_propagated)

log_reg.score(X_test, y_test)

0.94


- 모델과 훈련 세트를 지속적으로 향상하기 위해 다음 단계로 능동 학습을 몇 번 반복할 수 있음
  1. 분류기의 확신이 부족한 샘플에 수동으로 레이블을 부여합니다. 가능하면 다른 클러스터에서 샘플을 선택합니다.
  2. 추가된 레이블을 사용해 새로운 모델을 훈련합니다.

 

### DBSCAN

- 밀집된 연속적 지역을 클러스터로 정의

- 작동방식

  1. 각 샘플에서 작은 거리인 입실론 내에 샘플이 몇 개 놓여 있는지 계산, 이를 입실론 이웃
  2. 자기 자신은 포함해 입실론 이웃 내에 적어도 min_samples개 샘플이 있다면 이를 핵심 샘플로 간주, 핵심샘플은 밀집된 지역에 있는 샘플
  3. 핵심 샘플의 이웃에 있는 모든 샘플은 동일한 클러스터에 속함, 이웃에는 다른 핵심 샘플이 포함될 수 있음, 따라서 핵심 샘플의 이웃의 이웃은 계속해서 하나의 클러스터 형성
  4. 핵심 샘플도 아니고 이웃도 아닌 샘플은 이상치

- 모든 클러스터가 충분히 밀집되어 있고 밀집되지 않은 지역과 잘 구분됨

- DBSCAN sklearn 예제

  ```python
  from sklearn.cluster import DBSCAN

  dbscan = DBSCAN(eps=0.05, min_samples=5)
  dbscan.fit(X)

  dbscan.labels_[:10]
  >> array([ 0,  2, -1, -1,  1,  0,  0,  0,  2,  5])
  • 일부 샘플의 클러스터 인덱스는 -1, 이것은 알고리즘에서 이상치로 판단했다는 의미
  • 핵심 샘플의 인덱스는 인스턴스 변수 core_sample_indices_에서 확인 가능
  • 핵심 샘플 자체는 인스턴스 변수 components_에 저장
  • len(dbscan.core_sample_indices_) >> 808 dbscan.core_sample_indices_[:10] >> array([ 0, 4, 5, 6, 7, 8, 10, 11, 12, 13]) dbscan.components_[:3] >> array([[-0.02137124, 0.40618608], [-0.84192557, 0.53058695], [ 0.58930337, -0.32137599]])
  • 위 그림에서 처럼 eps 거리를 0.05 보다 0.2로 증가해 샘플의 이웃 범위를 높이면 좋은 결과를 보임
  • DBSCAN은 새로운 샘플에 대해 클러스터 예측을 할수 없음
    • predict() 매소드 지원안하고 fit_predict()만 지원
    • KNeighborsClassifier 에 DBSCAN 예제
      • 샘플 몇 개를 전달하여 어떤 클러스터에 속할 가능성이 높은지 예측하고 각 클러스터에 대한 확률 추정
      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]])
      knn.predict(X_new)
      >> array([1, 0, 1, 0])
      
      knn.predict_proba(X_new)
      >> array([[0.18, 0.82],
                 [1.  , 0.  ],
                 [0.12, 0.88],
                 [1.  , 0.  ]])
      
      • 해당 분류기는 DBSCAN에서 얻은 핵심샘플에서만 훈련했지만 모든 샘플에서 훈련가능
      • 최대 거리를 사용하면 두 클러스터에서 멀리 떨어진 샘플을 이상치로 분류 가능
        • KNeighborsClassifier의 kneighbors() 메서드 사용, 해당 메서드에 샘플은 전달하면 훈련 세트에서 가장 가까운 k개 이웃의 거리와 인덱스를 반환
  • DBSCAN은 클러스터의 모양과 개수에 상관없이 감지할 수 있음
  • 이상치에 안정적이고 하이퍼파라미터가 두 개뿐(eps, min_samples)
  • 클러스터 간의 밀집도가 크게 다르면 모든 클러스터를 올바르게 잡아내는 것은 불가능
  • 계산 복잡도는 대략 O(m log m), 샘플 개수에 대해 거의 선형적으로 증가

 

다른 군집 알고리즘

  • 병합군집
    • 클러스터 계층을 밑바닥부터 쌓아 구성하는 방식
    • 병합된 클러스터 쌍을 트리로 모두 그리면 클러스터의 이진 트리를 얻을 수 있음
    • 대규모 샘플과 클러스터에 잘 확장되며 다양한 형태의 클러스터를 감지할 수 있음
    • 특정 클러스터 개수를 선택하는 데 도움이 되는 유용한 클러스터 트리를 생성할 수 있음
    • 예제
    • from sklearn.cluster import AgglomerativeClustering X = np.array([0, 2, 5, 8.5]).reshape(-1, 1) agg = AgglomerativeClustering(linkage="complete").fit(X) def learned_parameters(estimator): return [attrib for attrib in dir(estimator) if attrib.endswith("_") and not attrib.startswith("_")] learned_parameters(agg) >> ['children_', 'labels_', 'n_clusters_', 'n_connected_components_', 'n_features_in_', 'n_leaves_'] agg.children_ >> array([[0, 1], [2, 3], [4, 5]])
  • BIRCH
    • 대규모 데이터셋을 위해 고안 됨
    • 특성 개수가 너무 많지 않다면 배치 k-평균보다 빠르고 비슷한 결과를 생성
    • 훈련 과정에서 새로운 샘플을 클러스터에 빠르게 할당할 수 있는 정보를 담은 트리 구조를 만듬
      • 해당 트리에 모든 샘플 저장 안함
    • 제한된 메모리를 사용해 대용량 데이터셋을 다룰 수 있음
  • 평균-이동
    • 작동방식
      1. 각 샘플을 중심으로 하는 원을 그림
      2. 원마다 안에 포함된 모든 샘플의 평균을 계산
      3. 원의 중심을 평균점으로 이동
      4. 모든 원이 움직이지 않을 때까지 평균-이동 반복
    • 지역의 최대 밀도를 찾을 때까지 높은 쪽으로 원을 이동
    • DBSCAN과 유사한 특징이 존재, 모양과 개수에 상관없이 클러스터를 찾을 수 있음
    • 하이퍼 파라미터로 밴드워스 라는 원 반경 존재, 이외에는 없음
    • 국부적인 밀집도 추정에 의존, DBSCAN과 달리 평균-이동은 클러스터 내부 밀집도가 불균형할 때 여러 개로 나누는 경향이 존재
      • 이 때문에 대규모 데이터셋에는 적합하지 않음
  • 유사도 전파
    • 투표 방식을 사용. 샘플은 자신을 대표할 수 있는 비슷한 샘플에 투표
    • 알고리즘이 수렴하면 각 대표와 투표한 샘플이 클러스터를 형성
    • 크기가 다른 여러 개의 클러스터를 감지할 수 있음
    • 계산 복잡도 O(m2), 대규모 데이터셋에는 적합하지 않음
  • 스펙트럼 군집
    • 샘플 사이의 유사도 행렬을 받아 저차원 임베딩 생성 (차원을 축소함)
    • 저차원 공간에서 또 다른 군집 알고리즘을 사용 (sklearn 구현은 k-mean 사용)
    • 복잡한 클러스터 구조를 감지하고 그래프 컷을 찾는 데 사용할 수 있음
    • 예제
    • from sklearn.cluster import SpectralClustering sc1 = SpectralClustering(n_clusters=2, gamma=100, random_state=42) sc1.fit(X) sc2 = SpectralClustering(n_clusters=2, gamma=1, random_state=42) sc2.fit(X) np.percentile(sc1.affinity_matrix_, 95)

 

가우시안 혼합(GMM)

  • 샘플이 파라미터가 알려지지 않은 여러 개의 혼합된 가우시안 분포에서 생성되었다고 가정하는 확률 모델
  • 하나의 가우시안 분포에서 생성된 모든 샘플은 하나의 클러스터를 형성
  • GMM은 다양한 변종이 존재, 가장 간단한 버전이 GaussianMixture 클래스에 구현되어 있음
  • GaussianMixture 예제
    • 해당 GMM은 기댓값-최대화(EM) 알고리즘을 사용
      • 해당 알고리즘은 k-mean과 공통점이 많음
      • 클러스터 파라미터를 랜덤하게 초기화하고 수렴 할때까지 두 단계를 계속 반복
      • 먼저 샘플을 클러스터에 할당, 이를 기대값 단계
        • 기대값 단계에서는 각 클러스터에 속할 확률을 예측
      • 클러스터를 업데이트 수행, 이를 최대화 단계
        • 최대화 단계에서 각 클러스터가 데이터셋에 있는 모든 샘플을 사용해 업데이트
      • 클러스터에 속할 추정 확률로 샘플에 가중치가 적용
        • 이 확률을 샘플에 대한 클러스터의 책임 이라고 함
      • 최대화 단계에서 클러스터 업데이트는 책임이 가장 많은 샘플에 크게 영향을 받음
      • k-mean처럼 EM이 나쁜 솔루션으로 수렴할수 있음, 여러 번 실행해서 가장 좋은 솔루션을 선택
    # 수렴여부
    gm.converged_
    >> True
    # 반복 횟수
    gm.n_iter_
    >> 4
    • 새로운 샘플을 가장 비슷한 클러스터에 할당하는 하드 군집 또는 특정 클러스터에 속할 확률을 예측할 수 있음 소프트 군집
      • 하드 군집을 위해서는 predict(), 소프트 군집을 위해서는 predict_proba() 메서드 사용
    gm.predict(X)
    >> array([0, 0, 1, ..., 2, 2, 2])
    gm.predict_proba(X)
    >> array([[9.76741808e-01, 6.78581203e-07, 2.32575136e-02],
               [9.82832955e-01, 6.76173663e-04, 1.64908714e-02],
               [7.46494398e-05, 9.99923327e-01, 2.02398402e-06],
               ...,
               [4.26050456e-07, 2.15512941e-26, 9.99999574e-01],
               [5.04987704e-16, 1.48083217e-41, 1.00000000e+00],
               [2.24602826e-15, 8.11457779e-41, 1.00000000e+00]])
    • GMM은 생성 모델임, 즉 모델에서 새로운 샘플을 생성할 수 있음
    X_new, y_new = gm.sample(6)
    X_new
    >> array([[-0.86944074, -0.32767626],
               [ 0.29836051,  0.28297011],
               [-2.8014927 , -0.09047309],
               [ 3.98203732,  1.49951491],
               [ 3.81677148,  0.53095244],
               [ 2.84104923, -0.73858639]])
    y_new
    >> array([0, 0, 1, 2, 2, 2])
    • 주어진 위치에서 모델의 밀도를 추정할수 있음
      • 이를 위해 score_samples() 사용
      • 샘플이 주어지면 이 메서드는 그 위치의 확률 밀도 함수(PDF)의 로그를 예측, 점수 높을 수록 밀도 높음
    gm.score_samples(X)
    >> array([-2.60768954, -3.57110232, -3.32987086, ..., -3.51347241,
               -4.39798588, -3.80746532])
    • 해당 점수들의 지숫값을 계산하면 샘플의 위치에서 PDF 값을 얻을 수 있음, 값은 하나의 확률이 아닌 확률 밀도
    • 샘플이 특정 지역 안에 속할 확률을 예측하려면 그 지역에 대해 PDF를 적분해야 함
    • 클러스터 평균, 결정 경계, 밀도 등고선 시각화
  • from sklearn.mixture import GaussianMixture gm = GaussianMixture(n_components=3, n_init=10, random_state=42) gm.fit(X) gm.weights_ >> array([0.39025715, 0.40007391, 0.20966893]) gm.means_ >> array([[ 0.05131611, 0.07521837], [-1.40763156, 1.42708225], [ 3.39893794, 1.05928897]]) gm.covariances_ >> array([[[ 0.68799922, 0.79606357], [ 0.79606357, 1.21236106]], [[ 0.63479409, 0.72970799], [ 0.72970799, 1.1610351 ]], [[ 1.14833585, -0.03256179], [-0.03256179, 0.95490931]]])
  • 특성이나 클러스터가 많거나 샘플이 적을 때는 EM이 최적의 솔루션으로 수렴하기 어려움
    • 어려움을 줄이기 위해 파라미터 개수를 제한해야 함, 클러스터의 모양과 방향의 범위를 제한
    • sklearn 에서는 covariance_type을 통해 제어
      • "spherial" : 모든 클러스터가 원형, 지름은 다를 수 있음(분산이 다름)
      • "diag" : 클러스터는 크기에 상관없이 어떤 타원형도 가능, 타원의 축은 좌표축과 나란해야 함(공분산 행렬이 대각 행렬이여야 함)
      • "tied" : 모든 클러스터가 동일한 타원 모양, 크기, 방향을 가짐(모든 클러스터는 동일한 공분산 행렬을 공유)
      • 기본값은 "full"
      • convariance_type 시각화

 

가우시안 혼합을 사용한 이상치 탐지

  • 이상치 탐지는 보통과 많이 다른 샘플을 감지하는 작업
  • gmm을 이상치 탐지에 사용하는 방법
    • 밀도가 낮은 지역에 있는 모든 샘플을 이상치로 볼 수 있음, 이를 위해 임계값 설정 필요
    • 예제
      • 이와 비슷한 작업은 특이치 탐지, 해당 알고리즘은 이상치로 오염되지 않은 '깨끗한' 데이터셋에서 훈련한다는 것이 이상치 탐지와 다름
        • 이상치 탐지는 이런 가정을 하지 않음, 실제로 이상치 탐지는 데이터셋 정제에 사용
    • densities = gm.score_samples(X) density_threshold = np.percentile(densities, 4) # 네 번째 백분위수를 임계값으로 사용 anomalies = X[densities < density_threshold]

 

클러스터 개수 선택하기

  • k-mean에서는 이너셔, 실루엣 스코어를 사용해 적절한 클러스터 개수를 선택
    • 하지만 gmm에서는 해당 지표를 사용할 수 없음, 해당 지표는 클러스터가 타원형이거나 크기가 다를 때 안정적이지 않기 때문
  • GMM은 BIC, AIC와 같은 이론적 정보 기준을 최소화 하는 모델을 찾음
    • BIC, AIC 모두 학습할 파라미터가 많은 모델에게 벌칙을 가하고 데이터에 잘 학습하는 모델에게 보상을 더함
    • 사용 예제
      • AIC, BIC 모두 최소점을 선택
    • gm.bic(X) >> 8189.747000497186 gm.aic(X) >> 8102.521720382148

 

베이즈 가우시안 혼합 모델

  • 최적의 클러스터 개수를 수동으로 찾지 않고 불필요한 클러스터의 가중치를 0으로 만드는 BayesianGaussianMixture 클래스를 사용할 수 있음
    • 클러스터 개수 n_components를 최적의 클러스터 개수보다 크다고 믿을 만한 값으로 지정
    • 해당 알고리즘은 불필요한 클러스터를 제거
    • 예제
      • 알고리즘이 자동으로 3개의 클러스터가 필요하다는 것을 볼수 있음
    • from sklearn.mixture import BayesianGaussianMixture bgm = BayesianGaussianMixture(n_components=10, n_init=10, random_state=42) bgm.fit(X) np.round(bgm.weights_, 2) >> array([0.4 , 0.21, 0.4 , 0. , 0. , 0. , 0. , 0. , 0. , 0. ])
  • 클러스터가 적을 것이라는 사전 믿음(낮은 농도), 반대로 높은 농도도 존재
    • 해당 사전 믿음은 weight_concentration_prior 매개변수를 통해 조절 가능
    • 데이터가 많을 수록 사전 믿음은 중요하지 않음

 

이상치 탐지와 특이치 탐지를 위한 다른 알고리즘

  • sklearn에서 제공하는 이상치탐지 및 특이치 탐지 전용으로 사용할 수 있는 알고리즘
    • PCA
      • 보통 샘플의 재구성 오차와 이상치의 재구성 오차를 비교하면 후자가 더 큰 값을 보임
      • 이를 통해 이상치 탐지
    • Fast-MCD
      • EllipticEnvelope 클래스에서 구현된 이 알고리즘은 이상치 감지에 유용
      • 데이터셋을 정제할 때 사용
      • 보통 샘플이 하나의 가우시안 분포에서 생성되었다고 가정, 이 가우시안 분포에서 생성되지 않은 이상치로 데이터 셋이 안좋아 졌다고 가정
        • 알고리즘이 가우시안 분포의 파라미터를 추정할 때 이상치로 의심되는 샘플을 무시
      • 해당 기법은 알고리즘이 타원형을 잘 추정하고 이상치를 잘 구분하도록 도움
    • 아이솔레이션 포레스트
      • 고차원 데이터셋에서 이상치 감지를 위한 효율적인 알고리즘
        • 무작위로 성장한 결정 트리로 구성된 랜덤포레스트 생성
        • 각 노드에서 특성을 랜덤하게 선택한 다음 랜덤한 임곗값을 골라 데이터셋을 둘로 나눔
        • 이런 식으로 데이터셋은 점차 분리되어 모든 샘플이 다른 샘플과 격리될 때까지 진행
      • 이상치는 일반적으로 다른 샘플과 멀리 떨어져 있으므로 평균적으로 정상 샘플과 적은 단계에서 분리
    • LOF
      • 이상치 탐지에 좋음
      • 주어진 샘플 주위의 밀도와 이웃 주위의 밀도를 비교
    • one-class SVM
      • 특이치 탐지에 사용
      • 고차원 데이터셋에 잘 작동
      • SVM과 같이 대규모 데이터셋으로 확장이 어려움

 

반응형

'Study > Self Education' 카테고리의 다른 글

핸즈온 머신러닝 - 11  (0) 2024.06.19
핸즈온 머신러닝 - 10  (0) 2024.06.19
핸즈온 머신러닝 - 8  (0) 2024.06.18
핸즈온 머신러닝 - 7  (0) 2024.06.18
핸즈온 머신러닝 - 6  (0) 2024.06.18