데이터가 고차원일수록(특성(Feature)의 개수가 많을수록) 모델을 학습시키거나 분석할 때 여러 가지 문제가 발생할 수 있음
-> 이 문제를 해결하기 위해 차원 축소가 필요
① 고차원의 문제
② 데이터 시각화
③ 노이즈 제거
④ 모델 효율성 향상
고차원 데이터를 저차원으로 축소하면서도 데이터의 중요한 정보를 최대한 보존하는 기법
-> 데이터의 주요 특징을 파악, 노이즈를 제거하거나 시각화를 용이하게 함
① 데이터는 처음 여러 차원으로 구성
② PCA는 각 차원의 분산(정보량)을 측정하고, 분산이 가장 큰 방향(축)을 찾음
③ 분산이 가장 큰 방향으로 데이터를 정렬하여 새로운 축을 정의
④ 새로운 축을 기준으로 데이터를 변환하여, 적은 차원에서도 데이터를 잘 설명할 수 있도록 처리
① 데이터 정규화
② 주성분 축을 찾기 위한 공분산 행렬 계산
③ 주성분 축을 찾기 위한 고유값과 교유벡터 계산
④ 주성분 선택
⑤ 데이터 투영
데이터의 분산(정보량)이 가장 큰 방향을 나타내는 축
데이터를 기존의 좌표축 대신 주성분 축으로 변환하는 과정
-> 투영 후의 데이터는 새로운 축(주성분) 상에서 표현, 불필요한 차원은 제거됨
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# 1. Iris 데이터셋 로드
iris = load_iris()
x = iris.data # 특성 데이터
y = iris.target # 타깃 데이터
# 2. 데이터 정규화
scaler = StandardScaler()
x_scaled = scaler.fit_transform(x)
# 3. PCA 객체 생성 및 적합
pca = PCA(n_components=2)
x_pca = pca.fit_transform(x_scaled)
# 4. PCA 결과 출력
print(pca.explained_variance_ratio_)
# 5. PCA 결과 시각화
plt.figure(figsize=(8, 6))
for target, color, label in zip([0, 1, 2], ['red', 'blue', 'green'], iris.target_names):
plt.scatter(x_pca[y == target, 0], x_pca[y == target, 1], color=color, label=label, alpha=0.7)
plt.title('PCA on Iris Dataset')
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.legend()
plt.grid()
plt.show()
고차원의 데이터를 저차원 공간으로 변환하여 데이터의 구조를 시각화하는데 사용되는 비선형 차원 축소 방법
① 고차원 공간에서 데이터 간 유사성 계산
② 저차원 공간에서 데이터 간 유사성 정의
③ 고차원과 저차원 공간의 유사성 차이 줄이기
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
# 1. MNIST 데이터셋 로드
mnist = fetch_openml('mnist_784', version=1)
x, y = mnist.data, mnist.target
# 2. 데이터 전처리
scaler = StandardScaler()
x_scaled = scaler.fit_transform(x)
# 3. t-SNE 모델 생성
tsne = TSNE(n_components=2, random_state=42, n_iter=1000, perplexity=30)
x_tsne = tsne.fit_transform(x_scaled[:2000])
# 4. 시각화
plt.figure(figsize=(10, 8))
scatter = plt.scatter(x_tsne[:, 0], x_tsne[:, 1], c=y[:2000].astype(int), cmap='tab10', s=10)
plt.colorbar(scatter, label='Digit Label')
plt.title('t-SNE Visualization of MNIST Data')
plt.xlabel('t-SNE Dimension 1')
plt.ylabel('t-SNE Dimension 2')
plt.grid()
plt.show()
데이터에서 일반적인 패턴과 크게 벗어나는 관측값을 식별하는 과정
데이터를 반복적으로 나누는 방식으로 이상치 탐지하기 위해 설계된 비지도학습 알고리즘
① 무작위 샘플링: 데이터에서 임의의 특징을 선택, 임의의 분할 값을 선택하여 데이터를 나눔
② 분리 깊이 계산: 이상치 일수록 다른 데이터로부터 분리되는데 필요한 단계가 작음
③ 여러 트리 구축: 데이터를 무작위로 분할하여 여러 개의 이진 트리 생성 -> 각 데이터 포인트가 나뉘는 평균 깊이 계산
④ 이상치 점수 산출: 분리 깊이에 따라 정해짐 -> 높은 점수를 받을수록 이상치일 가능성 높음
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest
# 1. 데이터 생성
np.random.seed(42)
# 정상/비정상 트래픽 데이터 생성
normal_traffic = np.random.normal(loc=50, scale=10, size=(100, 2))
anomalous_traffic = np.random.uniform(low=100, high=150, size=(10, 2))
# 데이터 결합 > 데이터프레임으로 변환
traffic_data = np.vstack((normal_traffic, anomalous_traffic))
traffic_df = pd.DataFrame(traffic_data, columns=['Request Count', 'Response Time'])
# 2. Isolation Forest 모델 생성 및 학습
model = IsolationForest(n_estimators=100, contamination=0.1, random_state=42)
# 모델 학습 후 예측 수행
traffic_df['Anomaly Score'] = model.fit_predict(traffic_data)
traffic_df['Anomaly'] = traffic_df['Anomaly Score'].apply(lambda x: 'Normal' if x == 1 else 'Anomaly')
# 3. 비정상 데이터의 범위 확인
anomalous_data = traffic_df[traffic_df['Anomaly'] == 'Anomaly']
min_request_count = anomalous_data['Request Count'].min()
max_request_count = anomalous_data['Request Count'].max()
min_response_count = anomalous_data['Response Time'].min()
max_response_count = anomalous_data['Response Time'].max()
print(f'요청 수(Request Count): {min_request_count} ~ {max_request_count}')
print(f'응답 시간(Response Time): {min_response_count} ~ {max_response_count}')
# 4. 시각화
plt.figure(figsize=(10, 6))
plt.scatter(traffic_df["Request Count"], traffic_df["Response Time"], c=traffic_df['Anomaly'].map({"Normal": "blue", "Anomaly": "red"}), label='Traffic')
plt.title("Traffic Data with Isolation Forest Anomaly Detection")
plt.xlabel("Request Count")
plt.ylabel("Response Time")
plt.legend(["Normal", "Anomaly"])
plt.grid()
plt.show()
데이터를 밀도가 높은 영역(군집)과 밀도가 낮은 영역(이상치)으로 나누는 밀도 기반 클러스터링 알고리즘
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
# 1. 데이터 생성
np.random.seed(42)
# 정상/비정상 트래픽 데이터 생성
normal_traffic = np.random.normal(loc=50, scale=10, size=(100, 2))
anomalous_traffic = np.random.uniform(low=100, high=150, size=(10, 2))
# 데이터 결합 > 데이터프레임으로 변환
traffic_data = np.vstack((normal_traffic, anomalous_traffic))
traffic_df = pd.DataFrame(traffic_data, columns=['Request Count', 'Response Time'])
# 2. DBSCAN 모델 생성
dbscan = DBSCAN(eps=15, min_samples=5)
traffic_df['Cluster'] = dbscan.fit_predict(traffic_data)
# 3. 이상치 탐지
traffic_df['Anomaly'] = traffic_df['Cluster'].apply(lambda x: 'Anomaly' if x == -1 else 'Normal')
anomalous_data = traffic_df[traffic_df['Anomaly'] == 'Anomaly']
min_request_count = anomalous_data['Request Count'].min()
max_request_count = anomalous_data['Request Count'].max()
min_response_count = anomalous_data['Response Time'].min()
max_response_count = anomalous_data['Response Time'].max()
print(f'요청 수(Request Count): {min_request_count} ~ {max_request_count}')
print(f'응답 시간(Response Time): {min_response_count} ~ {max_response_count}')
# 4. 시각화
plt.figure(figsize=(10, 6))
plt.scatter(traffic_df["Request Count"], traffic_df["Response Time"], c=traffic_df['Anomaly'].map({"Normal": "blue", "Anomaly": "red"}), label='Traffic')
plt.title("Traffic Data with DBSCAN Anomaly Detection")
plt.xlabel("Request Count")
plt.ylabel("Response Time")
plt.legend(["Normal", "Anomaly"])
plt.grid()
plt.show()