티스토리 뷰

728x90

문제 : https://github.com/tjd229/DS/blob/main/Practice/6.ipynb

 


VberEats.csv 데이터 구조

 

import pandas as pd
import numpy as np

from sklearn.tree import DecisionTreeRegressor
from sklearn.preprocessing import MinMaxScaler

df =pd.read_csv("../Dataset/VberEats.csv")
print(df.dtypes)
print(df.shape)
df.head()

shape의 출력값으로 (18951, 8)이 나온다.

 

이번 문제에서는 공통 전처리가 있다.

#0-1  : 결제 총 금액(purchases)에 결측값(Null)이 포함된 데이터를 Test Set으로, 그 외 데이터는 Train Set으로 분할한다.

 

isna 함수와 notna 함수를 이용하여 쉽게 분할 할 수 있다.

 

tr = df[df['purchases'].notna()]
tet = df[df['purchases'].isna()]

분할 후, Test Set의 데이터 개수가 203개가 맞는지 확인하자.

 

#0-2 : 식별 번호(ids)와 결제 총 금액(purchases) 컬럼을 제외한 모든 컬럼에 대해 Train Set을 기준으로 MinMax 표준화(Standardization) 한다.

 

ids 컬럼과 purchases 컬럼을 제외한 6개의 컬럼은 아래와 같다.

['ages', 'orders', 'bookmarks', 'replies', 'ratings', 'period']

위 리스트를 cols에 저장하면 아래와 같이 간편하게 코드를 구현할 수 있다.

cols = ['ages','orders','bookmarks','replies','ratings','period']
tr_nor = tr.copy()
scaler = MinMaxScaler()
tr_nor[cols] = scaler.fit_transform(tr_nor[cols])

tet_nor = tet.copy()
tet_nor[cols]=scaler.transform(tet_nor[cols])

 

Train Set을 기준으로 scaler를 fitting하는 점을 잊지말자

 

#0-3 : Train Set으로 DecisionTreeRegressor 모델을 학습하고, Test Set에 적용하여 VberEats 데이터의 결측값을 모델의 예측값으로 대체한다.

 

아래와 같이 모델을 학습하고, 예측값을 구할 수 있다.

위에서 정의한 cols를 이용하여 컬럼 순서를 준수하면서 모델에 적용하자.

DecisionTree는 컬럼 순서가 다르면 다른 결과를 출력할 수 있다.

tree = DecisionTreeRegressor(random_state=229)
tree.fit(X=tr_nor[cols], y = tr_nor['purchases'])

pred = tree.predict(X=tet_nor[cols])

 

이 예측값을 Test Set에 넣는게 아니라, 처음 파일을 읽은 데이터인 df 결측값에 예측값을 넣어주면 된다.

 

df.loc[df['purchases'].isna(),'purchases'] = pred

결측값을 채운 후, df['purchases'].mean()으로 평균값을 확인하고, 최종 데이터셋을 customer 변수로 저장하자.

customer = df.copy()

 


Q1

from sklearn.preprocessing import MinMaxScaler  
from sklearn.cluster import KMeans  
from sklearn.metrics import silhouette_score 

q1 = customer.copy()

 

 

#1-1 : 데이터의 25%를 샘플링한다.  

sample 함수를 이용하여 샘플링한다. 

q1 = q1.sample(frac = 0.25,random_state=229)


#1-2 : 고객 데이터의 ages 컬럼을 이용하여 아래 규칙에 따라 age_cls 컬럼을 새로 생성한다.
문제 4처럼 아래와 같이 age_cls 컬럼을 정의할 수 있다.

q1['age_cls'] = "10s"
for age in [20,30,40,50]:
    q1.loc[q1['ages']>=age,'age_cls'] = str(age)+'s'



#1-3 : 나이(ages), 주문 수(orders), 즐겨찾기 수(bookmarks), 답글 수(replies), 별점 수(ratings), 가입 기간(period) 컬럼을 MinMax 표준화(Standardization) 한다.       

 

6개의 종속 변수를 cols 리스트에 저장하여, 아래와 같이 간편하게 정규화를 수행할 수 있다.

cols = ['ages','orders','bookmarks','replies','ratings','period']

q1_sub = q1[cols].copy()
q1_sub_nor = MinMaxScaler().fit_transform(q1_sub)

 


#1-4 : 독립 변수들에 대해 K-means 군집 분석을 수행한다. 이 때, 군집 수는 2~5개 중 K-means Silhouette 를 통해 구하고, 이 중 첫 번째로 높은 score를 최적의 K로 설정한다.  

 

아래와 같이 루프문을 이용하여 최적의 K를 찾기 위한 Silhouette score를 계산할 수 있다.

for k in range(2,5+1):
    model= KMeans(n_clusters=k, random_state=229)
    pred = model.fit_predict(X=q1_sub_nor)
    score = silhouette_score(X=q1_sub_nor,labels = pred)
    print(k,":",score)

 

군집수가 2일 때, 스코어가 0.16X로 가장 크므로, 최적의 K는 2가 된다.
            
#1-5 : 최적의 K로 K-means 군집 분석 수행 후, age_cls별 가장 큰 군집 비율을 구한다. 그 중에서 최대값을 구하시오

 

아래와 같이 라벨 값을 q1 컬럼에 넣자

K=2
model= KMeans(n_clusters=K, random_state=229)
pred = model.fit_predict(X=q1_sub_nor)

q1['labels'] = model.labels_

 

age_cls별 가장 큰 군집 비율을 구해야한다.

groupby의 기준은 age_cls가 될 것이고, 그 중 labels컬럼에 대하여 value_counts 함수를 사용하면, age_cls별 라벨값이 0인 개수와 1인 개수가 출력될 것이다.

q1.groupby('age_cls')['labels'].value_counts()

 

문제는 군집 비율을 물어보기 때문에 normalize=True 매개변수로 비율을 출력하도록 해보자

q1.groupby('age_cls')['labels'].value_counts(normalize=True)

age_cls가 20s이면서 라벨값이 0인 군집 비율이 0.526X로 가장 크다.

혹은 .max()로 가장 큰 값을 바로 출력할 수도 있다.

 

q1.groupby('age_cls')['labels'].value_counts(normalize=True).max()

 

 

Q1 정답 : 0.53

 


Q2

from statsmodels.stats.outliers_influence import variance_inflation_factor

q2 = customer.copy()

5개의 변수 컬럼 리스트를 먼저 정의하자

 

cols = ['orders', 'bookmarks', 'replies', 'ratings', 'period']

 

단순히 다중공선성 값을 구하는 것 까지는 아래와 같이 간단히 구할 수 있다.

vif = [ variance_inflation_factor(df[cols].values,i) for i in range(len(cols))]

 

vif 리스트의 순서는 cols 리스트의 순서와 같다.

값이 7.53X인 replies가 정답이 된다.

 

만약, 위 결과를 DataFrame 형태로 보고 싶다면 아래와 같이, 새로운 DataFrame을 생성하고, 각 컬럼값과 vif 값을 삽입해주면 된다.

vif_df = pd.DataFrame()
vif_df['cols'] = cols
vif_df['factor'] = vif
vif_df

 

 

patsy 라이브러리의 dmatrices를 이용하는 경우 아래와 같이 구하면 된다.

이 때, dmatrices의 결과에는 절편이 포함되어 있으므로 vif계산 전, 절편 컬럼을 제거해주면 된다.

from patsy import dmatrices

y,X = dmatrices('purchases ~ '+(" + ".join(cols)), data = q2, return_type='dataframe')
X = X.drop(columns='Intercept')

vif = [ variance_inflation_factor(X.values,i) for i in range(X.shape[1])]

 

Q2 정답 : replies

 


Q3

 

from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
from sklearn.metrics import recall_score

q3 = customer.copy()

 

단계 1 : 주문 수(orders) 컬럼을 이용하여 아래 규칙에 따라 regular 컬럼을 새로 생성한다.    

 

np.where를 이용하여 regular 컬럼을 쉽게 생성할 수 있다.

avg = q3['orders'].mean()
q3['regular'] = np.where(df['orders']>avg,1,0)



단계 2 : Train Set과 Test Set을 2:8 비율로 나눈다.     

 

train_size 매개변수에 0.2를 넣으면 된다.

Train Set의 데이터 개수는 3790, Test Set의 데이터 개수는 15161개가 된다.

tr,tet = train_test_split(q3,train_size =0.2, random_state = 229)


단계 3 : Train Set으로 나이브 베이즈 분류 모델을 학습한다.  

종속 변수 6개를 cols 리스트에 저장하고, 아래와 같이 모델 정의 및 학습을 실시한다.

cols = ['ages','purchases', 'bookmarks', 'replies', 'ratings', 'period']
clf = GaussianNB()
clf.fit(X = tr[cols], y=tr['regular'])


            
단계 4 : 단계 3에서 학습한 모델을 Test Set에 적용한다. 모델의 예측 확률값이 threshold보다 큰 경우를 positive로 정의한다. threshold는 0.4, 0.5, 0.6 세 경우에 대하여 recall_score를 계산하고 그 중 최대값을 구하시오

 

predict_proba 함수가 각 클래스별 확률을 반환한다.

만약 0번 데이터가 0번 라벨일 확률은 [0,0]에 저장된다.

 

이 문제에서는 라벨 값이 1인 경우가 positive이므로 아래의 값에 대하여 threshold를 비교하면 된다.

clf.predict_proba(X=tet[cols])[:,1]

 

세 가지 threshold에 대하여 루프문을 이용하여 계산하자.

res = clf.predict_proba(X=tet[cols])
true = tet['regular']
for th in [0.4,0.5,0.6]:
    pred = res[:,1]
    pred = np.where(pred>th,1, 0)
    score = recall_score(true,pred)

 

threshold가 0.4일 때, recall score가 0.63로 가장 크다.



Q3 정답 : 0.6

728x90

'Computer Science > Data Science' 카테고리의 다른 글

문제 5) Solution  (0) 2023.03.19
문제 4) Solution  (3) 2023.03.19
문제 3) Solution  (6) 2023.03.19
문제 2) Solution  (4) 2023.03.19
문제 1) Solution  (11) 2023.03.19
댓글
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함