본문 바로가기

AI/Kaggle

San Francisco Crime Classification 2일차

반응형

Randomforest -> 덜 복잡한 데이터 셋 작업에서 성능 우수 
LGBM -> 복잡한 데이터 셋 작업에서 성능 우수

 

836/2332 스코어 2.531

 

# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load in 

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the "../input/" directory.
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

# Any results you write to the current directory are saved as output.

 

 

train = pd.read_csv("/kaggle/input/sf-crime/train.csv")
train.head(100)

 

train["Dates"] = train["Dates"].astype("datetime64")
train["year"] = train["Dates"].dt.year
train["month"] = train["Dates"].dt.month
train["dayofweek"] = train["Dates"].dt.dayofweek
train["hour"] = train["Dates"].dt.hour
train["minute"] = train["Dates"].dt.minute
train["day"] = train["Dates"].dt.day

 

 

train["ndays"]= (train["Dates"].dt.date-train["Dates"].dt.date.min()).apply(lambda x:x.days)
#days가 생략됨 days에 대한 숫자만 나옴 

#min()이 붙으면서 Dates칼럼에서 최소 값을 찾음 그리고 lambda x는 x.days로 구성되는 값중에 x를 추출.

#모든 사건 중에 최초로 발생한 사건으로부터 어떤 사건이 얼마의 기간이후에 발생했는지에 대한 정보.

 

test = pd.read_csv("/kaggle/input/sf-crime/test.csv")
test.head()

 

train["x-y"] = train["X"]-train["Y"] #좌표 정보에 대한 값은 사칙연산으로 성능개선이 될 수 도 있음.
train["x+y"] = train["X"]+train["Y"] #성능 감소시 빼기.

 

test["Dates"] = test["Dates"].astype("datetime64")
test["year"] = test["Dates"].dt.year
test["month"] = test["Dates"].dt.month
test["dayofweek"] = test["Dates"].dt.dayofweek
test["hour"] = test["Dates"].dt.hour
test["minute"] = test["Dates"].dt.minute
test["day"] = test["Dates"].dt.day

test["x-y"] = test["X"]-test["Y"] #좌표 정보에 대한 값은 사칙연산으로 성능개선이 될 수 도 있음.
test["x+y"] = test["X"]+test["Y"]

 

test["ndays"]= (test["Dates"].dt.date-test["Dates"].dt.date.min()).apply(lambda x:x.days)

y =  train["Category"]
train = train.drop(["Dates","Category","Descript","DayOfWeek","Resolution"],1)

test = test.drop(["Id","Dates","DayOfWeek"],1)

 

train["Address"].nunique()
test["Address"].nunique()  #개수파악으로 칼럼 비교가능.

#각각 실행해서 각각의 unique의 개수 파악가능.

 

sub = pd.read_csv("/kaggle/input/sf-crime/sampleSubmission.csv")

sub.head()

 

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
train["PdDistrict"] = le.fit_transform(train["PdDistrict"]) #unique한 값이 같으므로 한번만 fit해주면 된다.
test["PdDistrict"] = le.transform(test["PdDistrict"])

 

#대소문자 구분 x case = False
train["block"] = train["Address"].str.contains("block",case = False)
train["avenue"] = train["Address"].str.contains("av",case= False)
train["street"] = train["Address"].str.contains("st",case= False)
test["block"] = test["Address"].str.contains("block",case = False)
test["avenue"] = test["Address"].str.contains("av",case= False)
test["street"] = test["Address"].str.contains("st",case= False)

#Address칼럼에서 block을 포함하는 문자열을 포함하면 true, 안 포함하면 false로 표시.  

 

re = LabelEncoder()
re.fit(list(train["Address"] )+list(test["Address"])) #train이랑 test는 address가 다르므로 인덱스 매칭이 안됨.

#위에 PdDistrict랑 다른점은 PdDistrict는 train,test 칼럼의 데이터 갯수가 같음. 따라서 알파벳순으로 인덱스를 정하면

#같은 PdDistrict에 대해 같은 인덱스지만 Address는 갯수차이가 발생하므로 전체 Address를 묶어서 가져온 후에

#쭉 번호를 매김, 그리고 그 안에 같은 Address간에는 같은 인덱스가 매겨지므로, 인덱스가 밀리거나 하는일없음

 

train["Address"] = re.transform(train["Address"])
test["Address"] = re.transform(test["Address"])

train.head()

#fit은 위에서 해주었으므로 transform만 해주면됨

 

from sklearn.model_selection import train_test_split
x_train,x_valid,y_train,y_valid = train_test_split(train,y,test_size = 0.25,random_state = 1,stratify = y)
x_train.shape,x_valid.shape,y_train.shape,y_valid.shape

 

from lightgbm import LGBMClassifier

p = LGBMClassifier(n_estimators = 100 , num_leaves = 200, min_child_samples = 100, colsample_bytree = 0.7,subsample = 0.9 ) #num_leaves default = 31 
#min_child _sample 노드가 스플릿 될때 노드에 최소한의 데이터가 몇개 들어갈지 옵션 지정. samples값이 커질수록 트리높이 감소 #default 20 
#질문은 데이터의 무질서 경향이 줄어드는 쪽으로 질문을 던짐 
#colsample_bytree 0~1 칼럼데이터의 일부만 넣음. / 칼럼이 100퍼 들어가면 중요한 칼럼만 넣어짐. 따라서 학습이 안되는 칼럼존재  #랜덤하게 뽑히므로 앙상블 효과, 과접합 방지가 가능해짐. default == 1

subsample도 비슷한 의미
#num_leaves => max_depth xgboost에서.
p.fit(x_train,y_train,eval_set = (x_valid,y_valid), early_stopping_rounds = 20)

 

 

 

 

importances_df = pd.DataFrame(p.feature_importances_).rename({0:"importances"},axis = 1)
importances_df["columns"] = x_train.columns 
importances_df = importances_df.sort_values("importances",ascending = False) #오름차순을 false로 
importances_df["importances"] = (importances_df["importances"]/importances_df["importances"].values.sum())*100
importances_df.head(10)

#중요도를 뽑음 pd사용해서 DataFrame만들고 그안에 p.feature_importances_를 채우면 p값은 지금 Category이므로 

#Category를 분류하는데 중요했던 칼럼이 중요도와 칼럼 번호로 매칭되어서 나타나고, 이 디비 이름을 rename으로 

#0에서 importances로 고쳐줌 ,axis는 열로 설정. 

#그리고 이 중요도에서 columns라는 칼럼 추가한뒤에 train함수의 칼럼을 넣어주면 칼럼과 중요도가 매칭되고

#내림차순으로 sort_values를 사용하여 정렬. 그리고 하나의 importance를 전체 value값의 합으로 나눈뒤 100 곱해서

#비율로 나타낼 수 있음.

 

x = p.predict_proba(test)

sub.iloc[:, 1:] = x

sub.to_csv("imu.csv",index = False)

 

#데이터 프레임으로 만든 후에 씌우는 느낌.

 

 

import seaborn as sns  #그림을 그림.
import matplotlib.pyplot as plt  #그림을 그릴 판을 만듬

_,banana = plt.subplots(1,1,figsize =(20,12))
#변수 두개가 필요한데 하나는 안써도 되므로, _이렇게 사용해도됨. 

                                                               #매개변수로 들어가는건 1,2 = 1열 2행, figuresize
sns.barplot(importances_df["columns"],importances_df["importances"])   
plt.xticks(rotation = 75) 

#칼럼과 importances를 표로 나타냄.

 

 

 

반응형