열역학 시뮬레이션 기반 랜덤 포레스트: 선박용 디젤 엔진 연소실 부품의 설명 가능한 고장 진단

Congcong Luo a , Minghang Zhao a,* , Xuyun Fu a , Shisheng Zhong a , Song Fu b , Kai Zhang c , Xiaoxia Yu d
a Department of Mechanical Engineering, Harbin Institute of Technology, Weihai, Weihai 264209, China
b School of Mechatronics Engineering, Harbin Institute of Technology, Harbin 150001, China
c School of Mechanical Engineering, Southwest Jiaotong University, Chengdu 610031, China
d School of Mechanical Engineering, Chongqing University of Technology, Chongqing 400054, China

초록

기존의 선박용 디젤 엔진 지능형 고장 진단 방법은 고장 훈련 데이터의 부족으로 인해 일반화 성능이 떨어지거나, 고장 메커니즘에 대한 사전 지식이 충분히 통합되지 않아 설명 가능성이 낮은 문제가 있었습니다. 이러한 문제를 해결하기 위해, 본 논문에서는 열역학 시뮬레이션 기반 랜덤 포레스트(TSRF) 방법론을 제안합니다.

이 방법은 열역학 시뮬레이션을 통해 고장 진화 특성을 규명하고, 이를 사전 지식으로 지능형 고장 진단 모델 설계에 통합합니다. 먼저, 시스템 기초 파라미터를 미세 조정하여 다양한 고장의 주요 특징을 모사함으로써 5개의 열역학 고장 모델을 개발했습니다. 그 후, 수치 시뮬레이션 결과를 바탕으로 연소실 부품의 열화를 나타내는 잠재적인 열역학 지표를 식별했습니다.

SHapley Additive explanations (SHAP) 값을 계산하여 특징 선택을 수행함으로써, 고장 상태와 유의미한 상관관계를 가진 변수만을 유지했습니다. 마지막으로 선별된 파라미터를 사용하여 연소실의 건전성 상태를 평가했습니다. 실험 결과, 제안된 TSRF 방법은 우수한 분류 성능을 보였으며, 고장 데이터셋에서 99.07%의 높은 평균 정확도를 달성했습니다.

키워드:
선박용 디젤 엔진 고장 진단 설명 가능한 AI SHAP 값

연구 동기

해양 공학 및 예지 보전(PHM) 분야에서 업계는 두 가지 오랜 병목 현상에 직면해 있습니다.

  • 데이터 희소성: 선박용 디젤 엔진(특히 원양 선박의 주 엔진)은 선박의 심장과 같아서, 해상에서 심각한 고장이 발생하면 동력 상실, 좌초, 심지어 해난 사고로 이어질 수 있습니다. 따라서 설계 시 안전 계수가 매우 높고, 실제로 심각한 고장이 발생할 확률은 매우 낮습니다. 또한, 해운 업계는 엄격한 예방 정비 시스템(예: 운전 시간 기반의 정기 점검)을 시행하고 있어, 대부분의 마모 부품은 실제로 파손되어 고장 데이터를 생성하기 전에 강제 교체됩니다. 이로 인해 정상 데이터와 초기 마모 데이터는 풍부하지만, 완전한 기능 상실이나 심각한 고장에 대한 실제 데이터는 극히 부족합니다.
  • '블랙박스' 문제: 딥러닝 모델은 일반적으로 투명성이 부족하기 때문에, 고장의 물리적 원인을 설명할 수 없다면 엔지니어가 모델을 신뢰하기 어렵습니다. 선급 협회의 엄격한 규제를 받는 해운업에서 이러한 불투명성은 치명적입니다. 만약 AI의 오진으로 인해 피스톤 소착(seizure)이나 크랭크축 파손이 발생했는데, 시스템이 그 오류의 원인이 데이터 편향인지, 알고리즘 결함인지, 센서 드리프트인지 추적할 수 없다면, 이는 해사 사고 조사에서 받아들여질 수 없습니다.

이러한 과제에 대응하기 위해 우리는 TSRF 방법론을 제안했습니다. 물리학 기반의 메커니즘 모델과 첨단 설명 가능성 기술을 융합하고, 고정밀 시뮬레이션 모델을 활용하여 데이터 희소성 문제를 해결함과 동시에 진단 결정이 열역학 기본 원리에 부합하도록 보장했습니다.


방법론

본 연구의 워크플로우는 다음 네 가지 주요 단계로 구성됩니다(그림 참조).

  1. 열역학 모델링: 물리적 테스트 벤치에만 의존하지 않고, 6기통 선박용 디젤 엔진의 고정밀 1차원 열역학 모델을 구축했습니다. 이 모델은 실제 운전 데이터를 기반으로 엄격하게 보정되었으며, 시뮬레이션 오차는 5% 이내로 제어됩니다.
  2. 고장 주입: 보정된 모델을 기반으로 물리적 파라미터를 미세 조정하여 5가지 특정 연소실 고장(예: 실린더 헤드 균열, 피스톤 소손 등)을 모사하고, 실제 엔진의 다양한 고장 수준을 포괄하는 데이터셋을 생성했습니다.
  3. SHAP 기반 특징 선택: SHAP 값을 이용해 핵심 특징을 정량적으로 식별하고, 진단 결정을 주도하는 14개의 주요 파라미터를 선별했습니다.
  4. 분류 진단: 물리학적으로 강화된 이 데이터셋을 활용하여 랜덤 포레스트(RF) 분류기를 훈련시킴으로써 고정밀 고장 진단을 실현했습니다.
Structure of TSRF method combining Thermodynamic Simulation and Random Forest for Explainable AI

그림 1: TSRF 방법론 아키텍처.


열역학 모델링 상세

높은 충실도를 보장하기 위해 1차원 디젤 엔진 시뮬레이션 모델을 구축했습니다. 이 메커니즘 모델은 물리적 정밀도와 데이터셋 생성에 필요한 계산 효율성 간의 균형을 맞추었습니다.

모델 토폴로지

엔진 시스템은 유체 파이프라인과 기능 구성 요소의 네트워크로 이산화됩니다.

  • 핵심 동력 장치: 6기통, 2행정 직렬 구성.
  • 가스 경로 시스템: 흡/배기 매니폴드(PL1, PL2)가 복잡한 파이프 네트워크를 통해 연결됨.
  • 과급 시스템: 터보차저(TC1)와 인터쿨러(CO1)가 결합됨.

보정 및 검증

고장 주입을 수행하기 전에, 베이스라인 모델은 실측 데이터를 기반으로 엄격하게 보정되었습니다.

  • 데이터 소스: 데이터 수집 모듈(DCM)을 통해 획득한 실제 선박 운항 데이터.
  • 검증: 주요 파라미터(출력, 배기 온도 등)의 편차는 ±5% 오차 범위 내 로 엄격하게 제어됨.
1-D thermodynamic simulation model

그림 2: 디젤 엔진 1차원 열역학 모델 개략도.

Model Validation Results

그림 5: 데이터 수집 모듈(DCM).

고장 주입 메커니즘

1차원 모델로는 3D 구조 결함을 직접 표현할 수 없으므로, 물리적 열화 메커니즘을 등가의 열역학 파라미터 변동으로 변환하는 현상학적 매핑 방법을 채택했습니다.

고장 유형 물리적 메커니즘 모델링 구현
F1: 실린더 헤드 균열 열전도 저해. 실린더 헤드 표면 온도($T_H$)를 346°C로 상승.
F2: 피스톤 소손 재료 손실 및 밀봉 실패. 피스톤 온도($T_P$) 상승 + 경미한 블로바이(0.01 kg/s).
F3: 실린더 라이너 마모 마모로 인한 보어 직경 확대. 보어 직경 확대 + 대량의 블로바이(0.03 kg/s).
F4: 피스톤 링 마모 가스 누출. 블로바이 질량 유량 조절(0.02 kg/s).
F5: 피스톤 링 고착 마찰력 증대 및 밀봉 실패. 보어 직경 변화 + 라이너 온도 상승 + 블로바이.

설명 가능성 분석

본 연구의 핵심 혁신 중 하나는 초점을 '고장이 무엇인가?'에서 '왜 해당 고장으로 판정했는가?'로 전환한 데 있습니다. 피스톤 링 마모(F4)의 사례 분석을 통해 이러한 능력을 입증했습니다.

  • 국소적 설명(Waterfall Plot): 워터폴 플롯은 구체적인 예측 논리를 분석합니다. 예를 들어, 모델이 '피스톤 링 마모'를 예측한 것은 블로바이 열류(P06)와 블로바이 질량 유량(P07)이 특정 수치를 나타내어 해당 고장의 예측 확률을 높였기 때문입니다. 이는 물리 법칙과 일치합니다. 피스톤 링 마모는 기밀성을 파괴하여 가스 누출(블로바이)을 유발합니다.
  • 전역적 설명(Beeswarm Plot): 전역 분석은 모델이 학습한 보편적인 법칙을 밝혀냅니다. 우리는 터빈 전 배기 압력(P11)의 낮은 값이 피스톤 링 마모의 강력한 지표임을 확인했습니다. 물리학적 관점에서도 이는 타당합니다. 마모된 피스톤 링은 실린더 가스 누출을 유발하여, 결과적으로 터빈을 구동할 가용 에너지를 감소시키기 때문입니다.
SHAP Analysis,including Waterfall plot, beeswarm plot, interaction plot and dependence plot

그림 11: SHAP 값 기반의 피스톤 링 마모(F4) 고장 분석: (a) Waterfall Plot; (b) Beeswarm Plot; (c) Interaction Plot; (d) Dependence Plot.

SHAP 시각화 코드 보기 (Python)

위 그래프의 구현 세부 사항에 관심이 있으시다면, 다음은 Waterfall, Beeswarm, Interaction 및 Dependence 플롯을 생성하기 위한 예제 코드입니다.👇

import shap
import matplotlib.pyplot as plt
import numpy as np

# --- 0. Setup & Global Settings ---
plt.rcParams['font.family'] = 'Arial'
plt.rcParams['font.size'] = '24'
plt.rcParams['axes.unicode_minus'] = False

# Assumption: 'best_model' is your trained XGBoost/RF model
# Assumption: 'X_train' and 'X_test' are pandas DataFrames

# 1. Calculate SHAP values as Numpy Arrays (for Beeswarm, Dependence, Interaction)
explainer_tree = shap.TreeExplainer(best_model)
shap_values_numpy = explainer_tree.shap_values(X_train) 

# 2. Calculate SHAP values as Explanation Object (Specifically for Waterfall)
explainer_obj = shap.Explainer(best_model, X_test)
shap_values_obj = explainer_obj(X_test)


##################################################################
#                                                                #
#                      (a) Waterfall Plot                        #
#          Visualizes contribution for a single sample           #
#                                                                #
##################################################################

class_idx = 4  # Target class
sample_idx = 3 # Specific sample to explain

plt.figure()
shap.plots.waterfall(
    shap_values_obj[sample_idx, :, class_idx], 
    max_display=9, 
    show=False
)

# Customizing style
ax = plt.gca()
ax.set_xlabel(ax.get_xlabel(), fontsize=36)
ax.set_ylabel(ax.get_ylabel(), fontsize=36)
ax.spines['bottom'].set_linewidth(3)
plt.show()


##################################################################
#                                                                #
#                      (b) Beeswarm Plot                         #
#              Global summary of feature importance              #
#                                                                #
##################################################################

class_idx = 5
plt.figure(figsize=(10, 8))

shap.summary_plot(
    shap_values_numpy[..., class_idx], 
    X_train, 
    feature_names=X_train.columns, 
    plot_type="dot", 
    show=False, 
    cmap='Greys' # or 'plasma'
)

# Customize Color Bar
cbar = plt.gcf().axes[-1] 
cbar.set_ylabel('Parameter Value', fontsize=24)
cbar.tick_params(labelsize=20)
plt.show()


##################################################################
#                                                                #
#                     (c) Interaction Plot                       #
#          Visualizes interaction effects between features       #
#                                                                #
##################################################################

# Note: Calculation can be expensive
shap_interaction_values = explainer_tree.shap_interaction_values(X_test)
class_idx = 4

plt.figure()
shap.summary_plot(
    shap_interaction_values[..., class_idx], 
    X_test, 
    show=False, 
    max_display=6, 
    cmap='Greys' 
)

# Clean up subplots
axes = plt.gcf().axes
for ax in axes:
    ax.spines['bottom'].set_linewidth(2)
    ax.tick_params(axis="x", labelsize=18, width=2)
    ax.set_title(ax.get_title(), fontsize=14) 

plt.subplots_adjust(wspace=0.3, hspace=0.4)    
plt.show()


##################################################################
#                                                                #
#                     (d) Dependence Plot                        #
#           Feature relationship colored by interaction          #
#                                                                #
##################################################################

Feature_X = 'P06'  # Main feature
Feature_Y = 'P07'  # Interaction feature
class_idx = 4

shap.dependence_plot(
    Feature_X, 
    shap_values_numpy[..., class_idx], 
    X_train, 
    interaction_index=Feature_Y, 
    dot_size=100, 
    show=False
)

# Customize Axes
ax = plt.gca()
ax.tick_params(axis='both', which='major', labelsize=36, width=2)
ax.set_ylabel(f'SHAP value ({Feature_X})', fontsize=36)
ax.spines['bottom'].set_linewidth(3)
ax.spines['left'].set_linewidth(3)
plt.show()


##################################################################
#                                                                #
#            (e) Advanced Composite Plot (Beeswarm + Bar)        #
#      Combines Beeswarm (Bottom Axis) & Importance (Top Axis)   #
#                                                                #
##################################################################

class_idx = 5
fig, ax1 = plt.subplots(figsize=(10, 8))

# 1. Main Beeswarm Plot (on ax1)
shap.summary_plot(
    shap_values_numpy[..., class_idx], 
    X_train, 
    feature_names=X_train.columns, 
    plot_type="dot", 
    show=False, 
    color_bar=True, 
    cmap='Greys' # or 'plasma'
)

# Customize Color Bar
cbar = plt.gcf().axes[-1] 
cbar.set_ylabel('Parameter Value', fontsize=24)
cbar.tick_params(labelsize=20)

# Adjust layout to make room for the top axis
plt.gca().set_position([0.2, 0.2, 0.65, 0.65]) 

# 2. Feature Importance Bar Plot (on Top Axis ax2)
# Create a twin axis sharing the y-axis
ax2 = ax1.twiny() 

shap.summary_plot(
    shap_values_numpy[..., class_idx], 
    X_train, 
    plot_type="bar", 
    show=False
)

# Align position with the main plot
plt.gca().set_position([0.2, 0.2, 0.65, 0.65]) 

# Style the bars (Transparent & Light Color)
bars = ax2.patches
for bar in bars:
    bar.set_color('#CCE5FB') # Light blue background bars
    bar.set_alpha(0.4)       # Transparency

# Customize Axes Labels
ax1.set_xlabel(f'Shapley Value Contribution (F{class_idx})', fontsize=24, labelpad=5)
ax1.set_ylabel('Parameters', fontsize=24)
ax2.set_xlabel('Mean Shapley Value (Parameter Importance)', fontsize=24, labelpad=10)

# Move ax2 (Bar plot axis) to the top
ax2.xaxis.set_label_position('top') 
ax2.xaxis.tick_top()

# Ensure ax1 (dots) is drawn ON TOP OF ax2 (bars)
ax1.set_zorder(ax1.get_zorder() + 1) 
ax1.patch.set_visible(False) # Make ax1 background transparent

plt.show()

연구 하이라이트

우리는 본 연구가 이 분야에 다음과 같은 주요 기여를 했다고 생각합니다.

  • 선박용 디젤 엔진 연소실 부품의 5가지 대표 고장에 대한 파라미터화 모델을 수립했습니다.
  • 다양한 특징 선택 방법과의 비교를 통해 SHAP 방법의 유효성을 검증했습니다.
  • 데이터 기반 방법과 열역학 메커니즘 모델을 융합하여 설명 가능한 고장 진단에 새로운 시각을 제공했습니다.

인용

이 연구가 귀하의 연구에 도움이 된다면, 다음 논문을 읽어보시길 권합니다 😊

BibTeX

@article{luo2025thermodynamic,
  title     = {Thermodynamic simulation-assisted random forest: Towards explainable fault diagnosis of combustion chamber components of marine diesel engines},
  author    = {Luo, Congcong and Zhao, Minghang and Fu, Xuyun and Zhong, Shisheng and Fu, Song and Zhang, Kai and Yu, Xiaoxia},
  journal   = {Measurement},
  volume    = {251},
  pages     = {117252},
  year      = {2025},
  publisher = {Elsevier},
  doi       = {10.1016/j.measurement.2025.117252},
}

표준 형식

C. Luo, M. Zhao, X. Fu, S. Zhong, S. Fu, K. Zhang, X. Yu. Thermodynamic simulation-assisted random forest: Towards explainable fault diagnosis of combustion chamber components of marine diesel engines[J]. Measurement, 2025, 251: 117252.