카테고리 없음

심화프로젝트 3일차 - 데이터 전처리 및 가설검증2

iron-min 2025. 11. 10. 21:48

1. 기초 EDA / 전처리 및 통계적 분석

 

2일차에 진행했던 가설 및 검정들을 정리하였습니다.

 

  • 형태결함(Pastry, Bumps) :
    • 면적 변수 : 크기는 비슷했나 산포도가 작아 특정 면적에 치중되는 것을 알 수 있다. 유의성 검정으로는 판별할 수 없으나 산포도 측면에서 주요변수로 판정 ( 왜 산포가 집중 되는지는 추가적인 정보 필요)
    • 이송 거리 변수 : 이송 거리가 많을 수록 평균적으로 형태결함이 발생한다는 것을 알 수 있음.
    • 철판 두께 : 유의성 검정 결과 유의하다고 나왔지만 바이올린 플롯을 보면 데이터의 분포나 형태로 보았을 때, 두께는 근소하게 영향을 미침을 알 수 있음
    • 방향도 : 결함의 방향성은 Pastry 양의 방향일 때, 영향을 미칠 수 있으나, Bumps는 영향을 안미침
  • 표면결함(스크래치, Stains, Dirtiness):
    • 면적 변수:
      • Dirtiness를 제외하고 대부분 유의성을 띔
      • K_Scratch를 제외하고 평균적으로 비슷하거나 좁은 면적에서 결함 발생
      • K_Scratch를 제외하고 산포도가 낮음
      • ➡️ 대부분 정상에 비해 비교적 좁은 면적에 결함이 발생하며, 산포도가 낮다. 그렇기에
    • 이송 거리 :
      • Dirtiness를 제외하고 산포도가 낮음
      • 대체적으로 정상에 비해 평균과 비슷
      • ➡️ 산포도가 낮은 것으로 미루어보아 특정 공정 단계에서 결함이 많이 발생
    • 철판 두께 :
      • Dirtiness를 제외하고 산포도가 낮음
      • Dirtiness는 평균 두께가 높고 나머지는 다 비슷함, Dirtiness는 두께가 클수록 결함 발생
      • ➡️ 대체적으로 산포도가 낮은 것으로 미루어보아 특정 두께에 결함이 치중되 있다는 것을 알 수 있음
    • 방향도 :
      • Z_Scratch와 Dirtiness는 양의 방향성을 가지고 K_Scratch와 Stains에서는 음의 방향성을 가짐
      • 방향도에 따른 주요 변수 분류
        • 양의 방향성 가짐 : Pastry, Z_scratch, Dirtiness
        • 음의 방향성 가짐 : Bumps, K_scratch, Stains
        • ➡️ 방향성 문제는 공정상의 문제라기보다 결정방향의 특징이라 orientation Index를 조작하여 한 결함(양의 방향성)을 줄이면, 다른 결함(음의 방향성)이 증가할 가능성이 매우 높다. 일명 Treadeoff라는 문제가 발생한다. 그래서 이 문제를 해결하기 위해서는 두 결함의 비용을 최소화하는 최적점을 찾는 것이 필요

 

 

2. 이산형 변수에 대한 카이제곱 검정

0과 1로 나누어지는 이산형 변수인 강종타입에 대해 카이제곱검정을 진행했습니다.

 

import pandas as pd
import scipy.stats as stats

fault_columns = ['Pastry','Z_Scratch', 'K_Scratch', 'Stains', 'Dirtiness', 'Bumps', 'Other_Faults']

#TypeOfSteel_A300과의 카이제곱 검정 반복 수행
results = {}

for fault in fault_columns:
    # 3-1. 각 결함 유형과 TypeOfSteel_A300 간의 분할표 생성
    contingency_table = pd.crosstab(df[fault], df['TypeOfSteel_A300'])

    # 3-2. 카이제곱 검정 실행 (correction=False는 Yates 보정을 사용하지 않음을 의미)
    # chi2_contingency는 (통계량, p-value)를 반환
    chi2, p_value, dof, expected = stats.chi2_contingency(contingency_table, correction=False)

    # 3-3. 결과를 딕셔너리에 저장
    results[fault] = {
        'Chi2_Statistic': chi2,
        'P_Value': p_value
    }

# 4. 결과 출력 및 정리
print("--- TypeOfSteel_A300 강철 타입별 결함 유형 연관성 검정 결과 ---")
print("비교 변수: TypeOfSteel_A300")
print("-" * 50)

for fault, res in results.items():
    print(f"결함: {fault}")
    print(f"  카이제곱 통계량: {res['Chi2_Statistic']:.4f}")
    print(f"  p-value: {res['P_Value']:.5f}")

    # p-value를 이용한 유의성 판단 (유의수준 0.05 기준)
    if res['P_Value'] < 0.05:
        print("  **결론: 강종타입과 통계적으로 유의한 연관성이 있음 (종속)** ✅")
    else:
        print("  **결론: 강종타입과 통계적으로 유의한 연관성이 없음 (독립)** ❌")
    print("-" * 50)

 

 

 

--- TypeOfSteel_A300 강철 타입별 결함 유형 연관성 검정 결과 ---
비교 변수: TypeOfSteel_A300
--------------------------------------------------
결함: Pastry
  카이제곱 통계량: 5.8531
  p-value: 0.01555
  **결론: 강종타입과 통계적으로 유의한 연관성이 있음 (종속)** ✅
--------------------------------------------------
결함: Z_Scratch
  카이제곱 통계량: 223.4955
  p-value: 0.00000
  **결론: 강종타입과 통계적으로 유의한 연관성이 있음 (종속)** ✅
--------------------------------------------------
결함: K_Scratch
  카이제곱 통계량: 321.9566
  p-value: 0.00000
  **결론: 강종타입과 통계적으로 유의한 연관성이 있음 (종속)** ✅
--------------------------------------------------
결함: Stains
  카이제곱 통계량: 46.5526
  p-value: 0.00000
  **결론: 강종타입과 통계적으로 유의한 연관성이 있음 (종속)** ✅
--------------------------------------------------
결함: Dirtiness
  카이제곱 통계량: 13.2285
  p-value: 0.00028
  **결론: 강종타입과 통계적으로 유의한 연관성이 있음 (종속)** ✅
--------------------------------------------------
결함: Bumps
  카이제곱 통계량: 181.9420
  p-value: 0.00000
  **결론: 강종타입과 통계적으로 유의한 연관성이 있음 (종속)** ✅
--------------------------------------------------
결함: Other_Faults
  카이제곱 통계량: 0.1192
  p-value: 0.72989
  **결론: 강종타입과 통계적으로 유의한 연관성이 없음 (독립)** ❌
--------------------------------------------------

 

 

3. 다중공선성 확인

 

선형회귀를 만들기 전에 다중공선성을 확인했습니다.

import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor
import statsmodels.api as sm

# 1. 제거할 종속변수
fault_columns_to_remove = ['Pastry', 'Z_Scratch', 'K_Scratch', 'Stains', 'Dirtiness', 'Bumps', 'Other_Faults','X_Minimum','X_Maximum','Y_Maximum','Y_Minimum','Log_X_Index','Log_Y_Index','Sum_of_Luminosity','TypeOfSteel_A300','TypeOfSteel_A400','LogOfAreas']

# 2. 독립변수만 선택
X = df.drop(columns=fault_columns_to_remove)

# 3. VIF 계산을 위해 상수항(Intercept) 추가
X_with_const = sm.add_constant(X)

def calculate_vif(X):
    vif_data = pd.DataFrame()
    vif_data["Variable"] = X.columns
    vif_data["VIF"] = [variance_inflation_factor(X.values, i)
                       for i in range(X.shape[1])]
    return vif_data.sort_values('VIF', ascending=False)

# VIF 계산 실행
vif_result_cleaned = calculate_vif(X_with_const)
print(vif_result_cleaned)

 

 

                 Variable         VIF
0                   const  729.075273
2             X_Perimeter   41.196053
3             Y_Perimeter   25.473857
1            Pixels_Areas   18.417797
14      Orientation_Index   14.214397
15       Luminosity_Index    9.950001
12          Edges_Y_Index    7.424633
17  Minimum_of_Luminosity    6.881343
10        Outside_X_Index    5.896991
4   Maximum_of_Luminosity    5.506218
11          Edges_X_Index    4.986966
13   Outside_Global_Index    4.624415
16         SigmoidOfAreas    3.344112
8             Empty_Index    2.071037
9            Square_Index    1.794472
7             Edges_Index    1.306507
18               X_Center    1.294079
5      Length_of_Conveyer    1.269765
6   Steel_Plate_Thickness    1.254149
19               Y_Center    1.082909

 

 

다중공선성이 높아서

'X_Perimeter','Y_Perimeter','Pixels_Areas' 변수에 대해 PCA를 진행했습니다. 이유는 전부 위치 방향 벡터이기 때문입니다.
 
 
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

PCA_df = df[['X_Perimeter','Y_Perimeter','Pixels_Areas']]

scaler = StandardScaler()
X_scaled_PCA = scaler.fit_transform(PCA_df)

pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled_PCA)

print("주성분 변환 결과:\n", X_pca)
print("기여율:\n", pca.explained_variance_ratio_)

 

시각화를 해보니 잘 적용된것을 볼 수 있습니다.

 

# Outside_Global_Index 제거

import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor
import statsmodels.api as sm

# 1. 제거할 종속변수
fault_columns_to_remove = ['Pastry', 'Z_Scratch', 'K_Scratch', 'Stains', 'Dirtiness', 'Bumps', 'Other_Faults','X_Minimum','X_Maximum','Y_Maximum','Y_Minimum','Log_X_Index','Log_Y_Index','Sum_of_Luminosity','TypeOfSteel_A300','TypeOfSteel_A400','LogOfAreas','X_Perimeter', 'Y_Perimeter', 'Pixels_Areas','Outside_Global_Index']

# 2. 독립변수만 선택
X = df.drop(columns=fault_columns_to_remove)


X_final = pd.concat([X.reset_index(drop=True),pd.DataFrame(X_pca, columns=['PC1', 'PC2'])], axis=1)


# 3. VIF 계산을 위해 상수항(Intercept) 추가
X_with_const = sm.add_constant(X_final)

def calculate_vif(X):
    vif_data = pd.DataFrame()
    vif_data["Variable"] = X.columns
    vif_data["VIF"] = [variance_inflation_factor(X.values, i)
                       for i in range(X.shape[1])]
    return vif_data.sort_values('VIF', ascending=False)

# VIF 계산 실행
vif_result_cleaned = calculate_vif(X_with_const)
print(vif_result_cleaned)

추가로 Outside_Global_Index 와 Orientation_index 또한 다중공선성이 높게 나왔고 데이터를 살펴보니  Outside_Global_Index 는 Orientation_index의 음양 방향만 나타내주었기에 제거하도록 했습니다.

 

그리고 결과를 보면

 

                 Variable         VIF
0                   const  697.835280
11       Luminosity_Index    9.853895
16                    PC1    7.594801
10      Orientation_Index    6.847634
13  Minimum_of_Luminosity    6.735392
9           Edges_Y_Index    6.550003
1   Maximum_of_Luminosity    5.478486
8           Edges_X_Index    4.624516
7         Outside_X_Index    4.402057
12         SigmoidOfAreas    3.226400
5             Empty_Index    2.068983
17                    PC2    1.985720
6            Square_Index    1.523274
4             Edges_Index    1.306253
14               X_Center    1.292959
2      Length_of_Conveyer    1.264637
3   Steel_Plate_Thickness    1.253889
15               Y_Center    1.080967

 

다중공선성이 깔끔하게 제거된 것을 볼 수 있습니다.

 

여기까지가 제가 한 역할이고 팀원분들이 한것을 확인하도록 하겠습니다.

 

 

1. 머신러닝 돌려서 적합한 모델 확인하기

 

XGBoost 결과

feature importance: 모델이 결과를 예측할 때 각 입력 변수가 얼마나 중요한 역할을 했는가?

1.Pastry 결함: 부풀어오른 요철, 비정상적인 덩어리

  • 주요 변수
    • Outside_Global_Index, Orientation_Index, Edge_Y_Index
  • 철판 가장자리의 불균일함과 패턴의 방향성이 Pastry 결함 발생에 관련 있음

2.Z_Scratch: 지그재그형 스크래치, 불연속적인 스크래치

  • 주요 변수
    • TypeofSteel_A300, Typeofsteel_A400, Length_of_Conveyer
  • 강종과 컨베이어 길이가 주요한 요인으로, 철판의 종류와 이송 조건의 차이가 Z 스크래치 결함에 영향을 미침

3.K_Scratch: 일자형 스크래치, 패턴을 가진 스크래치

  • 주요 변수
    • Steel_Plate_Thickness, Log_Y_Index, Outside_X_Index
  • 두꺼운 철판일수록 K스크래치 발생 가능성이 높고, X 방향으로의 불균일성이 주요 원인

4.Stains: 변색, 오염으로 보이는 얼룩

  • 주요 변수
    • Pixels_Areas, LogOfAreas, SigmoidofAreas
  • 얼룩은 결함 영역의 크기와 연관된 시각적 요인이 핵심

5.Dirtness: 먼지, 이물, 기름막 등

  • 주요 변수
    • Square_Index, Orientation_Index, Typeofsteel_A400
  • 형상적 불균일함과 재질 차이(강종)에 따라 dirtness 결함이 발생할 수 있음

6.Bumps: 표면이 불룩하게 튀어나온 미세 돌기나융기로 인한 결함

  • 주요 변수
    • X_Perimeter, Pixels_Areas, Square_Index
  • 돌출 결함은 물리적인 형상의 특성(길이나 면적)과 밀접한 연관이 있음

 

 

 

 

느낀점

 

이렇게 조원들과 역할을 분담하여 스스로 할일을 하니 프로젝트가 잘되어가고 있는 느낌입니다.

현업에서도 이렇게 잘맞는 팀원들과 협업하여 의미있는 성과를 내었으면 좋겠습니다.