ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 3. 탐색한 데이터로 모델 성능 개선
    교육/코칭스터디<Data Science Projects 2024> 2024. 1. 27. 21:28
    728x90

    3.1 탐색한 데이터를 바탕으로 모델의 성능 개선하기

    3.1.1 연속 수치 데이터를 범주형 변수로 변경하기

    수치의 범위가 넓으면 수치형 변수의 조건이 너무 세분화되어 tree가 깊어짐

    샘플의 수가 적으면 오버피팅(과적합)이 발생할 가능성 증가

    =>수치형 데이터를 범주화하여 성능 개선

    임신 횟수가 7회가 넘어가면 발병수가 높음, 이를 범주화
    df["Pregnancies_high"]=df["pregnancies"]=6
    
    #Pregnancies와 Outcome을 뺀 다른 feature들을 리스트 형태로 만듦
    feature_names=train.columns.tolist()
    feature_names.remove("Pregnancies")
    feature_names.remove("Outcome")
    
    #Outcome을 분류하고 싶은 답안으로 지정
    label_name='Outcome'
    
    #학습 데이터셋 생성
    X_train=train[feature_names]
    
    #이전과는 다르게 Pregnancies가 중요한 역할을 하지 않음
    sns.barplot(x=model.feature_importances-, y=feature_names)
    
    #전체적으로 틀린개수가 39개 줄어들어 점수가 74점으로 높아짐
    diff_count=abs(y_test-y_predict).sum
    (len(y_test)-diff_count)/len(y_test)*100

    3.1.2 범주형 변수를 수치형 변수로 변환하기 - 원핫인코딩

    #나이를 25세 미만, 25~60세 미만, 60세 이상으로 3개의 카테고리를 만듦
    df["Age_low"]=df["Age"]<25
    df["Age_middle"]=(df["Age"]>=25)&(df["Age"]<=60)
    df["Age_high"]=df["Age"]>60
    
    #나이를 30세 미만, 30~60세 미만, 60세 이상으로 3개의 카테고리를 만듦
    df["Age_low"]=df["Age"]<30
    df["Age_middle"]=(df["Age"]>=30)&(df["Age"]<=60)
    df["Age_high"]=df["Age"]>60

    모델 성능이 오히려 더 나빠졌음

    좋은 기법을 쓴다고 해서 더 나은 성능이 항상 나오는 것은 아님

    다양한 방법을 시도해봐야함

    3.1.3 결측치 평균값으로 대체하기

    #결측치 확인
    df.isnull().sum()
    
    #인슐린의 0값을 null로 채우는 Insulin_nan열을 만듦
    df["Insulin_nan"]=df["Insulin"].replace(0,np.nan)
    
    #인슐린 결측치 갯수 확인
    df["Insulin_nan"].isnull().sum()
    
    #인슐린 결측치 양 확인
    df["Insulin_nan"].isnull().mean()
    
    #Insulin과 Insulin_nan의 차이가 많이 남
    #결측치가 너무 많으면 학습할 때 안 좋음
    df.groupby(["Outcome"])["Insulin","Insulin_nan"].agg(["mean","median"])
    
    #null값인 데이터 중에서 Outcome에 따라 평균값을 채워줌
    df.loc[(df["Outcome"]==0)&(df["Insulin_nan"].isnull()),"Insulin_nan"]=68.7
    df.loc[(df["Outcome"]==1)&(df["Insulin_nan"].isnull()),"Insulin_nan"]=100.3
    
    #피처 중요도 시각화
    sns.barplot(x=model.feature_importances_,y=feature_names)
    
    #23개가 틀려서 성능이 85%로 높아짐
    diff_count=abs(y_test-y_predict).sum()
    (len(y_test)-diff_count)/len(y_test)*100

    3.1.4 결측치 중앙값으로 대체하기

    #결측치를 중앙값으로 채움
    df.loc[(df["Outcome"]==0)&(df["Insulin_nan"].isnull()),"Insulin_nan"]=102.5
    df.loc[(df["Outcome"]==1)&(df["Insulin_nan"].isnull()),"Insulin_nan"]=169.5
    
    #오차가 16으로 89%의 성능이 나옴
    diff_count=abs(y_test-y_predict).sum()
    (len(y_test)-diff_count)/len(y_test)*100

    3.1.5 수치형 변수를 정규분포 형태로 만들기

    한쪽에 데이터가 몰려있으면 학습에 어려움이 발생

    첨도, 왜도가 둘 다 높은 것을 알 수 있음

    #log변환=>정규분포와 비슷해짐
    sns.distplot(np.log(df.loc[df["Insulin"]>0,"Insulin"]+1))

    sns.distplot(df["Insulin_nan"])

    중앙값으로 채워줬기 때문에 뾰족하게 첨도가 높은 것을 볼 수 있음

    우린 이걸 두들겨서 낮춰줘야함

    df["Insulin_log"] = np.log(df["Insulin_nan"] + 1)
    sns.distplot(df["Insulin_log"])

    첨도가 낮아짐, 로그변환을 하면 성능이 좋게 나오기도 하지만 이 데이터는 변화 없음

    3.1.6 상관 분석을 통해 파생변수 만들기

     

    댓글

Designed by Tistory.