image-right





AI 부트캠프 8주차 : Section 2 Project

부트캠프를 시작한지 벌써 두 달 가까이 지나갔다.
그리고 시작한 두 번째 프로젝트.
두 번째 프로젝트는 자유주제였다.
주제선정, 데이터 선정 부터 분석, 발표까지 ‘알아서’ 해야 한다.





주간회고

더 공부가 필요한 부분

  • 머신러닝을 프로젝트에 적용할 때 프로젝트에 알맞은 데이터, 모델, 해석, 시각화가 다른 것 같다.
    다양한 프로젝트를 경험하고 싶다.

5F 회고

  • 사실(Fact)
    머신러닝 프로젝트의 기획부터 발표까지의 과정을 얕게나마 경험하였다. 제출된 모든 동료들의 발표영상을 시청하였다.

  • 느낌(Feeling)
    정말 다양한 머신러닝의 주제가 있고, 창의적이고 새로운 전처리, 모델링, 분석 방법이 있음이 놀라웠다.

  • 교훈(Finding)
    나는 학습하며 배운 것만 반복 연습했는데, 그래서 창의력이 떨어지는 결과물이 나온것 같다.

  • 향후 행동(Future action)
    창의력은 성장의 원동력이 되기 때문에 조금 더 새로움을 시도해 보자.

  • 피드백(Feedback)
    발표 PPT의 가독성을 높이면 좋겠다는 피드백을 받았다.
    중요특성 갯수를 왜 4개로 선정했는지에 대한 질문을 받았다.





완성영상 보기





프로젝트 계획 및 과정

1. 프로젝트 계획

날짜 내용
1/31 (화)~2/2 (목) • 프로젝트 준비✅
• 주제 선정
• 데이터 탐색
2/3 (금) • 프로젝트 START🚀
• 관련 아티클 검색
2/4 (토) • 데이터 전처리
2/5 (일) • Feature Engineering
• 탐색적 데이터분석
2/6 (월) • 모델링
• 하이퍼파라미터 튜닝
• 머신러닝 모델해석
2/7 (화) • PPT 슬라이드 작성
• 스크립트 작성
2/8 (수) • 영상촬영
• 최종 제출🚩





2. 주제선정

  • 상황 가정
    • 인공지능 데이터를 기반으로 건축을 하는 ‘AI건설’은 직원이 3,000명 정도 되는 대기업이다.
    • 회사의 직원들은 ‘현장 건설 직원’, ‘건축 자제 대형마트 직원’, ‘컴퓨터 데이터분석 직원’ 3분야의 직원들이 있다.
    • 3가지 산업분야의 직원들이 섞여있기 때문에 똑같은 포상제도에 불만을 가지고, 핵심인력이 회사에서 퇴사하는 문제가 생겼다.
    • 3가지 산업분야의 직원들에게 효과적인 포상제도를 마련하여 한정된 자원안에서 효과적으로 직원이탈을 줄이고자 한다.
    • 이를 위하여 머신러닝을 통하여 각 분야의 직원들에게 효과적인 포상제도는 무엇인지 분석하고 제안하고자 한다.





3. 주제관련 아티클 조사

  • 포상의 의미
    • 포상은 다양한 수요를 반영하고 칭찬과 격려, 모범사례의 확대라는 긍정적 의미를 지니지만, 포상이 남발되거나 대상자가 제대로 선정되지 않을 경우 포상의 권위와 신뢰성이 떨어지는 문제가 발생함
    • 포상은 '보상'과는 다르다.
    • ‘보상’은 행위에 대한 금전적 보상의 의미가 강하지만, 포상은 조직의 목표 달성을 위한 인센티브의 의미가 강하다.
    • 직원들에게 효과적으로 포상 주는 핵심방법 3가지 포인트
      • 포상을 할 때 중요한 3가지
        • 비 현금성 포상
        • 비균일성 포상
        • 비제도성 포상
      • 효과적인 포상이 되려면
        • 실용보다 더 큰 명예로움을 포상
        • 실물보다 더 큰 감사를 포상
        • 실무자의 업무가 아닌 경영자의 리더십으로 포상
    • 소속감 다지는 인센티브 여행, 가장 효과적인 직원 포상 방법





4. 데이터 선정

  • 한국노동패널 데이터 원자료
    • 한국노동패널조사(Korean Labor and Income Panel Study: KLIPS)는 우리나라에서 가장 오래된 패널조사 가운데 하나
    • 도시지역에 거주하는 가구와 가구원을 대표하는 패널표본 구성원을 대상으로 1년에 1회씩 조사를 실시하여 1998년 1차 조사를 시작으로 2021년 24차 조사까지 완료된 신뢰성있는 데이터이기 때문에 본 연구에 적합함
    • 각 산업분야 근로자들의 근로관련 특성과 직무만족도, 생활만족도와 같은 본 연구를 위한 특성이 존재하여 본 연구에 적합함





5. 데이터 전처리

  • 데이터 준비
    • 데이터를 불러와 객체로 저장
# 노동패널 조사 차수 리스트
wave_list = [ 
    '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', \
    '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', \
    '21', '22', '23', '24'
    ]

# Read Data
for i, val in enumerate(wave_list):
  globals()[f'klips_{val}_raw'] = pd.read_stata(path_data + f'klips{val}p.dta')
  • 전체 column : 16,169 개
  • 전체 case : 348,029 개
  • ‘복리후생 관련 문항’이 4차년도부터 조사되었기 때문에 4차년도 이후만 사용
  • 특성 선택
    • 기본 특성, 가구 정보, 기업형태 및 규모관련 문항, 근로계약 관련 문항, 근로시간 관련 문항, 임금 및 소득 관련 문항, 노조관련 문항, 복리후생 관련 문항, 요인별 직무만족도, 기술 적합도 및 향후 일자리 전망, 직업훈련 관련 문항, 자격증 관련 문항, 혼인관련 문항, 만족도 관련 문항
  • 케이스 선택
    • 8차 한국표준산업분류
    • 컴퓨터 직군 : 정보처리 및 기타 컴퓨터 운영 관련업
      • 721, 722, 723, 724, 729
    • 판매업 직군 : 소매업
      • 521, 522, 523, 524, 525, 526
    • 건설업 직군 : 종합 건설업
      • 451, 452
  • 특성공학
    • 타겟 : 생활만족
    • 교육수준 : 초등학교 이하, 중학교, 고등학교, 전문대, 대학교, 석박사
    • 거주지역 : 수도권(서울,인천,경기도), 비수도권
    • 소득 : 평균 월 급여액
    • 재직기간 : 취업일부터 현재까지의 경과 날짜
  • object 데이터타입을 category 데이터타입으로 변경
    • category 데이터타입으로 순서 지정
    • 메모리 사용량 감소
변환 전 메모리 사용량 :  6,392,838
변환 후 메모리 사용량 :  1,775,009





6. 탐색적 데이터분석

  • 탐색적 데이터분석
    • 타겟 : ‘만족한다’라고 응답한 비율 37%
      • 약하게 타겟이 불균형 함

    image-right

    • 숫자형 변수
      • 데이터 분포
        • 편향된 분포가 보이지만 분류문제에서는 데이터의 분포가 성능에 크게 영향을 미치지

      image-right

      • 타겟에 따른 데이터 분포1
        • 이상치가 일부 보이지만 우려할 수준은 아님

      image-right

      • 타겟에 따른 데이터 분포2
        • 나이, 소득 등에서 타겟의 분포가 다르게 나타남
        • 타겟의 분포가 다른 특성이 주요한 특성으로 예상 됨

      image-right

      • 직업군에 따른 데이터 분포
        • 직업군에 따른 데이터분포가 서로 다르게 나타남

      image-right

      • 타겟과 직업군에 따른 데이터 분포
        • 직업군에 따른 타겟의 데이터분포가 서로 다르게 나타남
        • 가설 ‘직업군에 따라 만족스런 포상이 다를 것’을 예측할 수 있음
      col_num = 3 # 세로 열 갯수 지정
      row_num = (len(numeric_features) // col_num) + 1
      
      fig = plt.figure(figsize=(col_num*6, row_num*4))
      # fig.suptitle('Numeric Features by Job', fontsize = 24, fontweight = 'bold', y = 0.9)
      
      for i, feature in enumerate(numeric_features) :
          ax = plt.subplot(row_num, col_num, i+1)
          sns.violinplot(data=df, x=df['work_industry'], y=feature, hue=target, split=True, palette = sns.color_palette('pastel'))
          i += 1
      
      plt.subplots_adjust(right=0.85, left=0.15, top=0.85, bottom=0.15, wspace=0.3, hspace=0.2) # 그래프 간격 조절
      plt.show()
      

      image-right

    • 문자형 변수
      • 막대그래프
        • 교육수준에 따른 타겟의 분포가 다르게 나타남

      image-right

      • 바이올린 그래프
        • 성별도 타겟의 분포가 다르게 나타날 수 있음

      image-right

      • 요인별 직무만족도 그래프
        • 요인별 직무만족은 타겟을 예측하는 주요한 특성임

      image-right

    • 상관관계
      • 특성사이에 강한 상관관계가 있는 부분이 있음
      • 복지유무 특성들, 직업교육과 직업스킬
      • 특성 사이의 강한 상관관계는 잘못된 예측을 할 수 있기 때문에 처리

    image-right





7. 모델링

  • 데이터 분할 2way hold out
    • train 8, test 2
  • 기준모델 : 최빈값
    • 정확도 : 0.633, ROC-AUC : 0.5
  • 모델 선정
    • Logistic Regression
      • 분류모델의 가장 전통적인 방법
      • 선형회귀에 시그모이드 함수 적용
    • Decision Tree
      • 나무기반 모델들의 기본
      • 타겟 데이터의 불순도를 최소화
    • Random Forest
      • 앙상블 베깅기법의 대표
      • 복원 추출된 샘플로 여러 모델을 병렬적으로 학습하여 합치는 과정
    • AdaBoost
      • 앙상블 부스팅 기법
      • 순차적으로 학습
      • 잘못 분류된 관측치에 가중치를 부여하여 잘 분류 되도록 보완
    • XGBoost
      • 앙상블 부스팅 기법
      • 순차적 학습
      • 잔차를 학습하여 잔차가 큰 관측치를 더 학습하여 보완
  • 기본값 모델
# Default Model Pipes

# https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html
lr_pipe = make_pipeline(
                        OrdinalEncoder(),
                        StandardScaler(),
                        LogisticRegression(random_state = rand_seed
                                           , class_weight   = 'balanced'
                                           ),
                        )

# https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier
dt_pipe = make_pipeline(
                        OrdinalEncoder(),
                        DecisionTreeClassifier(random_state = rand_seed
                                               , class_weight   = 'balanced'
                                               ),
                        )

# https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html#sklearn.ensemble.RandomForestClassifier
rf_pipe = make_pipeline(
                        OrdinalEncoder(),
                        RandomForestClassifier(random_state = rand_seed
                                               , class_weight   = 'balanced'
                                               ),
                        )

# https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.AdaBoostClassifier.html#sklearn.ensemble.AdaBoostClassifier
ad_pipe = make_pipeline(
                        OrdinalEncoder(),
                        StandardScaler(),
                        AdaBoostClassifier(random_state = rand_seed
                                           ),
                        )

# https://xgboost.readthedocs.io/en/latest/parameter.html
xg_pipe = make_pipeline(
                        OrdinalEncoder(),
                        XGBClassifier(random_state = rand_seed
                                      , scale_pos_weight    = all_y_train.value_counts()[0] / all_y_train.value_counts()[1]
                                      ),
                        )

model_list        = ['Logistic Regression', 'Decision Tree', 'Random Forest', 'Ada Boost', 'XGB']
score_list        = ['Accuracy', 'F1', 'AUC']
model_initial     = ['lr', 'dt', 'rf', 'ad', 'xg']

# 모델 학습
for i, model in enumerate(model_initial) :
    print(f'✅ {model_list[i]}')
    globals()[f'{model}_pipe'].fit(all_X_train, all_y_train)
    globals()[f'{model}_pipe_score_def'] = print_score(globals()[f'{model}_pipe'], all_X_train, all_y_train)
  • 불균형한 타겟을 처리하기 위한 파라미터 추가
    • Logistic Regression : L2 패널티 정규화 기본값
    • AdaBoost : Decision Tree max_depth=1 기본값
    • XGBoost : max_depth=6 기본값

image-right

  • 하이퍼파라미터 튜닝1
    • 러닝커브
      • Logistic Regression
        • C : 기본설정된 L2패널티의 정규화 강도, 작을수록 강한 정규화
        • 기본값 1 유지

      image-right

      • max_depth
        • 결정나무의 최대 깊이, 클수록 과적합이 우려
        • Decision Tree : 약4에서 최적화, 7이 넘어가면 과적합 우려

        image-right

        • Random Forest : 약5에서 최적화, 8이 넘어가면 과적합 우려

        image-right

        • AdaBoost : 1에서 최적화, 기본값 유지

        image-right

        • XGBoost : 약3에서 최적화, 5 넘어가면 과적합 우려

        image-right

    • RandomizedSearchCV
      • GridSearchCV는 지정한 파라미터의 모든 조합을 검색
        • 찾고자 하는 파라미터의 범위가 넓을 경우 시간이 오래걸림
      • 처음 분석하는 데이터이기 때문에 폭넓은 범위를 효율적으로 찾을 수 있는 RandomizedSearchCV 선택
      • Decision Tree : max_depth: 5
      • Random Forest : max_depth: 8
      • XGBoost : max_depth: 5
    • Random Forest, XGBoost는 과적합 여지가 있음

    image-right

  • 하이퍼파라미터 튜닝2
    • 러닝커브
      • Random Forest
        • min_samples_leaf : 리프노드에 필요한 최소 샘플 수, 클수록 모델 단순화

      image-right

      • XGBoost
        • min_child_weight : 하위 항목(child)에 필요한 최소한의 객체 가중치(weight), 클수록 모델 단순화

      image-right

    • RandomizedSearchCV
      • Random Forest
        • min_samples_leaf: 1
        • max_depth: 7
      • XGBoost
        • min_child_weight: 64
        • max_depth: 6

    image-right

  • 최종모델
    • Accuracy, F1, ROC-AUC 에서 고르게 높은 점수를 기록한 Random Forest, XGBoost을 최종 모델로 선택
    • 평가데이터셋에 최종모델 학습
    • 기준모델보다 성능이 뛰어난 최종모델

    image-right





8. 모델 해석

  • 모델 해석
    • 3가지 직업군 타겟 확인

    image-right

    • 3가지 직업군에 따라 모델 학습
    # rf_max_depth            7
    # rf_min_samples_leaf     1
    # xg_max_depth            6
    # xg_min_child_weight    64
    def rf_pipe_fit(X_train, y_train):
        """ Random Forest Classifier 파이프를 만들고 모델에 학습하는 함수 """
        rf_pipe = make_pipeline(
                        OrdinalEncoder(),
                        RandomForestClassifier(random_state       = rand_seed
                                              , class_weight      = 'balanced'
                                              , max_depth         = int(best_params_read.loc['rf_max_depth'][0])
                                              , min_samples_leaf  = int(best_params_read.loc['rf_min_samples_leaf'][0])
                                              ),
                        )
        return rf_pipe.fit(X_train, y_train)
    
    def xg_pipe_fit(X_train, y_train):
        """ XGBClassifier 파이프를 만들고 모델에 학습하는 함수 """
        xg_pipe = make_pipeline(
                        OrdinalEncoder(),
                        XGBClassifier(random_state          = rand_seed
                                      , scale_pos_weight    = y_train.value_counts()[0] / y_train.value_counts()[1]
                                      , max_depth           = int(best_params_read.loc['xg_max_depth'][0])
                                      , min_child_weight    = int(best_params_read.loc['xg_min_child_weight'][0])
                                      ),
                        )
        return xg_pipe.fit(X_train, y_train)
    
    • 모든 직군에서 ‘월평균소득’과 ‘혼인상태’는 공통으로 중요한 특성
    # 컴퓨터 직업군 소득, 혼인상태
    com_pdp = PartialDependenceDisplay.from_estimator(com_rf_step_model, com_rf_X_test_enc, ["income", "marriage"], ax=ax, line_kw={"color": "blue"})
    # 판매업 직업군 소득, 혼인상태
    ret_pdp = PartialDependenceDisplay.from_estimator(ret_rf_step_model, ret_rf_X_test_enc, ["income", "marriage"], ax=ax, line_kw={"color": "red"})
    # 건설업 직업군 소득, 혼인상태
    bld_pdp = PartialDependenceDisplay.from_estimator(bld_rf_step_model, bld_rf_X_test_enc, ["income", "marriage"], ax=ax, line_kw={"color": "orange"})
    
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
    com_pdp.plot(ax=[ax1, ax2], line_kw={"label": "com_pdp", "color": "blue"})
    ret_pdp.plot(ax=[ax1, ax2], line_kw={"label": "ret_pdp", "color": "red"})
    bld_pdp.plot(ax=[ax1, ax2], line_kw={"label": "bld_pdp", "color": "orange"})
    
    ax1.set_ylim(0.35,0.65)
    ax2.set_ylim(0.3,0.6)
    
    ax1.legend(['Computing Data', 'Retail', 'Building'])
    ax2.legend(['Computing Data', 'Retail', 'Building'])
    

    image-right

    • 컴퓨터 직군 중요 특성
      • 요인별직무만족도-6.개인의발전가능성
      • 요인별직무만족도-8.인사고과의공정성

    image-right

    image-right

    • 판매업 직군 중요 특성
      • 요인별직무만족도-7.의사소통및인간관계
      • 요인별직무만족도-4.근무환경

    image-right

    image-right

    • 건설업 직군 중요 특성
      • 요인별직무만족도-3.하고있는일의내용
      • 요인별직무만족도-5.근로시간

    image-right

    image-right

    • 직군별 가장 중요한 특성
      • 컴퓨터 직군 : ‘직무만족도-6.개인의발전가능성’
      • 판매업 직군 : ‘직무만족도-7.의사소통및인간관계’
      • 건설업 직군 : ‘직무만족도-3.하고있는일의내용’

    image-right

    • 건설업 관력 직군의 ‘직무만족도-3.하고있는일의내용’ - ‘직무만족도-5.근로시간’

    image-right





9. 결론

  • 모든 직업군에서 공통으로 ‘소득’과 ‘혼인상태’는 ‘만족한다’라고 응답할 확률을 올리는 중요한 특성
    • 평균 소득이 낮은 ‘판매직’📌에게 ‘소득’을 올려주는 포상이 다른 직군보다 효과적으로 예상 됨
    • 싱글 비율이 가장 높은 ‘건설직’🎉에게 ‘혼인상태’를 개선해주는 포상이 다른 직군보다 효과적으로 예상 됨
  • 컴퓨터 직군
    • ‘개인의 발전가능성’, ‘인사고과의 공정성’이 중요한 특성
    • 공정한 성과급을 지급하고, 각종 연수나 교육 등이 효과적으로 예상 됨
  • 판매업 직군
    • ‘의사소통 및 인간관계’, ‘근무환경’이 중요한 특성
    • 직장 내 소통을 원활하게 할 수 있는 각종 단합대회, 근무환경을 개선시킬 수 있는 환경개선 사업 등이 효과적으로 예상 됨
  • 건설업 직군
    • ‘하고 있는 일의 내용’, ‘근로 시간’이 중요한 특성
    • 업무 순환제도를 이용하거나, 조기퇴근 등이 효과적으로 예상 됨
  • 한계점
    • 타겟인 '전반적 생활만족'과 포상제도의 연관성 부족
      • 선행연구 조사를 통하여 '포상제도'와 '만족도'의 관계 연구 필요
    • 모델 최적화가 부족
      • 데이터에 맞는 알맞는 하이퍼파라미터 튜닝 노력
      • 서포트벡터머신 등 새로운 알고리즘 적용 필요
    • 패널데이터의 통합분석
      • 시계열 특성을 통제해야 함





끝까지 읽어주셔서 감사합니다😉





댓글남기기