신용카드 거래내역의 이상징후를 탐지하는 지난 포스팅에 이어, KDDCUP데이터셋의 이상징후를 탐지하는 분석을 해보자
(이전 포스팅에 RBM에 관한 설명이 있으니 먼저 읽는 것을 추천한다.)
2023.07.11 - [대학원 공부/anomaly detection] - [Anomaly detection] RBM을 이용한 이상 징후 탐지-신용카드 데이터셋
[Anomaly detection] RBM을 이용한 이상 징후 탐지-신용카드 데이터셋
RBM(제한된 볼츠만 머신)을 활용하여 신용카드 거래의 이상징후를 탐지해보자. RBM에 대한 자세한 설명은 아래 링크에서 확인할 수 있다. 이 포스팅을 정독하여 읽고 RBM에 대하여 확실히 이해하고
ozzzih.tistory.com
KDDCUP데이터셋은 다양한 침입 공격을 나타내는 방대한 양의 데이터이다.
아래 링크에서 'kddcup.data.gz' 데이터를 다운받고 압축을 해제한다.
https://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html
위 링크에서 다운로드가 안될 시 아래 링크 참고
https://www.kaggle.com/code/mukeshgupta819/starter-kdd-cup-1999-data-bc41cfca-a
Starter: KDD Cup 1999 Data bc41cfca-a
Explore and run machine learning code with Kaggle Notebooks | Using data from KDD Cup 1999 Data
www.kaggle.com
데이터를 불러왔다면 이제 코딩을 시작해보자.
1. 데이터 불러오기
컬럼명이 없는 데이터라서 42개의 컬럼명을 직접 작성한다.(필자는 책을 참고하였다.)
#필요한 패키지 불러오기
import pandas as pd
import tensorflow as tf
from sklearn.metrics import roc_auc_score as auc
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from rbm import RBM
from sklearn.preprocessing import LabelEncoder
columns=["duration", "protocol_type", "service", "flog", "src_bytes", "dst_bytes", "land", "wrong_fragment", "urgent",
"hot", "num_failed_logins", "logged_in", "num_compromised", "root_shell", "su_attemped", "num_root", "num_failed_creations",
"num_shells", "num_access_filed", "num_outbound_cmds", "is_host_login", "is_guest_login", "count", "srv_count", "serror_rate",
"srv_serror_rate", "rerror_rate", "srv_rerror_rate", "same_srv_rate", "diff_srv_rate", "srv_diff_host_rate", "dst_host_count",
"dst_host_srv_count", "dst_host_same_srv_port_rate", "dst_host_diff_srv_rate", "dst_host_same_src_port_rate", "dst_host_srv_diff_host_rate",
"dst_host_serror_rate", "dst_host_srv_serror_rate", "dst_host_rerror_rate", "dst_host_srv_rerror_rate", "label"]
df=pd.read_csv("kddcup.data.corrected", sep=",", names=columns, index_col=None)
print(df.shape)
df.head()
(output)
데이터의 shape가 (4898431,42)로 굉장히 방대하다.
2. 데이터 전처리
이번 분석은 HTTP공격에 집중하여 이상징후를 탐지하는 것으로 목적으로 한다.
따라서 'service' 변수에서 'http' 항목만을 필터링한다.
df=df[df["service"]=="http"]
df=df.drop("service", axis=1)
columns.remove("service")
LabelEncoder()를 활용하여 문자형 데이터를 수치로 변경해준다.
for col in df.columns:
if df[col].dtype=="object":
encoded=LabelEncoder()
encoded.fit(df[col])
df[col]=encoded.transform(df[col])
이 데이터셋은 데이터 양이 매우 많기 때문에 이상 징후에 해당하는 데이터를 아주 의미 없게 만들어 버린다.
또한, RBM에는 모든 데이터 값을 전달할 필요가 없기 때문에 정상 데이터 일부와 모든 이상 징후 데이터를 활용하여 새로운 데이터셋을 만든다.
정상 데이터는 label이 4로 라벨링 되기 때문에 이것으로 정상과 비정상을 구분한다.
import numpy as np
anomaly=df[df["label"]!=4]
normal=df[df["label"]==4]
for f in range(0,10):
normal=normal.iloc[np.random.permutation(len(normal))]
novelties=pd.concat([normal[:50000], anomaly])
novelties.shape
(output)
데이터 변수별 분포를 확인해보자.
with pd.option_context ('display.max_row', 5, 'display.max_columns', 41):
print(novelties)
(output)
데이터에 0 또는 0 근처의 값이 굉장히 많은 것을 알 수 있다.
RBM학습할 때 이러한 값들은 AUC에 악영향을 미치기 때문에 표준화가 필요하다.
(이러한 극단적인 값들은 'exploding gradient' 또는 'vanishing gradient'현상을 일으킬 가능성이 높다.)
범주형 변수인 'protocol_type', 'flag', 'label'은 표준화하지 않는다.
for c in columns:
if(c != "protocol_type" and c != "flag" and c != "label"):
novelties[c]=StandardScaler().fit_transform(novelties[c].values.reshape(-1,1))
novelties.head()
(output)
3. 데이터셋 분리
훈련과 테스트를 위하여 데이터셋을 분리한다.
43,000개의 항목을 약 80:20으로 분리한다.
x_train=novelties.iloc[:43000, 1:-2].values
y_train=novelties.iloc[:43000, -1].values
x_test=novelties.iloc[43000:, 1:-2].values
y_test=novelties.iloc[43000:, -1].values
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)
(output)
RBM은 비지도학습이라, y_train과 y_test는 학습에 이용되지 않는다.
4. 모델 학습
model=RBM(x_train.shape[1], 20, visible_unit_type='gause', main_dir="./", model_name="rbm_model2.ckpt",
gibbs_sampling_steps=4, learning_rate=0.001, momentum=0.95, batch_size=512, num_epochs=20, verbose=1)
모델의 파라미터는 이전 포스팅에 설명되어있다.
model.fit(x_train, validation_set=x_test)
(output)
error가 점점 감소하는 모습이다.
5. 평가
현재 정상 데이터는 4로 라벨되어있고, 비정상 데이터는 그외 숫자로 라벨되어있다.
AUC평가지표를 확인하기 위하여 정상 데이터는 1로, 비정상 데이터는 0으로 라벨링한다.
for f in range(0, len(y_test)):
if y_test[f]==4:
y_test[f]=0
else:
y_test[f]=1
auc평가지표를 계산한다.
costs=model.getFreeEnergy(x_test).reshape(-1)
score=auc(y_test, costs)
print(score)
(output)
0.9973142857142856
이전 포스팅의 결과보다 좋은 결과이다.
normal과 anomaly의 분리된 모습을 확인할 수 있다.
-'파이썬 딥러닝으로 시작하는 이상징후 탐지' 책을 참고하였음
'대학원 공부 > anomaly detection' 카테고리의 다른 글
[Anomaly detection] RBM을 이용한 이상 징후 탐지-신용카드 데이터셋 (0) | 2023.07.11 |
---|