Machine Learning 과정
- 문제정의
- 데이터 수집
- 데이터 전처리 (인코딩,특성공학)
- 탐색적 데이터 분석 (시각화, 특성선택)
- 모델 선택 및 학습
- 하이퍼파라미터 튜닝 (교차검증,그리드서치)
- 모델 평가
import pandas as pd
import numpy as np
데이터 사전
- PassengerId : 탑승객 id
- Survived : 생존여부 (0 = 사망, 1 = 생존)
- Pclass : 티켓 클래스 (1등급, 2등급, 3등급)
- Name : 이름
- Sex : 성별 (male = 남성, female = 여성)
- Age : 나이
- SibSp : 형제/배우자의 수
- Parch : 부모/자녀 수
- Ticket : 티켓 번호
- Fare : 요금
- Cabin : 객실번호
- Embarked : 승선항 C = 쉘 부르그, Q = 퀸즈타운, S = 사우스 햄튼
Feature engineering
데이터로드
train과 test를 병합해서 사용
# train,test 데이터 로드
train = pd.read_csv('./data/train.csv')
test = pd.read_csv('./data/test.csv')
# 생존여부를 별도로 분리
# inplace 속성으로 drop결과를 바로 적용
targets = train.Survived
train.drop(['Survived'], axis = 1, inplace=True)
# 두 개의 데이터 병합
# ignore_index 속성으로 train,test의 인덱스를 순차적으로 만듬
combined = train.append(test,ignore_index=True)
# PassengerId는 삭제
combined.drop(['PassengerId'], 1, inplace=True)
combined
combined.shape
combined.head()
탑승객 호칭 처리
- Braund, Mr. Owen Harris
- Heikkinen, Miss. Laina
- Oliva y Ocana, Dona. Fermina (귀부인)
- Peter, Master. Michael J (도련님)
def split_title(x):
return x.split(',')[1].split('.')[0].strip()
titles = train["Name"].apply(split_title).unique()
titles
몇 개의 타이틀로 정리
- Officer (장교)
- Royalty (귀족)
- Mr
- Mrs
- Miss
- Master
Title_Dictionary = {
"Capt": "Officer",
"Col": "Officer",
"Major": "Officer",
"Jonkheer": "Royalty",
"Don": "Royalty",
"Sir" : "Royalty",
"Dr": "Officer",
"Rev": "Officer",
"the Countess":"Royalty",
"Mme": "Mrs",
"Mlle": "Miss",
"Ms": "Mrs",
"Mr" : "Mr",
"Mrs" : "Mrs",
"Miss" : "Miss",
"Master" : "Master",
"Lady" : "Royalty"
}
combined['Title'] = combined["Name"].apply(split_title)
#map함수를 통해 딕셔너리의 키 값과 시리즈의 인덱스 값이 같은 데이터를 찾아 변경
combined['Title'] = combined.Title.map(Title_Dictionary)
combined.head()
나이 처리
- 시각화를 위해 중간 값으로 단순히 처리했지만, 좀 더 세분화 해서 나이를 채워보자
- 성별,선실등급,호칭으로 묶어서 평균나이를 구해보자
# as_index 속성으로 그룹을 묶는 컬럼을 인덱스에서 제외하자
grouped_train = combined.iloc[:891].groupby(['Sex','Pclass','Title'],as_index = False)
grouped_median_train = grouped_train.median()
grouped_median_train = grouped_median_train[['Sex', 'Pclass', 'Title', 'Age']]
grouped_median_train
# 성별과 선실등급 그리고 호칭에 따라 평균 나이가 조금씩 다르다.
def fill_age(row):
condition = (
(grouped_median_train['Sex'] == row['Sex']) &
(grouped_median_train['Title'] == row['Title']) &
(grouped_median_train['Pclass'] == row['Pclass'])
)
if np.isnan(row['Age']):
return grouped_median_train[condition]['Age'].values[0]
else :
return row['Age']
combined['Age'] = combined.apply(fill_age, axis=1)
이름 처리
- 이름 특성 삭제
- 카테고리화 되어있는 호칭을 Model이 계산 할 수 있도록 one-hot-encoding
#이름 특성 삭제
combined.drop('Name', axis=1, inplace=True)
titles_dummies = pd.get_dummies(combined['Title'], prefix='Title')
titles_dummies.head()
combined = pd.concat([combined, titles_dummies], axis=1)
combined.drop('Title', axis=1, inplace=True)
combined.head()
요금 처리
combined.Fare.fillna(combined.Fare.mean(), inplace=True)
승선항 처리
- 결측치는 많은 사람들이 탑승한 S로 채운다
- encoding
combined.iloc[:891].Embarked.value_counts()
# 결측치 처리
combined.Embarked.fillna('S', inplace=True)
# one-hot-encoding
embarked_dummies = pd.get_dummies(combined['Embarked'], prefix='Embarked')
combined = pd.concat([combined, embarked_dummies], axis=1)
# 승선항 특성 삭제
combined.drop('Embarked', axis=1, inplace=True)
combined.head()
객실번호
- 결측치는 U(Uknown)로 대체
- 숫자를 제거한 맨 앞 글자로 변경
- encoding
# 결측치는 U로 대체
combined['Cabin'].fillna('U',inplace=True)
# Cabin의 첫 글자로 변경
combined['Cabin'] = combined['Cabin'].str[0]
# one-hot-encoding
cabin_dummies = pd.get_dummies(combined['Cabin'], prefix='Cabin')
combined = pd.concat([combined, cabin_dummies], axis=1)
# Cabin 특성 삭제
combined.drop('Cabin', axis=1, inplace=True)
combined.head()
성별 처리
# 남성은 1 여성은 0으로 변경
combined['Sex'] = combined['Sex'].map({'male':1, 'female':0})
combined.head()
객실등급 처리
# one-hot-encoding
pclass_dummies = pd.get_dummies(combined['Pclass'], prefix="Pclass")
combined = pd.concat([combined, pclass_dummies],axis=1)
# 객실등급 특성 삭제
combined.drop('Pclass',axis=1,inplace=True)
combined.head()
티켓 처리
def cleanTicket(ticket):
# .과/를 없애준다.
ticket = ticket.replace('.', '')
ticket = ticket.replace('/', '')
# 공백 기준으로 자른다.
ticket = ticket.split()
print(ticket)
# 자른 리스트의 각 항목의 양쪽 공백을 없애준다.
ticket = map(lambda t : t.strip(), ticket)
# 숫자가 아닌 것만 필터링해서 리스트로 만듬
ticket = list(filter(lambda t : not t.isdigit(), ticket))
if len(ticket) > 0:
return ticket[0]
else:
return 'XXX' #티켓 글자가 없으면 XXX로 표시
combined['Ticket'] = combined['Ticket'].map(cleanTicket)
tickets_dummies = pd.get_dummies(combined['Ticket'], prefix='Ticket')
combined = pd.concat([combined, tickets_dummies], axis=1)
combined.drop('Ticket', inplace=True, axis=1)
combined.head()
가족관련 특성 처리
- 부모,자녀,배우자,형제 모두 합친 특성을 새롭게 만듬
- 가족 숫자에 따라 1인, 소규모 가족, 대규모 가족으로 구분
# 본인을 포함하여 모든 가족수 특성 생성
combined['FamilySize'] = combined['Parch'] + combined['SibSp'] + 1
# map함수는 apply처럼 함수를 넣어서 사용가능
# lambda는 간단한 함수를 줄여서 쓰는 방식
combined['Singleton'] = combined['FamilySize'].map(lambda s: 1 if s == 1 else 0)
combined['SmallFamily'] = combined['FamilySize'].map(lambda s: 1 if 2 <= s <= 4 else 0)
combined['LargeFamily'] = combined['FamilySize'].map(lambda s: 1 if 5 <= s else 0)
combined.head()
모델링
X_train = combined.iloc[:891]
y_train = targets
X_test = combined.iloc[891:]
print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
앙상블
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import LinearSVC
knn_model = KNeighborsClassifier()
tree_model = DecisionTreeClassifier()
forest_model = RandomForestClassifier()
voting_model = VotingClassifier(
estimators = [
('knn1', knn_model),
('tree1', tree_model),
('forest1', forest_model)
],
voting='soft'
)
voting_model.fit(X_train,y_train)
pre = voting_model.predict(X_test)
pre
forest_model2 = RandomForestClassifier(n_estimators=1000, max_features=0.7, max_depth=5, min_samples_leaf=15, max_leaf_nodes=50)
from sklearn.model_selection import GridSearchCV
param_grid = {
'max_depth' : [5, 10, 15, 20],
'n_estimators' : [1000, 1500, 2000, 2500],
'max_features' : [0.5, 0.7],
'max_leaf_nodes' : [20, 50, 80]
}
grid = GridSearchCV(forest_model2,
param_grid,
cv=3)
grid.fit(X_train, y_train)
print('best score : ', grid.best_score_)
print('best params : ', grid.best_params_)
final_forest_model = RandomForestClassifier(max_depth = 5, max_features= 0.5, max_leaf_nodes= 80, n_estimators= 1000 )
final_forest_model.fit(X_train, y_train)
pre = final_forest_model.predict(X_test)
result =pd.read_csv('data/gender_submission.csv')
result['Survived']=pre
result.to_csv('HHD_submission_0211_02.csv', index=False)
'Programming > Machine Learning' 카테고리의 다른 글
네이버 영화리뷰 감성분석 (0) | 2020.02.17 |
---|---|
Sentiment Analysis(영화리뷰데이터) (0) | 2020.02.17 |
손글씨 분류 실습 (0) | 2020.02.17 |
보스턴주택 값 예측 (0) | 2020.02.17 |
Linear Model - Regression (0) | 2020.02.17 |