▶이전글 : EDA
캐글 샌프란시스코 범죄발생률 예측 : EDA
파이썬으로 진행하였고, 데이터 분석 강의 4주차를 마무리하고 캐글에 최종적으로 제출한 버전을 기반으로 코드를 설명했다. (중간 과정이 궁금하다면 github를 참고! github.com/helloMinji/Kaggle_crime_Sa
hellominji.tistory.com
데이터 전처리
여기서는 train에 대해서만 기재하지만, test에도 같은 과정을 거쳤다.
1 Dates
train["Dates-year"] = train["Dates"].dt.year
train["Dates-month"] = train["Dates"].dt.month
train["Dates-day"] = train["Dates"].dt.day
train["Dates-hour"] = train["Dates"].dt.hour
train["Dates-minute"] = train["Dates"].dt.minute
train["Dates-second"] = train["Dates"].dt.second
# 분에서 30을 뺀 후 절댓값
train["Dates-minute(abs)"] = np.abs(train["Dates-minute"]-30)
시간을 단위별로 나눈다.(연, 월, 일, 시, 분, 초)
분은 자세히 기록되어 있지 않기 때문에, 분에 30을 뺀 후 절대값을 씌운다. 이렇게 하면 0분을 기준으로 상대적인 플러스/마이너스치를 알 수 있다.
2 DayOfWeek
train_dayofweek = pd.get_dummies(train["DayOfWeek"], prefix = "DayOfWeek")
train = pd.concat([train, train_dayofweek], axis = 1)
요일은 문자라서 머신이 인식할 수 없다. 이를 위해 one-hot encoding을 진행한다.
3 PdDistrict
train_pddistrict = pd.get_dummies(train["PdDistrict"], prefix = "PdDistrict")
train = pd.concat([train, train_pddistrict], axis = 1)
경찰서의 이름은 문자라서 머신이 인식할 수 없다. 이를 위해 one-hot encoding을 진행한다.
4 Address
train["Crossroad"] = train["Address"].str.contains("/")
교차점인지 아닌지에 따라 특정 범죄의 발생률에 차이가 있기 때문에 변수로 활용하기 위하여 새로운 컬럼을 생성하였다.
def clean_address(address):
if "/" not in address:
return address
address1, address2 = address.split("/")
address1, address2 = address1.strip(), address2.strip()
if address1<address2:
address = "{} / {}".format(address1, address2)
else:
address = "{} / {}".format(address2, address1)
return address
train["Address(clean)"] = train["Address"].apply(clean_address)
교차로 이름이 a/b와 b/a로 순서가 다른 경우가 있기 때문에
주소값을 비교하여 알파벳이 빠를수록 작은 값이라고 가정하고, 작은 값을 앞으로, 큰 값을 뒤로 배치하여 교차로의 이름을 통일시킨다.
address_counts = train["Address(clean)"].value_counts()
top_address_counts = address_counts[address_counts >= 100]
top_address_counts = top_address_counts.index
train.loc[~train["Address(clean)"].isin(top_address_counts), "Address(clean)"] = "Others"
주소값을 많은 순으로 정렬하고, 주소 발생 횟수가 100회 미만인 주소들은 Others로 값을 통일하여 다른 값에 대한 정확도를 높인다.
train_address = pd.get_dummies(train["Address(clean)"])
from scipy.sparse import csr_matrix
train_address = csr_matrix(train_address)
주소는 데이터 특성 상 one-hot encoding 후에는 해당 열에 0의 비율이 굉장히 높게 만들어진다.
이에 메모리의 효율적인 사용을 위해 CSR Matrix로 변환한다.
▶CSR Matrix란?
Python : csr_matrix (데이터의 수를 줄이는 방법)
5 7 1 4 2 3 6 2 1 6 4 5 7 희소행렬: 대부분의 값이 0. 이런 희소행렬을 메모리 낭비가 적도록 변환하고자 한다! → CSR 형식을 사용! ▶ 필요한 패키지 불러오기 from scipy.sparse import csr_matrix import n..
hellominji.tistory.com
학습
feature_names = ["X", "Y", "Dates-year", "Dates-month", "Dates-day", "Dates-hour", "Dates-minute(abs)", "Dates-second"]
feature_names = feature_names + list(train_dayofweek.columns)
feature_names = feature_names + list(train_pddistrict.columns)
label_name = "Category"
X_train = train[feature_names]
X_test = test[feature_names]
y_train = train[label_name]
# CSR Matrix 합치기 - hstack
from scipy.sparse import hstack
X_train = hstack([X_train.astype('float'), train_address])
X_train = csr_matrix(X_train)
X_test = hstack([X_test.astype('float'), test_address])
X_test = csr_matrix(X_test)
전처리를 통해 생성된 컬럼들을 feature_names로 만든다.
hstack을 이용하여 원래 train 데이터와 CSR Matrix를 합치고, 이를 다시 CSR Matrix로 변환한다.
모델 생성
하이퍼 파라미터 최적화를 통해 파라미터값을 정한다
▶ coarse to fine
하이퍼파라미터 튜닝 : Coarse & Fine Search
모델의 가장 성능의 좋은 파라미터를 선택하기 위해, 하이퍼파라미터 튜닝 작업을 거친다. 이 때 Coarse & Fine Search를 사용하여 파라미터를 찾는다. Coarse Search Random Search를 하되, 이론상으로 존재
hellominji.tistory.com
이를 통해 생성된 최종 모델은 다음과 같다.
best_hyperparameters = finer_hyperparameters_list.iloc[0]
Lgb = LGBMClassifier(n_estimators = best_hyperparameters['n_estimators'],
learning_rate = best_hyperparameters['learning_rate'],
num_leaves = best_hyperparameters['num_leaves'],
max_bin = best_hyperparameters['max_bin'],
min_child_samples = best_hyperparameters['min_child_samples'],
subsample = best_hyperparameters['subsample'],
subsample_freq = best_hyperparameters['subsample_freq'],
colsample_bytree = best_hyperparameters['colsample_bytree'],
class_type = best_hyperparameters['class_type'],
random_state = best_hyperparameters['random_state'])
평가 및 예측
from sklearn.model_selection import train_test_split # 데이터를 일정 비율로 두 개로 쪼개줌
# train 데이터를 train_kf, test_kf로 쪼개서 모델성능 평가
X_train_kf, X_test_kf, y_train_kf, y_test_kf = train_test_split(X_train, y_train, test_size = 0.3, random_state = 37)
# 학습(LightGBM)
%time Lgb.fit(X_train_kf, y_train_kf)
# 범죄가 발생할 확률(LightGBM)
y_predict_test_kf = Lgb.predict_proba(X_test_kf)
# score 계산: 캐글에 업로드하지 않아도 순위 예상 가능
from sklearn.metrics import log_loss
score = log_loss(y_test_kf, y_predict_test_kf)
print(f"Score = {score:.5f}")
### Predict
%time Lgb.fit(X_train, y_train)
prediction_list = Lgb.predict_proba(X_test) # 진짜 test로 예측
해당 컴페티션의 score 방식을 확인하여 결과파일을 업로드하지 않아도 대략적인 score를 예측할 수 있도록 한다.
※ 예측에 쓰이는 함수가 predict_proba?
컴페티션에서 요구하는 예측 결과가 하나만 예측하라!가 아닌 각각의 범죄가 일어날 확률로 되어있기 때문!
제출
sample_submission = pd.read_csv("sampleSubmission.csv", index_col = "Id")
submission = pd.DataFrame(prediction_list,
index = sample_submission.index,
columns = model.classes_)
submission.to_csv("baseline-script.csv")
나의 스코어는 2.30406으로 약 상위 15.2% 정도였다.
강의를 들으면서 좋았던 건, LightGBM과 coarse to fine 방법을 배운 것이다. 이 두가지는 예측 score를 상당히 높이는데 도움이 되었다.
'Data Science : Project > 개인 프로젝트' 카테고리의 다른 글
캐글 샌프란시스코 범죄발생률 예측 : EDA (0) | 2020.11.24 |
---|---|
캐글 타이타닉 생존자 예측 (0) | 2019.11.22 |