본문 바로가기
TIL

내배캠 TIL 34일차

by ColorConeHead 2024. 2. 5.
반응형

머신러닝 개인 과제

선택과제

1) balance 음수값 보정

2) np.log() 대신 np.log1p 사용 이유

 

3) 더 나은 인코딩

 

4) 결측치 처리


3, 4를 한꺼번에 코드에서 다뤘다.

(1) 결측치 처리.
## 결측치 확인
df = pd.read_csv('./bank_marketing.csv')

df.isnull().sum()

## job, eduaction, contact 까지는 대치할만한데
## poutcome은 버리는 게 좋을 거 같다

## 결측치 처리를 위한 모듈 불러오기
from sklearn.impute import SimpleImputer

## 대치는 최빈값으로
imputer = SimpleImputer(missing_values=np.nan, strategy='most_frequent')

## 결측치가 있는 컬럼을 명확하게 알기 때문에 df2 통으로 집어넣는다
df = pd.DataFrame(imputer.fit_transform(df), columns=df.columns, index=df.index)

## 결측치가 너무 많았던 poutcome은 일단 컬럼을 아예 없애본다
## 없앴다가 점수가 더 낮게 나와서 다시 추가

## 확인
df.isnull().sum()​


(2) 더 나은 인코딩.
     기존의 인코딩 함수를 두번째 블럭의 get_category_modified로 만들었다.
     label 리스트에 있는 것들은 LabelEncoder를 돌리려다가 순서가 의미 없는 범주임을 깨닫고
     철회했는데 리스트를 없애지 못했다.
## 인코딩 개선
## get_dummies() output 중에서 컬럼 하나 제거하기
## 다중 공선성을 일으키는 컬럼 색출하기
## result 값
## 범주형 컬럼,  상관계수 최대조합 리스트
## 상관계수 최대조합 리스트 = [카테고리1, 카테고리2, 상관계수(절댓값)]

## 결과를 보면
## marital, education, default, housing, loan
## 위 컬럼들에서 get_dummies를 할 때
## output에서 컬럼을 하나씩 제거할 수 있다
df = pd.read_csv('./bank_marketing.csv')
category_col = ['job','marital','education','default','housing','loan','contact','month', 'poutcome']
corrs = [['default', 'default', 0] for i in range(len(category_col))]


for i, col in enumerate(category_col):

    df_dum = pd.get_dummies(df[col])
    corr = df_dum.corr(method='pearson')
    
    for category in corr.columns:
        max_index = corr[category].abs().sort_values(ascending=False)[1:].index[0]
        max_corr_abs = corr[category].abs().sort_values(ascending=False)[1:][0].round(3)
        
        max_combis = [category, max_index, max_corr_abs]
        
        if max_combis[2] > corrs[i][2]:
            corrs[i] = max_combis
        else:
             continue
         

for i, list in enumerate(corrs):
    print(category_col[i], list)​
def get_category_modified(X_train:pd.DataFrame, X_test:pd.DataFrame):
    #범주형변수
    # 'job','marital','education','default','housing','loan','contact','month','poutcome'
    
    # 모델 불러오기
    from sklearn.preprocessing import LabelEncoder
    
    # modified
    modified = ['marital', 'education', 'default', 'housing', 'loan']
    label = ['job', 'month']
    #범주형 컬럼 더미화 하기
    X_train_dummies_total = pd.DataFrame()
    X_test_dummies_total = pd.DataFrame()
    
    for col in category_col:
        X_train_temp = X_train[col]
        X_test_temp = X_test[col]
        
        X_train_dummies = pd.get_dummies(X_train_temp)
        X_test_dummies = pd.get_dummies(X_test_temp)
        
        if col in modified:
            X_train_dummies = X_train_dummies.iloc[:, 1:]
            X_test_dummies = X_test_dummies.iloc[:, 1:]
            
            
        X_train_dummies_total = pd.concat([X_train_dummies_total, X_train_dummies], axis = 1)
        X_test_dummies_total = pd.concat([X_test_dummies_total, X_test_dummies], axis = 1)
    
    # 더미화한 변수를 기존 데이터셋에 합치기
    X_train = pd.concat([X_train, X_train_dummies_total], axis = 1)
    X_test = pd.concat([X_test, X_test_dummies_total], axis = 1)
    
    return X_train, X_test, X_train_dummies_total.columns.to_list()


 

 

5) 하이퍼 파라미터 최적화 하기.


최적화된 하이퍼 파라미터를 찾는 함수를 만들어
기존에 모델 성능을 채점하는 함수에서
함수를 통해 찾아낸 하이퍼 파라미터를 적용하는
get_score_modified 함수로 수정한다.

def grid_search(X_train, y_train, x_var_list):
    # 모듈 불러오기
    from sklearn.linear_model import LogisticRegression
    from sklearn.model_selection import GridSearchCV
    
    # 일부 컬럼만 가져오기
    X_train = X_train[x_var_list]
    
    # 모델 생성
    logit = LogisticRegression()
    params = {'solver' : ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'],
              'max_iter' : [100, 200, 300]
              }
    
    gs = GridSearchCV(logit, param_grid=params, cv=5)
    gs.fit(X_train, y_train)
    
    return gs.best_params_
    
    
best_params = grid_search(X_train, y_train, col_dummies + numeric_col)
best_params
def get_score_modified(train:pd.DataFrame,  test:pd.DataFrame, x_var_list:list, best_params:dict):
    """ train과 test 데이터와 X변수 컬럼을 받아 평가지표를 내는 함수입니다.

    Args:
        train (pd.DataFrame): train 데이터프레임
        test (pd.DataFrame): test 데이터프레임
        x_var_list (list): 모델링에 사용할 변수 리스트
    """
    #외부 전달인자를 내부변수에 할당
    X_train = train 
    X_test = test

    #일부 컬럼만 가져오기
    X_train = X_train[x_var_list]
    X_test = X_test[x_var_list]
    
    '''문제 시작'''
    #모듈불러오기
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import f1_score, accuracy_score
    
    #모델가져오기 & 학습하기
    logit = LogisticRegression(solver=best_params['solver'],
                               max_iter=best_params['max_iter'])
    logit.fit(X_train, y_train)
    
    # 학습하여 결과 저장
    y_pred_train = logit.predict(X_train)
    y_pred_test = logit.predict(X_test)
    
    
    '''문제 끝'''
    
    #평가표 생성
    result = pd.DataFrame({'acc' : [accuracy_score(y_train, y_pred_train), accuracy_score(y_test, y_pred_test)],
                            'f1_score' : [f1_score(y_train, y_pred_train), f1_score(y_test, y_pred_test)]},
                            index = ['train','test'])
    
    display(result.round(2))

 

1. 결측치 처리 & 인코딩 개선.
2. 하이퍼 파라미터 최적화.

1, 2번 모두 원래 데이터와
오버샘플링한 데이터에서
모두 모델을 돌려봤고,
과제에 원래 제시되어 있던
모델과 성능도 비교해보았다.

결론은
원형 데이터 = 성능 소폭 상승.
오버샘플링 데이터 = 성능 소폭 하락.

원형 데이터는 애초에
데이터 불균형으로 인해
성능이 안 나왔던 것을 생각했을 때,
소폭 상승은 거의 의미가 없다.

오버샘플링 데이터에서의 하락은
1. 그냥 진짜 하락
2. 과적합 소폭 해소

라고 생각할 수 있겠는데
아마 1이겠지..

팀 프로젝트가 임박했다.
주제 몇개를 제시하고
그 중에 선택하는 방식을 차용하신다고 하는데
주제에 매몰되는 시간이 짧아지는 만큼
분석의 질이 높아질 수 있기 때문에
좋은 방향인 듯 하다.

 

반응형

'TIL' 카테고리의 다른 글

내배캠 TIL 36일차  (1) 2024.02.07
내배캠 TIL 35일차  (0) 2024.02.06
내배캠 TIL 33일차  (0) 2024.02.02
내배캠 TIL 32일차  (0) 2024.02.01
내배캠 TIL 31일차  (0) 2024.01.31