지금까지 데이터 분석 과제를 여러번 수행했었는데 떨어진 것도 있고 붙은 것도 있다. 간단 후기들은 아래 링크에 있다.
상반기에 또 과제 테스트를 진행하며 느꼈던 점 및 개인 공부용으로 글을 수정 발행한다.
https://emperor-one-data-study.tistory.com/61
https://emperor-one-data-study.tistory.com/58
[데이터 구하기]
우선 회귀 / 분류로 나누어 최대한 다양한 데이터를 분석해보고 감을 잡는 게 중요할 것 같다. 처음에는 타이타닉, 주택가격 데이터 등 기본 데이터로 연습 -> 데이콘이나 캐글 더러운 데이터 연습으로 확장하는 것이 좋다.
https://www.kaggle.com/datasets
회귀와 분류를 나눠서 데이터를 선택할 수 있다.
데이콘은 대회용으로 정제되지 않은 데이터를 얻기에 좋다.
프로그래머스에 과제트스트란이 있으니 해당 테스트를 연습해봐도 좋다. 부분의 기업에서 프로그래머스에서 과제 테스트를 진행하므로 실전 연습하기 좋다. 채용 공고 추천 과제랑 미술 작품 분류 과제가 있는데 채용공고 추천 과제는 과제 테스트 준비용으로 해봐도 좋을것 같다. 미술 작품 분류 과제는 AI 직무로 지원하는 사람에게 추천한다.
https://school.programmers.co.kr/skill_check_assignments
[분석 흐름 정리하기]
난 나만의 분석 흐름을 정리해두고 빠른 시간 내에 구현할 수 있도록 연습했다. 진행하는 과정에 WHY를 부여하는게 중요하다고 생각한다. (왜 결측치를 이렇게 채웠는지, 왜 이런 피쳐를 생성했는지) 다만, 듣기로는 성능으로 1차적으로 필터링한 후 세부 분석 과정을 확인한다는 이야기를 들었었다. (기업 By 기업)
베이스라인 모델을 먼저 만들고 성능 향상을 위한 작업 ( 튜닝,세부 EDA 기반 피쳐 생성) 진행하는 게 나을 것 같다. 경험상 EDA 를 먼저 하다가 후에 모델링을 제대로 못할 수도 있었던 것 같다. 빠르게 1차 모델을 구축하고 성능 향상을 시도하자 (우선 제출을 해야한다)
하지만 EDA는 데이터 분석에서 중요한 게 맞긴하다. 피쳐 생성 부분만 스킵하고 나머지 부분(분포 확인, 변수간 연관성 확인 등)은 꼭 하고 넘어가자!
모든 과정에는 꼭 주석으로 설명 추가하자.
1. 데이터 로드 및 기본 정보 확인
2. Simple EDA & 전처리 : 결측치 채우기, 분포에 따라 transformation
: 우선 간단히 모델링 할 수 있을 정도록 변환
3. 인코딩, 스케일링
3. Baseline Model : 성능 확인하기
4. Model Tuning : 성능 향상
5. feature engineering을 통한 성능 향상 (세부 EDA)
분석 흐름 코드로 정리
1. 데이터 로드 및 기본 정보 확인
보통 train 데이터 test 데이터 하나씩 csv 파일로 제공해준다. train 데이터로 EDA 및 성능 검증을 수행하고 (train/ validation) test 데이터의 label을 채워서 제출한다.
#데이터 전처리 및 시각화 라이브러리 설치
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
#경고 무시 (가독성 확보) : 생략 가능
import warnings
warnings.filterwarnings(action = "ignore")
#데이터 로딩
df= pd.read_csv("")
df.head() #데이터 확인
#데이터 정보 확인 & 결측치 확인
df.info()
df.describe()
#타겟 변수 설정하기
y=
#y의 분포 확인
df.y.value_counts(normalize =True) #분류
sns.countplot(x= target, data= df) #분류 시각화
sns.histplot(y) #회귀
데이터 기본적인 정보 확인 + 테스크에 맞는 y 정의 및 분포 확인하기
#상관 계수 확인
corr = df.corr()
corr["y변수 이름"].sort_vaules(ascending =True) #y변수와의 상관관계 확인
#시각화
plt.figure(figsize=(10, 8))
sns.heatmap(corr, annot=True, center=0)
#변수들간 관계 시각화 : 변수들 간 선형 관계 등 확인 가능 -> 데이터수가너무 크면 X
sns.pairplot(df)
#시각화할 때 크기 지정
plt.figure(figsize =(10,5))
- 결측치 있는 지 확인할 것 : 있을 경우 채운 후 (Step 2-1) Simple EDA 수행
2. Simple EDA + processing
* 전처리 하는 부분들은 무조건 test set에 대해서도 적용해줘야한다. 잊지 말자. EDA 하면서 기본 전처리 사항들 할때마다 함수에 추가해주기
- 수치형 변수 / 범주형 변수 구별해서 데이터 만들기
- 타겟 변수 지정 : 타겟 변수별 변수 분포 확인을 통해 변수가 영향 주는 지 여부를 시각화하거나 인사이트 도출 가능
numeric_cols = df.select_dtypes(include=['int','float']).columns
categ_cols = df.select_dtypes(include=['object', 'bool']).columns
수치형 변수 처리
- 수치형 변수의 경우 plot 시각화해서 보여주기
#numerical variable distribution
df[numeric_cols].hist()
- 주의할 점 : 이미 인코딩되어 있는 변수는 사실상 범주형 변수이다. titanic data의 pclass의 경우 dtype은 실수지만 스케일링 등을 할 수 있는 수치형 변수가 아니다.
- skewed한 변수가 있을 경우 (치우친 데이터) : 정규성 확보 필요함. 따라서 Transformation 수행
- 해당하는 변수에 대해서만 수행해줄 것
1. 왼쪽으로 치우쳐 있을 경우(positive skewed) : 로그 변환 (0또는 음수 값이 있을 때는 사용 X / 비율 변수도 사용 x)
0포함되어 있는 경우는? -> 1을 더해서 오류 방지 (0이 아닌 작은 값을 더해줌으로써 0이 포함되지 않은 범위로 변환 수행 가능.데이터 순서 바꾸지 않으면서 로그 변환 적용 가능한 방법임)
가격 데이터에 많이 활용
np.log(df['해당되는 변수'])
2. 왼쪽으로 치우쳐 있을 경우(Negative skewed) : Power Transformation (제곱근, 역수 변환 등 보통 제곱근 변환)
np.sqrt(df['해당변수'])
2-1. Imputate Missing Value
데이터의 크기가 작은 경우 무작정 제거하지 말고 최대한 채우는 쪽이 좋을 것 같다. 대부분 과제 테스트 수행시에는 시간 제한이 있기 때문에 데이터가 크기가 작은 경우가 많다. 따라서 최대한 채우는 방식을 고려해보자.
1. 기술 통계량으로 채우기
평균, 최빈값, 중앙값 등
ex) df['deck'] = df.deck.fillna(df.deck.mean())
*주의할 거 : 그냥 mean으로 하면 안된다 괄호 주의
*df.변수.mode()[0]
2. backfill, fowaradfill
3. 기타 알고리즘 활용
darwing, KNN 등 알고리즘 활용 가능
-> 하지만 과제 테스트 시에는 모델링에 집중하고 비교적 단순한 방식으로 채우자 !
4. 새로운 값으로 채우기
결측치가 70% 이상이나 수가 너무 많을 때. 단순 제거하기에는 타겟 변수별로 차이가 극명히 나타날 때
-> unknown 등 아에 다른 걸로 채우고 이에 대한 근거를 설명으로 써넣기
*갑자기 채워지지 않은 경우 : dtypes가 category인 경우, df.astype({'deck':'object'} 처럼 object로 만들어주어야 새로운 문자열으로 채워줄 때 에러가 나지 않는다
3. 인코딩, 스케일링
인코딩
categorical 변수 인코딩 시에는 여러가지 방법을 고려할 수 있음. 대표적인 것이 원핫 인코딩, 라벨 인코딩이 있음. 원핫 인코딩은 신경망 계열 모델 활용 시에 라벨 인코딩은 트리 모델 시에 유용하게 쓰일 수 있다.
https://emperor-one-data-study.tistory.com/7
데이터에 따라 어떤 방식을 쓰냐의 차이가 있지만 나만의 메뉴얼을 정했다.
- 남/ 여 처럼 0,1로 나눌 수 있는 건 그냥 인코더 사용 없이 맵핑하여 사용하기
- 클래스가 여러개라면 라벨 인코더 사용 : 기존 변수는 삭제하는 거 잊지 말기 / 3개 정도라면 원핫인코더 사용
스케일링
주의할 점: train/ test 데이터에 쓰이는 함수가 다른 것을 잊지 말자
train -> StandardScaler.fit_transform(X_train)
validation, test-> StandardScaler.transform(X_test)
from sklearn.preprocessing import OneHotEncoder, StandardScaler
#라벨 인코딩 예시
label_cols=['embarked', 'deck', 'embark_town']
l_encoder= LabelEncoder()
for i in label_cols:
df[i]=l_encoder.fit_transform(df[i])
#스케일링은 train/ test에 각각 다른 함수가 적용된다
#X, y 분리
X= df.drop(["survived"], axis=1)
y= df[["survived"]]
from sklearn.model_selection import train_test_split
#XXyy의 순서다! (헷갈리지 않게 val로 이름 설정할 것 )
X_train, X_val, y_train, y_val= train_test_split(X,y, test_size = 0.8, random_state=42)
실제 분석 시에는 train/ test가 나누어 제공되는 경우가 많다. validation에 대해 평가 후 모델링 진행하고 test에 대해 최종 제출함을 잊지 말자
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_std = scaler.fit_transform(X_train)
X_val_std =scaler.transform(X_val)
X_test_std = scaler.transform(X_test)
음수값이 나온다? : MinMaxScaler로 대체
4. 베이스라인 모델 구축
- 모델 각각 정의하기: 설치 필요한 부스팅 계열 제외하고 최대한 단순하게 , 각 모델이 어떤 라이브러리에 들어있는지 확인
- 각 모델에 대한 성능 확인하기
- 모델 중 성능 높은 3개 뽑아서 voting: hard/ soft 성능 비교
#분류
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
#회귀
from sklearn.linear_model import LinearRegression, Lasso, Ridge
from sklearn.ensemble import RandomForestRegressor,AdaBoostClassifier, GradientBoostingClassifier
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
모델은 LGBM, Catboost 등 부스팅 계열 사용이 안되는 경우가 많았다 (설치 해야함)
마음 편하게 sklearn 내에 있는 모델들만 활용해야겠다
#각 모델 정의
lo = LogisticRegression()
rf = RandomForestClassifier()
ada = AdaBoostClassifier()
gb = GradientBoostingClassifier()
dt = DecisionTreeClassifier()
svc =SVC()
#hard voting, soft voting 비교
voting = VotingClassifier(estimators, voting = 'hard')
voting.fit(X_train, y_train)
y_voting = voting.predict(X_test)
print('validation accuracy:', acc(y_test, y_voting))
#모델 튜닝 예시
## 랜덤포레스트의 하이퍼파라미터 튜닝
from sklearn.model_selection import RandomizedSearchCV
rf = RandomForestClassifier()
params = {
'n_estimators': [100, 200, 300],
'min_samples_split': [2, 3, 4],
'criterion': ['gini', 'entropy', 'log_loss'],
'max_features': ['sqrt', 'log2', None]
}
rf_cv = RandomizedSearchCV(rf, params, n_iter = 10, random_state = 42)
rf_cv = rf_cv.fit(X_train, y_train)
y_rf_cv = rf_cv.predict(X_test)
print(rf_cv.best_params_)
print(acc(y_test, y_rf_cv))
각 결과 비교해보고 best socre로 test set 만들어서 제출하기
help(모델)을 통해 하이퍼파라미터 종류와 범위를 알 수 있으니 적극 활용하기
평가 score는 분류는 accuracy, 회귀는 rmse로 진행한다.
[기타 준비하면서 느낀 사항들]
- 튜닝은 필수다 : 성능 차이가 많이 난다 (Bayesian Search를 쓰면 좋겠지만 기본 sklearn 내에서 쓰자)
- correalation이 낮다고 단순 제거하면 안된다 : 연관성을 보여주기는 하지만 target 변수와의 직접적인 인과 관계를 나타내지는 못한다, 너무 낮은 변수에 대해 regplot 그려보고 선형 관계가 있는지 확인해보자
- 세세한 EDA 전 딱봐도 상관 없는 변수 제거 (인덱스, 아이디), 결측치 처리, 범주형 변수 인코딩, 문자열 처리, 스케일링 정도만 하고 모델링 바로 수행 → 베이스라인 성능 보고 EDA 추가할 것 ⇒ a to z를 만드는 것이 우선이다
- 모델링 후 앙상블 꼭 해보기(시간되면)
- 주석과 설명을 많이 추가하자
- plot 많이 그려보기
- 웬만하면 변수 단순 제거하지는 말자 : 설명 쓰면서 최대한 채워보기
- 처음부터 무리하게 변수를 추가로 생성하지 말고 베이스라인 모델 구축을 우선으로 하자 !
- 생각보다 전처리할 요소 없이 깔끔한 데이터가 많았다 (기업 By 기업이겠지만)
- 한문제는 간단한 전처리 문제 + 하나는 모델링 문제인 기업도 있었다.
[연습 코드]
https://github.com/HwangJae-won/Data_project_practice
'Machine Learning' 카테고리의 다른 글
[ML/DL] Introduction of ML/ ML을 위한 기초 지식 (0) | 2023.06.12 |
---|---|
[Python/ EDA] categorical data를 다루는 방법 : onehot encoding/ label encoding (0) | 2022.04.17 |