심각하게 심각하게 게으른 자의 C-Mapss 분석 2-2편이다...
잊을만할 때마다 댓글을 달아주시는 분들이 계셔서 적게 된다.. 감사!!
금번 자료의 주제는 Fault Classification with Deep learning이다.
ML 기반의 대표 알고리즘 Random Forest와 DL 기반의 대표 알고리즘 Convolutional Neural Network(CNN)을 사용할 것이다.
고장 유형 분류와 어떤 파라미터가 원인 인자였는지 분석해서 각 고장 유형에 대해 어떤 것이 문제였는지 분석해볼 예정이다.
이번 포스팅의 주요 카테고리는 아래와 같다.
1. C-MAPSS 데이터의 고장 유형 분류
2. 각 고장 유형의 혐의 인자 분석
혐의 인자에 대한 공정 분석은 엔진의 원리를 알아야 하지만,,, 그건 내 영역이 아닌 관계로 pass..!
1. C-MAPSS 데이터의 고장 유형 분류 알고리즘
1.1 EDA 결과 재확인 : 고장 유형 2가지
저번 포스팅에서 우리는 C-MAPSS 데이터의 고장 유형이 총 2가지인 것으로 파악했다.
누차 얘기하지만, C-MAPSS 데이터 공식 설명 자료에는 고장 유형은 1가지(=FD001 train)라고 표현되어 있다.
따라서 본 포스팅의 접근은 한 개인의 분석론으로 받아들여야 하며, 정론으로 받아들여서는 안된다.
위 EDA 결과를 기반으로 고장 유형을 2가지(Fault A, B)로 정의하고 분석을 진행하겠다.
FD 001 Train에는 총 100가지의 Run 이력이 있다. 각각의 Run에 대해서 고장 유형을 부여해서 모델이 학습할 수 있도록 준비한다.
for k in embedding_result['keys'].unique():
embedding_result_key = embedding_result[embedding_result['keys']==k]
max_label = embedding_result_key['label'].value_counts(ascending=False).index.tolist()[0]
k_idx = sf[sf['key']==k].index.tolist()
sf['faultclass'].loc[k_idx] = max_label
이제 분류용 데이터를 모두 준비했다! 다음 스텝으로 이동하자.
1.2 Random Forest를 이용한 고장 유형 분류
Random Forest는 Machine learning 계열에서 가장 흔히 쓰이는 알고리즘이다.
금번 포스팅에서는 classification이 주 목적이므로, classifier 기능이 있는 random forest를 사용해서 Cmapss 데이터를 분류하고, 어떠한 파라미터가 가장 많은 영향을 끼쳤는지 분석한다.
위에서 준비한 데이터 셋중, 80%는 훈련, 나머지는 실험용으로 사용한다.
scikit learn의 train test split 라이브러리를 활용해도 괜찮습니다,,, 구닥다리 머리가 버릇을 사용하는 바람에... 자기 마음대로 설정해도 무방합니다.
keys = sf['key'].unique()
train_keys = np.sort(np.random.choice(keys, int(round(len(keys)*0.8)), replace=False))
test_keys = np.sort(np.setdiff1d(keys, train_keys))
train_x = pd.DataFrame()
for k in train_keys:
sf_key = sf[sf['key']==k]
train_x = pd.concat([train_x, sf_key])
test_x = pd.DataFrame()
for k in test_keys:
sf_key = sf[sf['key']==k]
test_x = pd.concat([test_x, sf_key])
train_x_val = train_x.iloc[:, 2:]
train_y_val = train_x.iloc[:, 1]
test_x_val = test_x.iloc[:, 2:]
test_y_val = test_x.iloc[:, 1]
여기까지 왔다면, 훈련/실험용 데이터 준비까지 완료된 것이다.
**똑똑한 사람들은 한가지 의문을 품을 것이다. "왜 전처리(Min-Max normalizing, Z-normalizing등..)를 안하는거지?"
Random forest는 결정 기반 트리 구조로서 Input 데이터의 각 변수별 값 range에 영향을 받지 않는다. 따라서 전처리를 해도 그만, 안해도 그만인 관계로,, 난 안한다. Random forest의 input으로 사용시에는 굳이 바꿔줄 필요가 없기 때문이다.**
다음은 Random forest를 훈련하는 과정이다.
from sklearn.ensemble import RandomForestClassifier
forest = RandomForestClassifier(n_estimators=1000, criterion='gini',
max_depth=30, min_samples_split=2,
min_samples_leaf=1, min_weight_fraction_leaf=0.0,
max_features='sqrt', max_leaf_nodes=None,
min_impurity_decrease=0.0, bootstrap=True,
oob_score=False, n_jobs=None, random_state=None,
verbose=0, warm_start=False, class_weight=None,
ccp_alpha=0.0, max_samples=None)
forest.fit(train_x_val, train_y_val)
model에 수많은 hyper parameter들이 있다. 하지만 여기서 중요하게 볼 것은 n_estimators, max depth를 중요하게 볼 예정이다.
scikit learn에서 정의한 default 값을 따르지 않고 더 over-fitting할 수 있도록 값을 키워줬다.
학습된 모델의 실험 결과를 보자
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
test_y_pred = forest.predict(test_x_val)
cm = confusion_matrix(test_y_val, test_y_pred, normalize='true', labels=forest.classes_)
# plt.figure(figsize=(8, 8))
# plt.title('Random Forest Result')
disp = ConfusionMatrixDisplay(confusion_matrix=cm,
display_labels=forest.classes_)
disp.plot(cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.title('Random Forest Result')
# plt.figure(figsize=(8, 8))
plt.show()
confusion matrix 결과를 놓고 봤을 때, Fault A에 대해서는 결과가 우수하지만 Fault B에 대해서는 결과가 엉망이다..
왜 이런 결과가 나오는 것인지, 머신러닝 관점에서의 분석이 필요하다.
자, 이러한 경우에는 역으로 추정해볼 수 있을만한 원인들이 있다. 2가지를 가설로 세우고 접근하겠다. Preprocessing, Data imbalance.
1. Data imbalance
- 학습 데이터에서 Fault A와 Fault B의 균형이 맞지 않아, 알고리즘의 학습 질이 저하됐을 가능성이 있다.
- imbalance 문제를 해결하기 위해, down/up sampling을 통해서 학습 데이터의 균형을 맞춘다.
2. Preprocessing
- Cmapss 데이터는 Run to Failure, 즉 엔진 시작부터 고장 발생까지의 데이터이다.
- 같은 의미로, FD001 train 데이터의 100개 key(=unit_nr)에서 초반 부분은 정상데이터라고 가정해도 무방하다.
- 그러므로 실험 대상에서 초반 부분은 제거하고 실험을 진행한다.
1.2.1 Data imbalance 현상 확인
학습 데이터에서 Fault A/B 간의 balance 문제는 없었는지 확인한다.
train_y_val.value_counts()
Fault B가 절반 수준으로, Data imbalance 문제가 있었다고 볼 수 있다.
이러한 경우에는 아래와 같은 방법들로 대응할 수 있다.
1.2.1.1. Up-sampling
상대적으로 데이터 수가 부족한 class에 대해 데이터를 더 뽑아내는 방식. 중복해서 뽑아내거나 약간의 noise를 더하는 방식들로 대응이 가능하다. 대표적으로 SMOTE, Over sampling등이 있다. 하지만 생성된 데이터가 원본과 너무 유사하여 over-fitting이 될 수 있다는 단점이 있다.
1.2.1.2. Down-sampling
상대적으로 데이터 수가 많은 class에 대해서 더 적은 양의 데이터를 선정하여 학습하는 방식. 데이터의 수를 쉽게 맞추는 장점이 있다. 하지만 활용할 수 있는 데이터를 활용하지 못한다는 점에서 부족한 부분이 생길 수 밖에 없다.
본 포스팅에서는 down-sampling을 통한 방식으로 data-imbalance 문제를 해결해보겠다.
train_idx = []
for cl in sf['faultclass'].unique():
cl_idx = sf[sf['faultclass']==cl].index.to_numpy()
train_idx.extend(np.random.choice(cl_idx, 5000, replace=False))
train_idx = np.array(train_idx)
test_idx = np.setdiff1d(sf.index.to_numpy(), train_idx)
train_x_val = sf.iloc[train_idx, 2:]
train_y_val = sf.iloc[train_idx, 1]
test_x_val = sf.iloc[test_idx, 2:]
test_y_val = sf.iloc[test_idx, 1]
Fault A, B에 대해서 5000개 씩으로 sampling을 한다. 결과는 아래와 같이 의도했던대로 나왔다.
위 다른 실험과 동일한 Random forest 모델로 실험을 진행하겠다.
기존 결과보다 소폭 상승했으나, down sampling으로 인해 원래 잘했던 Fault A에 대한 정확도가 저하되는 현상이 발생됐다. 이는 잘하는 것을 못하게 하고, 못하던 것을 조금 잘하게 된 결과이므로, 유익한 결과라고 판단하기 어렵다.
1.2.2 Preprocessing
CMAPSS 데이터에서 초반 부분을 제거하고 실험을 진행한다. 동일하게 모든 데이터의 초반 100포인트 정도를 제거한다.
아무래도 데이터 관점에서 정상과 각 고장 유형 데이터들이 섞여 있어서 결과가 안좋았던 것으로 예상된다. 줄글로만 쓰면 이해가 안된다. ppt로 명확하게 그려보자.
기존(왼쪽 그림)에는 Key 1~100 안에 정상(데이터 초반)과 고장데이터가 모두 섞여 있었다. 따라서 모델 관점에서는 왼쪽 그림처럼 정상과 실제 고장 데이터를 Fault A 또는 Fault B로 학습하는 것이기 때문에 모델 성능 저하 현상이 발생할 수 밖에 없었다. 하지만 오른쪽처럼 정상데이터를 걸러주고 학습을 시킨다면 실험의 결과가 크게 달라질 것으로 예상된다.
keys = sf['key'].unique()
train_keys = np.sort(np.random.choice(keys, int(round(len(keys)*0.8)), replace=False))
test_keys = np.sort(np.setdiff1d(keys, train_keys))
train_x = pd.DataFrame()
for k in train_keys:
sf_key = sf[sf['key']==k]
sf_key = sf_key.iloc[100:, :] # --> 초반 100개 포인트 제거
train_x = pd.concat([train_x, sf_key])
test_x = pd.DataFrame()
for k in test_keys:
sf_key = sf[sf['key']==k]
sf_key = sf_key.iloc[100:, :] # --> 초반 100개 포인트제거
test_x = pd.concat([test_x, sf_key])
train_x_val = train_x.iloc[:, 2:]
train_y_val = train_x.iloc[:, 1]
test_x_val = test_x.iloc[:, 2:]
test_y_val = test_x.iloc[:, 1]
초반 100개를 제거했을 때의 결과. TPFN의 결과가 확연히 좋아진 것이 보인다. 정확도 기준으로 약 35%가 개선되었다.
성능 저하 현상이 보였던 이유는 정상데이터가 섞여서 고장 데이터를 학습하는 것에 방해가 됐던 것으로 추정된다.
'Predictive Maintenance' 카테고리의 다른 글
Predictive Maintenance: [2-1] C-Mapss 데이터 분석편 (주제: Fault Classification) (2) | 2023.07.26 |
---|---|
Predictive Maintenance: [1] C-Mapss 데이터 EDA편 (2) | 2022.02.22 |