포스트

[Data Analysis] 차원축소 기반 이상 탐지

PCA, t-SNE을 이용한 이상탐지 구현해보기

[Data Analysis] 차원축소 기반 이상 탐지

PCA 이상 탐지

PCA(Principal Component Analysis)란 변수에서 가장 가까운 초평면을 구한 다음, 초평면을 투영(Projection)하여 차원을 축소하는 기법입니다.

AutoEncoder의 작동원리인 정보를 압축하고 복원하면서 데이터를 실제와 가깝게 복원시키기 위해 정상 데이터의 패턴을 학습하고 비 정상인 데이터는 복원 패턴을 배우지않으며 비정상인 데이터를 찾는 것과 비슷합니다.

pca

PCA는 다음과 같은 단계로 이루어집니다.

  1. 학습 데이터셋에서 분산이 최대인 축(axis)을 찾습니다.
  2. 이렇게 찾은 첫번째 축과 직교(orthogonal)하면서 분산이 최대인 두 번째 축을 찾습니다.
  3. 첫 번째 축과 두 번째 축에 직교하고 분산을 최대한 보존하는 세 번째 축을 찾습니다.
  4. 1~3과 같은 방법으로 데이터셋의 차원(특성 수)만큼의 축을 찾습니다.
  • 장점
    • 선택한 변수들의 해석이 용이함
    • 고차원에서 저차원으로 줄일 수 있음
  • 단점
    • 변수간 상관관계를 고려하기 어려움
    • 추출된 변수 해석 어려움

주의 : PCA는 정규화를 필수로 요구합니다.(아래 데이터는 정규화가 진행되어있습니다.)

1
2
3
4
5
from sklearn.decomposition import PCA
import pandas as pd

data = pd.read_csv('creditcard.csv')
data
TimeV1V2V3V4V5V6V7V8V9...V21V22V23V24V25V26V27V28AmountClass
00.0-1.359807-0.0727812.5363471.378155-0.3383210.4623880.2395990.0986980.363787...-0.0183070.277838-0.1104740.0669280.128539-0.1891150.133558-0.021053149.620
10.01.1918570.2661510.1664800.4481540.060018-0.082361-0.0788030.085102-0.255425...-0.225775-0.6386720.101288-0.3398460.1671700.125895-0.0089830.0147242.690
21.0-1.358354-1.3401631.7732090.379780-0.5031981.8004990.7914610.247676-1.514654...0.2479980.7716790.909412-0.689281-0.327642-0.139097-0.055353-0.059752378.660
31.0-0.966272-0.1852261.792993-0.863291-0.0103091.2472030.2376090.377436-1.387024...-0.1083000.005274-0.190321-1.1755750.647376-0.2219290.0627230.061458123.500
42.0-1.1582330.8777371.5487180.403034-0.4071930.0959210.592941-0.2705330.817739...-0.0094310.798278-0.1374580.141267-0.2060100.5022920.2194220.21515369.990
..................................................................
284802172786.0-11.88111810.071785-9.834783-2.066656-5.364473-2.606837-4.9182157.3053341.914428...0.2134540.1118641.014480-0.5093481.4368070.2500340.9436510.8237310.770
284803172787.0-0.732789-0.0550802.035030-0.7385890.8682291.0584150.0243300.2948690.584800...0.2142050.9243840.012463-1.016226-0.606624-0.3952550.068472-0.05352724.790
284804172788.01.919565-0.301254-3.249640-0.5578282.6305153.031260-0.2968270.7084170.432454...0.2320450.578229-0.0375010.6401340.265745-0.0873710.004455-0.02656167.880
284805172788.0-0.2404400.5304830.7025100.689799-0.3779610.623708-0.6861800.6791450.392087...0.2652450.800049-0.1632980.123205-0.5691590.5466680.1088210.10453310.000
284806172792.0-0.533413-0.1897330.703337-0.506271-0.012546-0.6496171.577006-0.4146500.486180...0.2610570.6430780.3767770.008797-0.473649-0.818267-0.0024150.013649217.000

284807 rows × 31 columns

1
2
# Time, Amomunt 변수 제거
data.drop(['Time', 'Amount'], axis=1, inplace=True)
1
2
pca = PCA()
pca.fit(data.drop(['Class'], axis=1))
PCA()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
1
2
3
4
5
6
7
8
9
10
11
# 차원축소 주성분 갯수 확인
features = range(pca.n_components_)
feature_df=pd.DataFrame(data=features,columns=['pc_feature'])

# 설명력 확인
variance_df=pd.DataFrame(data=pca.explained_variance_ratio_,columns=['variance'])
variance_df["cumulative_variance"] = variance_df["variance"].cumsum()

# 전체 분산에 95% 이상 설명 가능(feature 22개 채택)
pc_feature_df=pd.concat([feature_df,variance_df],axis=1)
pc_feature_df
pc_featurevariancecumulative_variance
000.1248380.124838
110.0887290.213567
220.0748090.288376
330.0652310.353608
440.0619900.415598
550.0577560.473354
660.0497990.523153
770.0464170.569570
880.0392750.608845
990.0385790.647423
10100.0339010.681325
11110.0324880.713812
12120.0322330.746045
13130.0299010.775946
14140.0272620.803208
15150.0249840.828192
16160.0234730.851665
17170.0228600.874526
18180.0215630.896088
19190.0193390.915427
20200.0175560.932983
21210.0171370.950120
22220.0126890.962809
23230.0119360.974745
24240.0088420.983587
25250.0075670.991153
26260.0053010.996455
27270.0035451.000000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

x = data.drop(['Class'], axis=1)
y = data['Class']

pca = PCA(n_components=22)
x_pca = pca.fit_transform(x)

pc_df=pd.DataFrame(x_pca,columns=[f'{i}' for i in range(22)]).reset_index(drop=True)
pc_df=pd.concat([pc_df,y],axis=1)

plt.rcParams['figure.figsize'] = [5, 5]
sns.scatterplot(data=pc_df,x='0',y='2',hue=y, legend='brief', s=50, linewidth=0.5);

pca-plot

t-SNE 이상 탐지

t-SNE(t-distributed Stochastic Neighbor Embedding)는 비선형 차원 축소 기법으로 t-분포를 사용하여 데이터 유사도를 계산하여 유사도가 낮은 데이터는 멀리 떨어뜨려 거리를 최대한 보존합니다.

t-SNE

🔹 t-SNE 동작 과정

  1. 고차원 공간에서 데이터 포인트 간 확률적 유사도 계산

  2. 저차원 공간에서 랜덤하게 초기화된 점들의 분포 생성

  3. 저차원 공간에서도 유사한 확률 분포를 유지하도록 위치 조정

  4. 최적화 수렴 후 최종 시각화 결과 생성

  • 장점
    • PCA 대비 클러스터링을 발견하기 쉬움
    • 비선형 관계의 데이터를 군집화 가능
  • 단점
    • 대량의 데이터에서 속도가 느림 (O(n²) 복잡도)
    • 매번 돌릴 때마다 다른 시각화 결과가 도출
1
2
3
4
5
6
7
from sklearn.manifold import TSNE
from sklearn.model_selection import train_test_split

# 데이터 갯수 줄이기(약 30만개의 데이터를 넣으면 시간이 오래걸립니다.)
df_reduced, _ = train_test_split(data, train_size=0.03, stratify=data['Class'], random_state=42)

df_reduced['Class'].value_counts()
count
Class
08529
115


1
2
3
4
5
# t-SNE 2차원 축소(t-SNE는 4차원 이상으로 변환할 수 없습니다.)
tsne_np = TSNE(n_components = 3, random_state=42).fit_transform(df_reduced.drop(['Class'], axis=1))

tsne_df = pd.DataFrame(tsne_np, columns = [f'{i}' for i in range(3)])
tsne_df
012
0-2.370444-12.13114519.459503
1-18.2612760.444234-0.662202
25.660702-2.703253-14.699653
30.7489794.1914034.901437
4-6.995453-8.831751-17.670755
............
853911.48457718.109447-3.144772
854011.60970114.8419928.453781
8541-6.828044-9.141667-16.934467
85422.451750-3.080299-7.047642
85437.451354-21.366283-0.024991

8544 rows × 3 columns

1
2
3
4
5
6
7
8
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

y = df_reduced['Class'].reset_index(drop=True)

plt.rcParams['figure.figsize'] = [5, 5]
sns.scatterplot(data=tsne_df,x='1',y='2',hue=y, legend='brief', s=50, linewidth=0.5);

t-sne-plot

 

참고자료

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.