분류 전체보기

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


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 ')


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


머신러닝 중 Supervised Learning(정답이 주어진 데이터를 학습하여 분석)에는 2가지 카테고리가 있다.
바로 Classification와  Regression이다.

image


Classification

classification에는 classifier(분류기)가 있다. 그에 해당하는 것이 knn, decision tree, SVM(딥러닝시 DNN, CNN ) 등등이 있다.

분류기에 정답을 가진 data로  train해주고 난 뒤, train이 끝나면, test시에는 정답이 없는 data를, 학습된 class를 기초로 판단하게 하는 것이다.



Regression

사람의 무게를 줬을 때, 그 사람의 키를 예측하는 등의 문제이다. 즉, class로 나눠져있지 않고 정답이 -무한대 ~ +무한대의 범위에 있는 것을 예측한다.



Linear Regression

직선, 즉 일차함수의 개념인 y = ax +b 직선을 임의로 그려놓고, 그 직선을 바탕으로 예측하는 것이 선형회귀이다.


그렇다면, 아래와 같은 초록색직선과 빨간색 직선중 어느 모델이 더 예측을 잘할까?

 image


잘 모르겠다면 아래 문제는 어떠한가?
둘중에 어느 직선이 더 예측하기 쉬울까?
image

많은 사람들이 왼쪽이 더 예측하기 쉬운모델이라고 한다. 왜냐하면 모든 점들이 직선상에 존재하기 때문이다.

이것을 수치적으로 나타내보자.
우리가 예측하기 위해 만든 모델인 y=ax+b직선과  실제 데이터를 찍어놓은 점들y값 차이를 error라고 한다.
즉, 아래와 같이 점과 직선사이의 수직거리가 있어야 'error가 있다'라고 말할 수 있는 것이다.
image

그에 비해 왼쪽에 있는 직선의 경우 에러가 전혀없다.
그렇다면, 왼쪽의 직선모델이 에러가 전혀없으므로, 왼쪽 직선모델이 더 낫다고 할 수 있다.


이제 수학적으로 더 파고 들어가 보자. error이외에 square error라는 것이 있다.

  1. error : 실제 데이터의 y값과 예측 직선모델의 y값의 차이
  2. Square error : 실제 데이터의 y값과 예측 직선모델의 y값의 차이를 제곱해서 넓이로 보는 것이다.

    image

error를 제곱해서 넓이로 보는 이유는 무엇일까?

  1. 우리 눈에 보이기 쉽다.
  2. 수학적으로 볼 때, 에러가 조금이라도 있다면, 값이 증폭되어 --> 큰값과 작은값의 비교를 쉽게 할 수 있다.
  3. 딥러닝 등의 알고리즘인 Gradient Descent의 Backpropagation개념에서 계산이 용이하게 편미분된다.


다시 처음 문제로 돌아가보자. 둘중 어떤 모델이 더 나은 모델일까?

선형회귀에서 어떤 모델이 나은지 확인하려면 Square error의 측면에서 확인해야한다.
 image



Square Error를 구하고, 그것을 평균 낸 Mean Square Error를 보면 왼쪽이 더 작다.
그러므로 왼쪽의 녹색의 예측직선모델이 예측을 더 잘하는 것이다.
image

여기에서는 확률의 개념은 등장하지 않는다. classification문제와 달리, Regression문제는 예측할 수 있는 정닶값이
앞서 말한 것처럼, -무한대 ~ +무한대 값을 가지기 때문이다.



Mean Square Error과 Cost funcion


이제 문제를 더 발전시켜 보자.
관찰된 값들이 있을 때(정답이 주어진 데이터가 있을 때), 가장 적합한 선(가장 적합한 선형회귀모델)을 그으려면 어떻게 해야할까?
즉, Linear Regression을 코딩하는 것이다.

image


여기서 사용하는 개념이 바로 Least Mean Squre Error (LMS Error)이다.
앞서 살펴본 개념들이 다 녹아있다.

  1. Error = h(x) - y  : 예측값h(x)(직선모델)   -   실제값y(실제 데이터의 y값)
  2. Square Error = Error를 제곱한 값 = ( h(x) - y )2
  3. Mean Square Error = Square Error를 다 더해서 n으로 나누어 평균낸 값 = image


개념(M.S.E)를 이용하여, best한 선형회귀모델( 주어진 데이터를 예측할 수 있는 최적의 직선)을 그을 것이다.
그 과정에서 사용되는 것이 Gradient Descent 알고리즘이다.
그리고 이 알고리즘을 사용하기 위해, 알아야할 개념인 Cost functionMean Square Error와 같은 것이라고 봐야한다.
즉, 실제값과 가설값(예측값)의 차이를 제곱해서 평균낸 개념이 비용함수 (J(w,b), cost function)인 것이다.
그리고 이 Cost function(MeanSquareError)를 최저로 만드는 개념이 Least Mean Square Error일 것이다.
그리고 이렇게 cost function을 최저로 만드는 목적을 가진 함수이므로 목적함수 (objective function)이라고도 한다.

image



Gradient Descent

정답이 주어진 데이터가 있을 때, 우리는 최적의 선형회귀모델(직선)을 만들고, 그 모델의 Mean Square Error 즉, cost function을 최소로 만드는 최적의 직선을 찾아야한다.
그 cost를 최소로 하는 직선을 구하는 과정을 train(학습)이라 하고, train에 사용되는 알고리즘이 Gradient Desent알고리즘이라 하였다.


간단한 예제로서, 
최초의 직선h(x) = wx라 두고, 이것의 cost function(image) 를 최소로 하는 w를 찾는 것이 목적이다.
그 과정에서 Gradient Descent알고리즘이 어떻게 사용되는지 보자.
( 머신러닝에서는 x앞에 우리가 찾아야할 w를 θ(세타)라고 한다. 나는 편의상 w라 하겠다)

  1. Graident Descent는 cost를 최소로 만드는 예측직선 h(x) = wx에서 최적의w를 업데이트하면서 찾아내는 과정이라고 볼 수 있다.
    즉, 공식으로서는 아래와 같다.

    image

    w = w - ɑ * ( cost func을 w로 편미분 한 것)인데, 여기서  w를 업데이트 하는 변화량 dw을 보면
    ɑ와 cost의 편미분이 곱해진 것이 Gradient의 핵심이라고 할 수 있다. 우항의 항목들을 살펴보자.
    1)W : 첫번째 w로서, 우리가 맨첨에 초기화한 상수이다. gradient를 태워서 cost를 최소로만드는 w로점점 업데이트 될 것이다
    2) ɑ : learning_rate로서, 학습속도를 조절하는 상수. 우리가 초기화한다.
    3) image : cost 즉, MeanSquareError를 w로 편미분한 것

    이것으로 미루어볼 때, 우리는 1)2) 최초w와 a는 상수이므로 놔두고,
    3) cost 편미분한것을 통해서 w를 변화시켜 최적(cost를 최소화하는)의 w로 업데이트 시킨다는 것을 확인할 수 있다.

  2. 임의로 최초 w는 1로, ɑ는 0.01로 초기화 하자.
    그러면 w에 대한 M.S.E.(cost function)을 시각화 해보면 아래와 같다.
    image
    image

    이 때, 그라디언트에서는 w변화량이   - (음수)(알파 : 양수) * ( 위 그림의 접선의 기울기 : 양수) 으로
    기존 w에서 마이너스(-)가 될 것이다.
    ( 참고 : cost의 편미분을 구할 때에는, 먼저 w와 cost(MSE)에 대한 시각화 후, 접선의 기울기를 생각하자!)

    image


    이제 업데이트된 w에 대해서, 그라디언트를 통해 다음 w를 구해보자.
    image
    image에서 w = 0.98 - (0.01) * ( +1) = 0.97로 조금 더 줄어들 것이다.

  3. 이러한 Graident -> w업데이트의 과정은 언제까지 반복될까?
    2차 곡선상의 접선의기울기(cost편미분량)이 거의 0이 나오는 지점인 converge 까지 반복해서 w가 업데이트 된다.
    이러한 w를 업데이트를 하는 과정에서 1번째의 h(x) = wx직선과    200번째의 h(x) = wx의 직선을 비교해보자.
    아래와 같이 graident를 통해 200회 업데이트된 w로 구성된 직선은 MSE값(cost 값)이 매우 작아진 것을 확인할 수 있다.

    1) h(x) = wx ( w=1, step1)
    image

    2) h(x) = wx( w = gradient 200회 업데이트한 w값, 0.5로 나왔다고 가정)
    image



그러면 h(x)=wx+b의 문제는 어떻게 풀 수 있을 까?
위에서 본 예제는 b=0인 문제였다. 그러나 실제에서는 b(bias)가 거의 붙어있다고 보면 된다.
이럴 때는, b를 새로운 w2라 보고
h(x) = w1x + w2x의 문제를 풀면된다.

우리가 위에서  cost(mse)를 시각화할 때는, w가 1개 뿐이라서 2차 함수였지만, w가 하나더 늘어났기 때문에 3차원으로 표시해야한다.
하지만, 우리의 눈은 2차원만 쉽게 해석되기 때문에 이 이후의 과정은 머신러닝으로 해결하도록 하자

image

image




learning_rate(ɑ)는 어떻게 설정해야할까?

러닝레이트는 w가 업데이트되는 량을 상수로서 앞에 붙어서 조절한다. 그리고 우리가 처음에 초기화했다.

러닝레이트가 너무 적으면, 업데이트가 적게되므로,  w들이 converge를 찾아서 내려가는 시간이 너무 오래 걸린다.
image

반대로 너무 높으면, 과격한 업데이트로, w가 converge를 지나쳐버리기도 한다.

image

결과적으로 적당히 조절해야 cost(loss)가 수렴한다.

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


확률론

image

위 그림에서 사과를 짚을 확률은 2/3. 바나나를 짚을 확률은 1/3이다.


다음은 조건부확률(Conditional Probablility)이다.
the probablity of an event (A), given that another (B) has already occurred

조건부 확률은 2가지 경우가 있다.

  1. A와 B사건이 서로 영향을 끼치지 않을 때,
    예를 들어, 녹색셔츠를 입고(B)갔을 때, 카지노에서 잭팟(A)이 터질 확률은?
    여기서 녹색셔츠를 입든 말든 잭팟이 터질확률 1%에 영향을 미치지 않는다. 반대도 마찬가지다
    이 경우에 A와 B가 동시에 일어날 확률 P(A ∩ B) P(A) * P(B)이다.
    그리고 B가 일어났을 때, A가 일어날 확률은, 그냥 P(A). 반대의 경우도 P(B)이다
    결과적으로 P( B/ A) = P( B) 반대의 경우도 마찬가지다.

    image

  2. A와 B사건이 서로 영향을 끼칠 때,
    예를 들어, 비가 오는 날(A)에는 우산 장사(B)가 더 잘될 것이다. 서로 영향을 미치는 것에 대해서는 조건부확률의 공식이 달라진다.
    A와 B가 동시에 일어날 P(A ∩ B)은 P(A) * P(B)가 아니라, P(A) * P( B/A) ( P(B) in the given P(A) )이다.
    즉, 조건부확률 P( B/A)  = P(A ∩ B) / P (A) 가 된다.
    image



나이브 베이즈(Naive Bayes) 알고리즘

만약 셜록 홈즈가 이런 말을 했다고 가정해보자

' 너는 여자친구가 없어, 왜냐하면 주말에 유튜브만 보고 있고, 뚱뚱하고, 패션감각이 없기 때문이지'

image


셜록홈즈는 항상 근거를 가지고 있다. 그리고 만약에 나이브베이즈 알고리즘을 썼다면, 근거가 있는 말일 것이다.
즉,  유튜브/뚱뚱한/패션감각없는 확률을 미리 알고 있었다면,  여자친구가 없을 확률에 대해 충분히 납득해야할 것이다.


앞서 학습한, 서로 영향을 끼칠 때의 두 사건에 대한 conditional probability를 사용해 나이브 베이즈 이론을 증명해보자

조건부확률 공식에서 분자를 기준으로 정렬하면 아래와 같다.
P(A ∩ B)은 , P(A) * P( B/A) 이다.
P(B ∩ A)은 , P(B) * P( A/B) 이다.
여기서 두 교집합은 서로 같다
P(A ∩ B) = P(B ∩ A)
그러므로 P(A) * P( B/A) = P(B) * P( A/B)가 성립하게 된다.
결과적으로 A가 일어났을 때의 B의 확률
P(B/A) = P(B) * P( A/B) / P(A)가 된다.


image



아래와 같은 문제에 나이브 베이즈 이론을 적용시켜보자.

image

10개의 메일 중에, 3개는 스펨메일이다. 그리고 그와 상관없이 free라는 단어를 포함하는 메일이 4개가 있다.
문제는 free라는 메일이 와있을 때(A) 그것이 스펨매일(B)인지 아닌지를 구분해야하는 것이다.

기본적으로 필요한 요소는 3가지이다.

  1. 스펨메일의 확률 = 3/10

  2. free를 포함하는 메일의 확률 = 4/10
  3. 스펨메일 중에 포함된 free포함메일 = 2/3


P(B/A) = P(B) * P( A/B) / P(A)
해석 : A(관련요소)가 일어났을 때, B(판단요소)의 확률 B(판단요소)확률 * B가 일어났을 때의 A 확률 / A(관련요소)의 확률

P( spam / free ) = P(spam) * P ( free / spam ) / P (free)
P( spam / free ) = 3/10 * 2/3  /  4/10
image


이렇게 2사건(판단요소(spam) + 관련요소(free))에 대한 3개의 요소를 가지고 있으면,
새로운 1개의 조건부 확률(관련요소가 있을 때의 판단요소 확률)을 구할 수 있다. 이게 바로 나이브베이즈 이론이다.

즉, 관련요소(free)가 일어났을 때, 판단요소(spam)에 대한 확률은
판단요소확률 * 판단요소가일어났을 때 관련요소의 확률  / 관련요소의 확률


여기까지는 너무 쉬울 수 있다. 머신러닝이 필요한가에 대한 의문도 들 수 있다.

하지만, 실제는 다르다. 머신러닝이 필요한 이유는 아래와 같다.

spam메일도 무수히 많을 뿐만 아니라,
free말고도 coupon , fuXX, sexy 등 무수히 많은 단어들이 스팸메일안에 들어가 있기 때문이다.




아래는 조금 더 복잡한 예제이다.
free뿐만 아니라, coupon이라는 단어도 동시에 포함되어있는 상황에서 스팸메일인지 아닌지를 알아보자.

14개의 메일 중에, free라는 단어를 포함하는 메일과 coupon이라는 단어를 포함하는 메일들이 와있다.

imageimage

이전 예제에서는 2가지요소에 대해서 3개의 인자를 알아야된다고 했는데,
이번엔 3가지 사건(판단(spame) + 관련요소1(free) 관련요소2(coupon)의 교집합 ) 에 대해서는 미리 3가지 요소를 알아야한다.

관련요소1과 관련요소2가 있을 때, 판단요소일 확률은?

  1. 스팸메일(판단요소)의 확률 : 6/14


  2. 스팸메일(판단요소) 중 free와 coupon을 모두 포함하는 메일(관련요소 교집합) = 1/2
    - P( free ∩ coupon / spam) = 1 / 2
  3. free와 coupon을 모두 포함하는 메일(관련요소 교집합) = 2/7
    - P( free ∩ coupon ) = P(free ) * P( coupon / free) = 7/14 *   4 / 7 = 2/7


결과적으로 확률은
P( spam / free ∩ coupon ) = P(spam) * P( free ∩ coupon / spam)   /   P( free ∩ coupon)
P( spam / free ∩ coupon ) = 6/14 * 1/2 / 2/7 
P( spam / free ∩ coupon ) = 3/14 * 7/2 = 3/4 ( 0.75 = 75%)

 

이러한 확률을 다른식으로 해석해보자.
계산에 있어서, 관련요소1,2 들은 모두 독립이라고 가정하게 되면, 분자 중 빨간색 부분을 아래와 같이 쪼갤 수있다.
P( spam / free ∩ coupon ) = P(spam) * P( free ∩ coupon / spam)   /   P( free ∩ coupon)

P( spam / free ∩ coupon ) =  P(spam) * P( free / spam) * P( coupon / spam)   /   P( free ∩ coupon) 방식으로 쪼갤 수 있다.P

분모 역시 아래와 같은 방식으로 쪼갤 수 있다.( 서로 독립이므로)

P( spam / free ∩ coupon ) =  P(spam) * P( free / spam) * P( coupon / spam)   /   P( free ∩ coupon) 

P( spam / free ∩ coupon ) =  P(spam) * P( free / spam) * P( coupon / spam)   /   P( free ) P(coupon) 방식으로 쪼갤 수 있다.


즉 요약하자면, 나이브 베이즈 알고리즘을 사용하는데 있어서,

독립적인 관련요소(w0,w1, w2, w3, ...)이 일어났을 때의 판단요소(spam)의 확률은

판단요소 * (관련요소1/판단요소) * (관련요소1/판단요소) * ... * (관련요소n /판단요소)
------------------------------------------------------------------------------------------------
관련요소1 * 관련요소2 * ... * 관련요소n
 


image




참고

free 와 coupon이 들어간 메일은 스팸메일거라는 확률이 75프로 (실제로 높은 확률이라고 생각하지만) 라는 근거로 이메일이 스팸이다 라고 가정할수 있는데, 혹시 몇 프로 이상일때 스팸일 것이라고 정의 할만한 유의확률(?) 같은 것이 있나요? 아니면 어디까지나 구현하는 사람의 기준에 의해 달라질수 있는 것인가요? (예로, 확률이 10프로 이상만 되도 스팸이라고 가정하는 것은 그런 시스템 구현자의 의지인가요? 아니면 머신러닝의 결과물이 되는건가요?)

정답은 없습니다만 많은 트레이닝과 실습으로 유의확률을 결정하는 게 거의 맞다고 보시면 될 거 같습니다. test 이후 confusion matrix를 보며 accuracy, precision 등등의 케이스를 연구 후 유의 확률을 높히는 것이 실제 더 맞을 거 같습니다.


0.75 라는 확률은free랑 coupon이 동시에 들어가있는 이메일이 스팸일 확률 인거죠? free만도아니고 coupon만도아니고 두개가 동시에. 그렇다면 강의 마지막 부분에 w1,w2,w3 등으로 여러단어를 나열했을때 더욱 의의가 있다고 하시는데. w1~w20까지 했을경우 그 20개단어가 모두 들어가는 이메일은 거의 없지 않을까요?답변 부탁드립니다 ㅜ


아주 예리한 질문이십니다. 인자가 많을 경우 오히려 올바른 예측을 못하게 되는 경우를 오버피팅(overfit)이라고 합니다.

참고이미지

2018. 8. 7. 22:06

image_thumb1


image

image

image

파이썬으로 하는 이유

  1. c++에 비해 간결하고, 쉬워서 배우기 싶다.
  2. 2016년 기준으로, python이 c++의 사용자수를 능가했음. 대신 script언어라서 느리다는 단점
  3. 그러나 python의 라이브러리들은 c++로 기본적으로 짜여져있고, python으로 랩핑한 것일 뿐이라서 성능상의 손해는 거의 없다


아래 사진은, 같은 기능을 c++로 구현한 것과 파이썬으로 구현한 것이다.
간결함이 비교가 안된다.

image


OpenCV c++이 필요한 이유는, 안드로이드 어플을 개발하려고 할 때, c++코드를 jni로 호출할 때 정도에 필요하다.
그러나, 프로토타입을 python으로 개발해놓고 --> C++로 변환하는 과정을 통해 쉽게 구현할 수 있다.


버전 비교 2.*  vs  3.*

기능 추가 및 연산속도가 발전했다.

그러나 알고리즘 개선과정에서 2.4버전과 하위호환의 거의 포기했다고 하니, 2.*사용자들은 주의해야할 것이다.
구현할 코드는 2.4버전으로 할 것이다.(그러나 지금 설치는 3.2라서 3.2로 도전해보고안되면 변환)
image


필요한 도구 - jupyter notebook

쥬피터 노트북은 iPython에서 발전한 것으로, 웹에서 바로 파이썬을 사용하도록 하는 어플리케이션이다.
쥬피터만의 강점은 블록(cell)별로 실행이 가능하니, 빠르게 디버깅이 가능하고, 마크다운으로 바로 문서화가 가능하다는 강점이 있다.

그리고 서버를 두고 가능하기 때문에, 여러사용자가 접근할 수 있다는 장점도 있다.
image


아나콘다

파이썬 패키지들과 그외 라이브러리들을 한곳에 모아놓은 통합개발환경으로, 다른 라이브러리 설치도 쉽게할 수 있다.

그리고 가상환경을 생성하여, 라이브러리들의 의존성을 명확하게 할 수 있는 장점도 있다.

image


명함인식의 과정

  1. 배경색과 차이가 나는 명함을 배경에 놓고 찍는다.
    image

  2. 이미지에서 색상이 급격하게 변하는 구간(배경->명함)을 엣지라고 하는데, 엣지 검출 알고리즘을 통해서 엣지를 찾아 아래 그림과 같이 흰색라인으로 보이게 만든다.
    - 이전에 엣지를 검출하기 전에, 노이즈를 어떻게 처리할지 에 대한 것을 다루어야한다.
    image

  3. 검출한 엣지 중에서 가장 외곽의 사각형을 검출한다.
    - 검출된 사각형은 꼭지점이 4개여야만 한다. 그래야 반듯한 사각형으로 변환할 수 있다.
    - 그 과정에서, 어떤 사각형을 외곽이라 판단할 것인지 와 찌그러진 부분이 있다면 어떻게 할지를 다루어야한다.
    image


  4. 반듯한 사각형으로 변환하기
    - 4개의 꼭지점 중에서 어느것이 좌상단 / 우상단인지.. 변환시 가로와 세로의 길이는 어떻게 할 것인지를 다루어야한다.
    image

  5. 그 다음으로, 조명의 영향을 제거한다. 마치 스캐너로 스캔한 것처럼 이미지를 흑백으로 바꾼다.
    - 어떤 기준으로 밝은부분->흰색 / 어두운부분->검은색으로 할지 기준을 정해야할 것이다.
    - 조명상태에 따라, 어떻게 반영할지를 생각해봐야할 것이다.
    image


  6. 마지막으로, 흑백사진에서 OCR을 적용해서 글자를 인색해본다.
    - 글자인식을 어떻게 더 성능을 높일지 고민해봐야 할 것이다.
    image

요약

image

2. opencv 활용사례

2018. 8. 7. 20:51

카메라앱의 필터

image

다 다른것 같지만, 기본적으로 다같은 효과의 필터를 opencv로 구현하고 있다고 보면 된다.
예를 들어, 3가지 blur효과를 적용한 결과이다.
image


객체인식

특히 글자나, 얼굴인식이 가장 연구가 활발하다.
객체인식의 성능을 높이기 위해서는, 단순히 opencv만이 아니라 사이킷런을 활용하여 많은 데이터를 학습시켜야 성능이 좋아진다고 한다.
숫자 인식은 opencv를 활용해서 객체인식할 수 있는 가장 기본적인 적이다.
image

얼굴인식의 예는 facebook이 대표적이라 할 수 있다.
얼굴뿐만 아니라 눈, 코, 입의 인식도 opencv 튜토리얼로 구현해볼 수 있다고 한다.
다만, 성별, 나이, 시간까지 구분하려면, 머신러닝과 딥러닝을 활용해야한다.
image


영상인식

이것 역시 opencv 튜토리얼로 금방 구현할 수 있는 영상인식의 예라고 한다.

image


투영변환

직접 구현해볼 것과 가장 유사한 아이디어인 스캔 앱이다.
물체의 테투리를 인식해서, 스캐너로 스캔한 것처럼 변환해주는 기술이다.
이를 컴퓨터비전 용어로는, 투영변환이라고 한다.

image

위의 그림과 같이 투영변환하려면, 최소4개의 꼭지점이 필요하고 찌그러진 사각형을 반듯하게 변환하는 과정이다.
그러기 위해서는, 문서의 외곽을 추출해야하므로, 문서의 색과 배경색이 명확하게 달라야한다.
그러므로, 스캔앱에서는 문서와 다른배경위에 문서를 올려놓으라고 배경이 뜬다.

투영변환의 응용

투영변환의 꼭지점을 4개가 아니라, 더 다양하게 응용하면, 얼굴을 갸름하게하고 몸매를 보정하고 할 수 있다.

image


머신러닝 알고리즘의 시각화

머신러닝의 결과를 시각화하는데 쓰이기도 한다. 현재 알려진 머신러닝의 알고리즘은 대부분 opencv가 지원한다고 한다.

image

1. 아나콘다에서 opencv 설치


conda install -c conda-forge opencv
image

2. tesseract-ocr-setup-3.02.02


https://sourceforge.net/projects/tesseract-ocr-alt/?source=typ_redirect
image

3. pytesseract 설치 ( 아나콘다에서 지원안하는 것 같음)


pip install pytesseract
image

4. 설치 확인


image


참고

설치하고 pytesseract 테스트하실때 eng.traineddata 를 로드할 수 없다고 에러를 내는 경우가 있는데요.
파이썬소스는 D:\에 있고 tesseract는 C:\\Program Files (x86)\\Tesseract-OCR\\ 에 설치 되어 있는 경우
에러가 발생합니다.
pytesseract가 경로에서 드라이브를 잘라 버리고 ‘.\\Program Files (x86)\\Tesseract-OCR\\’ 폴더를 이렇게
데이터파일 폴더를 찾더라구요.

대부분 소스는 D드라이브나 별도의 외장하드에 저장하면서 테스트를 하실텐데요.

그럴 경우 image_to_string함수 실행전에 os.chdir(‘C:’)로 드라이브를 바꿔주고나서 하면 잘되긴합니다

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


Desicion Tree에서 하나의 속성을 잡고, 데이터를 split(나눌때)할 때, 가장 유명한 알고리즘은 ID3 알고리즘이다.

ID3알고리즘EntropyInformation Gain이라는 2가지 컨셉을 가지고 있다.

image

  1. 8개의 사진이 주어졌을 때, 첫번째 속성을 잡기전에 먼저, base entropy를 알아야한다.
    Entropy를 구하는 공식은 아래와 같다.
    E[+, -] =
    image

    8개의 사진 중에서, 목적인 겨울가족사진에 해당하는 것은 1개, 아닌 것은 7개 이므로  p(+) = 1/8 , p(-) = 7/8 을 대입한다.
    image
    계산 결과 base entropy는 0.543인 것이다.

  2. 다음은, information Gain을 구해야한다.
    공식은, 임의의 1개의 속성을 잡았을 때, base entropy - new entropy이다.
    즉, E( 겨울가족사진 ) - E( 겨울가족사진, 카툰?) 의 계산값이다.

    new entropy인 E(겨울가족사진, 카툰?)을 계산하는 방법은
    1) 8개의 사진 중에 카툰사진은 4개이다. p(+) = 4/8
    2) 그 4개의 사진가운데, 겨울가족사진인 것 0개, 겨울가족사진이 아닌 것 4개 = E[0+, 4-]

    3) 8개의 사진 중 카툰이 아닌 사진은 4개이다. p(-) = 4/8
    4) 그 4개의 사진 가운데, 겨울가족사진인 것 1개, 겨울가족사진 아닌 것 3개 = E[1+, 4-]
    각각 곱해서 더한다.
    new entropy = 4/8 * E[0+,4-] + 4/8 * E[1+,4-]
    information Gain = base entropy(0.543) - new entropy( 4/8 * E[0+,4-] + 4/8 * E[1+,4-] )

    image

    같은 방식으로, 겨울?  / 1명이상?  을 첫번째 속성(attribute)로 잡았을 때의 information Gain을 구할 수 있다.
    image


결과적으로, Information Gain가장 높게 나온 카툰? 첫번째 속성으로 사용하게 되는 것이다.
image

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


의사결정 트리

image

위의 그림이 있는 상태에서, 아무것도 모르는 애기한테 '겨울가족 사진 한번 찾아봐' 라고 얘기했다고 가정해보자.
애기는 아무것도 모르니까 우리는 힌트를 줘야한다.
'1. 사람이 있어야 가족사진이란다.'

image

그렇다면, 애기는 만화가족사진 + 사람가족사진 중 사람가족사진 걸러낼 것이다.

두번째 힌트는 '2. 이 있어야 겨울사진이지'라고 힌트를 주자. 그렇다면 눈없는 사람가족사진 + 눈있는 사람가족사진 중 눈있는 가족사진을 걸러낼 것이다.

image


세번째 힌트는 '3.사람이 여러명 있어야 겨울가족사진이란다'라고 주자.

image


이렇게 학습이 된 애기한테, 다른 사진을 보여주면서 겨울가족사진인지 알아맞추라고 해보자.

image


엘사사진 -> 만화라서 바로 걸러진다.
겨울가족사진 -> 만화x사람o -> 눈o-> 1명이상 o -> 겨울가족사진 맞아!
라는 답이 나올 것이다.
image


여기서 애기는 머신이고, 우리가 가르쳐준 것을 배우는 러닝을 하였고, 이러한 과정을 통해서 푸는 것이 Decision Tree 알고리즘이다.


의사결정트리의 2가지 메인 컨셉

image

  1. 머신은 애기와 같이, 아무것도 모른다. 우리가 알려줘야한다. 일단 문제부터 알려줘야한다. -> Define Problem
    여기서는, 겨울가족사진이 맞는지?을 Define Problem으로 선택했다.
    그리고 맨처음 8개 사진을 준 것이 -> Collect training Data이다.

  2. 두번째는 Decision Tree를 만드는 과정이다. --> Build a tree
    tree를 만들려면
    1) Extract Data ( Data에서 중요한 feature(여기서는 cartoon? / winter?1명이상? ) 를 뽑아내야한다.
    2) 그 다음에 Build a tree한다.

  3. 만든 Decision Tree알고리즘으로 머신을 돌리는 것을 Deploy Machine이라고 한다.

  4. 이제 학습이된 똑똑한 머신에게 새로운 data(여기서는 사진 ,엘사/스키장사진)를 보여주는 것을 Test라 한다.


Extract Data란? 

데이터에서 중요한 feature(속성)를 뽑아내서 tree의 결정 기준으로 삼는 과정이다.
겨울가족사진 data에서 extract한 feautre는 cartoon? / winter?1명이상? 3가지였다.
image



Build a Decision Tree

뽑아낸 중요feature(속성)어떤 것을 먼저 사용해야 효율적일까?

image

카툰?을 기준으로 split해보면-----> 4개가 떨어져나간다.
winter? 로 split해보면 -----------> 3개가 떨어져나간다
1명이상?으로 split해보면 --------> 3개가 떨어져나간다.

가장 직관적으로 가장 많이 떨어져나가는 카툰? 을 먼저 사용하는 것이 효율적이게 된다.

image
남은 것은
winter? --> 1개 떨어져나감
1명이상?-> 2개 떨어져나감.
2번째로는 1명이상? 을 tree의 기준으로 삼아주고 마지막으로 winter?로 나누면 될것이다.
image


Entropy?

image

왼쪽 방처럼 많이 어질러져있다면, High Entropy / 오른쪽방처럼 조금 어질러져있다면 Low Entropy라 한다.


다시 아까 tree를 만드는 과정으로 돌아와보자.
image


3개의 속성(attribute, feature in data)을 사용하여 data를 split함으로써, 깔끔해진다고 해서 Entropy가 낮아진다고 할 수 있다.


Information Gain? (Base entropy - new entropy)

information gain 은  base entropy - new entropy 값이다.
전문적으로 다음 attribute(feature)를 선택할 때, 이 information gain이 가장 높을 것을 선택한다..
공식상으로는, base entropy는 주어진 8개 사진이라 고정이고, new entropy가 낮아져야한다.

즉, 8개의 사진 중에서 data가 split 됨에 따라, new entropy가 점점 낮아지는데,
new entropy가 최대한 낮아지도록 많이 split된다면, 그만큼 information gain은 높아질 것이다.

그래서 가장 데이터가 많이 split되는 카툰? 속성이 가장 먼저 선택되는 것이다

+ Recent posts