반응형
crazyj_kaggle_first

Kaggle first time

crazyj7@gmail.com

동기

처음에 이 사이트를 보고 단순히 무료로 데이터 파일들을 다운받을 수 있는 사이트 인줄 알았다. 거의 방문을 안하다가 가끔 데이터 파일 쓸모있는게 있나 찾다가 여러가지 다른 기능들이 많은 것을 발견했다.
학습에 도움이 많이 될 거라는 생각에 모니터링 중 Competition이 있는 것을 알게 되고 국내에서 주최한 대회가 있다는 것에 흥미를 느끼고 장난삼아 도전해 보려고 했다.
그간 AI쪽을 제대로 공부한 적은 없지만 나름대로 독을 좀 했. 다만 혼자서 하려니 어디 물어볼 데도 없고, 이해가 안가서 막히는 것들이 많아 진행 속도가 더디었다.

캐글 사용기

커널을 대체 어떻게 사용해야 되는지 어렵다.
느리고, 자꾸 끊기고, 에러나고, 아웃풋을 못찾겠고, 이어서 되는 건지 아닌지 모르겠고. 커밋은 git 처럼 소스 커밋을 말하는 건지…

  • 커널을 여러 개 동시에 돌릴 수 있다고 한다. 최대 5개 던가? 아직 해 보지는 않았다.
    • 3개 4개 돌려보니 잘 된다. 계속 하다 보면 익숙해짐.
  • 커널 이용 최대시간은 9시간 이라고 하는 것 같다. 학습이 이 시간을 넘어가면 짤린다는 것이겠다. 중간 저장이 필수겠다.
  • 가공 생성한 파일들은 대체 어디에 있는 것일까?
    • 현재 디렉터리에 생성된다. /kaggle/working 인 듯. 디렉터리 탐색도 커맨드 실행으로 할 수 있다. 커널버전 보기에서 Output 메뉴에 생성한 파일들 목록이 보여서 다운로드는 할 수 있다.
    • 그런데 이어서 작업할 때는 왜 output 파일이 다 없어지는 것일까? 디렉터리 탐색시 다 사라진다. 작업 디렉터리인 working 디렉터리는 세션 실행시 초기화된다. output이 다 없어진다. 주의! 이전 커밋은 버전을 찾아 들어가면 output을 받을 수 있다.
  • 소스는 여러 개를 올릴 수 있는 것일까?
    • 안되는 것 같다.
    • 한 파일만 되는 듯. ipynb (노트북)와 py(스크립트) 변환을 지원하고 업로드기능이 있으니 잘 활용하면 된다. 스크립트는 올릴필요없이 복붙하면 쉽다.
  • 대체 커밋이 뭐지?
    • 커밋은 소스 전체를 실행하는 것이다. 에러없이 모두 성공해야지만 output 파일이 생성되고, 다운 받을 수 있다. 중간에 실패하면 날라간다. ㅜ.ㅜ
  • 생성한 output을 유지할 수는 없나?
    • 시행착오 끝에 output을 다운 받아서 dataset에 추가하고 커널에서 dataset을 추가해서 불러서 사용하면 된다.
  • 데이터셋 업데이트는?
    • 안된다. 올라간 데이터셋을 삭제하고, 새로운 데이터셋을 동일한 이름으로 올리는 식으로 업데이트 할 수 있다. 불편함. 해당 데이터셋을 참조하는 커널에서는 링크깨진 데이터셋을 삭제하고 다시 만든 것을 추가해 주어야 한다.

캐글 사용 정리

  1. 로컬 환경에서 먼저 자료 분석을 한다.
    데이터 셋을 받은 다음 jupyter notebook이나 lab으로 자료 관찰하고, 데이터 전처리를 하는 것을 만든다.
  2. 데이터 전처리된 파일들을 데이터셋으로 만들어 업로드한다.
  3. 가급적 경로를 로컬환경과 캐글환경을 일치시키면 올릴때 경로 수정이나 환경플래그값을 변경하지 않아도 되어 편하다.
    따라서 …/input/dataset이름/파일명 이나 …/input/dataset이름/압축파일명/내부파일명 으로 접근.
  4. 커널을 만들고 데이터셋을 추가하여 테스트해 본다
  5. 로컬 환경에서 디버그 모드를 만들어 적은 데이터로 빠르게 학습할 수 있도록 준비한다. 잘 되면 릴리즈모드로 만들고 커널에 임포트하여 커밋해 본다.
  6. 기본이 되는 커널을 잘 만든다. 여러가지 테크닉을 집어 넣기 전에 기본이 되는 커널이 잘 작동하고 성능도 좋게 만들 방안을 찾는다.
  7. 데이터가 크면 메모리 부족 에러를 아주 많이 볼 것이다. 이미지의 경우 numpy로 만들어 로딩하여 쓰다 보면 그리고 data type을 float로 변환하면 엄청나게 증가한다. 미리 메모리에 로딩하지 말고 필요한 만큼. 일정 크기만큼 불러서 처리하고 결과 저장하고를 반복하여 메모리 부족을 방지해야 한다. 전처리 후 이미지 크기도 크게 영향을 받는다. 이미지가 너무 작으면 성능이 떨어질 것 같고, 너무 크면 학습도 어렵고 메모리도 부족할 것 같다.
  8. EarlyStopping을 사용하여 멈출 때를 정한다. metric을 평가 방식에 맞게 설정한다. (loss, acc, f1_score 등)
  9. Checkpoint 저장. 중간 중간 best를 계속 저장하도록 한다.
  10. 테크닉?
  • 이미지 전처리를 바꿔본다. 크기, Margin추가, 색상, color scale, … cut-out (이미지 일부를 삭제), normalize, …
  • Image Augument Generator로 학습 데이터를 늘린다. zoom, shift, rotation, shear, flip, brightness, …
  • Pre-Trained Model 변경 : xception, efficientnet, resnet, …
  • Dropout 추가
  • Train/Validation 비율 변경 / 샘플링 기법 변경 : oversampling, straitifiedKFold, …
  • ReduceLROnPlateau 적용
  • Cross Validation : 결국 모든 학습데이터를(validation 포함) 훈련하게 되는 방식으로 학습데이터가 많아서 결과도 더 좋아진다.
  • 앙상블 : 여러 네트웍의 결과를 보고 판단. (5% 정도 올랐음)
  • TTA : 시험시에 시험 이미지에 Augument를 가해서도 측정해 보고 그 결과를 반영해 본다. (0.2% 올랐음)
  1. 몇 개의 폴드로 나눠서 폴드 번호를 지정하고 학습할 수 있는 스크립트를 만들고, 커널에 올려 돌린다. 이 커널을 Fork하여 폴드 번호를 바꿔가면서 계속 커널을 만들어 commit한다. 동시에 4개까지 model을 만들 수 있을 것이다.
  2. model들을 다운 받아 모델 데이터셋을 만든다.
  3. 모델들을 합쳐 앙상블 결과를 내는 스크립트를 만들어 돌린다.
  4. 마지막에 TTA를 추가해 본다.
  5. pseudo labeling 적용 테스트. (효과가 있을지는 모르겠다.)

용어

  • val ; validation. 검증용 데이터. 모델 학습시에는 모델은 검증 데이터를 전혀 본적없는 데이터이다.
  • k fold ; train, val 셋을 분리하는데, k개의 다른 방식으로 데이터를 나눈다. 따라서 fold별로 하나씩 모델을 만들 수 있다.(k개의 모델 생성 가능). 나중에 생성된 모델들을 합친다(? 앙상블한다는 의미인가?)
  • stratifiedkfold ; kfold를 할 때, 원본 데이터의 클래스 비율을 유지하여 분리한다.
  • oversampling / undersampling ; stratified하는 것 대신, 샘플 수를 고르게 맞추는 방식이다. over는 많은 개수 기준. under는 부족한 개수 기준.
  • tta ; 학습시가 아닌 테스트시에 augmentation을 하여 앙상블 결과를 내놓는다.
  • cross validation ; 학습이 다 끝나면 나중에 validation data도 학습한다.
  • 앙상블 ; 여러 다른 모델의 결과를 합친다. (? 합치는 방식이 여러가지 일 듯. average, max count)
  • pseudo label ; 어느정도 성능이 나온 훈련모델로 test셋의 결과를 예측하여 99% 가량 강하게 맞다고 한 데이터의 라벨을 가상으로 붙여 훈련셋에 추가한다. 훈련데이터 개수 확장 효과.
  • cut-out image ; 이미지에서 랜덤하여 자름. 랜덤한 영역의 블록을 잘라버림. (노이즈)
    -했다면 했다고 할 수 있다.

Car model classify

문제는 자동차 모델명을 분류하기.
학습 이미지 데이터와 라벨이 있고 더구나 Bounding box도 있어서 도전해 볼만 했다. 근데 클래스가 상당히 많았다. 정확도가 높게 나오지 않을 것 같은데…라는 생각이 들었다. 그러나 나중에 보니 다른 참가팀들의 정확도에 놀랐을 뿐이다.

Try1 ; 70%

  • mobilenetv2

전에 한 번 구글이미지 검색으로 동물들 데이터셋을 만들어 이미지 분류 테스트를 해봤었는데 단순한 몇 개 클래스 구분하는 것도 만만한 일이 아니란 걸 알았다.
나름대로 CNN을 활용하여 Sequential 모델로 만들어봤지만 쉽사리 정확도가 높아지지 않았다는 기억이 났다.
그 때 데이터량의 부족, 학습이 안되는 현상, 과적합 현상 등 어려움이 많았다.
나중에 이미지 분류에 미리 학습된 모델들을 활용한 전이학습이 있다는 것을 보고 적용해 보니 손쉽게 정확도가 높아지는 것을 보았다.

  • 데이터 전처리
    • 이미지 crop 하고 resize, RGB 3 channel로 보정
  • mobilenetv2 사용
    • 뒤에 Dense1개, Softmax1개 사용

Test 데이터셋으로 accuracy가 70% 정도??

  • 나중에 알고보니 image color를 rescale하지 않았었다. 수정 완료. rescale=1/255로 color값을 [0,1] 범위로 함.

Try2 ; 80%

  • ImageAugumentation 으로 학습 데이터 확장. 좌우반전. 사이즈. 뒤틀림 등.
    mobilenetv2에 Dense 2개, Softmax1개 사용
    정확도 80%로 향상됨.

Try3.v1 ; 80%

training set의 정확도가 99%가 넘는데, validation은 80%였다.

  • Cross Validation?
    훈련 데이터셋 부족으로 데이터셋 재분배하여 test set, validation set으로 나누어 이어서 학습.
    training , validation set 모두 90% 이상 나옴. 그러나 학습이 계속되면 train은 99% val은 79정도로 떨어짐. test set은 80%로 여전함.
  • OOM이 자주 발생해서 고생함. batch_size 줄임. 네트웍 사이즈 줄임. 더 이상 필요없는 변수들 삭제.

Try4.v2 ; 81%

이미지의 일부를 지워서 학습??
Image part Random Remove ; resnet에 있다는 모듈을 적용시도.
ImageAugment ; shift 추가.
성능이 약간 좋아졌으나 별차이 없는 정도. 이론상 좋은 듯 한데.
lb acc 81%

Try5.v3 ; More Deep ; 83%

  • xception

원래는 Resnext50을 사용하고 싶었으나, keras 버전이 오래된 거라서 그런지 지원이 안된다.

  • 학습전이 모델 변경. mobilenetv2에서 xception으로. 파라미터수가 5배는 차이난다. 400만개 vs 2천2백만개.
  • 처음부터 다시 학습. 시간이 오래 걸림.
  • 모델은 처음부터 freezing하지 않고, 어느 정도 학습 한 후에 전이 모델만 freezing한다. 처음부터 freezing하니 정확도가 잘 안올라갔다. freezing을 풀고 학습하니 빠르게 상승하였다. 20~30에폭만에 train 80%, val 70%가 나온다. 어떤 경우는 전이모델의 상단 일부만 freezing하기도 한다.
  • train 93%, val 82% 정도까지 나옴.
  • 위 모델 2개를 만들고 병합하니 lb 83% 정도 나옴.
  • 더 학습 시킬 필요가 있어서 모델3을 생성 중. EarlyStopping 조건을 변경하여 더 오래학습되도록 patience를 증가. delta는 더 작게.

Try6. v3 ; metrics ; 91.5%

EarlyStopping 조건이 중요하다. f1_score를 조건으로 주고, 이어서 학습하되. 전이모델은 weight freezing시켰음.

  • 평균 80에폭정도 학습.
  • train 97%, val 85% 정도 나옴.
  • 데이터셋 구간을 달리하여 (cross validation) 모델 3개를 생성.
  • 개별 최대는 lb 86.8% 로 올라감.
  • 세 모델을 앙상블했더니 무려 5%나 상승하여 LB 91.58%. 드디어 90대 진입.
  • 그런데 개별로도 그 정도 나와야 되지 않나?

Try7.v4 ; 92.7%

개선해야 될 점.

  • 모델 세 개를 하나씩 불러 예측하려니 시간이 많이 소요됨. 웨이트만 저장하여 불러쓰는 것으로 하자. (이렇게 해봤는데 속도 차이가 거의 없음???)
  • weight는 best_only로 checkpoint를 저장하는 방식 사용. (monitor에 val_f1_score, mode는 max로 지정해야 함)
  • 3개를 만들어 앙상블 ; 92% (LB)

Try8. v5 ; 93.5%

  • 5개의 fold로 데이터 구분하여 새로 학습하고 5개를 앙상블해 보자.

More or Stop?

  • 일단, 현재까지 버전 commit.
  • 좀 더 올릴 수 없을까?
  • 이미지 전처리에서 crop할 때 margin을 추가할까?
  • 이미지 일부 제거 기능을 끄는 것이 좋을까?
  • 일괄 처리로 모델 5개 생성해서 다시 시도?
  • 전이학습 모델을 다른 것으로 변경해 볼까?

Try v6

  • 이미지 crop시 마진 20픽셀 추가. 이미지 왜곡시에 덜 잘릴 듯.
  • 이미지 일부 삭제 기능(cut-out)은 off 시키니까 acc 2% 감소.
  • 이미지 일부 삭제 기능이 있는 것이 좋다!

Try v7

  • 이미지 일부 삭제 on ; 반드시 사용해야 겠다.
  • 마진도 사용하는 것이 좋을 것 같다.

Try v8

  • xception과 resnet50 모델을 각각 5개씩 만들고 val_f1_score가 높은 순서대로 5개를 골라서 합의.
  • 합의 방식 ; 기존 : np.sum(a,b, axis=0)
  • 최대,최소를 버리고 중간 판정자 점수 합계??? 테스트 필요.
    • minv = np.min(…), maxv = np.max(…), np.sum() - (minv+maxv)
  • xception이 가장 괜찮은 것 같다. resnet50은 느리고 학습이 잘 안됨. mobilenetv2는 되긴 하지만 성능이 좀 떨어진다. efficientnetb2도 학습이 잘 안됨.
  • xception만으로 구성하는 것이 가장 낫다는 결론.
  • xception 모델 5개를 앙상블하면 개별로는 f1_score가 85,86,87 정도인데, 합치면 92 정도로 올라간다. (5%정도 인상)
  • Pseudo Labeling??? xception 모델에서 성능이 가장 좋은 것을 선정하여 test셋을 예측하였고, 예측시 가장 높은 확률의 클래스의 확률값을 히스토그램으로 보니, 0.99 이상이 반 정도 나왔다. 0.99 이상으로 예측한 라벨을 맞다고 가정하여, test 셋에서 라벨을 할 수 있는 부분들을 추출하여 pseudo set을 만들었다.
  • train set에 pseudo set을 추가하여 학습할 데이터를 뻥튀기하여 학습!
  • xception 모델에서 성능이 가장 좋은 것을 선정하지 않고, 앙상블하여 판단한 결과를 사용하였다. (더 확률이 올라감)
  • 90% 이상 정도는 맞출 것이고, 그 중 상위 50% 정도를 추가 학습데이터로 한 것이-라 어느 정도 일리가 있다.
  • 이렇게 훈련셋을 증가하고 기존 개별 모델들은 연속 학습하니, 개별 모델들의 f1 score가 더 올라갔다. 대략 85,86,87에서 94,95,96 정도로.(10%인상?) 이것을 다시 앙상블 한다면?
  • 결론은… 92. TT
  • 마지막에 1epoch만 all set을 대상으로 학습. 약간의 보정???
    -stratifiedkfold 적용. fold 나눌 때 클래스 비율을 유지해준다고 한다.

Try9

  • 이미지 크기 확장. 왜 224x224로 했지?(처음했던 mobilenetv2 기준). 299x299로 확장.(xception기준). 아무래도 이미지가 커야 더 잘 구분하겠다.
  • xception 베이스 모델 사용. : 기존 유지
  • cut out image (일부 손실. 자름. 검은 박스 노이즈 추가) : 기존 유지
  • 마진 20픽셀 유지하고 resize.
  • straitifiedkfold 적용. fold5으로 모델 3개 생성
  • pseudo label 삭제.
  • 진행. 먼저 single model의 성능부터 파악하자. 앙상블은 나중에.
  • 기존은 개별이 85정도 val f1 score 였다.
  • 메모리 사용량 증가로 batch는 16으로 낮춤. 나중에는 4로 낮춤.
  • Augument parameter!
    • rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip=True, vertical_flip=False, shear_range=0.5, brightness_range=[0.5, 1.5], fill_mode=‘nearest’, preprocessing_function=get_random_eraser(v_l=0, v_h=255)
    • 현재 진행 중인 것은 rotation은 15. 나머지는 0.1. brightness 추가. 이하 상동.
  • 메모리 부족… OOM. 메모리 부족 관련하여 좀 더 분석해야 할 것 같다.
    • 가공한 이미지를 numpy로 저장하여 불러서 다시 나누어 사용했는데, 이게 메모리 부족을 야기시키는 것 같다. 아예 처음부터 가공된 이미지를 디렉터리별 저장하고 kfold시 index로(파일명)으로 폴드에 맞는 이미지들만 로딩하여 사용하는 것이 좋은 것 같다.
    • 전체를 다 로딩하여 나누지 말고, Generator에서 디렉터리 지정하고, from dataframe으로 필요한 파일명 목록을 주는 방식으로 로딩.
    • 미처 다 못해보고 컴피티션이 종료됨.
    • 개발 환경이 좀 아쉽다. 캐글 커널로 좀 더 컴팩트하게 테스트할 수 있도록 준비가 필요할 것 같다.
    • 랜덤 고정 필요. 계속 변경되면 기준이 없어서 모델의 평가가 어렵다.

After… 94.1%

  • 다른 Pretraining Model 적용 비교
  • 이미지 전처리 결과를 numpy로 하지 않고, 이미지 파일로 저장하여 데이터셋 생성 및 로딩 방식으로 함.
  • flow_from_dataframe을 사용.
  • 이미지 크기를 299에서 250으로 줄였더니 메모리 압박에서 벗어났다.
  • Dropout 추가 : 개별로 최고 90%도 찍는다. (val_f1_score) 대략 89,90정도가 나옴.
  • Fold를 6개로 늘림.
  • 6개 네트웍 앙상블 결과 93.9%대가 나옴.
  • TTA 추가 ; 단순하게 좌우 flip만 하였다. 0.2%상승하여 94.1%대가 나옴. (최종적으로 12개의 결과를 합쳐서 평균으로 판단한 결과)

못해본 것 들…
다른 기본 네트웍 사용.
gray scale image 로 학습하는 것은 어떨까?
contour image 로 학습하는 것은 어떨까?

kaggle command

download kaggle api token (account menu)
copy to ~/.kaggle from ~/downloaddir/kaggle.json
chmod 600 ~/.kaggle/kaggle.json

kaggle competitions list -s titanic
kaggle competitions download titanic
데이터 파일 다운로드

kaggle kernels list --user junheeshin
kaggle kernels pull junheeshin/titanic-analyze
커널 소스 파일 가져옴.

Authors: crazyj7@gmail.com

'AI(DeepLearning)' 카테고리의 다른 글

[ChatGPT] 글쓰기 테스트  (1) 2023.02.09
XGBoost 요약  (0) 2019.12.06
Custom EarlyStopping  (0) 2019.11.11
타이타닉 kaggle 자료 분석  (0) 2019.08.23
Jupyter Lab/ TensorBoard 원격접속/방화벽  (1) 2019.08.09
반응형
crazyj7 kaggle EDA start

Kaggle EDA Start

데이터 분석 / 그래프 작성 / 통계 정보 등

Author: crazyj7@gmail.com

In [1]:
# 경고 무시 (쓸데없는 로그 출력금지)
import warnings
warnings.filterwarnings('ignore')

import numpy as np
import pandas as pd

# 그래프 관련 
import matplotlib.pyplot as plt
import seaborn as sns
In [2]:
# plot 환경설정 기본값과 달라진 점
class DictDiffer(object):
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """
    def __init__(self, current_dict, past_dict):
        self.current_dict, self.past_dict = current_dict, past_dict
        self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
        self.intersect = self.set_current.intersection(self.set_past)
    def added(self):
        return self.set_current - self.intersect 
    def removed(self):
        return self.set_past - self.intersect 
    def changed(self):
        return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
    def unchanged(self):
        return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])
In [3]:
# make default graph configure
# 그래프 설정값을 디폴트로 리셋해 준다. 
# (가끔 앞의 그래프 설정 변경으로 잘 나오던 그래프가 이상하게 나올때 사용)
def pltconfig_default():
    sns.reset_defaults()
    %matplotlib inline
    
pltconfig_default()
In [4]:
def pltconfig_check():
    d=DictDiffer(plt.rcParams, plt.rcParamsDefault)
    for it in d.changed():
        print(it, plt.rcParamsDefault[it], plt.rcParams[it])
        
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125

load data

In [5]:
inputdir='./'
outputdir='./'

df_train = pd.read_csv(inputdir+'train.csv')
df_test = pd.read_csv(inputdir+'test.csv')

데이터 탐색

head(n), describe(), info(), columns, index
value_counts()

data explore

In [6]:
# 데이터의 일부를 관찰. (파라미터가 없으면 디폴트로 5개)
df_train.head(3)
Out[6]:
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
In [7]:
# 데이터의 분포를 간략히 요약. 
# 개수, 평균, 표준편차, 사분위수(최소, 최대) 등.
df_train.describe()
# 개수를 보면 어느 필드에 빠진 데이터들이 있는지 알 수 있음.
Out[7]:
PassengerId Survived Pclass Age SibSp Parch Fare
count 891.000000 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000
mean 446.000000 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 223.500000 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200
In [8]:
# info는 필드들의 정보. 데이터타입. 개수 등
df_train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
In [9]:
df_test.head()
Out[9]:
PassengerId Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 892 3 Kelly, Mr. James male 34.5 0 0 330911 7.8292 NaN Q
1 893 3 Wilkes, Mrs. James (Ellen Needs) female 47.0 1 0 363272 7.0000 NaN S
2 894 2 Myles, Mr. Thomas Francis male 62.0 0 0 240276 9.6875 NaN Q
3 895 3 Wirz, Mr. Albert male 27.0 0 0 315154 8.6625 NaN S
4 896 3 Hirvonen, Mrs. Alexander (Helga E Lindqvist) female 22.0 1 1 3101298 12.2875 NaN S

NULL (Missing) 데이터 검사

In [10]:
df_train.isnull().sum()
Out[10]:
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64
In [11]:
# 데이터 분포도
# 히스토그램으로 구간별 카운팅
# 박스플롯으로 어느 지점에 데이터가 밀집해 있는지 알 수 있다. 
fig, axs = plt.subplots(1,2)
df_train.Fare.plot.hist(ax=axs[0])
df_train.boxplot(['Fare', 'Age', 'SibSp', 'Parch'], ax=axs[1])  # 파라미터 지정이 없으면,  주어진 dataframe의 모든 컬럼별 데이터 분포
Out[11]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f29002a30b8>
In [12]:
# 평균 , 표준편차
print('fare mean=', df_train.Fare.mean(), df_train.Fare.std())
# 표준 편차는 정규분포를 따를때,  평균에서 +- 1 표준편차는 전체의 65% 정도가 해당되고,
# # +-2표준편차는 95%, +-3표준편차는 99%정도로 본다. (1.96이 95%, 2.58이 99%)
# 사분위수
print('quantile = ', df_train.Fare.quantile(0), df_train.Fare.quantile(0.25), df_train.Fare.quantile(0.5), df_train.Fare.quantile(0.75), 
                  df_train.Fare.quantile(0.99), df_train.Fare.quantile(1))
fare mean= 32.204207968574636 49.6934285971809
quantile =  0.0 7.9104 14.4542 31.0 249.00622000000033 512.3292

데이터 수정/병합

In [13]:
# df3 = pd.concat([df1 , df2], axis=0)  
# df3 = df1.append(df2, ignore_index=True)  
# df4.drop(columns='age', inplace=True)  

df_train.head()
print(df_train.shape)
(891, 12)
In [14]:
df_test.head()
df_test.shape
Out[14]:
(418, 11)
In [15]:
# train, test 데이터가 survived를 제외하고 동일함. 합쳐서 전처리 작업을 할 수 도 있다.
# drop은 columns or rows를 삭제할 수 있다. (array로 여러개 지정 가능)
# concat은 병합. axis로 방향. 다른 방법으로는 df_train.append(df_test)을 리턴으로 받으면 된다.
# iloc는 array index로 filtering
# inplace는 자체 수정 여부. (False이면 자체수정없이 수정된것을 반환.)
# ignore_index=True 옵션을 주면, 인덱스를 0부터 새로 매긴다. False이면 인덱스 값이 중복되더라도 유지한다.

# df_all = pd.concat([df_train.iloc[:,2:], df_test.iloc[:,1:]], axis=0)
# or
df_all = pd.concat([df_train.drop(columns='Survived'), df_test], axis=0)
In [16]:
# passengerid는 의미없으므로 제거.
df_all.drop(columns='PassengerId', inplace=True)
In [17]:
df_all.head()
Out[17]:
Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
In [18]:
# 컬럼 타입별로 구분. 숫자와 숫자 아닌 것. 위에 info()에 마지막에 dtypes 참고.
df_num = df_all.select_dtypes(include=['int64', 'float64'])
df_str = df_all.select_dtypes(include=['object'])

df_num.describe()
Out[18]:
Pclass Age SibSp Parch Fare
count 1309.000000 1046.000000 1309.000000 1309.000000 1308.000000
mean 2.294882 29.881138 0.498854 0.385027 33.295479
std 0.837836 14.413493 1.041658 0.865560 51.758668
min 1.000000 0.170000 0.000000 0.000000 0.000000
25% 2.000000 21.000000 0.000000 0.000000 7.895800
50% 3.000000 28.000000 0.000000 0.000000 14.454200
75% 3.000000 39.000000 1.000000 0.000000 31.275000
max 3.000000 80.000000 8.000000 9.000000 512.329200
In [19]:
# 스트링 컬럼으로 보면, 클래스 개수(unique참조), 전체 개수 파악(미싱제외)
df_str.describe()
Out[19]:
Name Sex Ticket Cabin Embarked
count 1309 1309 1309 295 1307
unique 1307 2 929 186 3
top Kelly, Mr. James male CA. 2343 C23 C25 C27 S
freq 2 843 11 6 914
In [20]:
# 필드값별로 카운팅
df_train['Survived'].value_counts()
Out[20]:
0    549
1    342
Name: Survived, dtype: int64
In [21]:
# ## 스트링 필드를 분할하여 추가 컬럼들을 만들기

lstPath = ['img100_GENUINE.jpg', 'img101_FRAUD.jpg', 'img102_GENUINE.jpg', 'img103_FRAUD.jpg', 'img104_FRAUD.jpg', 'img105_GENUINE.jpg']
dfSample = pd.DataFrame({'path':lstPath})
dfSample
Out[21]:
path
0 img100_GENUINE.jpg
1 img101_FRAUD.jpg
2 img102_GENUINE.jpg
3 img103_FRAUD.jpg
4 img104_FRAUD.jpg
5 img105_GENUINE.jpg
In [22]:
# expand를 True로 하면 n개의 컬럼으로 리턴.
# expand를 False로 하면 1개의 컬럼내에 list로 리턴.
dfSplit = dfSample['path'].str.split('_', expand=False)
print(dfSplit[0][0], dfSplit[0][1])
print(dfSplit[1][0], dfSplit[1][1])
img100 GENUINE.jpg
img101 FRAUD.jpg
In [23]:
dfSplit = dfSample['path'].str.split('_', expand=True)

dfSample['name'] = dfSplit[0]
dfSample['tf'] = dfSplit[1].str.replace('.jpg', '')

dfSample
Out[23]:
path name tf
0 img100_GENUINE.jpg img100 GENUINE
1 img101_FRAUD.jpg img101 FRAUD
2 img102_GENUINE.jpg img102 GENUINE
3 img103_FRAUD.jpg img103 FRAUD
4 img104_FRAUD.jpg img104 FRAUD
5 img105_GENUINE.jpg img105 GENUINE

Submission 데이터만들기

In [24]:
df_submit = pd.read_csv(inputdir+'gender_submission.csv')
print(df_submit.head())
print(df_submit.columns)
   PassengerId  Survived
0          892         0
1          893         1
2          894         0
3          895         0
4          896         1
Index(['PassengerId', 'Survived'], dtype='object')
In [25]:
# 필드값 바꿔서 제출하기
# df_submit.describe()
print('record count=', df_submit.shape[0])
dfsubmit2 = df_submit.copy()
# 원하는 필드값을 변경한다.
dfsubmit2['Survived'] = np.zeros(df_submit.shape[0], dtype=int)
print(dfsubmit2.head())
# dfsubmit2.to_csv('result.csv')
record count= 418
   PassengerId  Survived
0          892         0
1          893         0
2          894         0
3          895         0
4          896         0
In [26]:
# 샘플을 참고하지 않고 직접 만들어 제출하기
pids = df_submit['PassengerId'].values
surv = df_submit['Survived'].values
print(pids.shape)
print(surv.shape)
(418,)
(418,)
In [27]:
dfresult = pd.DataFrame({'PassengerId':pids, 'Survived':surv})
print('columns=', dfresult.columns)
print('index=', dfresult.index)
print(dfresult.head())
columns= Index(['PassengerId', 'Survived'], dtype='object')
index= RangeIndex(start=0, stop=418, step=1)
   PassengerId  Survived
0          892         0
1          893         1
2          894         0
3          895         0
4          896         1
In [28]:
# 경우에 따라 인덱스를 특정 필드로 지정해줘야 되는 서미션도 있음. 제출형식을 확인해야 함.
dfresult.set_index('PassengerId', inplace=True)
print('columns=', dfresult.columns)
print('index=', dfresult.index)
print(dfresult.head())
columns= Index(['Survived'], dtype='object')
index= Int64Index([ 892,  893,  894,  895,  896,  897,  898,  899,  900,  901,
            ...
            1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309],
           dtype='int64', name='PassengerId', length=418)
             Survived
PassengerId          
892                 0
893                 1
894                 0
895                 0
896                 1

matplotlib plot

matplotlib 그래프 좌표축의값 없애기

plt.axis('off')
 axarr[uid].axis('off')
 axarr[uid].set_xticks(p[])
 plt.xticks([])

박스 제거

 ax1 = plt.axes(frameon=False)   # remove box
 or
 ax1 = plt.axes() ;
 ax1.set_frame_on(False)

y축 뒤집기

plt.gca().invert_yaxis()
 # or
 ax=plt.gca()
 ax.set_ylim(ax.get_lim()[::-1])

그래프간 간격 조정

plt.subplots_adjust(hspace=0.5, wspace=0.4)

가로/세로 비율 유지(좌표값을 절대적 기준)

ax.set_aspect('equal', 'box')

직선 그리기 (by 기울기)

def abline(slope, intercept):
     axes = plt.gca()
     x_vals = np.array( axes.get_xlim())
     y_vals = intercept+slope*x_vals
     plt.plot(x_vals, y_vals, 'r--')

plot 파라미터/함수

     lw : 선 두께
     c : 색깔
     s : 사이즈
     alpha : 투명도 (0일 수록 투명. 1일수록 불투명)
     label : legend 출력시 표시
     marker : 표시도형 o, x 등 
     'r--' : 빨간 점선
     'g^' : green 세모
     'ro' : 빨간 o
     'bs' : 파란 네모

     plt.title()
     plt.xlabel()
     plt.ylabel()
     plt.xlim(0,10) : x 범위
     plt.ylim(20,30) : y 범위
     plt.grid() : 눈금 표시
     plt.plot() : 꺽은선 그래프. 좌표들을 연결. lw, c, alpha, label
     plt.scatter() : 산점도 그래프. 좌표에 점(마커)를 찍는다. marker, c, alpha, label, s
     plt.legend() : 비고 박스, edgecolor='r' 로 박스라인 색깔지정 가능

     plt.tight_layout() : 여백없앰
     plt.scatter(x,y, linewidth=1, marker='o', facecolors='none', edgecolors='r')  : 빈 원 그리기
     plt.axhline(y, color='r') : 가로선
     plt.axvline(x, color='b') : 세로선

plot 저장

 plt.figure()
 plt.plot...
 plt.savefig('aaa.png') # 파일로 저장. 화면 출력여부는 아래코드
 plt.show() # 이것을 생략하면 화면 출력 안됨.
 plt.close()

ax 함수

ax.set_title()
 ax.set_xlabel()
 ax.set_ylabel()
 ax.set_xlim()
 ax.set_ylim()

개수 분포 그래프

  • dataframe.value_counts().plot.bar() / plot.pie()
  • sns.countplot()
In [29]:
# scatter 그래프

plt.figure()
# plt.grid('on')
plt.title('age and fare')
flagman=df_train['Sex']=='male'
plt.scatter( df_train.loc[flagman]['Age'], df_train.loc[flagman]['Fare'], c='blue', alpha=0.3, label='male')
flagfemale = ~flagman
plt.scatter( df_train.loc[flagfemale]['Age'], df_train.loc[flagfemale]['Fare'], marker='x', c='red', alpha=0.3, label='female')
plt.axhline(y=200)
plt.xlabel('Age')
plt.ylabel('Fare')
plt.legend(edgecolor='red')  # 비고박스(legend) 외곽라인 색 지정 가능 
plt.show()
plt.close()
In [30]:
# plot . x 라벨 지정 및  회전 
x = [1, 2, 3, 4]
y = [1, 4, 9, 6]
labels = ['Frogs', 'Hogs', 'Bogs', 'Slogs']
plt.plot(x, y)
# You can specify a rotation for the tick labels in degrees or with keywords.
plt.xticks(x, labels, rotation='vertical')
# Pad margins so that markers don't get clipped by the axes
plt.margins(0.2)
# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=0.15)
plt.show()
plt.close()
In [31]:
# 개수 분포, 그래프
df_train['Survived'].value_counts().plot.bar()
Out[31]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ffba2160>
In [32]:
# 카테고리 분포 
df_train['Embarked'].value_counts().plot.pie(autopct='%.2f %%')
plt.legend()
Out[32]:
<matplotlib.legend.Legend at 0x7f28ffb96e80>
In [33]:
# 카테고리 분포. 그룹별. stack bar
dfembarkedsurv = df_train.groupby(['Embarked', 'Survived'])['Survived'].count().unstack('Survived').fillna(0)
dfembarkedsurv.plot(kind='bar', stacked=True)
Out[33]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ffafc9b0>
In [34]:
# 여러 그래프를 한 번에 그리기.
# 두 가지 방법이 있다.
# plt.subplots 와 plt.subplot 
#  subplots는 리턴받아 사용. subplot은 리턴값 안받고 그때그때 사용.
# 
# ex) subplot(행,열, 현재번호)
# plt.subplot(1,2,1)
# plot...
# plt.subplot(1,2,2)
# plot...
# ex) f,ax = subplots(행,열)
# plots... by ax[인덱스번호]
# 
# 생존자 비율
# plt.figure()
f, ax = plt.subplots(1,2)

df_train['Survived'].value_counts().plot.pie(explode=[0, 0.1], autopct='%.2f%%', ax=ax[0], shadow=True)
ax[0].set_title('Survived ratio')
ax[0].set_ylabel('')

# Survived 컬럼 카운트 (dataframe plot보다 이쁨)
sns.countplot('Survived', data=df_train, ax=ax[1])
Out[34]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ffa24b38>
In [35]:
# 위와 같은 그림을 다른 방식으로
plt.figure(figsize=(2*5,5))
plt.suptitle('Bit Title', fontsize='x-large')

plt.subplot(1,2,1)
plt.title('title1')
xs = df_train['Survived'].value_counts()
print(xs.values)
df_train['Survived'].value_counts().plot.pie(autopct='%.2f %%', labels=['Dead', 'Survived'])  #autopct='%.2f %%'

plt.subplot(1,2,2)
plt.title('title2')
sns.countplot('Survived', data=df_train)

plt.show()
[549 342]
In [36]:
# 가로축에 값이 많은 경우, 글씨가 안보임. 글씨 회전
import random
# 랜덤 스트링 분포도
rs=[]
rs2=[]
for i in range(1000):
    c = chr(np.random.randint(0, 26)+ord('A'))  # 주의! random.randint(0,26) 이 아니다. np.random.randint와 사용방식이 다름!
    rs.append(c)
    c = chr(random.randint(0, 25)+ord('A'))  # random.randint는 마지막값이 범위에 포함된다!!! 
    rs2.append(c)
# print(rs)
# print(rs2)

from collections import Counter

# +
counter1 = Counter(rs)
dfc1 = pd.DataFrame([ [x1,x2] for x1,x2 in counter1.items() ], columns=['Letter', 'Count'])
dfc1 = dfc1.sort_values('Count', ascending=False)

plt.figure()
# sns.barplot(dfc1['Letter'], dfc1['Count'], color='blue', label='LetterCount')
sns.barplot(dfc1['Letter'], dfc1['Count'], label='LetterCount') # 색상이 없으면 무지개색 
plt.show()
In [37]:
# x 축을 일치시키고 y값 비교하기 / x축 회전 rotation

dfc1 = dfc1.sort_values('Letter', ascending=True)

counter2 = Counter(rs2)
dfc2 = pd.DataFrame([ [x1,x2] for x1,x2 in counter2.items() ], columns=['Letter', 'Count'])
dfc2 = dfc2.sort_values('Letter', ascending=True)
xvalue = dfc1['Letter']

plt.figure(figsize=(8, 6))
plt.title('Letter Count')
plt.xticks(rotation=90)   # x 라벨 회전. (글자가 겹칠때 유용함)
sns.barplot(xvalue, dfc1['Count'], color='blue', alpha=0.5, label='by np')
sns.barplot(xvalue, dfc2['Count'], color='red', alpha=0.5, label='by random')
plt.legend()
plt.show()
    
# -

그룹별 카운팅

  • dataframe.groupby() : array로 여러개 가능
  • sns.countplot() : hue
  • dataframe.crosstab() : 표생성. 세로필드, 가로필드. (세로필드를 array로 어러개 가능)
  • sns.factorplot(x,y,hue) : y평균값 그래프. hue로 지정된 필드의 종류만큼 라인이 그려짐.
  • sns.violinplot(x,y,hue) : y값의 범위와 분포를 알 수 있는 그래프.
In [38]:
# 성별과 생존 관계
df_train.groupby(['Sex', 'Survived'])['Survived'].count()
Out[38]:
Sex     Survived
female  0            81
        1           233
male    0           468
        1           109
Name: Survived, dtype: int64
In [39]:
sns.countplot('Sex', hue='Survived', data=df_train)
Out[39]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff7fa278>
In [40]:
sns.countplot('Embarked', hue='Sex', data=df_train)
Out[40]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff78f898>
In [41]:
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125
In [42]:
# 두 개의 기준으로 groupby한 카운팅
pd.crosstab(df_train['Sex'], df_train['Survived'], margins=True).style.background_gradient(cmap='summer_r')
Out[42]:
Survived 0 1 All
Sex
female 81 233 314
male 468 109 577
All 549 342 891
In [43]:
## 피클래스와 생존 관계
pd.crosstab(df_train['Pclass'], df_train['Survived'], margins=True).style.background_gradient(cmap='summer_r')
Out[43]:
Survived 0 1 All
Pclass
1 80 136 216
2 97 87 184
3 372 119 491
All 549 342 891
In [44]:
sns.countplot('Pclass', hue='Survived', data=df_train)
Out[44]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff1d3828>
In [45]:
## 성별과 피클래스에 따른 생존
In [46]:
pd.crosstab([df_train.Sex, df_train.Pclass], df_train.Survived, margins=True).style.background_gradient(cmap='summer_r')
Out[46]:
Survived 0 1 All
Sex Pclass
female 1 3 91 94
2 6 70 76
3 72 72 144
male 1 77 45 122
2 91 17 108
3 300 47 347
All 549 342 891
In [47]:
pd.crosstab([df_train.Sex, df_train.Survived], df_train.Pclass, margins=True).style.background_gradient(cmap='summer_r')
Out[47]:
Pclass 1 2 3 All
Sex Survived
female 0 3 6 72 81
1 91 70 72 233
male 0 77 91 300 468
1 45 17 47 109
All 216 184 491 891
In [48]:
## 평균 꺽은선 그래프
In [49]:
sns.factorplot('Pclass', 'Survived', hue='Sex', data=df_train)
Out[49]:
<seaborn.axisgrid.FacetGrid at 0x7f28ff75a278>
In [50]:
sns.factorplot('Pclass', 'Age', hue='Sex', data=df_train)
Out[50]:
<seaborn.axisgrid.FacetGrid at 0x7f2935cdef60>
In [51]:
sns.violinplot('Pclass', 'Age', hue='Survived', data=df_train, split=True)
Out[51]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f2934c07a90>
In [52]:
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125

히스토그램

  • dataframe.plot.hist(bins=count, color='blue')
  • sns.FaceGrid(data, hue), map, plt.hist : hue를 주면 hue로 지정된 필드의 종류별로 겹침.
In [53]:
# +
# df_train['Age'].value_counts()

# +
# 히스토그램. 두 개 비교.

# 연령대별 생존자 수, 사망자 수 2개 그래프 겹침 
grid = sns.FacetGrid(df_train, hue='Survived', size=4)
# bins는 개수로 지정할 수 도 있지만, 구간을 입력할 수도 있다.
grid.map(plt.hist, 'Age', alpha=.6, rwidth=0.8, bins=[0,10,20,30,40,50,60,70,80,90,100])
# bins 구간에 맞추어 x tick을 지정해 준다.
xlist=list(range(0, 110, 10))
print(xlist)
plt.xticks(xlist)
grid.add_legend()
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
Out[53]:
<seaborn.axisgrid.FacetGrid at 0x7f2934ba26d8>
In [54]:
# 위 히스토그램을 각각 그리기
grid = sns.FacetGrid(df_train, col='Survived', size=4, margin_titles=True)
grid.map(plt.hist, 'Age', bins=[0,10,20,30,40,50,60,70,80,90,100], color='green', histtype='step') # histtype 생략시(default='bar') 색칠한 일반 모양
# title을 value로 지정
# grid.set_titles(row_template='{row_name}', col_template='{col_name}')  # 이것을 생략하면 제목은 알아서 column=value가 된다. 
Out[54]:
<seaborn.axisgrid.FacetGrid at 0x7f28ffcd70b8>
In [55]:
# 히스토그램. 
df_train[ df_train['Survived']==0 ].Age.plot.hist(bins=20, color='red', rwidth=0.9)  
# rwidth (0~1)범위로 가로크기 비율을 정해 여백을 줄 수 있다.
xlist = list(range(0, 85, 5))
plt.xticks(xlist)
plt.margins(x=0)  # 안쪽 x 마진 제거
plt.show()
In [56]:
# FacetGrid로 가로로 여러 그래프 그리기(그룹/컬럼별)
grid = sns.FacetGrid(df_train, col='Embarked', size = 3)
grid.map(sns.barplot, 'Sex', 'Survived', palette='deep', order=['female','male'])  
# order가 없으면 male, female 순으로 나온다. 
Out[56]:
<seaborn.axisgrid.FacetGrid at 0x7f28ff811cf8>

상관계수

In [57]:
# Dataframe 상관계수 테이블 correlation 
df_num.corr()
Out[57]:
Pclass Age SibSp Parch Fare
Pclass 1.000000 -0.408106 0.060832 0.018322 -0.558629
Age -0.408106 1.000000 -0.243699 -0.150917 0.178740
SibSp 0.060832 -0.243699 1.000000 0.373587 0.160238
Parch 0.018322 -0.150917 0.373587 1.000000 0.221539
Fare -0.558629 0.178740 0.160238 0.221539 1.000000
In [58]:
# 상관계수 히트맵 
sns.heatmap( df_train.drop('PassengerId', axis=1).corr(), annot=True)
Out[58]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f28ff880ac8>
In [59]:
cols = ['Survived', 'SibSp', 'Parch', 'Fare']
cm = np.corrcoef(df_train[cols].values.T)
sns.set(font_scale=1.25)
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, 
  fmt='.2f', annot_kws={'size':10} , yticklabels=cols, xticklabels=cols)
In [60]:
# 컬럼별 2차원 데이터 분포도. scatter, histogram.
sns.set()
cols=['Age', 'Survived', 'Fare']
sns.pairplot(df_train[cols], size=2.5)
plt.show()

pltconfig_check()
grid.color #b0b0b0 white
patch.force_edgecolor False True
lines.solid_capstyle projecting round
ytick.color black .15
xtick.minor.width 0.6 1.0
patch.edgecolor black w
font.size 10.0 12.0
xtick.labelsize medium 11.0
ytick.major.size 3.5 6.0
axes.titlesize large 12.0
axes.linewidth 0.8 1.25
xtick.color black .15
axes.facecolor white #EAEAF2
axes.prop_cycle cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']) cycler('color', [(0.2980392156862745, 0.4470588235294118, 0.6901960784313725), (0.8666666666666667, 0.5176470588235295, 0.3215686274509804), (0.3333333333333333, 0.6588235294117647, 0.40784313725490196), (0.7686274509803922, 0.3058823529411765, 0.3215686274509804), (0.5058823529411764, 0.4470588235294118, 0.7019607843137254), (0.5764705882352941, 0.47058823529411764, 0.3764705882352941), (0.8549019607843137, 0.5450980392156862, 0.7647058823529411), (0.5490196078431373, 0.5490196078431373, 0.5490196078431373), (0.8, 0.7254901960784313, 0.4549019607843137), (0.39215686274509803, 0.7098039215686275, 0.803921568627451)])
text.color black .15
interactive False True
xtick.minor.size 2.0 4.0
ytick.major.width 0.8 1.25
xtick.bottom True False
ytick.minor.width 0.6 1.0
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
axes.labelsize medium 12.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
axes.axisbelow line True
grid.linewidth 0.8 1.0
font.sans-serif ['DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif'] ['Arial', 'DejaVu Sans', 'Liberation Sans', 'Bitstream Vera Sans', 'sans-serif']
legend.fontsize medium 11.0
figure.subplot.bottom 0.11 0.125
xtick.major.width 0.8 1.25
axes.edgecolor black white
ytick.labelsize medium 11.0
axes.grid False True
patch.facecolor C0 (0.2980392156862745, 0.4470588235294118, 0.6901960784313725)
ytick.minor.size 2.0 4.0
axes.labelcolor black .15
ytick.left True False
xtick.major.size 3.5 6.0
image.cmap viridis rocket

Evaluation

In [61]:
#  confusion_matrix( real, predict ) : real vs predict 결과 비교. 대각선이 많을수록 맞춘것임.

from sklearn.metrics import confusion_matrix

y_real=[]
y_predict=[]
for i in range(1000):
    v = np.random.randint(0, 10)
    y_real.append(v)
    if np.random.rand()<0.8:
        y_predict.append( np.random.randint(0, 10))
    else:
        y_predict.append(v)
cm = confusion_matrix(y_real, y_predict)  # row=real, column=predict
cm
Out[61]:
array([[21,  8,  7,  8,  9,  7,  7,  7,  6,  7],
       [12, 15,  4,  9,  6, 10, 10, 12,  6,  2],
       [ 7, 10, 33,  5, 10,  8,  8,  6,  9,  8],
       [ 9, 13,  7, 27,  9,  8,  9,  6, 14, 10],
       [ 6, 10, 10,  7, 41, 13, 12,  6,  8,  8],
       [ 6,  9,  9,  7,  3, 29,  9,  8, 14,  5],
       [14,  7,  6, 11,  7, 12, 23, 10,  7,  7],
       [15, 10, 11,  8,  7,  4,  6, 22,  4,  6],
       [ 9,  5,  8,  6,  5,  9,  4,  8, 34, 11],
       [ 6,  8,  4,  6,  9,  7, 12,  8,  4, 31]])
In [62]:
# draw confusion matrix with seaborn
df_cm = pd.DataFrame(cm, index=range(10),
                  columns=range(10))
# plt.figure(figsize = (10,7))
# sns.set(font_scale=1.4)  # for label size. 변경시 다른 plot도 전부 영향을 받음.
sns.heatmap(df_cm, annot=True,annot_kws={"size": 10})  # font size
# sns.set(font_scale=1.0) # back to the default font size.... 
# 설정 변경시 이후 다른 plot 환경 변화로 문제가 발생.
Out[62]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f29349d73c8>
In [63]:
pltconfig_check()
grid.color #b0b0b0 white
patch.force_edgecolor False True
lines.solid_capstyle projecting round
ytick.color black .15
xtick.minor.width 0.6 1.0
patch.edgecolor black w
font.size 10.0 12.0
xtick.labelsize medium 11.0
ytick.major.size 3.5 6.0
axes.titlesize large 12.0
axes.linewidth 0.8 1.25
xtick.color black .15
axes.facecolor white #EAEAF2
axes.prop_cycle cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']) cycler('color', [(0.2980392156862745, 0.4470588235294118, 0.6901960784313725), (0.8666666666666667, 0.5176470588235295, 0.3215686274509804), (0.3333333333333333, 0.6588235294117647, 0.40784313725490196), (0.7686274509803922, 0.3058823529411765, 0.3215686274509804), (0.5058823529411764, 0.4470588235294118, 0.7019607843137254), (0.5764705882352941, 0.47058823529411764, 0.3764705882352941), (0.8549019607843137, 0.5450980392156862, 0.7647058823529411), (0.5490196078431373, 0.5490196078431373, 0.5490196078431373), (0.8, 0.7254901960784313, 0.4549019607843137), (0.39215686274509803, 0.7098039215686275, 0.803921568627451)])
text.color black .15
interactive False True
xtick.minor.size 2.0 4.0
ytick.major.width 0.8 1.25
xtick.bottom True False
ytick.minor.width 0.6 1.0
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
axes.labelsize medium 12.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
axes.axisbelow line True
grid.linewidth 0.8 1.0
font.sans-serif ['DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif'] ['Arial', 'DejaVu Sans', 'Liberation Sans', 'Bitstream Vera Sans', 'sans-serif']
legend.fontsize medium 11.0
figure.subplot.bottom 0.11 0.125
xtick.major.width 0.8 1.25
axes.edgecolor black white
ytick.labelsize medium 11.0
axes.grid False True
patch.facecolor C0 (0.2980392156862745, 0.4470588235294118, 0.6901960784313725)
ytick.minor.size 2.0 4.0
axes.labelcolor black .15
ytick.left True False
xtick.major.size 3.5 6.0
image.cmap viridis rocket
In [64]:
pltconfig_default()
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125
In [65]:
import itertools

def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    plt.figure()
    plt.grid('off')
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j],
                 horizontalalignment="center", verticalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
In [66]:
plot_confusion_matrix(cm, classes=range(10))
plt.show()
plt.close()
In [67]:
pltconfig_check()
figure.edgecolor white (1, 1, 1, 0)
figure.dpi 100.0 72.0
figure.figsize [6.4, 4.8] [6.0, 4.0]
figure.facecolor white (1, 1, 1, 0)
interactive False True
figure.subplot.bottom 0.11 0.125
In [ ]:
 
In [ ]:
 

+ Recent posts