머신러닝 & 딥러닝/머신러닝 기초

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


개요

딥러닝에 있어서, 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 데이터이다.

  1. 나나 2018.10.02 09:59

    안녕하세요 글 잘 읽었습니다.
    다름이 아니고 질문이 한 가지 있는데
    정확도와 roc커브의 auc면적은 다를 수도 있는건가요?
    헷갈리네요...

    • 나나 2018.10.02 10:00

      클래스별 분포가 같을 경우에 어떨지 궁금하네요. 혹시 답변 얻을 수 있을까요?

    • nittaku 2018.10.02 13:29 신고

      계산방식이 다르므로 다르게나옵니다

    • nittaku 2018.10.02 13:34 신고

      저는 클래스변 같은데이터만 학습시킨결과 클래스별로 auc가 나왔어요.
      정확도랑은 달랐습니다

  2. 장서연 2020.05.04 17:17

    와... 통계에 대한 개념이 부족해서 과제 수행에 어려움을 겪고 있었는데 덕분에 정말 큰 도움이 되었습니다!
    너무 감사합니다!!!!!
    좋은 하루 보내세요!!!

  3. 옐란 2020.06.20 06:07

    ROC에서 TNR을 사용하는게 맞나요? 어떤 블로그는 FallOut을 사용하는데 분모의 값은 같으나, 분자로 쓰는 값이 (TN -> FP로 상이하네요)

    https://datascienceschool.net/view-notebook/731e0d2ef52c41c686ba53dcaf346f32/
    위양성율(fall-out)은 실제 양성 클래스에 속하지 않는 표본 중에 양성 클래스에 속한다고 출력한 표본의 비율을 말한다. 다른 평가점수와 달리 낮을수록 좋은 모형이다. FDS의 경우에는 실제로는 정상 거래인데 FDS가 사기 거래라고 예측한 거래의 비율이 된다. FPR(false positive rate)또는 1에서 위양성률의 값을 뺀 값을 특이도(specificity)라고도 한다.
    fallout=FP/ (FP+TN)

  4. 나나 2020.06.22 11:31

    1-TNR
    - > 1- FN = FPR 입니다

  5. 2020.12.09 14:40

    비밀댓글입니다

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


머신러닝을 가지고 모델을 만들어 예측하다보면, 하나의 꼬리를 가지고 여러 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로 채택하자!





    1. minsuk 2018.10.08 11:39

      안녕하세요. 자료의 출처를 밝혀주시면 더욱 좋을 것 같아요! 요약해주셔서 감사합니다.

      • 2018.10.08 12:09

        비밀댓글입니다

    2. Daviec 2019.05.05 21:12 신고

      잘보고 갑니다! 자료의 출처 남겨주시면 더 좋을 것 같아요

    3. skybook 2020.06.24 15:21

      안녕하세요 글이 너무 좋아
      매번 다시 보면서 곱씹고 있습니다.

      궁금한점은

      accuracy 와 f1-score 를 둘 중에 하나만 평가지표로 쓰는 것이 아니라 50% 비중으로 둘 다 사용하는 것에 대해서는 어떻게 생각하시는지?
      그리고 balance data 에 대해서 accuracy 와 f1-score 둘 다를 평가지표로 사용하는 것에 대해서는 어떻게 생각하시는지요?

    4. 777천재777 2021.08.25 11:56 신고

      좋은 정보 감사합니다.
      그런데 f1score 가 실제 계산 한 값과 비교해볼 때 소수점 6이나 7번째 에서 달라지는데
      왜 그런 걸까요?

      2*(p * r) / (p + r) 계산 순서는 아래가 맞는 것 같고요

      1. (p * r)
      2. (p + r)
      3. (p * r) / (p + r)
      4. 2 * (p * r) / (p + r)

      • 777천재777 2021.08.25 12:10 신고

        sklearn 의 f1_score 함수를 썼을 때와 confusion matrix 를 보고 실제 공식으로 계산한 결과와 비교해서요

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


    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별로 몇퍼센트를 맞추었는지 알 수 있다.


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


    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>


    1. Thomaspiketty 2021.10.07 04:23

      글 잘 읽었습니다.
      from sklearn.decomposition import PCA
      pca_result = pca.fit_transform(DataFrame)
      혹시 이렇게 라이브러리를 사용해서 결과를 얻은 값과 선생님이 하신 방법과의 차이가 있는지요?

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


    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에서는 어디서 사용할까?¶</