머신러닝 & 딥러닝

dataframe에서 slice 개념

깃허브 3. 은행 이탈고객 예측

깃허브 4. 인디안 당뇨병 예측

[ 0:3 ]  -> 0, 1, 2 : 0번 칼럼부터 3전 까지
[ 3:13 ] -> 3번(0부터니까 4번째) 칼럼부터 13번 전 까지
* 시작은 0번 칼럼부터 세서, 앞쪽은 포함 뒤쪽은 불포함이다. 수학에서 ●-----○ 개념

개수는 쉽게 13-3 = 10으로 계산하면 되지만,
처음부터 세려면 index 3은 0부터 시작하므로, 4번째 칼럼부터다.

*쉽게하기 (my)

인덱싱의 앞부분 : 뒷부분 중 앞부분만 해석 / 뒷부분은 그냥 읽기
[a:b] =========>  읽을 때는(+1) (a+1)번째 칼럼부터 b번째 칼럼까지
c번째 칼럼부터 d번째 칼럼까지 작성할 때는 (-1) ====> [c-1:d]

image
- 첫번째 칼럼처럼 보이는 index는 칼럼이 아니다!
- 0번 칼럼은 RowNumber 13번 칼럼인 Exited는 불포함!



sklearn.preprocessing.py에 있는 Label Encoder와 OneHot Encoder 클래스

DataFrame에 values값이 문자열일 때, 연산이 불가능하므로

  1. 딕셔너리를 이용해서 mapping(0, 1, 2)해도 되지만
  2. sklearn이라는 라이브러리를 이용하여 Label Encoder클래스를 이용하면, 특정칼럼의 값을 자동으로 0, 1, 2, 3으로 배정해준다.
    - 하지만 이럴경우, 0과 1,2,3은 크다작다의 대소관계가 생겨버려 연산시 잘못된 계산을 할 수 있다.
    - LabelEncoder( 문자열 칼럼-> 숫자)  ====>  OneHotEncoder( 숫자 -> 각 행당 1을 한개만 가지는 2진 matrix)  ====> to.array()
  3. OneHot Encoder는  대소관계를 가지는 숫자들 0, 1, 2에 대해서, 각 행당 1개만 1로 주고 나머지는 0으로 주어 절대적인 크기가 1로서 다 같도록 만든다.
    - 2진 코드로 만들어 진다.
    image
    - 따로 이것을 .toarray()를 통해 array로 만들어줘야 딥러닝 모델에 넣을 수 있는 데이터가 된다.


train_test_split

이전에는 from sklearn.cross_validation import train_test_split 를 통해서 train/test -> train/valid 를 나누었지만
- trainX, testX, trainY, testY = train_test_split(X, y, test_size= 0.2, random_state=42)
- trainX, valX, trainY, valY = train_test_split(trainX, trainY, test_size=0.2, random_state=42)


여기서는 cross validation을 사용하지 않으면서 & valid set 없이 & random_state라는 seed도 주지않고 0.2만큼 잘라내는 것을
from sklearn.model_selection import train_test_split 을 통해서 수행한다.
- X_train, X_Test, y_train, y_test = train_test_split(X, y, test_size=0.2)


StandardScaler 과 Normalization

참고 사이트 : https://datascienceschool.net/view-notebook/f43be7d6515b48c0beb909826993c856/

스케일링

스케일링은 자료 집합에 적용되는 전처리 과정으로 모든 자료에 선형 변환을 적용하여 전체 자료의 분포를 평균 0, 분산 1이 되도록 만드는 과정이다.스케일링은 자료의 오버플로우(overflow)나 언더플로우(underflow)를 방지하고 독립 변수의 공분산 행렬의 조건수(condition number)를 감소시켜 최적화 과정에서의 안정성 및 수렴 속도를 향상시킨다.

my)
StandardScaler는 수치적으로는 평균은 0, 분산(표준편차) 1을 만들어주는  Z = X-m/a를 적용하여
값의 범위가 어떤 값을 가지든지 간에 표준 정규분포 안의 곡선으로 들어가도록 잡아준 것이다.

.

Scikit-Learn에서는 스케일링을 위한 함수와 클래스를 각각 제공한다. 스케일링 함수는 다음과 같다.

  • scale(X): 기본 스케일. 평균과 표준편차 사용
  • robust_scale(X): 중앙값(median)과 IQR(interquartile range) 사용. 아웃라이어의 영향을 최소화
  • minmax_scale(X): 최대/최소값이 각각 1, 0이 되도록 스케일링
  • maxabs_scale(X): 최대절대값과 0이 각각 1, 0이 되도록 스케일링

.

만약 파이프라인을 이용하면 스케일링을 함수가 아닌 Scaler 클래스로 구현해야 한다. scale 함수에 대응하는 클래스는 StandardScaler 클래스이다.

StandardScaler클래스의 사용 방법은 다음과 같다.

  1. 클래스 객체 생성
  2. fit() 메서드와 트레이닝 데이터를 사용하여 변환 계수 추정
  3. transform() 메서드를 사용하여 실제로 자료를 변환

또는 fit_transform() 메서드를 사용하여 계수 추정과 자료 변환을 동시에 실행할 수도 있다.


from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler.fit(data1)
data2 = scaler.transform(data1)

data1.std(), data2.std()
(1.974000985027335, 1.0)

정규화 (Normalization)

정규화(Normarlization)는 스케일링과 달리 개별 데이터의 크기를 모두 같게 만들기 위한 변환이다. 따라서 개별 데이터에 대해 서로 다른 변환 계수가 적용된다.

정규화는 다차원 독립 변수 벡터가 있을 때 각 벡터 원소들의 상대적 크기만 중요한 경우에 사용된다.

from sklearn.preprocessing import normalize

x = np.vstack([np.arange(5, dtype=float) - 20, np.arange(5, dtype=float) - 2]).T
y1 = scale(x)
y2 = normalize(x)

print("original x:\n", x)
print("scale:\n", y1)
print("norms (scale)\n", np.linalg.norm(y1, axis=1))
print("normlize:\n", y2)
print("norms (normalize)\n", np.linalg.norm(y2, axis=1))
original x:
 [[-20.  -2.]
 [-19.  -1.]
 [-18.   0.]
 [-17.   1.]
 [-16.   2.]]
scale:
 [[-1.41421356 -1.41421356]
 [-0.70710678 -0.70710678]
 [ 0.          0.        ]
 [ 0.70710678  0.70710678]
 [ 1.41421356  1.41421356]]
norms (scale)
 [2. 1. 0. 1. 2.]
normlize:
 [[-0.99503719 -0.09950372]
 [-0.99861783 -0.05255883]
 [-1.          0.        ]
 [-0.99827437  0.05872202]
 [-0.99227788  0.12403473]]
norms (normalize)
 [1. 1. 1. 1. 1.]
from sklearn.datasets import load_iris
iris = load_iris()

data1 = iris.data[:,:2]
data3 = normalize(data1)

In [8]:

sns.jointplot(data1[:,0], data1[:,1])
plt.show()

In [9]:

sns.jointplot(data3[:,0], data3[:,1])
plt.show()



인코딩(Encoding)

인코딩은 카테고리 값이나 텍스트 정보를 처리가 쉬운 정수로 변환하는 과정이다.

One-Hot-Encoder

One-Hot-Encoder는 one-of-K 인코딩이라고도 불리며 0 ~ K-1 의 값을 가지는 정수 스칼라값을 0 또는 1 값을 가지는 K-차원 벡터로 변환한다. 만약 입력이 스칼라가 아니라 벡터이면 각 원소에 대해 인코딩된 결과를 모두 연결한다. 각 원소의 위치 정보는 feature_indices_ 속성에 저장된다. 또 입력이 벡터인 경우에 특정한 열만 카테고리 값이면 categorical_features 인수를 사용하여 인코딩이 되지 않도록 지정할 수 있다. 이 때 인코딩 결과의 순서가 바뀔 수 있으므로 주의한다.

fit 메서드를 호출하면 다음과 같은 속성이 지정된다.

  • n_values_ : 각 변수의 최대 클래스 갯수
  • feature_indices_ : 입력이 벡터인 경우 각 원소를 나타내는 슬라이싱(slice) 정보
  • active_features_ : 실제로 사용된 클래스 번호의 리스트

One-Hot-Encoding 결과는 메모리 절약을 위해 스파스 행렬(sparse matrix) 형식으로 출력된다. 일반적인 배열로 바꾸려면 toarray 메서드를 사용한다.


from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()


X = np.array([[0], [1], [2]])
X
array([[0],
       [1],
       [2]])


ohe.fit(X)
ohe.n_values_, ohe.feature_indices_, ohe.active_features_
(array([3]), array([0, 3]), array([0, 1, 2]))


ohe.transform(X).toarray()
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])


X = np.array([[0, 0, 4], [1, 1, 0], [0, 2, 1], [1, 0, 2]]) 
X
array([[0, 0, 4],
       [1, 1, 0],
       [0, 2, 1],
       [1, 0, 2]])


ohe.fit(X)
ohe.n_values_, ohe.feature_indices_, ohe.active_features_
(array([2, 3, 5]), array([ 0,  2,  5, 10]), array([0, 1, 2, 3, 4, 5, 6, 7, 9]))


ohe.transform(X).toarray()
array([[1., 0., 1., 0., 0., 0., 0., 0., 1.],
       [0., 1., 0., 1., 0., 1., 0., 0., 0.],
       [1., 0., 0., 0., 1., 0., 1., 0., 0.],
       [0., 1., 1., 0., 0., 0., 0., 1., 0.]])


ohe = OneHotEncoder(categorical_features=[False, True, False])
ohe.fit_transform(X).toarray()
array([[1., 0., 0., 0., 4.],
       [0., 1., 0., 1., 0.],
       [0., 0., 1., 0., 1.],
       [1., 0., 0., 1., 2.]])


ohe.n_values_, ohe.feature_indices_, ohe.active_features_
(array([3]), array([0, 3]), array([0, 1, 2]))



Sigmoid와 Relu

image

  1. sigmoid는 마이너스->0 부분에서 왜곡된 부분을 가지므로
  2. relu가 은닉층에서 마이너스를 모두 0으로 치환시킨 다음
  3. 마지막에만 sigmoid를 activation func으로 써주는게 관례이다.


py파일

깃허브 3. 은행 이탈고객 예측

깃허브 4. 인디안 당뇨병 예측

필요 패키지

깃허브 2. 유방암 남/녀 예측

  1. cython : c계열의 라이브러리 사용 / c방식으로 파이썬 코딩 가능
    - https://anaconda.org/anaconda/cython
    - conda install -c anaconda cython
  2. numpy : 수치 처리 / matrix 계산 가능
  3. pandas : 데이터 과학에 필수적인 dataframe 등을 사용 / csv, 텍스트 파일 등을 사용한다.
  4. keras : 딥러닝 라이브러리, 프론트 엔드를 담당
  5. sklearn : 사이킷런, 파이썬이 기본적으로 제공하는 머신러닝 라이브러리
  6. tensorflow : 딥러닝 백엔드

Sequential과 Dense

Sequential은 선형으로 설명가능한 모델일 경우 사용할 수 있다. 즉, 어떤 선을 기준으로 구분할 수 있을 때이다.
선형 회귀분석용 / 분류용 가설 모델들은 대부분 Sequential을 사용한다.
예를 들어, 암이다 / 암이 아니다.
마이너스 방향으로도 선형으로 설명가능한 모델일 경우, Sequential을 쓰면 된다.

image

Dense는 입력층과 출력층을 모두 연결하는 Layer이다. 그래서 은닉층으로 많이 사용된다.


그외 라이브러리들

  1. sklearn의 cross_validation 클래스 안에 있는 train_test_split
    예를 들어, 100개의 문제가 있는데, 이것을 trainset과 validationset 그리고 testset으로 구분지어야하는 상황이다.
    image
    이 때, 검증셋과 시험셋에 대해서 시험셋에 예측하기 쉬운 것만 들어가서 100점을 맞을 수 있고,
    검증셋에 모르는 것만 들어가서, 학습자체가 제대로 안될 수 있다.
    이 때 생각해낸 것이 여러번 교차적으로 짤라내서 정밀도를 높이는 방법이 교차검증이다.
    image

  2. IPython.display 클래스의  clear_output
    콘솔에 출력할 때, 기존의 내용들을 지운 다음 다시 출력해주는 클래스이다.

  3. sklearn.metrics 클래스의 confusion_matrix
    주로 이진분류에서 사용되는 혼동행렬은, 원래 데이터와 예측값을 출력해주는 오류의 갯수를 나타내는 이진분류 결과표로서
    아래와 같이 생각하면 된다.

                      원래1                               원래2                             원래3
    원래1     원래1 예측1 표본수     원래1 예측2인 표본의 수     원래1 예측3인 표본의 수  -> a/a+b+c : 민감도
    원래2     원래2 예측1 표본수     원래2 예측2인 표본의 수    원래2 예측3인 표본의 수
    원래3     원래3 예측1 표본수     원래3 예측2인 표본의 수    원래3 예측3인 표본의 수
                   d/ d+e+f  = precision

Spyder로 작성한 py 파일

깃허브 2. 유방암 남/녀 예측

Spyder 설치 in anaconda

깃허브 1. 기초

이상하게 노트북에서 아나콘다 통합환경실행 및 Spyder 실행이 안된다...

https://anaconda.org/anaconda/spyder

cmd창에서

conda install -c anaconda spyder

image


Keras

구글 엔지니어가 개발한 것으로, 백엔드로 Tensor나 Theano를 지정할 수 있다.


list와 tuple

[ , , , ] 은 list이다. 하나의 리스트는 [ 0 ]하나로 나타내지만,

(, , , )은 tuple이다. 하나의 튜블은 빈 콤마라도 찍어야한다. ( 0 , )

- list의 대괄호는 생략가능하지만, tuple은 ( , )의 소괄호는 생략해서는 안된다.


keras model

  1. Sequential()은 선형 모델을 사용하겠다는 의미
  2. Dense라는 layers는 input과 output을 모두 연결하는 layer이므로, 은닉층에서 쓰기 좋다.
    - 이 때, 첫번째 파라미터는 output계층의 수이다.
    - 2번째 파라미터는 input계층의 수이다.
  3. complie은 컴퓨터가 알아들을 수 있게 하는 함수인데, 이 때 들어가는 파라미터로 이해하면 쉽다.
    - SGD : <최적화 방식>stochastic gradient Descent 통계적 경사하강의 방법으로 최적의 weight와 bias를 예측한다.
    - mse : <손실 함수> mean square error 평균을 제곱하여 에러를 확장시켜 차이가 명확하게 보이게 한다.
  4. fit은 training, 학습 한다는 의미이다.
    - X, y, 학습횟수, 메세지 출력형태 정도 이다.
  5. predict는 학습을 통해 얻어진 예측값들을 받아오는 함수이다.
    - 이 때, flatten()은 array형태로 얻어지는 예측값(행렬형태)를  1차원 배열로 바꾼 것이다.

  6. 이제 Target값인 y(정해진 답)과  예측한값 predict를 같이 print해서 비교해보자.


예제파일

깃허브 1. 기초

그림 및 글작성에 대한 도움 출저 : 유튜브 - 테리 엄태웅님의 딥러닝 토크


개요

딥러닝에 있어서, Accuracy말고도 여러가지 metric을 보아야하는 것 중 하나가 ROC커브이다.

저번시간에 다룬 아래의 4가지 개념에 대해서 다시한번 상기해보자.

image

  • True Positive : 올바른(예측)값들에 대해서, (실제값도) 올바른 경우,
    - 혼동행렬에서의 \ 대각선 라인을 의미(전체클래스의 TP)
  • True Negative for 특정클래스 : 거절해야할 (예측)값에 대해서, (실제값도) 거절되어야하는 경우,
  • False Positive for 특정클래스 : 올바른 (예측)값에 대해서, (실제값이) 거절한 경우,
  • False Negative for 특정클래스 : 거절해야할 (예측)값에 대해서, (실제값이 거절하지못하고) 올바른 경우

다르게 해석해보면, True/False는  예측값이 실제값과 같다/다르다를 얘기하는 것이다.
True인 경우는 실제값과 같으니 \ 대각선 방향에 위치하게 된다. 그 이외 박스들은 다 False라 보면 된다.
Positive/Negative예측값이 어떻게 나왔는지이다.
여기서는, 4가지 경우에 대해서만 다루니, 이렇게 해석이 가능한 것 같다.


예를 들어, True Positive 는 실제랑 예측이랑 같은 레알, 그 예측값이 양성으로 나온 경우이다.
True Negative는 실제값과 예측값이 같은 레알, 그 예측값이 음성으로 나온 경우이다.
image

False Positive는 실제랑 예측이랑 다른 거짓으로, 그 예측값이 양성으로 나온 경우이다.
- 거짓이려면, \대각선 이외의 값들 중에서 --> 예측값이 양성인 암으로 예측한 경우이다.
- 쉽게 외우려면, False Positive = False Alarm 거짓으로 알람이 울렸다고 외우면 된다.
False Negative는 실제랑 예측이랑 다른 거짓으로, 그 예측값이 음성으로 나온 경우이다.


Accuracy

정확도는 전체 중에, 맞은 것(\대각선, True, 레알)만 선택하면 된다.

image

그러나, 정확도는 클래스별 분포가 같을 때만 이용가능하다고 저번시간에 언급했다.
image

정상환자의 정확도는 988 / 990 =99.8%이지만,
암환자의 정확도는 9/10 = 90%이다.
전체 정확도는 99.7%로,,, 암환자의 정확도(90%)가 정확하게 반영되지 않는다.


정상환자의 분포는 990명, 암환자의 분포는 10명으로 여기서 accuracy를 보면 안된다. 머신러닝에서는 f1-score를 이용하면 된다고 했다.

Accuracy의 단점을 보완하는 성능척도가 Precision과 Recall이 그리고 ROC curveAUC이다.


Precision과 Recall

ROC curve에 대해 언급하기 전에, Precision과 Recall을 복습하자

Precision은 혼동행렬의 세로방향으로써,  특정 클래스의 예측값(Positive 판정)에 대해 실제 정답값은 얼마나 있는지이며,
Recall은 혼동행렬의 행방향으로써,  특정 실제값에 대해, 해당 예측값은 어떻게 당겨왔는지이다.
image


image


ROC curve

ROC curve는 보통 binary classification(2개의 클래스 분류) 나 medical application에서 많이 쓰는 성능 척도이다.

image

위의 그래프에서 어느것이 더 좋은  ROC 커브인가?
빨간색이 좋은 커브이다.

빨간색 커브가 더 좋은 이유는?
아래 면적을 구해서 더 큰 것이 좋은 커브가 된다. ROC curve 아래 면적을 AUC라(Area Under the Curve)라고 한다.
image


ROC curve를 쓰는 이유는 무엇일까?
클래스별 분포가 다를 때, Accuracy의 단점을 보완하면서 더 자세히 보기 위해서이다.

image

위의 그림처럼, 양 끝쪽은 확실히 정상이나 암환자로 구분이 가능하다.
하지만, 가운데 쪽은 판단이 불분명한 부분이 있을 수 밖에 없다.
image

이 상황에서 최선의 판단(초록색 선을 그는 행위를)하려면, 항상 error들을 포함할 수 밖에 없다.

아래의 그래프는 위에서 등장했던 그래프보다 훨씬 판별하기가 쉽다.
이 차이를 보는 것이 ROC curve이다.

image

내가 판단선(초록색선)을 내리는데, 왼쪽 <->오른쪽 으로 움직일 수록, 어느정도로 안좋은 결과를 초래하는지에 대한 얘기가 ROC curve라 할 수 있다.
아래의 분포는 초록선을 움직이더라도 error가 많이 안생길 것이다. 이러한 경우가 처음 등장한 ROC curve 그래프의 빨간색 선에 해당한다.

만약 위의 분포처럼 많이 겹치는 부분이 많을 수록 직선에 가까워 지게 된다.

image


ROC curve의 이용

feature를 골라내는 곳에 이용할 수 있다.
예를 들어, 누가 더 잘달리는 지 예측한다고 가정하자

feature로는 키, 몸무게를 선택한다.
그러면 키 큰 사람들 중에 못 달리는 사람, 키 작은 사람들 중에 빨리달리는 사람,
몸무게가 많이 나가지만 빨리달리는 사람, 몸무게가 적게나가지만 못 달리는 사람 정도가 겹치게 될 것이다.

data를 지난대회 것을 사용한 뒤, 100등을 기준으로 빨리 달리는사람과 못달리는 사람을 가른다고 가정해보자.
data자체가 양질의 데이터이기 때문에, ROC curve가 빨간색과 같은 것이 나올 것이다.
만약 90등이나 110등을 기준으로 짜르더라도, 민감도가 크지않을 것이다.

ROC curve는 양질의 데이터라면, 더 넓은 면적을 가질 것이며, 더 좋은 성능의 모델일수록 더 넓은 면적을 가질 것이다.


즉, ROC curve가 좋은 것을 사용한다
-> 머신러닝의 경우, raw_data에서 내가 정하는 Decision Boundary에 덜 민감하면서, label을 구분하는데 더 믿음이 가고 잘 예측되겠구나를 결정할 수 있다.
-> my) 딥러닝의 경우, 클래스별 분포가 다를 때, accuracy의 대용으로 사용한다. 특히 딥러닝 모델비교 및 사람과의 비교에 쓸 것이다.


ROC curve에서의 수식

image

기본적으로 ROC curve는 Recall( 행방향 : 실제값에 대해서 예측값이 어느정도로 )에 대한 얘기이다.

이 때 등장하는 개념이,
y축 : TPR(True Positive Rate) = Recall = sensitivity
x축 : 1 - ( TNR(True Negative Rate) = specificity )

- Recall이 높다는 것은 초록색선을 쭉 왼쪽으로 당겨서 실제 Positive 분포(TP)초록색 우측의 예측 Positive가 다 들어오도록 만드는 행위다.
  FN이 줄어들면서, TP는 엄청나게 증가한다. 그래서 TPN은 증가한다.
image

- 그러나 그렇게 된다면, 실제 Negative 분포(TN) 중 FP가 엄청나게 늘어나고 + 실제 검출되는 (TN)가 엄청나게 줄어들 것이다.
image

즉, Recall값을 높일 수록 TPR은 증가하지만, 그만큼 TNR은 줄어드는 Trade off가 생길 것이다.

이러한 변화에 대해서 TPN 및 TNR의 비율을 그래프로 그린 것이 ROC curve이다.
만약, TPN과 TNR의 비율을 그린다면 아래와 같은 모양으로 나타나게 되고,
image
TPN과 1-TNR의 비율을 그린다면, 처음 봤던 ROC curve 그래프가 나타나게 된다.
image


극단적으로 판단선을 왼쪽으로 옮겨보자.
image
이 경우, TN가 모두 FP가 되면서, TN=0이 된다.그렇다면 1-TNR은 1이 된다
FN도 0이 되어서, TPR은 1이 된다.
ROC curve 그래프 상에서는 우측상단이 될 것이다.
image


반면에, 판단선을 가장 우측으로 밀어넣으면,
TP가 모두 FN가 되면서, TP=0 -> TPR =0
FP가 모두 TN가 되면서, TNR =1 -> 1-TNR = 0이 되면, 그래프상에는 아래와 같은 점이 찍힌다.
image



요약하자면,
Accuracy가 다가 아니다.
클래스가 imbalanced한 data라면 Precision과 Recall도 봐야한다.
- Recall같은 경우, 1차 검사에서 예측값을 암환자로 다 가져와야하는 경우에 잘 봐야한다. 실제값에 대해 판정도 다 들어와야하는 경우
- Precision의 경우, 판단(예측)이 실수하면 안되는 경우에 잘봐야한다. 유죄판결한 경우, 모두 실제값이어야한다.

ROC curve는, 판단 선(cut off, decision boundary)를 움직였을 때, 얼마나 성능(결정)들이 민감한지에 대한 것이다.
AUC가 넓을 수록, 안정된 예측을 할 수 있는 모델 or 데이터이다.

캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


머신러닝을 가지고 모델을 만들어 예측하다보면, 하나의 꼬리를 가지고 여러 classifier로 만들 수 있다.
예를 들어, kNN이나 Decision Tree 등으로 만드는 것이다.
이 분류기(classifier)들 가운데 가장 성능이 좋은 것으로 채택해야하는데, 이 때 사용되는 개념이

  1. Accuracy
  2. precision
  3. recall
  4. f1 score

4가지 개념이다.


이전 시간을 학습한 Confusion Matrix를 통해, 우리가 만든 모델(classifier)를 평가할 수 있었다.


아래 2 Model이 2개의 classifier라고 가정해보자.
2개의 분류기 가운데 어느 것을 선택해야할까?

image

그 과정에서 사용되는 개념이 위의 4가지 개념이었다.

  1. Accuracy
  2. precision
  3. recall
  4. F1 score


    기본개념

    성능평가는 AccuracyF1 score가 주요개념이며,  이 f1score를 다루기 위해서는 precision과 recall을 알아야하는 것이다.
    그리고 이러한 개념들을 다루기 위해서는 아래와 같은 기본개념을 이해해야한다.

    1. TP(True Positive)
    2. TN(True Negative)
    3. FP(False Positive)
    4. FN(False Negative)
      image



    my) 뒤에서부터 해석
    올바른 것/거절해야할 것을( Posi/nega )-칼럼으로 매칭 ==>  True/False 에 잘 한것/반대로 한 것 - 행으로 매칭

    1. True Positive

    말 그대로, input 클래스(True)에 대해서
    올바른 것(Positive)을 --> 올바르게 예측(True)한 것이다.
    - Confusion matrix내에서는 대각선을 의미한다.

    image


    2. True Negative for A

    거절해야할 것을 (Negative) : B,C,D칼럼 --> 잘 거절 한 것(True) : B,C,D행이다.
    A 클래스 입장에서는, 아래 파란색 cell들이 True negative라고 할 수 있다.
    image

    예를 들어, D입장에서는 아래 구간이 True Negative라 할 수 있다.
    image


    3. False Positive for A

    올바른 것(Positive) --> 잘못 거절-다른 것을 예측(False)해버린 것이다.
    A예측 칼럼------------> A제외 B,C,D로 잘못예측한 것들
    image


    예를 들어서 False Positive for B는
    B칼럼(올바른것-positive) 중에서 --->  B제외 잘못예측한 것(A,C,D행)
    image


    4. False Negative for A

    거절해야할 것(B,C,D칼럼) -----> 거절하지 않고 잘못 맞다고 한 것(A행)
    - confusion matrix에서는 해당 row에서 대각선(True Positive)를 뺀 나머지 cell들이다.
    image





    Performance Measure 1. Accuracy

    Accuracy의 계산방법은 간단하다.

    True positive(대각선)의 합 / Confusion Matrix의 모든 cell의 합
    image


    이제 2개의 분류기의 Accuracy를 비교해보자.
    Accuracy만 따지면 Model1 분류기를 사용할 것이다.
    image


    이러한 Accuracy로 Performance Mesure를 사용할 때는,
    데이터가 balance할 때 효과적이라고 한다.
    image

    즉, 각 클래스별로 input되는 데이터량이 동일할 때, 사용한다.


    주의점)
    만약, 데이터가 imbalance하여 각 클래스별 input량이 다를 때는 정확하지 않을 수도 있다고 한다.
    즉, 해당 분류기의 performance가 좋지 않음에도 불구하고 아래와 같이 좋다고 얘기를 해버린다고 한다.
    image

    A에만 input데이터가 쏠린 imbalanced data이다.
    Accruacy는 Model2가 높지만, 사실상 자세히 들여다보면,
    B, C, D에 대해서는 10개중에 1개밖에 못맞추는 모델이다. 즉, A만 잘맞추는 모델이다.

    이것들 Model1보다 좋다고 얘기할 순 없는 것이다.
    오히려, 전반적으로 예측을 잘하는 Model1이 더 낫다.


    이렇게 imbalanced data가 주어진 상황에서는 어떤 performance measure를 사용해야할까?


    Performance Measure 2. f1-score

    F1-Score는 왜 imbalanced data에서도 성능 측정을 잘 할 수 있을까?


    먼저, recallprecision에 대해서 알아보자.

    아래의 confusion matrix가운데,

    1. Recall에 해당하는 행 방향
      input된 class에 대해서, 분류기(Classifier)가 어떤 class로 예측을 하는지에 대한 척도이다.
    2. Precision에 해당하는 칼럼 방향
      예측한 값들 중에서 제대로 예측했는지에 대한 척도이다.
      image


    f1-score
    는 이 Recall과 precision을 이용하여 조화평균(harmonic mean)을 이용한 score이다.
    image


    조화 평균은 [ 2 * ab / a + b ]의 공식을 가지고 있으며, 그림으로 나타내면 아래와 같다.
    즉, 2개의 길이에 대해서 반대편으로 선을 내릴 때, 서로 만나는 점의 길이다.
    image
    A가 B보다 큼에도 불구하고, 조화를 이루어서 B에 가깝에 어떠한 평균이 나타나게 된다.


    그렇다면, Recall과 Precision에 대해서도 아래와 같이 나타날 수 있다.
    비록, precision이 큰 경우에도, 작은 recall에 대해 조화를 이루는 높이를 평균으로 채택하게 된다. 반대도 마찬가지이다.
    image


    즉, 조화평균은 단순하게 평균을 구하는 것이 아니라, 먼가 큰 값이 있다면 패널티를 주어서, 작은값 위주로 평균을 구하게 된다.
    이러한 원리로, imbalanced data에 대해서 큰 값을 가진 A class가 있더라도, 강력한 효과를 통해 평균을 구하게 된다.

    image


    이제 이 F1 score를 구하려면, Precision과 Recall을 계산하여야할 것이다.


    공식상으로는 각 클래스별 precision =   TP / TP + FP 을 구한 뒤 평균을 내면 된다.
    FP는 올바른 것을 틀리계 예측한 것이므로, 각 칼럼 4개 cell 중 3개를 더하면 된다.

    모델 1의 경우
    - A의 precision은 100/ 100 + 0 = 1
    - B : 9 / 9 + 82
    - C : 8 / 8 + 10
    - D : 9 / 9+12
    image
    image


    이번에는 Recall을 계산해보자.
    공식상으로는 각 클래스별 =  TP / TP + FN를 구한 뒤 평균이다.
    FN는 아닌 것을 반대로 맞다고 판단하는 것이므로, BCD칼럼 중 A행을 택하는 것이다. 그러므로 TF이외에 행방향의 3개의 cell을 더하면 된다.
    - A의 recall : 100  / 100 + (80+10+10)  와 마찬가지로 다 구해서 평균을 낸다.
    image

    image


    모델2도 마찬가지로 precision과 recall을 계산하면, 0.342가 나온다.

    이렇게 imbalnaced data에서 모델간의 성능측정을 해보니, Accuracy와는 반대로 Model 1가 높게 나왔다.
    image

    결론적으로

    balanced data -> Accuracy로 Perfomance Measure로 채택

    imlbalanced data -> f1-score로 채택하자!





    캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    Confusion Matrix

    머신러닝이 얼마나 잘 예측하는지를 나타내주는 Matrix가 바로 Confusion Matrix이다.


    예를 들어, 만들어진 머신러닝 모델에
    A를 입력하였더니, A라고 판단했다. 아래 테이블에 input A에 대한 output A가 1로 찍힌다.

    image


    이번에는 B가 조금 희미하게 input되었더니, 우리의 머신러닝 모델은 D라고 판단했다.
    이 때는 input B에 대한 output D칼럼에 1이 찍힌다.
    image


    다음으로 C, D는 잘 판단하여 각각 (C,C) (D,D)에 1이 들어갔다.

    imageimage


    이번에는 희미한 D를 input하였는데도, D라고 잘 판단했다.
    (D,D)는 +1이 된 2가 들어갔다.

    image



    이렇게 찍은 테이블이 바로 Confusion Matrix이다.
    input A에 대해서는 전체 1개 중에 1개를 A로 잘 맞추었다. C와 D역시 전체 1개, 2개 중에 전부 잘 맞추었다.
    반면 input B에 대하여 전체 2개의 input가운데, 1개는 잘 맞추었지만, 다른 1개는 잘못판단하였다.

    이렇게 머신이 잘맞추었는지, 혼동은 없었는지 판단하는 matrix가 바로 confusion matrix인 것이다.
    image


    데이터 사이언스에서는 눈으로 보이는 혼동이외에, 조금더 과학적인 방법으로 성능을 확인할 수 있다.
    그 종류로는

    1. Accuracy
    2. Precision
    3. Recall
    4. F1 score

    등등 이 있다.


    실습




    4. Confusion matrix
    In [16]:
    import seaborn as snsimport pandas as pdimport matplotlib.pyplot as plt%matplotlib inlinesns.set(font_scale=2) # 혼동행렬 폰트 크기! 1이면 너무 작다.

    1. 혼동없는 혼동행렬 만들기

    In [18]:
    # array로 행렬만들기 -> df에 넣으면서 인덱스+칼럼명 주기 -> heatmaparray = [    [5, 0, 0, 0],    [0, 10, 0, 0],    [0, 0, 15, 0],    [0, 0, 0, 5],]#인덱스와 컬럼을 문자열--> 리스트로 인식되어서 하나씩 입력되도록df_cm= pd.DataFrame(array,                   index = [ i for i in "ABCD"],                    columns=[i for i in 'ABCD']                   )#맷플롯립으로는 figure 사이즈와 타이틀 정하기plt.figure(figsize=(10, 7)) # 7, 7 주면 정사각형이 안된다. 옆에 게이지 때문에 더 줘야함plt.title('confusion matrix without confusion')#시본으로 df를 히트맵으로 만들기sns.heatmap(df_cm, annot=True) # annot 옵션이 각 cell안에 숫자를 나타내게 한다.
    Out[18]:
    <matplotlib.axes._subplots.AxesSubplot at 0x2bc302f6a90>

    2. 혼동이 있는 혼동행렬 만들기

    In [40]:
    array = [    [9, 1, 0, 0],    [1, 15, 3, 1],    [5, 0, 24, 1],    [0, 4, 1, 15],]df_cm= pd.DataFrame(array,                   index = [ i for i in "ABCD"],                    columns=[i for i in 'ABCD']                   )plt.figure(figsize=(10, 7))plt.title('confusion matrix without confusion')sns.heatmap(df_cm, annot=True)
    Out[40]:
    <matplotlib.axes._subplots.AxesSubplot at 0x2bc314cf208>

    대각선이 밝은색위주로 되어있으니, 나름대로 잘 작동을 하는 모델임을 판단한다

    하지만 Normalization 하지 않았기 때문에, 어떤 input에 대해 효과적인지 쉽게 대답할 수 없다.

    3. Normalization한 혼동행렬 만들기

    • 각 A,B,C,D의 input되는 갯수가 다르기 때문에 어느것이 정확도가 더 좋은지 제대로 알아보기 힘들다.

    3-1. 노멀리제이션 먼저 하기

    In [41]:
    import numpy as npfrom numpy import linalg as LA
    In [42]:
    # 1. 혼동행렬(array상태)의 가로방향별로  각 input별 합을 구한다.total = np.sum(array, axis=1)total
    Out[42]:
    array([10, 20, 30, 20])
    In [43]:
    total[:, None]
    Out[43]:
    array([[10],       [20],       [30],       [20]])
    1. 각 칼럼별 합을 나누는데, 그냥 나누면 안된다array = array / totalarray
    In [44]:
    # 2. 각 input의 총 갯수를 None인덱싱한 total을 이용하여,  ( total [ : , None])#    각 예측값의 합 [10,20,30,20] 을 칼럼이 없도록 행으로 세운다#    [10],#    [20],#    [30],#    [20],#    이를 통해, 가로별 합을 가로별로 나눌 수 있게 된다. 그러면 가로별 총 합은 1이 될 것이다.array = array / total[:,None]array
    Out[44]:
    array([[0.9       , 0.1       , 0.        , 0.        ],       [0.05      , 0.75      , 0.15      , 0.05      ],       [0.16666667, 0.        , 0.8       , 0.03333333],       [0.        , 0.2       , 0.05      , 0.75      ]])

    3-2. Normalization된 array로 히트맵 그리기

    In [45]:
    df_cm= pd.DataFrame(array,                   index = [ i for i in "ABCD"],                    columns=[i for i in 'ABCD']                   )plt.figure(figsize=(10, 7))plt.title('confusion matrix without confusion')sns.heatmap(df_cm, annot=True)
    Out[45]:
    <matplotlib.axes._subplots.AxesSubplot at 0x2bc3155c6d8>

    이제 대각선이 각각 input별로 몇퍼센트를 맞추었는지 알 수 있다.


    15. Batch size & Batch Norm

    2018. 8. 19. 16:04

    Batch size

    batch size란 sample데이터 중 한번에 네트워크에 넘겨주는 데이터의 수를 말한다.
    batch는 mini batch라고도 불린다.

    이 때 조심해야할 것은, batch_size와 epoch은 다른 개념이라는 것이다.
    image

    예를 들어, 1000개의 데이터를 batch_size = 10개로 넘겨준다고 가정하자.
    그러면 총 10개씩 batch로서 그룹을 이루어서 들어가게 되며, 총 100개의 step을 통해 1epoch을 도는 것이다.
    즉, 1epoch(학습1번) = 10(batch_size)  * 100(step or iteration)
    image
    image


    하지만, batch_size가 커지면 한번에 많은 량을 학습하기 때문에, train과정이 빨라질 것이다.
    그러나 trade off로서, 컴퓨터의 메모리 문제때문에 우리는 한번에 모두다 학습하는 것이 아니라 나눠서 하는 것이다.
    image


    즉, batch_size를 100으로 준 상태에서, 컴퓨터가 학습을 제대로 하지 못한다면, batch_size를 낮춰주면 된다.


    실습

    keras에서 batch_size의 선택은 fit()함수 호출 시 할 수 있다.

    image



    Batch Norm

    data를 Neural Network에 train시키기전에, preprocessing을 통해 Normalize 또는 Standardize를 했다.

    Regression문제에서는 사이킷런의 MinMaxScaler를 이용하여, 각 feature의 데이터를 0~1사이로 squarsh한 것이 예이다.
    머신러닝이나 딥러닝은, 큰 수들을 좋아하지 않기 때문에 = 각 feature의 간격이 동일해야 편견없이 처리할 수 있다
    (예를 들어, a feature는 0~13값을 가지고 b feature는 0~4값을 가지는데, 13을 4보다 더 큰 요소로 인식해버리 떄문)
    image

    Normalize나 Standardize는 모두, 모든데이터를 같은 scale로 만들어주는 것이 목적이다.
    (Regularization은 weight를 줄이도록 loss를 변형(L2 Reg)하여, 모델의 복잡도를 낮추어 overfitting을 방지한다)
    image

    1. Normalization : 구체적으로 10~1000 범위를 가진 feature를 --> 0~1값을 가지도록 Scaling한다.
    2. standardization : 각 데이터에 평균을 빼고 -> 표준편차를 나누어서 ->  평균0 표준편차1인 데이터로 변형한다.
      - standardization 역시 Normalization으로 불리기도 한다.


    이러한 작업을 하는 이유는 위에도 설명했지만, 아래 예를 다시보자.

    miles Driven feature 와 age feature가 있다.


    2 feature는 같은 Scale을 가지고 있지 않은 non-Normalized상태이다.
    이러한 data는 Neural Network에서 불안정성을 야기한다.
    즉, 너무 큰 범위의 feature값이 들어가게 되면, gradient를 태워 weigt를 업데이트할 때, 큰 문제가 발생하게 된다.
    train하기도 힘들어지고, train속도도 느려진다.
    image


    하지만 Normalization을 통해 Scale을 0~1로 통일 시키면,
    속도도 향상되면서, gradient를 태울 떄 문제가 발생하지 않게된다.
    image



    하지만 normalized된 데이터( scale통일 )도 문제가 발생시킨다는 것이 발견되었다.

    train시 SGD로 그라디언트를 태워 w를 업데이트 하는 와중에
    weight하나가 극단적으로 크게 업데이트되었다고 가정하자.
    image


    첫번째 hidden Layer에 도달하는 weight는 (8, 6)개의 matrix이다.
    여기서 (4, 4)에 해당하는weight가 극단적으로 크게 업데이트 되었다.
    이 weight에 상응하는 neuron (1hidden-4node)역시 커질 것이다.
    그리고 다음 N.N.를 통과하면서 이러한 imbalance들이 문제를 야기할 것이다.

    이 때 등장한 개념이 Batch Normalization이다.
    비록 input data는 Normalization(0~1scaling)되었다 하더라도, weight가 커져버려 output도 커지는 상황이 발생한다.

    정규화(loss를 변형하여, weight줄임->복잡도내려가고 variance줄임->overfitting방지)처럼,
    Batch norm 역시 전체 모델 중 특정Layer를 선택하여 적용할 수 있다.

    구체적으로는
    이전Layer의 weight가 커져, 매우커저버린 output인 a(z(x))에다가

    1. activation funcion값을 Starndardization(평균0 표준편차1)을 만들어서,
    2. 임의의 상수를 곱함(trainable)
    3. 임의의 상수를 더함(trainable)

    --> 다음Layer의 input이 되게 만드는 것이다.

    image
    image


    이러한 과정을 거쳐 최적화 된 g와 b상수도 결정되게 된다.


    Batch Norm은 gradient의 process에 포함되기 때문에, 특정weight가 극단적으로 커지거나 작아지는 것을 막아주게 된다.


    결과적으로, input dataNormalization을 통해 같은 Scale을 가질 수 있게 하여 --> 속도향상 + gradient problem을 막고
    각 Layer의 output(a(z(x))에는 Batch Norm을 통해 같은 Scale을 가질 수 있게항 --> weight의 imbalance를 막는다.
    - 이러한 과정은 모델에 input되는 Batch단위로 이루어지기 때문에, Batch norm이라 한다.


    실습

    image

    14. Regularization

    2018. 8. 19. 16:03

    Regularization은 오버피팅(feature가 너무 많거나 지엽적인 데이터를 학습하여, 새로운 데이터에 대해서는 예측을 잘 못하는 것)모델의 해결방안 중 하나라고 언급된다.

    정확하게는 복잡성을 줄여서 --> 오버피팅을 줄이거나 분산을 줄이는 것이다.
    image

    그 결과 training data에 대한 학습정도 <----> unseen data에 대한 일반화 정도를 trade off하는 것이다.
    image


    첫번째 간단한 방법으로는, 머신러닝 기초에서 설명한 것처럼, loss함수에 람다*(w1+w2+...+wn)을 붙히는 것이다.
    이것은 상대적으로 큰 weight들에 작은 상수를 곱하여, weight를 줄이는 것이다.
    image


    더 일반적 많이 쓰는 Regularization은  L2 Norm을 가지고 정규화 하는 것이다.
    즉 상수 람다/2m * ( 각 weight들의 제곱의 함)을 더하는 것이다.
    그리고 이것의 의미는, 양수로서, 벡터공간 속에서 피타고라스와 같은 거리를 구하는 공식으로 생각하면 된다.

    그리고 여기서의 m은 input되는 feature의 수이며,
    람다는 regularization hyperparameter로서, 우리가 정하고 테스트해서 바꾸는 수이다.
    image



    요약하자면, 정규화란?
    우리가 가진 weight들은 큰값도 있고, 작은 값도 있을 것이다. 큰 weight를 가진 feature는 모델에 크게 반영될 것이다.
    하지만 L2를 이용한 정규화를 사용하여, loss함수에 제약을 걸면 상대적으로 큰 weight라도 다른 w와 비슷하게 w를 업데이트 시키게 된다.
    그래서 상대적으로 큰 weight들도 작은 weight처럼 약하게 적용되는 것이다.

    만약 람다(lr)를 높혔다고 가정해보자. 그러면 loss는 빠르게 w를 업데이트 시켜 0에 가까워질 것이다.
    하지만 L2정규화를 통해 loss에 람다 * 양수가 곱해져있는 상황으로 loss혼자는 0으로 갈지라도 뒤에 값들이 더 커지게 된다.
    그래서 전체loss는 2개의 합이므로 0에 수렴하진 않을 것이다.
    그 결과 lr를 조절하는 것이 아니라,
    결과적으로 loss전체를 최소로 만들려면 뒤에 더해진 weight들이 줄어드는 방식으로 w가 결정될 것이다.

    w들이 줄어든다면
    1)Regression문제에서는 해당 예측값h(x)의 전체적인 가파른 정도가 줄어든 것일 것이다.
    image
    2) 딥러닝에서는, 극단적으로 weight가 0으로 결정된다면, 해당 Layer는 사라질 것이다.
    이러한 방식으로 복잡도를 줄여서, 마치 Dropout처럼 복잡도를 줄여나간다.
    image


    weight가 줄어들면, variance(분산)도 줄어든다고 한다. 그 결과 overfitting도 해결된다고 한다.


    my)

    Regularization은 loss 에 L2를 더해서, loss를 줄이려면 weight들을 줄여야한다.

    낮아진 weight로 인해 모델의 복잡도도 줄어들면서, Overfitting이 해결된다.


    실습

    케라스에서는 모델전체의 loss에 l2정규화를 하는 것이 아니라, 각 Layer별로 정규화를 적용하여 overfitting을 방지하도록 해준다.
    image

    캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    PCA : Principal Component Analysis (주 성분 분석)

    PCA는 언제 많이 사용할까?

    바로 시각화를 위해 사용한다. 여태껏 시각화를 위해 feature 2개만 사용하는 2~3차원 정도의 데이터만 사용했다.
    이 차원축소를 이용하면 다차원의 feature도 시각화가 가능해진다.


    1. 차원축소를 이용하여, 고차원 데이터를 3차원 이하로 축소시킬 수 있고, 시각화가 가능해진다
    2. 그 이외에 이미지의 noise제거에도 사용되며,
    3. 정보를 적은차원에 적은메모리로 저장되어, 퍼포먼스 향상에도 사용된다.


    PCA의 원리

    PCA는 어떻게 동작할까?
    2차원을 1차원으로 줄이는 예를 보면서 이해해보자.


    아래와 같이 2차원 공간안에 x1, x2 2개의 feature가 축으로 설정되어있다. 그리고 7개의 점이 존재한다.

    image


    어떻게 2차원을 1차원으로 줄일 수 있을까?
    가장 쉬운방법은 하나의 축을 선택하여, 점을 몰아넣는 방법이다.
    image


    이러한 방식을 사용하면 몇개의 점은 서로 겹치게 되는 문제점이 발생한다. 이 경우, 정보의 유실이 있을 수 있다.
    image
    image



    정보의 유실을 막으면서 차원을 줄이는 방법은 무엇일까?
    과학적인 방법으로서, 분산이 가장 넓은 지역을 찾는 것이다.
    image


    분산이 가장 넓은 곳을 직선으로 표시하였다. 여기로 점들을 옮기게 된다면
    각 점들이 퍼져있는 정도를 지켜줄 수 있게 된다. 그 결과 점들은 겹치지 않게 된다.

    image

    image


    이게 바로 PCA 알고리즘이다.
    위에서 찾은 분산이 가장 넓은 지역을 PC(Princal Component)라 한다.
    이 PC를 긋는 방법은 각 점들이 겹치지 않을 수 있게 살려서 긋는다.
    이 때, x축으로 모은 거리나 y축으로 모은 거리보다 긴 것을 확인할 수 있다.

    image



    머신러닝에서 수학적으로 구하는 PC

    image

    수학적으로 PC를 구하는 방법은, 각 점들이 가지고 있는 feature(x1, x2)들의 Covariance Matrix에 있는 Eigen Vector이다.


    EigenVector(PC)2차원에서는 2개가 존재한다.
    4차원이라면 4개가 존재할 것이다.

    image


    여러개의 EigenVector 중 어느 것을 선택해야할까?

    가장 넓게 퍼지게 만드는 EigenVector를 찾아야한다. 즉, 분산이 큰 것을 의미하는 Eigen value가 높은 값을 찾아야한다.

    image

    우리는 Covariance Matrix 중 Eigen value가 높은 값을 찾아 EigenVector를 찾고, 그 것을 기준으로 데이터들을 옮겨 차원을 축소한다.

    image


    이 과정을 파이썬으로 실습해보자.


    실습


    3. PCA 알고리즘
    In [1]:
    from IPython.core.display import display, HTMLdisplay(HTML("<style> .container{width:90% !important;}</style>"))
    In [1]:
    import pandas as pd

    1. 데이터 만들기, 식습관들(feature)에 따른 ---> 체형(label)

    In [3]:
    df = pd.DataFrame(columns=['calory', 'breakfast', 'lunch', 'dinner', 'exercise', 'body_shape'])
    In [4]:
    df.loc[0] = [1200, 1, 0, 0, 2, 'Skinny']df.loc[1] = [2800, 1, 1, 1, 1, 'Normal']df.loc[2] = [3500, 2, 2, 1, 0, 'Fat']df.loc[3] = [1400, 0, 1, 0, 3, 'Skinny']df.loc[4] = [5000, 2, 2, 2, 0, 'Fat']df.loc[5] = [1300, 0, 0, 1, 2, 'Skinny']df.loc[6] = [3000, 1, 0, 1, 1, 'Normal']df.loc[7] = [4000, 2, 2, 2, 0, 'Fat']df.loc[8] = [2600, 0, 2, 0, 0, 'Normal']df.loc[9] = [3000, 1, 2, 1, 1, 'Fat']
    In [5]:
    df
    Out[5]:
    calory breakfast lunch dinner exercise body_shape
    0 1200 1 0 0 2 Skinny
    1 2800 1 1 1 1 Normal
    2 3500 2 2 1 0 Fat
    3 1400 0 1 0 3 Skinny
    4 5000 2 2 2 0 Fat
    5 1300 0 0 1 2 Skinny
    6 3000 1 0 1 1 Normal
    7 4000 2 2 2 0 Fat
    8 2600 0 2 0 0 Normal
    9 3000 1 2 1 1 Fat

    1-1. feature와 label 나누기

    In [7]:
    X = df[['calory', 'breakfast', 'lunch', 'dinner', 'exercise']]X
    Out[7]:
    calory breakfast lunch dinner exercise
    0 1200 1 0 0 2
    1 2800 1 1 1 1
    2 3500 2 2 1 0
    3 1400 0 1 0 3
    4 5000 2 2 2 0
    5 1300 0 0 1 2
    6 3000 1 0 1 1
    7 4000 2 2 2 0
    8 2600 0 2 0 0
    9 3000 1 2 1 1
    In [8]:
    Y = df[['body_shape']]Y
    Out[8]:
    body_shape
    0 Skinny
    1 Normal
    2 Fat
    3 Skinny
    4 Fat
    5 Skinny
    6 Normal
    7 Fat
    8 Normal
    9 Fat

    1-2. 수치가 굉장히 높은 calory칼럼때문에, 전체데이터를 Rescaling해주기

    • 사이킷런의 StrandardScaler를 이용하여, 각 feature가 같은범위내에 있도록 바꿔준다.
    • Normalization을 사용해도된다
    In [9]:
    from sklearn.preprocessing import StandardScalerx_std = StandardScaler().fit_transform(X)
    In [10]:
    x_std
    Out[10]:
    array([[-1.35205803,  0.        , -1.3764944 , -1.28571429,  1.        ],       [ 0.01711466,  0.        , -0.22941573,  0.14285714,  0.        ],       [ 0.61612771,  1.29099445,  0.91766294,  0.14285714, -1.        ],       [-1.18091145, -1.29099445, -0.22941573, -1.28571429,  2.        ],       [ 1.89972711,  1.29099445,  0.91766294,  1.57142857, -1.        ],       [-1.26648474, -1.29099445, -1.3764944 ,  0.14285714,  1.        ],       [ 0.18826125,  0.        , -1.3764944 ,  0.14285714,  0.        ],       [ 1.04399418,  1.29099445,  0.91766294,  1.57142857, -1.        ],       [-0.15403193, -1.29099445,  0.91766294, -1.28571429, -1.        ],       [ 0.18826125,  0.        ,  0.91766294,  0.14285714,  0.        ]])

    2. feature들의 Covariance Matrix 만들기

    • 각 칼럼별로 존재하는 feature들을 row순으로 변형시키는 과정이 필요하다. 그래야 covariance Matrix를 만들 수 있음
    In [12]:
    import numpy as np

    2-1. feature들을 칼럼방향이 아닌 row방향으로 변환시킨다.

    In [13]:
    features = x_std.T

    2-2. 각 feature들이 row방향으로 향해있다면, np.cov를 이용해 covariance matrix를 만들 수 있다.

    In [14]:
    covariance_matrix = np.cov(features)print(covariance_matrix)
    [[ 1.11111111  0.88379717  0.76782385  0.89376551 -0.93179808] [ 0.88379717  1.11111111  0.49362406  0.81967902 -0.71721914] [ 0.76782385  0.49362406  1.11111111  0.40056715 -0.76471911] [ 0.89376551  0.81967902  0.40056715  1.11111111 -0.63492063] [-0.93179808 -0.71721914 -0.76471911 -0.63492063  1.11111111]]

    3. c_matrix를 이용해 EigenValue의 최대값인 EigenVector(PC) 구하기

    • 이 과정에서는 np.linalg.eig()이 사용된다. 이 때 eigen_value와 eigen_vector 리스트를 반환해준다.
    • feature가 5개인 5차원이므로, eigen_vector도 5개가 나온다.
    In [16]:
    eig_vals, eig_vecs = np.linalg.eig(covariance_matrix)
    In [17]:
    eig_vals
    Out[17]:
    array([4.0657343 , 0.8387565 , 0.07629538, 0.27758568, 0.2971837 ])
    In [18]:
    eig_vecs
    Out[18]:
    array([[ 0.508005  ,  0.0169937 , -0.84711404,  0.11637853,  0.10244985],       [ 0.44660335,  0.36890361,  0.12808055, -0.63112016, -0.49973822],       [ 0.38377913, -0.70804084,  0.20681005, -0.40305226,  0.38232213],       [ 0.42845209,  0.53194699,  0.3694462 ,  0.22228235,  0.58954327],       [-0.46002038,  0.2816592 , -0.29450345, -0.61341895,  0.49601841]])

    3-1. eig_vals의 최대값을 눈으로 확인후 가져오고, 전체 중 비율을 구한다.

    • 만약 하나의 eig_vecs만 사용한다면, 5->1차원으로 줄이면서
    • 전체 중 비율값이 = 전체정보 중 그만큼의 정보를 유실없이 가진다는 뜻이다.
    In [19]:
    eig_vals[0]  /  sum(eig_vals)
    Out[19]:
    0.7318321731427544

    1개의 eigen_vector사용으로 5->1차원 축소시 73% 정보유실이 없는채로 축소할 것이다.

    3-2. 해당 eigen_vector를 이용해, 칼럼방향별 feature 데이터를 projection시킨다.

    • projection이란 eigen_vector 직선위에 모든 데이터를 올려놓겠다는 의미이다.(그림생각)
    In [23]:
    # 칼럼방향의 feautre array를 dot연산을 통해 아이겐벡터 최대값(eig_vecs[0])에 projection시킨다.# 이  때, eig_vecs는 row방향별 feature로 생성한 것이므로, T로 뒤집어준다.projected_X = x_std.dot(eig_vecs.T[0])
    In [24]:
    projected_X
    Out[24]:
    array([-2.22600943, -0.0181432 ,  1.76296611, -2.73542407,  3.02711544,       -2.14702579, -0.37142473,  2.59239883, -0.39347815,  0.50902498])

    3-3. PCA로 프로젝션된 각 데이터들을 df로 만들자.

    In [30]:
    result  =  pd.DataFrame(projected_X , columns=['PC1'])result['y-axis'] = 0.0result['label'] = Y
    In [31]:
    result
    Out[31]:
    PC1 y-axis label
    0 -2.226009 0.0 Skinny
    1 -0.018143 0.0 Normal
    2 1.762966 0.0 Fat
    3 -2.735424 0.0 Skinny
    4 3.027115 0.0 Fat
    5 -2.147026 0.0 Skinny
    6 -0.371425 0.0 Normal
    7 2.592399 0.0 Fat
    8 -0.393478 0.0 Normal
    9 0.509025 0.0 Fat

    4. 이제 5차원--> PC(eigen_vector)로 프로젝션--> 1차원 된 데이터들을 시각화

    In [32]:
    import matplotlib.pyplot as pltimport seaborn as sns%matplotlib inline
    In [33]:
    sns.lmplot('PC1', 'y-axis', data=result, fit_reg=False,  # x-axis, y-axis, data, no line           scatter_kws={"s": 50}, # marker size           hue="label") # color# titleplt.title('PCA result')
    Out[33]:
    Text(0.5,1,'PCA result')

    5. 사이킷런 PCA 모듈로 한방에 표시하기

    In [34]:
    from sklearn import decompositionpca = decomposition.PCA(n_components=1)sklearn_pca_x = pca.fit_transform(x_std)
    In [35]:
    sklearn_result = pd.DataFrame(sklearn_pca_x, columns=['PC1'])sklearn_result['y-axis'] = 0.0sklearn_result['label'] = Ysns.lmplot('PC1', 'y-axis', data=sklearn_result, fit_reg=False,  # x-axis, y-axis, data, no line           scatter_kws={"s": 50}, # marker size           hue="label") # color
    Out[35]:
    <seaborn.axisgrid.FacetGrid at 0x26516c89ef0>


    캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    Norm

    Norm이란 무엇일까?

    선형대수 안에서는 Norm이란 벡터공간에서 벡터의 크기 또는 길이를 측정할 때 사용되는 개념이다.
    공식은 아래와 같이, 절대값을 취한뒤 다 더해주는 것이다. 이것은 양수가 나오며 길이나 사이즈를 측정할 수 있게 된다.
    image

    대표적으로 Norm은 2가지 종류가 있다.

    1. L1 Norm : 위 공식상의 p값이 1이다.
      image

    2. L2 Norm : p값이 2이다. 해당 x값을 제곱해서 더하고, 마지막에 루트를 취한다.
      image


    아래부터는 쥬피터 노트북 실습화면으로 같이 보자.


    실습

    2. Norm
    In [1]:
    from IPython.core.display import display, HTMLdisplay(HTML("<style> .container{width:90% !important;}</style>"))

    L1 Norm : 주사위 게임으로 이해하기

    • 1부터 6대신 -3부터 3까지 나오는 주사위을 굴린다.
    • -3이 나오면 뒤로 3걸음, 3이 나오면 앞으로 3걸음 갈 것이다
    In [2]:
    import pandas as pdimport numpy as npfrom numpy import linalg #리니어 알제브라 함수

    1. 데이터 프레임 만들기

    • size (3,3) 으로 -3~3이 나오도록 만든다.
    • 각 행별로,총 3사람이 주사위를 던지는 것이다.
    • 각 칼럼별로, 3회 던지는 것이다.
    In [4]:
    df = pd.DataFrame( np.random.randint(low=-3, high = 3, size=(3,3)))df
    Out[4]:
    0 1 2
    0 -3 -3 1
    1 1 2 2
    2 -3 1 0
    In [5]:
    df.columns=['move_1', 'move_2','move_3',]
    In [6]:
    df
    Out[6]:
    move_1 move_2 move_3
    0 -3 -3 1
    1 1 2 2
    2 -3 1 0

    2. 누가 가장 많이 걸었을까?

    • 뒤로 걷든, 앞으로 걷든 벡터의 크기를 구해야한다
    • 이 때 사용되는 개념이 **L1 Norm**일 것이다.
    • 간단하게 p=1이므로, 각 행을 절대값 취해서 더할 때 L1 norm을 쓴다.

    2-1. 계산을 위해 df를 array로 만든다.

    In [8]:
    movements = df.values
    In [9]:
    movements
    Out[9]:
    array([[-3, -3,  1],       [ 1,  2,  2],       [-3,  1,  0]])

    2-2. norm은 numpy의 linearalgebra 모듈안에 있다.

    Norm의 종류는 ord로 구분한다.

    • ord = 1 : L1 norm을 사용한다.
    • ord = 2 : L2 norm을 사용한다.

      L1 norm을 axis=1로 행방향으로 절대값 취해서 더해진다.

    In [10]:
    # Norm의 종류는 ord로 구분한다.linalg.norm(movements, ord=1, axis=1)
    Out[10]:
    array([7., 5., 4.])

    3. L1 norm(절대값 취해서 다 더하는 것)은 Computer Science에서는 어디서 사용할까?

    • L1 Regularization
    • Computer Vision에서 사용된다.

    L2 Norm

    공식상으로 p=2이므로, 각 x를 제곱해서 다 더한다음 마지막에 루트를 취한다.

    고등학교 때 배운 피타고라스의 정리와 일치한다.

    1. 각 데이터 포인트의 거리를 측정하기 위해 df를 만들자.

    • 3행2열의 size로, 1부터 10까지 랜덤한 정수가 들어가도록 만들자
    In [11]:
    df = pd.DataFrame( np.random.randint(low=1, high=10, size=(3,2)))df
    Out[11]:
    0 1
    0 5 1
    1 2 2
    2 2 1
    In [12]:
    df.columns = ['x', 'y']df
    Out[12]:
    x y
    0 5 1
    1 2 2
    2 2 1

    2. df로 만든 x, y 좌표쌍을 시각화하자

    In [13]:
    import matplotlib.pyplot as pltimport seaborn as sns%matplotlib inline #plot명령시 바로 차트가 보여진다.

    2-1. 벡터의 크기를 구하는 피타고라스 같은 L2 norm이므로.. 차트를 그려놓고 보자

    In [16]:
    sns.lmplot('x', #x축 들어갈 칼럼                  'y', #y축 들어갈 칼럼          data=df, #dataFrame          fit_reg=False, #Regression line을 표시할 것인가          scatter_kws={'s':200}) # S maker와 sizeplt.title('data point visualization')plt.xlabel('x')plt.ylabel('y')
    Out[16]:
    Text(6.675,0.5,'y')

    3. (0,0)에서 가장 가까운 점을 찾기위해 L2 Norm을 사용해보자.

    3-1. 어떠한 계산을 위해서는 df->values로 array로 풀어주자

    In [18]:
    data_points = df.valuesdata_points
    Out[18]:
    array([[5, 1],       [2, 2],       [2, 1]])
    In [19]:
    ## 3-2. array를 가지고 L2 norm을 적용시켜보자.linalg.norm(data_points, ord=2, axis=1)
    Out[19]:
    array([5.09901951, 2.82842712, 2.23606798])

    L2 norm은 어디서 사용할까?

    머신러닝에서 사용하는 유클리디언 디스턴스가 바로 L2 norm이다.

    • kNN algorithm
    • kmean algorithm

    둘다 벡터의 거리가 이용되는 알고리즘 들이다.


    캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    머신에게 공이 무엇인지 학습시킨다고 가정해보자.
    마치, 애기에게 공이 무엇인지 학습시키는 것과 유사하다.


    먼저, 공은 야구공, 농구공, 축구공처럼 동그랗게 생긴 것이다 공이야~ 라고 가르칠 것이다.

    image


    이제 학습이 끝나고 testing단계에 돌입해보자.
    imageimageimage
    학습시킬 때 주어진 데이터는, 동그래서 공이라고 잘 판단할 것이다.


    하지만 동그란 사과와 달까지 공이라고 판단해 버린다.

    imageimage


    이건 바로, 공 = 동그랗게 생긴 것이라고 만 학습시켜서이다.
    그래서 학습시킬 때, 동그란 것 이외에 다른 공들의 공통점을 찾아낼 것이다.

    1. 동그란 것 ------------->
      많은 공통된 특성이 있음에도 불구하고 한가지 특성만으로 학습시킬 경우, 머신러닝 용어로 too BIAS하게 train된 모델이라 한다.
      그리고 testing단계에서 새로운 데이터를 너무 잘 예측해버리는 모델을 underfitting된 모델이라고 한다.
      (이전 시간에는, 새로운 데이터를 예측하지 못하는 모델overfitting된 모델이라고 하였다.)
    2. 먹을 수 없는 것
    3. 가지고 놀 수 있는 것
      을 추가해서 학습더니 잘 예측하게 되었다.
      image
      이제 욕심을 내서 아래와 같이 공통된 특성이외에 지엽적인 특성들을 과하게 학습시켰다.
    4. 실밥을 가지는 것
    5. 지름이 7cm보다 큰 것
      하지만 아래와 같이 결과가 더 안좋았다. 골프공, 탁구공까지 배제해버리는 것이다.
      봤던 데이터는 잘 맞추는데, 새로운 데이터는 잘 예측하지 못하게 된다. 이러한 경우를 머신러닝 용어로 high variance한 모델이라고 한다.
      그리고 testing단계에서 새로운 데이터를 예측하지 못하는 overfitting 모델이라고 한다.

      image


    ㅇ요약하자면,
    많은 공통특성 중 일부 특성만 반영하여, too bias하게 train되어, 새로운 데이터도 막 예측해버리는 모델 : UnderFitting
    많은 공통특성 이외에 지엽적인 특성까지 반영하여, high variance하게 train되어, 새로운 데이터에 대해서는 예측하지못하는 모델 : overfitting

    Bias 와 Variance

    위에 설명한 언더피팅, 오버피팅을 극복하기 위해서는 bias와 variance개념을 알아야한다.
    image

    1. Bias : 실제값에서 멀어진 척도
    2. variance : 예측된 값들이 서로 얼마나 떨어져있는가

    언더피팅 모델은 high bias모델이라고 했다. 일부특성만 반영하여( 둥근것은 공이야라는) 편견을 가지고 있어서,
    예측값들이 실제 값(공)과 거리가 멀어져서 예측한다
    image

    오버피팅 모델은 high variance모델이라고 했다. 지엽적인 특성까지 다 반영되서(실밥, 7cm이상),
    학습된 것은 잘 예측하는데, 학습되지 않은 것들은 학습된 것의 예측값과는 떨어져서, 낮은 값으로 예측된다.
    image


    우리의 목표는 low bias하여 실제값과 가까이에서 예측되어야하고, low variance하여 예측값들이 서로 뭉쳐있어야한다.
    image



    그래프로 보자.


    둥근것이 공이야 : (일부 특성만 반영)feature가 너무 적어 high bias하여 실제값과 떨어진 underfitting 모델은 왼쪽이다.
    ---> variance는 낮다.
    실밥, 7cm이상까지 공이야 :
    (지엽특성까지 다 반영->) feature가 많아져 high variance하여 예측값들이 떨어져있는 overfitting 모델은 오른쪽이다.
    ---> bias는 낮다.
    둘다 error가 높다.
    image


    우리가 선택해야할 모데른 error가 낮은 중간지점이다.
    image


    my)
    욕심내서 feature를 많이 반영하면, high variance되어, 오버피팅이다.
    관심없어 feature를 적게 반영하면, high bias하여, 언더피팅이다.



    bias와 variance를 활용하여 언더피팅, 오버피팅 극복하기


    언더피팅은 어떻게 극복할 수 있을까?
    먼저, 언더피팅 모델인지 아닌지 판단 : 새로운 데이터도 너무 예측을 막 잘해버린다.
    언더피팅은 (관심없어 feature가 적게 반영된) high bias모델이므로, trade off로서 bias를 낮추고 variance를 높이는 전략을 쓴다

    1. feature를 더 많이 반영하여, variance 높이기
    2. variance가 높은 머신러닝 모델 사용하기 --> Decision Tree, kNN, SVM 모델로 사용해서 예측하기




    오버피팅 방지 1 : Validation set으로 k-fold cross validation하면서 / train방법을 learing_rate를 높혀 Regularization

    오버피팅은 어떻게 극복할 수 있을까?
    먼저, 오버피팅 모델인지 아닌지 판단 : 새로운 데이터를 너무 예측 못함.
    오버피팅은 (욕심내서 feature가 많이 반영된) high variance모델이므로, trade off로서 bias를 높이고, variance를 낮추는 전략을 쓴다.

    1. validation set을 갖추고, k-fold cross validation을 사용하여, train set과 비교한다.(train보다 낮으면 overfitting)
      image
      cf) keras의 경우, fit()함수에서 validation_split을 쓰면, k-fold cross validation이 아닌 마지막 10%만 반영되므로.. 조심
      validation set을 새로운데이터로서, accuracy가 낮다면 train방법을 바꾸어서 validation accuracy를 높여야한다.
      -> regularization을 반복해서 시행해야한다.


    2. validation set의 accuracy가 train보다 낮다면 Regularization을 계속해서 반복해야한다.
      쉽게 이해하기 위해서, 아래 Regression모델 3가지를 살펴보자. (y축은 cost함수 or loss함수인 것 같다)

      1) 3번째의 overfitting된 모델을 보자.
          데이터 분포에 비해 loss함수가 복잡해지고 smooth하지 않다. overfitting되어서,
         새로운 데이터를 넣으면 제대로 예측하지 못할 가능성이 높다.

      2) 2번째의 모델을 보자. 아래와 처럼 데이터분포와 조화가 되어서 smooth하다
          이러한 smooth한 곡선이 되기 위해서는, variance를 낮추어야한다.

       
      image

      두 그래프의 차이점은 무엇일까?
      3번째 그래프는 Regularization이 안되어서 울퉁불퉁한 그래프를 띈다고 한다.
      즉, overfitting 그래프 = variance 높은 그래프 = 울퉁불퉁한 그래프 = Regularization안된 그래프 =>
      variance를 낮추는 것이 Regularization => smooth한 그래프가 되어, 예측도 더 잘된다.


    3. 딥러닝의 테크닉인 조기종료(Early Stopping)- 아래에서 설명


    cost function  in Regression문제(MSE) 의 변형으로 variance를 낮출 수 있다.

    Regression문제를 해결하는데 있어서 cost function은 Mean squared Error를 쓴다고 했다.
    실제값과 예측값의 차이를 제곱해서 평균내는 것이다. 공식은 아래와 같다.
    (참고 : classification문제를 해결하는데 있어서 cost function은 Cross-entropy를 쓴다)

    image


    variance를 낮추는 방법은 아래와 같다.
    기존의 cost function에 100(w1 + w2 + w3 + w4)를 더하는 방법이다.

    cost function을 최소화하는 w1, w2, w3, w4를 찾는 것이 목적인데,
    더해진 양수인 ( w1+ w2 + w3 + w4 )의 값을 낮추어야만 한다.
    image

    w1 ~ 4는 h(x) (예측값, Regression함수) 의 계수값이었다.
    아래의 예처럼, 계수값을 반으로 줄였다고 가정해보자.

    기존의 h(x)가 가파란 것이 완만해진다.
    결과적으로 각 미분값인 접선의 기울기값들이 낮아졌다.
    variance값도 낮아지게 된다.

    image

    결과적으로, h(x)의 계수값인 w1, w2,w3 ..를 낮추면, variance가 낮아져서, Regression함수(h(x))도 smooth하게 된다.

    좀더 공식적으로 +100(w1+w2+w3+w4)를 일반적인 공식으로 나타내면 아래와 같다.
    image

    이제, 돌아가서
    울퉁불퉁한 그래프는 cost function 뒤에 Regularization을 의미하는 람다(w1+w2+w3..)가 붙지 않은 cost function을 가진다고 볼 수 있다.
    즉, Overfitting한 그래프는 람다 = Learning rate가 0인것이다.
    만약 람다(Learning rate)가 너무 높으면,  그만큼 w계수들 (코에피던시)들이 반대로 너무 낮아져서, 접선의 기울기 낫-> variance는 너무낮은 underfitting함수가 되어버린다.
    image



    my) 오버피팅을 방지하기 위한 Regularization -> 코스트함수에 Learning Rate를 붙혀서 variance를 낮춘다.
    Learning Rate가 너무 높으면 w는 그만큼 너무 낮아져서 varinace가 너무 감소하여 언더피팅이 된다.


    즉, 오버피팅된 상황에서는 learning rate를 높혀 Regularization한다??


    오버피팅 방지 2 : Early stopping in Deep learning

    오버피팅을 방지 방법으로

    1. validation set을 이용하여 k-fold cross validation을 통해, train방법을 피드백 하는데
      그 과정에서 learning_Rate를 높이는 Regularization을 한다고 했다.

    2. 조기종료(Early stropping)이 두번째 방법이다.
    3. DropOut


    딥러닝이란, 여러 Layer로 이루어진 뉴런들을, epoch수를 통해 반복해서 계속 학습시키는 것이다.
    그러나, 게쏙 반복학습하게 되면 어느시점에서, 가지고있는  train set은 accuracy가 올라가나,
    test set과 마찬가지로 작용하는 validation set의 accuracy가 멈추거나 낮아지는 지점이 온다.

    예를 들어, epoch을 50으로 준 상태에서, epoch 30에서 validation set의 accuracy가 제일 높았다고 가정하자
    validation accuracy가 더이상 올라가지 않을 때, stop시키는 것을 early stopping이라고 한다.


    image



    오버피팅 방지3 : Dropout

    1. validation set을 이용하여 k-fold cross validation을 통해, train방법을 피드백 하는데
      그 과정에서 learning_Rate를 높이는 Regularization을 한다고 했다.

    2. 조기종료(Early stropping)이 두번째 방법이다.
    3. DropOut

    드랍아웃은 train과정 중에서 몇개의 neuron을 쉬도록 만드는 것이다.



    image


    이러한 방식은 어떻게 Overfitting을 방지할 수 있을까?

    1. 몇개는 쉬게하고, 몇개는sub group을 맺어서 학습하게 되면, variance가 낮아진다고 한다.
      즉, 앙상블 방법과 비슷하게, 적은 variance로 예측을 서로 도와준다
      한다.

    2. 몇번 쉬게 되어 over train을 막아준다.


    9. 머신러닝 : 오버피팅

    2018. 8. 17. 20:34

    캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    오버피팅이란?

    한마디로 현재의 데이터에서는 잘 예측하는데, 새로운데이터에서는 잘 예측 못한다.


    청바지를 만들어 판다고 가정해보자.
    우리는 슈퍼모델을 고용하여, 이들에게 맞는 가장 멋진 청바지를 만들 것이다.

    그러나 고객들이 사지 않을 것이다. 왜일까?

    image


    그 이유는 청바지를 슈퍼모델에게만 맞도록 만들었기 때문이다.
    하지만, 고객들은 다양한 체형을 가지고 있다.
    image


    이제 우리는 다양한 체형에 맞춰서 청바지를 만들 것이다.
    image



    다양한 체형을 생각하지 못하고, 슈퍼모델들의 체형에 맞춰서 청바지를 제작한 경우가 바로 오버피팅(Overfitting)이다.
    image


    오버피팅 상황이라면, 우리가 가지고 있는 데이터는 슈퍼모델 데이터만 가진체 학습시킨 상황이다.
    하지만, 우리가 실제 우리가 보지 못한 다양한 체형들이 존재하므로, 오버피팅이 발생한다.



    Key conceps 살펴보기


    1. 슈퍼모델 데이터 = 현재 우리가 가진 데이터
    2. 실제 고객층 데이터 = unseen 데이터
    3. 실제 고객들이 사지 않는 상황 = 오버피팅

    즉 요약하자면, unseen data에 우리의 머신러닝이 제대로 예측하지 못하는 상황이 overfitting이다.


    그래프로 보기

    파란색 점들은 슈퍼모델 데이터들이다.
    빨간 선은 Decision Boundary이다.

    머신러닝에선 이 Decision Boundary 위 있는 것을 True라고 하고, 밖에 있는 것을 False라 할 것이다.


    이 상황에서, 새로운 점을 대입해보자.
    만약, 새로운 슈퍼모델 데이터를 입력한다면, Decision Boundary보다 위에 위치할 확률이 높을 것이다.(True)

    image

    만약, 다양한 체형의 고객층들의 데이터를 입력한다면, Decision Boundary보다 아래에 위치할 확률이 높을 것이다.(False)

    image


    이러한 오버피팅의 상황을 벗어나기 위해, 우리는 다양한 체형의 고객층의 데이터들도 같이 학습시켜
    새로운 Decision Boundary
    를 만들어서 Overfitting을 극복할 것이다.
    image



    Overfitting을 방지하는 방법

    1. Regularization
    2. Cross validation
    3. Add more data(다양한 체형의 데이터 대입하는 방법)


    타이타닉 분석3. modeling, validation, testing
    In [1]:

    # 캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    #-*- coding: utf-8 -*-# 블로그용 html조절from IPython.core.display import display, HTMLdisplay(HTML("<style> .container{width:90% !important;}</style>"))
    In [1]:
    import pandas as pdimport matplotlib.pyplot as plt%matplotlib inlineimport seaborn as snssns.set() #시본을 default plot으로 지정한다# label칼럼은 수동으로 적고, 행인덱싱, 이후, 행인덱싱 순서대로 합쳐진 df의 index명도 지정해줘야함.def bar_chart(feature):    #label 칼럼 수동으로 종류별 행인덱싱    survived = train.loc[ train['Survived'] == 1,: ][feature].value_counts()    dead = train.loc[ train['Survived'] == 0,: ][feature].value_counts()    df = pd.DataFrame([survived, dead])    #label 칼럼의 종류별로 합쳐진 df의 index 수동으로 순서대로 바꿔주기.    df.index = [ 'Survived', 'Dead']        print(df.head())    df.plot(kind='bar', stacked = True, figsize =(10,5))    
    In [48]:
    import pickletrain_data= pickle.load(open('fe_train.p', 'rb'))target= pickle.load(open('fe_target.p', 'rb'))test= pickle.load(open('test.p', 'rb'))

    1. Modeling

    In [49]:
    train_data.head()
    Out[49]:
    Pclass Sex Age Fare Cabin Embarked Title FamilySize
    0 3 0 1.0 0.0 2.0 0 0 0.4
    1 1 1 3.0 2.0 0.8 1 2 0.4
    2 3 1 1.0 0.0 2.0 0 1 0.0
    3 1 1 2.0 2.0 0.8 0 2 0.4
    4 3 0 2.0 0.0 2.0 0 0 0.0
    In [50]:
    train_data.info()
    <class 'pandas.core.frame.DataFrame'>RangeIndex: 891 entries, 0 to 890Data columns (total 8 columns):Pclass        891 non-null int64Sex           891 non-null int64Age           891 non-null float64Fare          891 non-null float64Cabin         891 non-null float64Embarked      891 non-null int64Title         891 non-null int64FamilySize    891 non-null float64dtypes: float64(4), int64(4)memory usage: 55.8 KB

    1.1 사이킷런(sklearn)에 있는 Classifier import하기

    In [51]:
    #kNNfrom sklearn.neighbors import KNeighborsClassifier#Decision Treefrom sklearn.tree import DecisionTreeClassifier#Random Forestfrom sklearn.ensemble import RandomForestClassifier#나이브 베이즈from sklearn.naive_bayes import GaussianNB# 서포터 벡터 머신from sklearn.svm import SVCimport numpy as np # np.mean 평균 등을 계산

    1.2 사이킷런에 있는 K-fold Cross validation import하기

    In [75]:
    from sklearn.model_selection import KFoldfrom sklearn.model_selection import  cross_val_score#train 데이터를 10개로 등분 낼 예정, shuffle은 10등분하기 전 전체데이터를 한번섞는다. 그 이후 10개 쪼개는 과정에서는 shuffle안한다.k_fold = KFold(n_splits = 10, shuffle = True, random_state = 0)

    2. Classifier로 분류하기

    2-1. kNN Classifier

    In [53]:
    #  k=13 개의 네이버를 사용한다.clf = KNeighborsClassifier(n_neighbors= 13 )scoring = 'accuracy'#cross_val_score에는 #1 분류기의 종류, 2 train, 3 label, 4cv= cross_validation의 종류, 5 ?? , 6. 정확도 등 표시할 것#cross_val_score()의 반환결과는 cv의 종류에 지정해준 splits 개수대로 정확도가 나온다.score = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)print(score)
    [0.82222222 0.76404494 0.80898876 0.83146067 0.87640449 0.82022472 0.85393258 0.79775281 0.84269663 0.84269663]
    In [54]:
    # 10개의 정확도 평균내기 ( 2번째 인자는 소수점 몇째짜리까지 표시되도록 반올림 할 것인가! )round(np.mean(score) * 100, 2)
    Out[54]:
    82.6

    2-2. Decision Tree

    • kNN에서 했던 것에서 분류기만 바꿔준다.
    In [55]:
    clf = DecisionTreeClassifier()scoring = 'accuracy'score = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)print(score)
    [0.76666667 0.80898876 0.7752809  0.76404494 0.8988764  0.76404494 0.83146067 0.82022472 0.75280899 0.79775281]
    In [56]:
    round(np.mean(score) * 100, 2)
    Out[56]:
    79.8

    2-3. Random Forest

    In [57]:
    #랜덤포레스트의 tree수를 지정해준다. 13개clf = RandomForestClassifier(n_estimators=13)scoring = 'accuracy'score = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)print(score)
    [0.8        0.83146067 0.82022472 0.79775281 0.86516854 0.80898876 0.80898876 0.82022472 0.76404494 0.79775281]
    In [58]:
    round(np.mean(score) * 100, 2)
    Out[58]:
    81.15

    2-4. Naive Bayes

    In [59]:
    clf = GaussianNB()scoring = 'accuracy'score = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)print(score)
    [0.85555556 0.73033708 0.75280899 0.75280899 0.70786517 0.80898876 0.76404494 0.80898876 0.86516854 0.83146067]
    In [60]:
    round(np.mean(score) * 100, 2)
    Out[60]:
    78.78

    2-5. SVM

    In [61]:
    clf = SVC()scoring = 'accuracy'score = cross_val_score(clf, train_data, target, cv=k_fold, n_jobs=1, scoring=scoring)print(score)
    [0.83333333 0.80898876 0.83146067 0.82022472 0.84269663 0.82022472 0.84269663 0.85393258 0.83146067 0.86516854]
    In [62]:
    round(np.mean(score) * 100, 2)
    Out[62]:
    83.5

    SVM이 가장 큰 score를 내었으니, SVM을 분류기로 채택하고 testing한다.

    테스트 데이터에... NaN이 있다.. 처리해보자.

    In [41]:
    test.info()
    <class 'pandas.core.frame.DataFrame'>RangeIndex: 418 entries, 0 to 417Data columns (total 9 columns):PassengerId    418 non-null int64Pclass         418 non-null int64Sex            418 non-null int64Age            332 non-null float64Fare           418 non-null float64Cabin          418 non-null float64Embarked       418 non-null int64Title          417 non-null float64FamilySize     418 non-null float64dtypes: float64(5), int64(4)memory usage: 29.5 KB
    In [65]:
    test['Age'].fillna ( test.groupby('Pclass')['Age'].transform('median') , inplace = True )
    In [69]:
    test['Title'].fillna ( test['Title'].mean(), inplace=True)
    In [70]:
    test.info()
    <class 'pandas.core.frame.DataFrame'>RangeIndex: 418 entries, 0 to 417Data columns (total 9 columns):PassengerId    418 non-null int64Pclass         418 non-null int64Sex            418 non-null int64Age            418 non-null float64Fare           418 non-null float64Cabin          418 non-null float64Embarked       418 non-null int64Title          418 non-null float64FamilySize     418 non-null float64dtypes: float64(5), int64(4)memory usage: 29.5 KB

    3. Testing

    In [71]:
    #SVM을 이용하여, train 데이터 학습시키기clf = SVC()clf.fit(train_data, target)# test데이터에서 PassengerId칼럼만 빼내기(필요없어서)test_data = test.drop('PassengerId', axis = 1).copy()# SVM을 이용하여 test데이터 예측하기prediction = clf.predict(test_data)
    In [72]:
    # prediction결과는 리스트로 test데이터 개수만큼 나온다.prediction
    Out[72]:
    array([0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1,       1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,       1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1,       1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1,       1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,       0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0,       0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,       0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,       1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1,       0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0,       1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,       0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,       0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,       0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1,       0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,       1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0,       0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0,       1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1,       0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1],      dtype=int64)

    4. prediction결과(단순리스트)를 df프레임 형태로 저장해보기

    • test데이터 원본에는 남아있던 PassengerId와 prediction을 딕셔너리로 만들어서 DataFrame에 담아준다
    • 이 때, prediction은 0or1으로 나타나는 Survived이므로, Survived로 키값(칼럼명)으로 지정해준다.
    In [73]:
    submission = pd.DataFrame({    'PassengerId' : test['PassengerId'],    'Survived' : prediction})#저장할 때, index=False를 주면, 불러올 때 이쁘게 불러와진다.# 반대로 그냥 정해놓고, 불러올 때 ignore_index=True를 줘도 된다.submission.to_csv('submission.csv', index=False)
    In [74]:
    submission = pd.read_csv('submission.csv')submission.head()
    Out[74]:
    PassengerId Survived
    0 892 0
    1 893 1
    2 894 0
    3 895 0
    4 896 1

    참고

    k_fold = KFold(n_splits=10, shuffle=True, random_state=0) 에서요 "shuffle = True"로 하면 어떤 의미인가요? 혹시 매번 CV할때마다 Shuffle한다는 의미일까요? CV의 가장 주된 목적이 모든 데이터를 validation set으로 써서 accuracy variation을 줄인것으로 생각하면 CV로 쪼갤때 마다 Shuffle은 좀 아닌거 같은데요 ㅎㅎ 찾아봐도 그 의미가 잘 안나와서요. kfold 없이 그냥 cv = 10인거 계속 돌려도 같은 값이 나오네요 ㅎㅎ shuffle의미가 저에게 어렵습니다 ㅎㅎㅎ

    seongmin lee 안녕하세요, shuffle=True할 경우, k개로 데이터를 나누기 전에 단 한번 데이터를 뒤섞게 됩니다. 10개의 데이터가 생성된 후 라운드마다 인덱스 1부터 10까지 검증데이터로 사용하게 되어있어요. 셔플링은 k의 수에 상관없이

    생존자 예측 모델을 여러개 테스트 해서 SVM이 제일 우수하다라는 것을 알게 되었습니다.SVM 모델을 어떻게 이용하면 prediction과 실제결과가 나오는 비교할 수있나요? prediction이 지금 array인데 이걸 DF타입으로 바꿔서 train의 survived를 새로운 열로 붙이면 되는 걸까요?

    아래 링크 가셔서 최하단 부분의 코드를 활용하시면 될 거 같습니다.https://github.com/minsuk-heo/wikibooks_python_ml/blob/master/jupyter_notebook/svm_%EB%86%8D%EA%B5%AC%EC%84%A0%EC%88%98_%ED%8F%AC%EC%A7%80%EC%85%98_%EC%98%88%EC%B8%A1_%EC%8B%A4%EC%8A%B5.ipynb

    갑자기 너무 많은 질문을 드려 죄송합니다만 ㅎㅎㅎ KFold를 하는 이유가 seed 설정때문에 하는거죠? 그냥 cross_val_score(cv = 10)으로 해도 되는데 이러면 매번 값이 바뀌기 때문이죠? 그래서 cv = KFold로 설정하는거죠? 여기서 질문드립니다. 제가 최적화된 n_neighbor 값을 KNN모델에서 찾으려고 루프를 돌렸는데요, 뭐가 잘못되었는지 for문에서는 Kfold가 iterable하지 않다고 하네요... 이럴때 gridSearch를 해야하는지요? 두개 코드를 다 돌려보면 좀 결과가 다른데 이유가 무엇인지 좀 알 수 있을까요?

    [knn Parameter 찾기]neighbors = np.arange(1, 502, 5)

    kfold = KFold(n_splits=5, random_state=123)

    score_list = []cv_score_list = []for n in neighbors: knn = KNeighborsClassifier(n_neighbors=n) knn.fit(X_train, y_train) score = knn.score(X_train, y_train) cv_score = cross_val_score(estimator=knn, scoring= 'accuracy', cv=5, X=X_train, y=y_train) score_list.append(score) cv_score_list.append(cv_score.mean())

    [Gridsearch해서 찾기]kfold = KFold(n_splits=5, random_state= 123)neighbors = np.arange(1, 502, 5)grid_param = {'n_neighbors':neighbors}

    knn = KNeighborsClassifier()grid = GridSearchCV(estimator=knn, param_grid = grid_param, cv= kfold, scoring='accuracy')grid_result = grid.fit(X_train, y_train)print(grid_result.bestscore)print(grid_result.bestparams)

    cross_val_score(cv = 10) 은 kfold의 k=10과 동일합니다. http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score.html제가 kfold 를 쓴 별다른 이유는 없지만, kfold를 더욱 비디오에서 명시적으로 보여드릴 수 있어서 사용했어요.두번째 질문은 sklearn가 내부적으로 어떻게 작용하는 지 알아야 대답할 수 있을 것 같은데, 제가 거기까진 잘 모르겠네요. 제가 아는바로는 둘 다 stratified k-fold cross-validation를 사용하는 걸로 알고 있는데, 차이 나는 이유는 잘 모르겠습니다.


    캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    먼저, feature는 2개로 간소화시켜서 설명한다.( 2개일 경우만 시각화가 가능)

    label(target)은 0(dead과 1(Survived)가 있다고 가정한다.

    이 때 사용할 수 있는 머신러닝Classifier의 종류는 5가지 정도로 요약될 수 있다.

    1. kNN
    2. Decision Tree
    3. Random Forest
    4. Naive Bayes
    5. SVM(Support Vector Machine)


    image


    kNN( k - Nearest Neighborhood) 분류기

    test데이터가 들어갈 때, 가장 가까운 3개의 이웃 중, 많은 label을 택한다.

    1. k=3일 경우,
      2명이 살았고, 1명이 죽었으니까 심슨은 Survive를 label로 예측할 것이다.
      image

    2. k=5일 경우, 심슨은 dead로 예측될 것이다.
      image

    보는 것과 같이, k에 따라 예측값도 달라진다. 그러므로 k라는 변수를 변화시키면서, 분류기의 accuracy를 살펴보아야할 것이다.


    Decision Tree 분류기

    Decision Tree의 경우,
    우리가 가지고 있는 feature를 모두 분석해서 tree를 build해준다.
    그리고 나서 test데이터만 넣어주면, 알아서 판단해준다.
    image


    Random Forest

    Decision Tree가 여러개 모여서 Forest를 이룬 것이다.
    Decision Tree보다는 조금 작은 Tree들이 여러개 들어간다.

    만약 feature가 9개인 상황이면, Random Forest에서는 3개의 Tree에다가 각각 3개의 feature를 쪼개어 할당한다.

    그리고 나서 3개의 Tree중에, 더많은 Tree의 예측결과를 따른다.
    아래그림과 같이 2개의 Tree가 dead라고 예측하였으니, 심슨은 Dead로 예측될 것이다.
    image



    나이브 베이즈(Naive Bayes)

    나이브 베이즈는 확률을 사용한다.
    만약, feature에 age와 sex 2개가 존재하는 상황에서, 심슨의 나이, 성별에 따라 Survive할 확률은 얼마인지를 Naive Bayes의 이론에 따라 계산하게 된다. 자세한 것은 이전에 포스팅 한 것을 참고하면 된다.

    image


    SVM(Support Vector Machine)

    서포터 벡터 머신은 기본적으로 Decision Boundary라는 직선이 주어진 상태이다.
    이 Decision boundary를 긋는 방법은 binary classification(Logistic regression문제)에서

    feature가 2개이므로, z(x) = w1x1 + w2x2 일 때, activation(x) = sigmoid ( z(x))이고,
    이 때, a(x) = h(x) 인, 단순 선형회귀일 경우에,
    예측값이 0도 아니고 1도 아닌, h(x) = 0.5를 만들게 하는 경우이다.

    즉, h(x) = a( z(x)) = sigmoid( z(x) )= 0.5
    image

    z(x) = 0

    w1x1 + w2x2 = 0을 만족시키는 w1와 w2에 의해 결정된다.
    x2 = - w1x1 / w2 이므로, 기울기는 -w1/w2일 것이다.


    아무튼, 심슨은 Decision Boundary보다 위에 있으므로 죽었다고 예측되고,
    심슨부인은 Decision Boundary보다 아래에 있으므로 살았다고 예측된다.

    image





    모델링과 Classifier가 있는 상태에서,
    Testing을 하기전에 반드시 해야할 것이 validation이다.

    k-fold Cross validation

    현재 가지고 있는 train데이터셋을 가지고 validation해야한다. (test데이터셋은 순서 테스트만 해야한다)

    1. 고전적인 방법으로는 train data에서 일부를 떼서 validation에 쓰는 것이다.
      그 결과, train을 통해 나오는 accuracy는 validation dataset의 accuracy이다.
      여기서 문제점은, train에서 떼어낸 특정 부분만의 accuracy이며,
      다른부분에서 떼어낼 경우 accuracy가 달라지게 된다.
      즉, bias(편견이 있는) validation이다.
      image

    2. k-fold cross validation방법은 고전적인 valdation방법을 보완한다.
      1) 먼저 k=10으로 가정하면, train data를 10등분한다.
      image

      2) 순서대로 돌아가면서 1/10을 validation으로 사용하며, 나머지 9개를 train으로 사용한다.
      image

      3) 10번의 validation결과로 나온 accuracy를 평균낸다.
      전문용어로는 validation accuracy score라고 한다.


    이제 머신러닝classifier 5개를 사용해보고
    k-fold cross validation을 거쳐
    final accuracy가 가장 높은 classifier를 채택하자.

    캡쳐 사진 및 글작성에 대한 도움 출저 : 유튜브 - 허민석님


    k-mean 클러스터링의 과정

    시각화와 설명을 위해서, 관여변수는 2개만 있다고 가정한다.

    1. 데이터를 준비한다.
      image
    2. 데이터에 대해 얼마나 많은 클러스트를 만들것인지 결정한다.(클러스트 개수 지정)
      - 예를 들어,  티셔츠 장사시에, 100명의 손님 모두 맞춤티셔츠를 만들기 힘들다. 이 경우 클러스터링을 통해 S, M, L 3가지로 평준화할 수 있다.
      - my) classification에서 class와 비슷한 개념인 듯 하다.


    3. 클러스터링시, 클러스트의 중심(centeroid)을 설정한다( 3가지 방법이 있다. )
      image

    4. 클러스트의 중심에 대해, 모든 데이터 점(data point)들을 가장 가까운 클러스트 중심에 할당한다.
      image
      ---->1번은 c1에 할당항 빨간색이 된다-->image
      imageimageimage
      image
      - 이렇게 첫번째 iteration이 끝난다.

    5. 각 클러스트의 중심을,  할당된 데이터 point들의 중심으로 옮긴다
      image
      - 클러스트의 중심이 움직였다면, 다시 데이터들을 옮겨진 클러스트에 대해 가장 가까운대로 할당하는 과정이 반복될 것이다.
    6. 클러스트들의 변화가 없을때까지 or 지정한 최대 횟수동안, 4번과 5번을 반복한다.
      - 2번째 iteration시에, 데이터point 4번은 새로운 클러스트에 할당된다.
      image
      - 2번째 과정이 모두 끝나면, 클러스트의 중심을 또 옮긴다.
      image
      - 3번째 iteration시에는 아무 데이터point도 클러스트 할당이 변경되지 않았다. 그러면 클러스트의 중심도 이동하지 않게 된다.
      image



    클러스트의 중심(centroid)를 초기화하는 3가지 방법

    1. randomly choose : 랜덤으로 막 정하는 것
    2. manually assig init centroid : 수동으로 할당해주는 법
      - 위도, 경도가 변수(속성, feature)일 때, 사람의 위치를, 3개의 도시(이미 정해져있는 지점)을 클러스트의 중심으로 지정할 수 있다.
      image
    3. k-mean++
      1) 랜덤으로 클러스트중심을 정했는데 ---> 결과가 만족스럽지 못하다
      2) 수동으로 줄 수 없는 상황이다


    K - mean ++ 알고리즘 for init centroid

    1. 첫번째 데이터point에 첫번째 클러스터링 중심을 할당한다
      image

    2. 첫번째 데이터에서 가장 먼 데이터에다가 2번째 클러스터 중심을 할당한다.
      image

    3. c1과 c2에 공통적으로 가장 먼 데이터point에 c3를 할당한다.


    실습


    k-mean

    0. 패키지 복사

    In [1]:
    #-*- coding: utf-8 -*-#블로그용 html조절# from IPython.core.display import display, HTML# display(HTML("<style> .container{width:90% !important;}</style>"))import pandas as pd #데이터 포인트 생성import numpy as np # 편한계산을 위한from sklearn.cluster import KMeans #사이킷런의 KMeans 패키지 사용import matplotlib.pyplot as plt #시각화import seaborn as sns # 시각화%matplotlib inline 

    1. create data points

    In [2]:
    # df 데이터없이 칼럼명만 생성하기df  = pd.DataFrame( columns = ['x', 'y'])df
    Out[2]:
    x y
    In [3]:
    #좌표(data points)들 입력df.loc[0] = [3,1]df.loc[1] = [4,1]df.loc[2] = [3,2]df.loc[3] = [4,2]df.loc[4] = [10,5]df.loc[5] = [10,6]df.loc[6] = [11,5]df.loc[7] = [11,6]df.loc[8] = [15,1]df.loc[9] = [15,2]df.loc[10] = [16,1]df.loc[11] = [16,2]
    In [4]:
    df.head(12)
    Out[4]:
    x y
    0 3 1
    1 4 1
    2 3 2
    3 4 2
    4 10 5
    5 10 6
    6 11 5
    7 11 6
    8 15 1
    9 15 2
    10 16 1
    11 16 2

    2. 시각화

    2-1 seaborn을 이용한 data points 시각화

    2-2 matplotlib을 이용한 전체 타이틀 + x,y축 라벨명 지정

    In [5]:
    #시본의 lm chart 이용하여 좌표찍기#x축에 들어갈 df의 칼럼명, y축 칼럼명, dataFrame, line여부, 마커사이즈sns.lmplot('x', 'y', data = df, fit_reg=False, scatter_kws={'s':100})#맷플롯립을 이용한 플롯 네이밍#만약 xlabel과 ylabel의 이름 안주면, seaborn의 df.의 '칼럼명1', '칼럼명2' 가 들어감plt.title('k-mean plot')plt. xlabel('x-axis')plt. ylabel('y-axis')
    Out[5]:
    Text(16.3,0.5,'y-axis')

    3. k-mean clustering

    In [7]:
    # 계산을 하려면 df 전체 값을-> array로data_points = df.valuesdata_points
    Out[7]:
    array([[3, 1],       [4, 1],       [3, 2],       [4, 2],       [10, 5],       [10, 6],       [11, 5],       [11, 6],       [15, 1],       [15, 2],       [16, 1],       [16, 2]], dtype=object)
    In [8]:
    # k-mean 돌리기,  KMeans( 클러스트수 = 3) . fit( 학습시킬 data points(좌표형태의 array))kmeans = KMeans(n_clusters=3).fit(data_points)
    In [9]:
    # 클러스트3개가 적용된 kmeans 속에,, 각 datapoints의 해당 클러스트보기kmeans.labels_
    Out[9]:
    array([1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0])
    In [10]:
    #해당 클러스트의 클러스트 중심(centeroid)보기kmeans.cluster_centers_
    Out[10]:
    array([[15.5,  1.5],       [ 3.5,  1.5],       [10.5,  5.5]])
    In [11]:
    df['cluster_id'] = kmeans.labels_
    In [15]:
    df
    Out[15]:
    x y cluster_id
    0 3 1 1
    1 4 1 1
    2 3 2 1
    3 4 2 1
    4 10 5 2
    5 10 6 2
    6 11 5 2
    7 11 6 2
    8 15 1 0
    9 15 2 0
    10 16 1 0
    11 16 2 0
    In [22]:
    # 4. 클러스터링까지 포함하는 df를 시각화하기#시본으로 시각화하는데, hue옵션을 주어, 특정칼럼에 따른 색 구분시키기sns.lmplot('x', 'y', data = df, fit_reg=False, scatter_kws={'s' : 100},          hue = 'cluster_id', # hue의 인자인 클러스트_id에 따라 찍히는 점의 색이 달라진다.          )# 맷플롯립은 라벨링만 해주기plt.title('after  kmean clustering')plt.xlabel('x - axis')plt.ylabel('y - axis ')
    Out[22]:
    Text(26.7781,0.5,'y - axis ')


    + Recent posts