yuns
Santander Product Recommendation 본문
Kaggle 우승작으로 배우는 머신러닝 탐구생활
Santander Product Recommendation
Can you pair products with people?
www.kaggle.com
Ready to make a downpayment on your first house? Or looking to leverage the equity in the home you have? To support needs for a range of financial decisions, Santander Bank offers a lending hand to their customers through personalized product recommendations. Under their current system, a small number of Santander’s customers receive many recommendations while many others rarely see any resulting in an uneven customer experience. In their second competition, Santander is challenging Kagglers to predict which products their existing customers will use in the next month based on their past behavior and that of similar customers. With a more effective recommendation system in place, Santander can better meet the individual needs of all customers and ensure their satisfaction no matter where they are in life. Disclaimer: This data set does not include any real Santander Spain's customer, and thus it is not representative of Spain's customer base.
고객이 신규로 구매할 제품이 무엇인지 예측하는 경진대회
평가척도: MAP@7(Mean Average Precision @7)
Average Precision이란? 예측 정확도의 평균
Prediction: (1일 경우 예측이 맞은 것, 0인 경우 예측이 틀린 것)
1 0 0 1 1 0
Precision: 해당 idx일 때까지 맞은 갯수(1일 경우에만 계산)
1/1 0 0 2/4 3/5 4/6 0
Average Precision: 정확도의 합을 정답의 개수만큼 나눈 숫자
(1/1 + 2/4 + 3/5 + 4/6) / 4 = 0.69
MAP@7의 예측의 순서에 매우 예민한 평가 척도(앞에서 많이 맞출 수록 더 좋은 점수를 받을 수 있음)
1 1 1 1 0 0 0 의 경우, average precision: (1/1 + 2/2 + 3/3 + 4/ 4) / 4 = 1.00
0 0 0 1 1 1 1 의 경우, average precision: (1/4 + 2/5 + 3/6 + 4/7) / 4 = 0.43
import numpy as np
def apk(actual, predicted, k=7, default=0.0):
# MAP@7 이므로, 최대 7개만 사용한다
if len(predicted) > k:
predicted = predicted[:k]
score = 0.0
num_hits = 0.0
for i, p in enumerate(predicted):
# 점수를 부여하는 조건은 다음과 같다 :
# 예측값이 정답에 있고 (‘p in actual’)
# 예측값이 중복이 아니면 (‘p not in predicted[:i]’)
if p in actual and p not in predicted[:i]:
num_hits += 1.0
score += num_hits / (i+1.0)
# 정답값이 공백일 경우, 무조건 0.0점을 반환한다
if not actual:
return default
# 정답의 개수(len(actual))로 average precision을 구한다
return score / min(len(actual), k)
def mapk(actual, predicted, k=7, default=0.0):
# list of list인 정답값(actual)과 예측값(predicted)에서 고객별 Average Precision을 구하고, np.mean()을 통해 평균을 계산한다
return np.mean([apk(a, p, k, default) for a, p in zip(actual, predicted)])
Tabular 형태의 시계열(Time-series) 데이터 제공
전처리 작업
데이터 수집 과정에서 생길 수 있는 데이터 노이즈가 반영되어 있기 때문에 다음과 같은 노이즈를 제거해준다.
- 입력된 값이 없음을 의미하는 결측값(NA 혹은 Not A Number NAN)
- 변수 분포를 따르지 않는 이상치(outlier)
- 사람의 실수로 인해 잘못 입력된 값
- 예) 나이에 222살이 입력된 경우
- 개인정보 보호를 위해 익명화된 변수
Tabular 형태의 시계열 데이터를 다룰 경우, 트리 기반의 앙상블 모델 사용할 것
- scikit-learn 라이브러리에서 DecisionTree, RandomForest, ExtraTrees, AdaBoost, GradientBoosting
데이터 준비
1. Kaggle API 설치
pip install kaggle
2. 제품키 등록
프로필 사진 > My Profile > Account > <Create API Token>
해당 json 파일 ~/.kaggle/kaggle.json 경로로 이동
I Understand and Accept를 읽은 뒤 아래의 명령어 입력하여 data 다운로드
kaggle competitions download -c santander-product-recommendation
환경 설정을 위한 아래의 명령어 입력
pip install -r kaggle_santander_product_recommendation/requirements.txt
탐색적 데이터 분석
데이터 로딩
# Reading Training Data
import pandas as pd
import numpy as np
import time
start_time = time.time()
trn = pd.read_csv('./train_ver2.csv')
print("%s sec" %(time.time() - start_time))
데이터 크기 확인: 13,00만 개의 고객 데이터가 존재하며 고객마다 48개의 변수가 존재
trn.shape
> (13647309, 48)
.head함수를 통한 데이터 첫 5줄 확인
trn.head()
모든 변수에 대하여 미리보기 (데이터 타입, 메모리 확인)
- age의 경우, object변수로 정의되어 있는데, 이는 데이터 전처리에서 int타입으로의 변환이 필요
for i in trn.columns:
print("{}\n".format(trn[i].head()))
탐색적 데이터 분석을 통하여 얻고자 하는 것?
데이터의 대략적인 이해
변수들을 통하여 전처리 과정 고려
모든 변수와 변수의 데이터 타입
trn.info()
데이터는 24개의 고객 관련된 변수와 24개의 금융 제품 변수로 나뉘어짐
Machine Learning에서는 모든 데이터 타입이 정수/실수형이여야 하기 때문에 string형태를 사용할 수 없음
csv파일로부터 pandas로 읽어오게 될 경우, 용량이 커지므로, 불필요한 변수들은 제거하는 과정이 이루어져야 한다.
데이터 특징
아래와 같이 data section에 가면 데이터에 대한 자세한 설명을 확인할 수 있음
수치형 / 범주형 변수
24개의 고객관련 변수 + 24개의 금융관련 변수
1) 고객 변수 알아보기
1-1) 수치형 변수 추출
num_cols = [col for col in trn.columns[:24] if trn[col].dtype in ['int64', 'float64']]
trn[num_cols].describe()
(ncodpers, ind_nuevo, indrel, tipodom, cod_prov, ind_actividad_cliente, renta)의 변수명이 정수/실수형 변수
.describe() 함수: pandas의 데이터 프레임의 수치형 변수에 대한 기초 통계를 보여줌
1-2) object변수 추출
cat_cols = [col for col in trn.columns[:24] if trn[col].dtype in ['O']]
trn[cat_cols].describe()
(fecha_dato ind_empleado pais_residencia sexo age fecha_alta antiguedad ult_fec_cli_1t indrel_1mes tiprel_1mes indresi indext conyuemp canal_entrada indfall nomprov segmento)의 변수명이 object변수
- unique: 해당 변수의 고유값 개수
- top: 가장 많이 나오는 값
- freq: top에서 표시된 최빈 데이터의 빈도수 (top에 해당하는 value가 나오는 빈도)
- top값이 숫자인 age는 전처리 과정에서 숫자로 변경할 것
for col in cat_cols:
uniq = np.unique(trn[col].astype(str))
print('-' * 50)
print('# col {}, n_uniq {}, uniq{}'.format(col, len(uniq), uniq))
object변수에서 unique한 개수와 해당 value들을 나타내기 위한 코드
ind_empleado, sexo의 경우, nan 값을 가지고 있음을 확인할 수 있음
시각화로 데이터 살펴보기
matplotlib와 seaborn
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline #브라우저에서 바로 볼 수 있도록 해줌
import seaborn as sns
skip_cols = ['ncodpers', 'renta']
for col in trn.columns:
if col in skip_cols:
continue
print('-' * 50)
print('col:', col)
#set the size of graph
f, ax = plt.subplots(figsize=(20, 15))
sns.countplot(x=col, data=trn, alpha=0.5)
plt.show()
그래프의 형태를 통하여 데이터 분포를 대략적으로 분석한다.
ex) fecha_alta: 1995년 부근과 2016년 부근이 높은 빈도를 보이는 것으로 보아, 장기 고객과 신규 고객의 비율이 높아 보인다.