머신러닝 활용 품질관리

Chapter.8 머신러닝 활용 품질관리(6)

devjjun 2026. 6. 23. 17:25

TIL(Today I Learned)


1️⃣실무에 바로 쓰는 머신러닝 기초 7

차원축소 

  • 선형적 차원 축소: 데이터를 특정 선형으로 투영하여 차원을 줄이는 방법 
  • 비선형 차원 축소: 데이터가 복잡한 기하학적 구조를 가질 때, 비선형 맵핑을 이용 

차원 축소와 노이즈 제거 

  • 대부분의 데이터에는 잡음(irrelevant feature)이 포함 
  • 차원 축소 시 중요한 변동을 설명하지 못하는 데이터를 제거함으로 불필요 정보 필터링

PCA

데이터의 가장 분산이 큰 방향(주성분)을 찾아 그 방향으로 투영하면 그 축이 데이터의 
중요한 변동을 설명할 수 있다. 

  • 주성분: 가장 큰 분산이 갖는 방향을 1주성분, 그 다음 큰 분산이 갖는 서로 직교하는 방향을 2주성분
  • 설명 분산: 몇 개의 주성분만으로 전체 분산의 몇 퍼센트를 설명할 수 있는지 

장단점

  • 장점: 계산이 비교적 간단, 결과 해석 용이, 노이즈 제거 효과
  • 단점: 선형이 아닌 패턴의 데이터일 경우 정보 손실 발생 가능성

t-SNE와 UMAP

t-SNE

고차원 공간에서 서로 가까운 데이터 포인트는 가까이 먼 데이터 포인트는 멀리 배치하려는 비선형 차원 축소 기법 

동작 원리

  1. 고차원에서 데이터 간 지역적 확률 분포를 추정한다. 
  2. 2차원 혹은 3차원에서 비슷한 확률 분포가 되도록 데이터들을 배치한다. 

UMAP

t-SNE와 유사하게 고차원 데이터 구조를 2D/3D로 매핑하는 비선형 차원 축소 기법 

 

t-SNE와 UMAP 모두 시각화 목적에서 많이 쓰이며,
데이터를 2D 한 눈에 군집 패턴을 볼 수 있다는 점이가장 큰 장점

코드 예시

더보기
import numpy as np
import matplotlib.pyplot as plt

# 1. 데이터 로드 (Iris 예시)
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data   # (150, 4) 형태: 꽃받침, 꽃잎 길이·너비
y = iris.target # (150,)  : 품종 라벨(0, 1, 2)

# 2. PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

# 3. t-SNE
from sklearn.manifold import TSNE
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
X_tsne = tsne.fit_transform(X)

# 4. UMAP
# (umap-learn 설치 필요할 수 있습니다 : pip install umap-learn)
from umap import UMAP
umap = UMAP(n_components=2, n_neighbors=15, random_state=42)
X_umap = umap.fit_transform(X)

# 5. 시각화 (PCA, t-SNE, UMAP 결과 비교)
fig, axes = plt.subplots(1, 3, figsize=(15, 4))

axes[0].scatter(X_pca[:, 0], X_pca[:, 1], c=y)
axes[0].set_title("PCA (2D)")

axes[1].scatter(X_tsne[:, 0], X_tsne[:, 1], c=y)
axes[1].set_title("t-SNE (2D)")

axes[2].scatter(X_umap[:, 0], X_umap[:, 1], c=y)
axes[2].set_title("UMAP (2D)")

plt.tight_layout()
plt.show()

코드 결과


이상탐지란?

데이터에서 정상 패턴과 크게 다른 행위를 보이는 특이한 패턴을 찾는 기법 

이상치 탐지와의 차이 

  • 이상치 탐지: 통계적으로 극단값을 찾는 것, 예) 평균에서 크게 벗어난 데이터 포인트를 찾는 방식 
  • 이상 탐지: 단순 극단값 뿐만 아니라, 맥락이나 시계열 상의 패턴을 함께 고려하여 판단하는 것 

One-Class SVM

  • 알고리즘 원리
    • SVM은 원래 이진 분류지만 단 하나의 클래스(정상 클래스)만을 학습해 정의하는 것 
    • 정상 데이터가 분포하는 공간 주위에 경계를 형성, 경계 밖의 데이터는 비정상 분류 
  • 특징
    • 고차원 공간에서도 비교적 잘 동작 가능
    • 데이터 스케일링과 커널 파라미터 선택이 중요 

Isolation Forest

 

  • 알고리즘 원리
    • Isolation Forest는 랜덤 포레스트와 유사한 아이디어에 기반한다.
    • 무작위로 특성과 분할값을 골라 데이터를 계속 나누어가는 과정에서 ‘쉽게 분리(또는 격리)되는’ 데이터는 이상일 가능성이 높다고 본다.
  • 특징
    • 랜덤 포레스트 방식으로 여러 개의 무작위 트리를 구성하고, 각 트리에서 한 데이터가 분리되는 “깊이(depth)”를 측정하여 이상 점수를 부여한다.
    • 대규모 데이터셋에서도 빠르게 동작하는 편이며, 구현이 간단하고 직관적이다.

이상 탐지 코드 예시

더보기
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# 1. 데이터 로드: Iris 데이터셋
from sklearn.datasets import load_iris
data = load_iris()
X = data.data
y = data.target  # 여기서는 실제 라벨을 이용하지 않음

# 간단히 2개 특성만 사용 (예: 꽃받침 길이, 꽃받침 너비) --> 시각화 편의를 위해
X_2d = X[:, :2]  # shape: (150, 2)

# 2. One-Class SVM
from sklearn.svm import OneClassSVM

oc_svm = OneClassSVM(nu=0.05)  # 예시 파라미터
oc_svm.fit(X_2d)
# 예측: 1(정상), -1(이상치)
y_pred_oc = oc_svm.predict(X_2d)

# 3. Isolation Forest
from sklearn.ensemble import IsolationForest

iso_forest = IsolationForest(contamination=0.05, random_state=42)
iso_forest.fit(X_2d)
# 예측: 1(정상), -1(이상치)
y_pred_if = iso_forest.predict(X_2d)

# 4. 이상치로 예측된 샘플 인덱스 추출
outliers_oc = np.where(y_pred_oc == -1)[0]  # One-Class SVM이 예측한 이상치
outliers_if = np.where(y_pred_if == -1)[0]  # Isolation Forest가 예측한 이상치

print("=== One-Class SVM ===")
print("이상치로 탐지된 샘플 개수:", len(outliers_oc))
print("이상치 인덱스:", outliers_oc)

print("\n=== Isolation Forest ===")
print("이상치로 탐지된 샘플 개수:", len(outliers_if))
print("이상치 인덱스:", outliers_if)

# 5. 시각화
# 2차원 특성 공간에서 이상치로 판별된 점들을 빨간색으로 표시
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

axes[0].scatter(X_2d[:, 0], X_2d[:, 1], label='Normal')
axes[0].scatter(X_2d[outliers_oc, 0], X_2d[outliers_oc, 1],
                color='red', edgecolors='k', label='Outliers')
axes[0].set_title("One-Class SVM")
axes[0].set_xlabel("Sepal Length")
axes[0].set_ylabel("Sepal Width")
axes[0].legend()

axes[1].scatter(X_2d[:, 0], X_2d[:, 1], label='Normal')
axes[1].scatter(X_2d[outliers_if, 0], X_2d[outliers_if, 1],
                color='red', edgecolors='k', label='Outliers')
axes[1].set_title("Isolation Forest")
axes[1].set_xlabel("Sepal Length")
axes[1].set_ylabel("Sepal Width")
axes[1].legend()

plt.tight_layout()
plt.show()

코드 결과 


💡 느낀점

차원 축소를 공부하면서 특성이 많을수록 무조건 좋은 것이 아니라 차원의 저주로 인해 데이터가 희박해지고 거리 개념
무의미해질 수 있다는 점을 알게 되었다. PCA에서는 분산을 정보량으로 보고 가장 많이 흩어진 방향이 데이터를 잘 설명한다는 발상이 인상적이었으며, 누적 설명 분산을 통해 적은 수의 주성분만으로도 대부분의 정보를 담을 수 있다는 점이 흥미로웠다. 다만 주성분이 원래 변수들의 선형 결합이라 해석이 어려워지는 트레이드오프가 있다는 점도 함께 느꼈다. 또한 PCA 같은 선형 기법과 t-SNE, UMAP 같은 비선형 기법은 목적이 달라 용도에 맞게 선택해야 하며, 차원 축소 전에는 스케일링이 필수라는 점도 다시 한번 정리할 수 있었다.