셀프스터디/빅데이터 분석기사
[11.29 월] 빅데이터 분석기사 실기 - Machine Learning (16~19강) 작업형 2유형 문제풀이
티로즈
2021. 11. 29. 22:11
1. 데이터 불러오기
# [0] 사용 라이브러리 import
import pandas as pd
# 데이타가 많은경우 모두 출력 안되고 ... 으로 생략해서 출력됨.
pd.set_option('max_rows',500) #출력할 max row를 지정
pd.set_option('max_columns',20) #출력할 max columns를 지정
#출력 format 지정 - 소수점아래 4자리까지
pd.set_option('display.float_format', '{:.4f}'.format)
|
# [1] 학습 데이터 X_train.csv 가져오기
X = pd.read_csv('bigdata/X_train.csv', encoding='cp949')
print(X.head(2))
|
# [2] 학습 데이터 y_train.csv 가져오기
Y = pd.read_csv('bigdata/y_train.csv')
print(Y.head(2))
|
# [3] 제출용 데이터 X_test.csv 가져오기
X_submission = pd.read_csv('bigdata/X_test.csv', encoding='cp949')
print(X_submission.head(2))
|
2. 데이터 전처리
X와 X_submission(제출용데이터)은 동일한 전처리 과정을 거쳐야 한다!
concat을 통해 한개로 만들어 한번에 전처리를 하고, 다시 분리해서 사용하는 방법 쓰기
2-1. X와 X_submission 결합하기
# [4] X, X_submission에 동일한 전처리를 위해 두 데이터 결합하기
# 'cust_id'를 index로 지정하여 df로 이름 붙이기
df = pd.concat([X, X_submission], axis=0)
df = df.set_index('cust_id')
print(df.head(2))
|
# [5] 각 컬럼의 dtype 및 행, 열 개수 확인
df.info()
|
2-2. 결측치 확인 및 처리
# [6] df의 컬럼별 결측치 확인하기
print(df.isna().sum())
|
# [7] 결측치를 채우기 위한 값 선정을 위한 작업
# 주구매상품별로 환불금액 평균이 다름을 확인
print(df.groupby('주구매상품')['환불금액'].mean())
|
# [8] '주구매상품'별 '환불금액' 평균으로 '환불금액'의 결측치를 채우기 한다
# 채우기 한 뒤 '환불금액'으로 추가한다.
s = df.groupby('주구매상품')['환불금액'].transform('mean')
df['환불금액'] = df['환불금액'].mask(df['환불금액'].isna(), s)
|
# [9] '환불금액' 컬럼의 결측치 행을 확인해 본다
df[df['환불금액'].isna()]
|
# [10] '주구매상품'별 평균을 구할 수 없는 경우 '환불금액'을 '환불금액'의 평균으로 채우기 합니다.
# 채우기 후에 채우기가 잘 적용되었는지 확인합니다.
df['환불금액'] = df['환불금액'].fillna(df['환불금액'].mean())
print(df.isna().sum().sum())
|
3. 상관분석
|
# [11] df에서 높은 상관계수 확인하기 (X Feature간)
df.corr() #0.9xx 이상만 제거 해주면 됨
|
temp = df.loc[:3500,:].reset_index()
print(temp.head(2))
print(Y.head(2))
|
# [12] df.loc[:3500,:], Y를 병합(merge)하여 temp를 만들어 사용
# df는 index를 cust_id로 가지고 있기 때문에 reset_index()하여 사용합니다.
temp = pd.merge(df.loc[:3500,:].reset_index(), Y)
print(temp.head(3))
|
# [13] temp의 상관계수 확인하기
# Y값인 'gender'와 다른 컬럼의 상관계수 확인
print(temp.corr()[['gender']].T)
|
4. Feature 변환 (정규화)
# [14] temp를 사용해 성별별 평균을 구한다.
# 'gender'에 따라 총구매액 ~ 구매주기에 값의 차이가 있는지 확인한다.
print(temp.groupby('gender').mean())
|
# [15] temp를 사용해 '주구매지점'별, 'gender'별 방문횟수를 확인한다
# 성별에 다른 분포가 있으므로 '주구매지점' 포함
print(temp.groupby(['주구매지점', 'gender'])[['주구매지점']].count())
|
# [17] df에서 '주구매지점'에 대해 중복을 제거해 본다 (고윳값을 확인함)
print(df['주구매지점'].unique())
|
# [18] '주구매상품'에 대해 중복을 제거해 본다 (고윳값을 확인함)
print(df['주구매상품'].unique())
|
# [19] '주구매지점', '주구매상품'에 대해 Label Encoding을 실행한다
df['주구매지점'] = df['주구매지점'].astype('category').cat.codes
df['주구매상품'] = df['주구매상품'].astype('category').cat.codes
|
# [20] 최종 데이터 점검
# 결측치 확인, 데이터타입 확인(수치형)
df.info()
|
5. 데이터 분리
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
|
print(df.columns)
Y.head(2)
|
# [21] X, Y 데이터 분리(선택)
X1 = df[['총구매액', '최대구매액','주구매상품', '주구매지점', '내점일수', '내점당구매건수', '주말방문비율','구매주기',
'환불금액']]
Y1 = Y['gender'] # 1-D, Series
print(X1.shape, Y1.shape)
|
# [22] StandardScaler를 사용한 Scaling
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X1) # ndarray
X_scaled[:1]
|
# [23] X_train, X_submission 분리
X_train = X_scaled[:3500, :] # ndarray
X_submission = X_scaled[3500:, :]
X_train.shape, X_submission.shape
|
type(X_train), type(Y) #X_train은 ndarray, Y는 dataframe => 형변환 과정이 필요함
|
(GridSearchCV 내용은 일단 패스)
|
# [25] X, Y 분리
XF = df4.iloc[:, :-1]
YF = df4.iloc[:, -1]
XF.shape, YF.shape
|
# [26] train, test 분리, 8:2, random_state=1234
x_train, x_test, y_train, y_test = train_test_split(XF, YF,
test_size = 0.2,
random_state=1234,
stratify=YF)
[x.shape for x in [x_train, x_test, y_train, y_test]]
|
6. 모델 생성 및 학습
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBClassifier
* 외워둘 것 * |
# [27] RandomForestClassifier 사용해서 대략의 score 확인
# random_state = 0 사용
model1 = RandomForestClassifier(random_state=0).fit(x_train, y_train)
model1.score(x_train, y_train), model1.score(x_test, y_test) # 과대적합(overfitting)
|
# [30] XGBClassifier 사용해서 대략의 score 확인
# n_estimator=5000, max_depth=4, random_state=0
model4 = XGBClassifier(n_estimator=5000, max_depth=4, random_state=0).fit(x_train, y_train)
model4.score(x_train, y_train), model4.score(x_test, y_test)
|
# [31] KNeighborsClassifier 사용해서 대략의 score 확인
# n_neighbors=6 사용
model5 = KNeighborsClassifier(6).fit(x_train, y_train)
model5.score(x_train, y_train), model5.score(x_test, y_test)
|
*이번 시험에서는 score 대신 ROC 값이 0.6이 넘어야 함
# [33] 각 모델의 roc_auc_score 구하기
from sklearn.metrics import roc_curve, roc_auc_score
for model in [model1, model2, model3, model4, model5, model6]:
score = model.predict_proba(x_test)[:, 1]
print(roc_auc_score(y_test, score)) # model3의 결과가 가장 좋다
|
# [34] 남자일 확률 구하기 (0: 여자, 1: 남자)
model1.predict_proba(x_test)[:, 1] # ndarray
|
x_sub = pd.DataFrame(X_submission, columns=x_train.columns)
x_sub.head(1)
|
7. 파일로 저장하기
# [35] X_submission 으로 cust_id와 예측한 남자일 확률을 파일로 저장하기
submission = pd.DataFrame()
submission['cust_id'] = pd.RangeIndex(3500, 3500+len(X_submission))
submission['gender'] = model3.predict_proba(x_sub)[:, 1]
submission.to_csv('submission.csv', index=False)
|