기타/통계, 머신러닝

250709_머신러닝(클러스터링, 이상탐지)

baektree 2025. 7. 9. 21:37

요약/나만의 인사이트

  • 비지도 학습은 정답값을 알려주지 않고 머신러닝을 학습시키는 것이다. 이중에 클러스터링(군집)이 있다.
  • 군집은 비슷한 특성을 가진 데이터를 묶는다. 이때 군집내유사도 최대화, 군집간 차이도 최대화하도록 한다.
  • 클러스터링 종류에는 K-Means, DBSCAN, 계층적 클러스터링이 있다.
  • 군집 분석 평가 시 실루엣 계수(군집내거리는 가깝니?, 군집간 거리는 머니?), Davies-Bouldin Index(군집끼리 얼마나 겹치니) 등을 통해 파악한다.

새롭게 알게 된 것

비지도학습

비지도학습이란❓ 정답값(레이블) 없이 데이터의 패턴이나 구조를 찾는 머신러닝 기법

  • 클러스터링(군집화)
  • 차원 축소
  • 이상치 탐지

클러스터링 종류

k-means 클러스터링 _ 거리기반

  • k 설정 : 군집의 개수 k를 사용자가 미리 정함
  • 초기 중심점 선택: k개의 중심점 임의 선택(보통 랜덤)
  • 할당 단계: 각 데이터 포인트를 가장 가까운 중심점에 할당하여 군집 형성
  • 이동 단계: 각 군집에 속한 데이터들의 평균값으로 중심점 위치 재조정
  • 수렴 조건 확인: 중심점이 더 이상 크게 변하지 않으면 종료

DBSCAN(Density-) _밀도기반

  • 해당하는 밀도를 가지는 군집을 찾음.
  • k값을 정하지 않도라도 밀도 조건에 해당되면 클러스터로 만듦. 그래서 클러스터가 개수가 자동으로 결정됨.
  • 또한 잡음 데이터에 대해 군집화 하지 않음.

계층적 클러스터링

  • 데이터 포인트들이 각각 하나의 군집으로 시작 → 유사도가 높은 군집끼리 병합 → 최종 군집트리 형성
  • 하나의 군집에서 분할해 나가는 접근
  • 덴드로그램으로 시각화 가능
  • 군집수를 결정짓지 않아도 덴드로그램의의 특정 높이에 따라 유연하게 군집 개수 결정 가능
  • 계산 복잡도가 높음.

클러스터링 평가 방법

Elbow Method

  • 정의: 클러스터링 할 때 최적의 군집수(k)를 찾기 위한 방법. 일반적으로 k-means 알고리즘에서 자주 사용됨
  • x축 : 설정한 군집수
  • y축 : 각 군집의 중심점과 데이터 포인트간의 거리제곱의 합(SSE = Sum of Squared Errors)

실루엣 계수

  • 군집간 거리 - 군집내 거리의 식으로 계산
  • 따라서 -1 ~ 1 의 값을 가짐
  • 1에 가까울수록 잘 군집되었음을 의미

Davies_Bouldin Index

  • 군집 내 분산과 군집 간 거리의 비율을 활용
  • 0이상의 값
  • 값이 높을수록 군집 간 겹침이 많다는 뜻. 품질이 좋지 않음.

외부평가

  • 정답과 군집 결과를 비교
  • 마케팅의 경우엔 고객 세그먼트 후 매출에 긍정적을 영향을 끼쳤는지 확인

클러스터 관련코드 해석

labels = dbscan.fit_predict(X)
 : X데이터에 DBSCAN을 적용해 각 데이터가 속한 클러스터 라벨 추출(비지도학습)
-1  노이즈(어디에도 속하지 않는 점)
eps : eps이 2이면 반지름 2 안에 있는 점들을 같은 그룹 후보로 생각한다. 반경거리
min_samples :min_samples이 5이면, 어떤 점을 중심으로 반경 2 안에 있는 5개 이상 데이터가 있어야 진짜 군집으로 임명한다. 최소 이웃 수
kmeans_db = davies_bouldin_score(X, kmeans_labels) : X라는 원본데이의 위치와 labels이라는 군집 번호를 활용해 군집간 거리와 내부 거리를 기준으로 Davies_Bouldin 점수를 계산하여 kmeans_db에 저장한다. 저장된 값은 하나이고 값이 낮을수록 좋다. 
PCA : 고차원 데이터를 2D로 축소해서 시각화하는 방법
pca = PCA(n_components=2)  13차원 데이터를 2차원으로 줄이기
X_pca = pca.fit_transform(X) X_pca는 시각화를 위한 2D 데이터
kmeans_labels : 각 데이터가 속한 군집 번호 (예: [0, 1, 2, 0, ...])

이상탐지(머신러닝 방법)

이상탐지란?

  • 이상탐지(Anomaly Detection) : 정상 패턴에서 벗어난 특이한 패턴을 식별

주요 이상 탐지 알고리즘

  • One-Class SVM
  • Isolation Forest

이상치(통계적 방법)

이상치란?

데이터 셋에서 다른 데이터들과 동떨어져 있거나 일반적인 패턴에서 벗어나는 데이터 포인트

 

Z-score

  • 데이터가 정규분포를 따른다고 가정할 경우
  • 평균이 0, 표준편차가 1인 표준정규분포(=z분포)로 변환
  • 이거 왜 하는지? 이상치(희귀하게 등장하는 데이터) 확인하기 위해
  • 평균에서 2표준편차 떨어져 있으면 등장확률 5% = 희귀하다고 봄

IQR

  • 백분율을 기준으로 이상치 판단
  • 하한 이상치: Q1 - 1.5*IQR
  • 상한 이상치: Q3 +1.5*IQR

차원축소

  • 고차원(변수가 여러개)의 경우 시각화, 연산 복잡도 측면에서 어려움이 있기 때문에 차원축소를 한다.
  • 차원축소의 종류 : pca(쉬운 계산으로 축소하는 방법), t-sne, umap 비선형구조에서 차원축소 하는 것이다.

특히 어려웠던 것

  • 코드카타 파이썬(replace, dictionary_items)
    • 문제
    • 문제 구조화
      • 문자열 바꾸기( 영단어 → 숫자)
    • 관련 개념
      • replace(바꿀대상, 바꾸려는 문자열)
        • 문자열을 바꿔주는 내장함수이다.
        • 원본은 그대로 이므로 새로운 변수에 담아줘야 한다.
      • 메서드 체이닝
        • 한 객체의 메서드를 연속적으로 호출
        • 가시성이 좋도록 코드를 입력하는게 관건
    • 나의 풀이 - replace활용
    • def solution(s):
          replaced_s = (
                    s.replace('zero', '0')
                    .replace('one', '1')
                    .replace('two', '2')
                    .replace('three', '3')
                    .replace('four', '4')
                    .replace('five', '5')
                    .replace('six', '6')
                    .replace('seven', '7')
                    .replace('eight', '8')
                    .replace('nine', '9')
          )
          answer = int(replaced_s)
          return answer
      
    • 다른 사람의 풀이 - 문자열과 숫자를 key, value로 하는 dictionary 미리 지정 후 for loop 통해 replace
      • 문자열과 숫자를 key, value로 하는 딕셔너리를 미리 정의해둠
      • ‘one’ → ‘1’
      • 딕셔너리 각 항목을 for loop로 순회하면서
      • replace 함수를 써서 문자 → 숫자로 바뀌게 됨
      • 단 s에 변화가 누적해서 발생해야 하니까 바꾸고 다시 s에 저장
      • 최종 int로 변환
      def solution(s):
          dict_str_to_num = {
              'zero': '0',
              'one': '1',
              'two': '2',
              'three': '3',
              'four': '4',
              'five': '5',
              'six': '6',
              'seven': '7',
              'eight': '8',
              'nine': '9'
          }
          
          for key, value in dict_str_to_num.items():
              s = s.replace(key, value)
          
          return int(s)
      
      

다음에 적용해 볼 것

 
랜덤포레스트 약한 것 같으니 꼭꼭 복습하자
 
머신러닝 라이브세션 훑으며 최대한 코드 위주로 학습하자 확장하자!!