참조

https://mambo-coding-note.tistory.com/284 - 개념참조

https://github.com/fmfn/BayesianOptimization - 코드참조

https://www.youtube.com/watch?v=sbbR-XRft9o&t=45s - 개념참조

베이즈 정리 간단히
  • 사전확률과 사후 확률사이의 관계를 나타내는정리

**사전확률/사후확률 : 어떤 일(evidence를 관측해서 갱신하하기 전/후의 내 주장에 관한 신뢰도

  • 새로운 정볼를 토대로 어떤 사건이 발생했다는 주장에 대해 신뢰도를 갱신해나가는 방법이다

**베이지안주의 관점 : 동전앞면이 나올확률은 50%, 100번동전을 던졌을때 앞면이 나왔다는 주장의 신뢰도가 50%라고 본다.

**빈도주의 관점 : 동전앞면이 나올확률은 50%, 100번동전을 던졌을때 50번은 앞면이 나온다고해석 (기존의 통계학)

  • 베이지안 관점의 통계에서는 사전확률과같은 경험에 기반한 선험적인,불확실성을 내포하는 수치를 기반을 하고 거기에 추가정보를 바탕으로 사전확률을 갱신한다.(귀납적 추론)

e.g.

질병 A의 발병률은 0.1%.이 질병이 실제로 있을 때 질병이 있다고 검진할 확률(민감도)은 99%, 질병이 없을 때 없다고 실제로 질병이 없다고 검진할 확률(특이도)는 98%라고 하자.

만약 어떤 사람이 질병에 걸렸다고 검진받았을 때, 이 사람이 정말로 질병에 걸렸을 확률은?

 

 

  • 한마디로 정의하면 : Random Search와 통계적인 기법 (Gaussian Distribution)을 기반으로 실제 data를 이용하여 surrogate model을 이용하여 실제 model을 찾지 않아도 Maximum value를 도출해낼 수 있다는것.

 

 

 

1. 지금까지 관측된 데이터 D = [(x1, f(x1)), (x2, f(x2)) … (xn, f(xn))]을 통해, Gaussian process prior로 function f(x)를 Estimation한다. (= surrogate model)

** Surrogate model(대체 모델, 근사수학모델)

이란 자동차 충돌 실험과 같이 제한된 계산 비용이 많이 드는 시뮬레이션을 기반으로 복잡한 시스템의 수많은 입출력 특성을 실제 모형과 유사하게 만드는 것

  • 여기서 f(x)는 함수이고, x는 하이퍼 파라미터이다!!!!!!!! (x가 여러개일수도 있음)

그러니까 앞에서 함수의 해당 하이퍼파라미터랑 , 탐색대상 함수를 쌍으로 만든다음, 이것을 대상으로 surrogaate model을 만들어서 평가를 순차적으로 업데이트하여 최적의 하이퍼파라미터조합을 탐색하는 과정

 


  • 관측치 수(코드에서 나오는데 n_iter로 몇번 반복할지 조정가능함) 가 증가함에 따라 사후 분포가 개선되고 알고리즘은 아래 그림에서 볼 수 있듯이 매개 변수 공간에서 탐색 할 가치가있는 영역과 그렇지 않은 영역이 더 확실해진다.(한마디로 위에 피피티 그림에서 회색부분 공간이 점점 줄어들고 대충 모양이 잡힌다는 뜻임)

(피피티 4개짜리 그래프 설명) 위 피피티에서 4개짜리 그림을 보면, 1번에서 모양이 살짝 바뀌었다. 두번째로는 제일 값이 높아보이는쪽으로 이동한다. 먼가 모양이 좀더 좁아졌다. 세번째로는 variance가 제일 높아보이는데로 이동했다. 이렇게 계속 반복반복하다보면 4번째 그림처럼 되고, 노란색 부분 즉 maximum값을 구할수있다.

→ 이렇게 Exploitation/Exploration 을 반복해주는 매커니즘이

acquisiton function

인것임 (용어는 뒤에....)

 

2. Function f(x)를 다음으로 관측할 지점 (xn+1, f(xn+1))으로 Acquisition Function(decision rule)으로 선택하여 이동한다.(제일 중요하다)

acquisition functio

n

은 surrogate model이 목적함수(우리가 찾고자하는 함수) 에 대해서 실제 데이터를 기반으로 다음번 조사할 x값을 확률적으로 계산해서 추천해주는 함수

**Exploitation 은 현재까지 조사된 값들의 근방으로 다시 조사를 하는 것이다. 착취를 말한다.

**Exploration 은 현재까지 조사된 값들의 근방으로 조사를 하지 않고, 불확실성이 제일 높은 구간을 조사한다. 탐험을 말한다.

<acquisition function 종류>

  1. EI (Expected Improvement / MEI 라고도함 )는 Exploration 과 Exploitation 방법을 모두 일정 수준 포함하도록 설계된 것이고, 제일 많이 쓰는 Acquistion Function이다.
  1. MPI
  1. UCB

!! acquisiton function 에 따라 성능이 달라진다 !!

 

<베이지안 옵티 코드!>

 

#!pip install Bayesian-Optimization
#https://github.com/fmfn/BayesianOptimization 참조

# underlying function!! , x,y를 하이퍼 파라미터 취급한다.
def black_box_function(x, y):
    return -x ** 2 - (y - 1) ** 2 + 1
from bayes_opt import BayesianOptimization
# Bounded region of parameter space
pbounds = {'x': (2, 4), 'y': (-3, 3)}   #하이퍼 파라미터 정해줌
optimizer = BayesianOptimization(  
    f=black_box_function, #앞에서 지정해준 black_box_funciton을 함수를 f에 넣어준다.
    pbounds=pbounds,  #하이퍼 파라미터 넣어준다.
    verbose=2, #verbose = 1 prints only when a maximum is observed, 0일땐 silent ,versbose=2 항상
    random_state=1,   #seed, 무작위성을 컨트롤 0이면,반복해도 똑같은값 출력함.
)
optimizer.maximize(
    init_points=2,  # init_points : 수행하려는 임의 탐색 단계 수. 무작위 탐사는 탐사 공간을 다양 화하여 도움을 줌.
    n_iter=3,  # n_iter :위에서 임의탐색한거 주위에서 찾아봄 (3.4, 3.5, 3.002, 2.7, 2.95 이렇게)
    acq='ei',  #aacquisition 선택 ( ei / poi / usb )  - 이것에 따라 성능이 갈리기도 한다.
)
# 임의 탐색2번 + 반복3번해서 총 5개 나오는것! 
>>
|   iter    |  target   |     x     |     y     |
-------------------------------------------------
|  1        | -7.135    |  2.834    |  1.322    |
|  2        | -7.78     |  2.0      | -1.186    |
|  3        | -7.11     |  2.218    | -0.7867   |
|  4        | -6.76     |  2.558    | -0.1028   |
|  5        | -17.39    |  4.0      | -0.5455   |
=================================================
print(optimizer.max)  # 가장 최대일때의 x,y값을 출력해준다.

>> 
{'target': -6.760373063273364, 'params': {'x': 2.558177239763734, 'y': -0.10277027219097953}}
for i, res in enumerate(optimizer.res):
    print("Iteration {}: \n\t{}".format(i, res))
    
>> 
Iteration 0: 
	{'target': -7.135455292718879, 'params': {'x': 2.8340440094051482, 'y': 1.3219469606529488}}
Iteration 1: 
	{'target': -7.779531005607566, 'params': {'x': 2.0002287496346898, 'y': -1.1860045642089614}}
Iteration 2: 
	{'target': -7.109925819441113, 'params': {'x': 2.2175526295255183, 'y': -0.7867249801593896}}
Iteration 3: 
	{'target': -6.760373063273364, 'params': {'x': 2.558177239763734, 'y': -0.10277027219097953}}
Iteration 4: 
	{'target': -17.38863150351646, 'params': {'x': 4.0, 'y': -0.5455198166042586}}
optimizer.set_bounds(new_bounds={"x": (-2, 3)})  #범위 수정해줌!!!!

optimizer.maximize(
    init_points=0,
    n_iter=5,
)   

>>
|   iter    |  target   |     x     |     y     |
-------------------------------------------------
|  6        | -1.769    | -1.57     |  1.552    |
|  7        | -1.362    | -1.438    |  1.542    |
|  8        | -1.447    | -1.395    |  1.708    |
|  9        | -0.6024   | -1.143    |  1.543    |
|  10       |  0.1307   | -0.8744   |  1.324    |
=================================================
optimizer.probe(  #probe는 탐색을 의미함
    params={"x": 0.5, "y": 0.7},
    lazy=True,  #기본으로 설정해놓는다.
)
#다음에 maximize를 호출할 때 평가함

optimizer.probe(
    params=[-0.3, 0.1],
    lazy=True,
)

# Will probe only the two points specified above
optimizer.maximize(init_points=0, n_iter=0)

>>
|   iter    |  target   |     x     |     y     |
-------------------------------------------------
|  13       |  0.1      | -0.3      |  0.1      |
|  14       |  0.1      | -0.3      |  0.1      |
=================================================

<string 유사도 구하기 알고리즘3가지 적용>

 

1. LCS알고리즘 (=최장공통부분 문자열)

=Longest Common Subsequence

(substring은 연속된 부분 문자열, subsequence는 연속적이지 않은 부분 문자열 - 핵심!)

두개 s1,s2가 주어졌을때, 공통으로 들어있는 부분열중 가장긴 열의 길이를 찾아낸다. (여기서 부분열이란? 몇몇 문자가 빠져도 순서는 바뀌지않는 문자열을 의미

def lcs(a, b):
    prev = [0]*len(a)
    for i,r in enumerate(a):
        current = []
        for j,c in enumerate(b):
            if r==c:
                e = prev[j-1]+1 if i* j > 0 else 1
            else:
                e = max(prev[j] if i > 0 else 0, current[-1] if j > 0 else 0)
            current.append(e)
        prev = current
    return current[-1]
   

2. 레벤슈타인 알고리즘(=편집거리 알고리즘)

→ 위에 LCS랑 거의 비슷한데 약간의 디테일만 다르다!!!!!!

두 문자열이 같아지려면, 몇번의 문자조작(삽입,삭제,변경)이 필요한지 구하는것 ( 위의 3개를 합치면 총 조작비용이 나온다)

#레반슈타인 알고리즘 ( 편집거리 알고리즘 )
import numpy as np
def levenshtein(seq1, seq2):
    size_x = len(seq1) + 1    #왜냐면 matrix에 넣어줄때, 제일 왼쪽에 0이 붙으니까~~
    size_y = len(seq2) + 1
    matrix = np.zeros ((size_x, size_y)) # matrix를 0으로 초기화함
    for x in range(size_x): 
        matrix [x, 0] = x
    for y in range(size_y):
        matrix [0, y] = y
# 참조링크 들어가보면 matrix 북서쪽에 0,1,2,... 이런식으로 숫자 채워줌
# matrix 북서쪽 채워주고 나머지는 전부 0
# 북서쪽이 뭐냐! 앞에서 len()+1로 더해준 0이랑 조작비용을 계산하는거라 0,1,2,3....이렇게 채워진다.


# 여기서부터 나머지 matrix값들 채워줌
    for x in range(1, size_x):  #북서쪽 앞에서 채워준거 제외해줘야하니까 1부터 시작~
        for y in range(1, size_y):  #for, for로 비교
            if seq1[x-1] == seq2[y-1]:  # seq[]이랑 matrix[]이거랑 따로!!! 그려서 넣어보면 바로이해감
                matrix [x,y] = min(
                    matrix[x-1, y] + 1,#문자삽입
                    matrix[x-1, y-1],   #문자제거 
                    matrix[x, y-1] + 1   #문자변경
                )
            else:
                matrix [x,y] = min(   #둘이 안같으면 그냥 전값에 1더해주기
                    matrix[x-1,y] + 1,
                    matrix[x-1,y-1] + 1,
                    matrix[x,y-1] + 1
                )
    #print (matrix)  
    return (matrix[size_x - 1, size_y - 1])  # matrix에서 제일 오른쪽아래값을 출력해줌 

3. n-gram

n개의 연속적인 단어나열 / n개의 단어뭉치단위로 끊어서 이것을 하나의 토큰으로 간주.

위에 두개는 subsequence로 연속적이지 않는 부분 문자열을 살폈지만, 이건 연속적인것으로 판단함

그러니까 2-gram이라고 하면, 두개씩 찢어서 찢어놓은 리스트에서 같은것이 몇개인가를 확률로 나타낸것.

#n-gram
def ngram(s, num): #
    res = []
    slen = len(s) - num + 1  # num개로 찢으면 몇개나오나 연산
    for i in range(slen): 
        ss = s[i:i+num]  #찢어준다!
        res.append(ss)   #res안에 조각조각낸거 넣어줌
    return res
def diff_ngram(sa, sb, num):   #sa,sb가 비교할 string, num은 몇개로 찢을거냐
    a = ngram(sa, num)  #sa를 num으로 찢은게 a
    b = ngram(sb, num)  #sb를 num으로 찢은게 b
    r = []
    cnt = 0
    for i in a:   #찢어준 리스트중에 머가 곂치는지 하나하나 비교해줌
        for j in b:
            if i == j:
                cnt += 1
                r.append(i) 
    return cnt / len(a)#곂치는 조각들을 모아서 리스트로 만들어줌
    #return cnt / len(a), r     # cnt을 리스트개수로 나눠서 출력/ r

4. 그외 문자열 유사도 구하는 다른 방법들... Hamming Distance / Smith-Waterman / Sørensen–Dice coefficient ......

 

 

 

- Lcs랑 레벤슈타인 피처들간의 연관도를 표로 만들었을때 차이점 (헷갈리지말기)

-> 연관도 있는 피처쌍을 뽑을때, lcs는 숫자가 큰것들을 필러팅 / 레벤슈타인은 숫자가 작은것들을 필터링해야한다

'<개념> > 기타' 카테고리의 다른 글

SHIFT 개념 이해하기 예제 with SIN/COS/TAN  (0) 2021.12.30
자주나오는 이산수학관련 내용  (0) 2021.11.28
RestfulAPI 개념정리  (0) 2021.08.14
AJAX,JSON 개념메모  (0) 2021.08.14
도커 초간단 개념정리  (0) 2021.05.09

 

 

#피처들 목록
'Device_AddN', 'Device_AddV2', 'Device_ArgMax',
       'Device_AssignAddVariableOp', 'Device_BiasAdd', 'Device_BiasAddGrad',
       'Device_Cast', 'Device_Conv2D', 'Device_Conv2DBackpropFilter',
       'Device_Conv2DBackpropInput', 'Device_DivNoNan', 'Device_DynamicStitch',
       'Device_Equal', 'Device_FusedBatchNormGradV3',
       'Device_FusedBatchNormV3', 'Device_LogicalAnd', 'Device_MatMul',
       'Device_MaxPool', 'Device_MaxPoolGrad', 'Device_Mul', 'Device_RealDiv',
       'Device_Relu', 'Device_ReluGrad', 'Device_ResourceApplyGradientDescent',
       'Device_Softmax', 'Device_SoftmaxCrossEntropyWithLogits', 'Device_Sum',
       'Device_Tile', 'Device_Unknown', 'Device__FusedConv2D',
       'Device__HostRecv', 'Host_FlushSummaryWriter', 'Host_IteratorGetNext',
       'Host_LogicalAnd', 'Host_WriteSummary', 'Device_AvgPool',
       'Device_AvgPoolGrad', 'Device_Square', 'Device_Mean',
       'Device_BroadcastTo'

  • Device_AddN

모두 더해서 출력한다

x = [9, 7, 10]
tf.math.add_n(x) ==> 26
  • Device_AddV2

요소별로 x + y 출력

tf.raw_ops.AddV2(x, y, name=None)
  • Device_ArgMax

전체 행렬에 대해 계산되어 단일 숫자를 반환함 (=몇번째가 제일큰지)

tf.raw_ops.ArgMax(
    input, dimension, output_type=tf.dtypes.int64, name=None
)
from numpy import argmax
vector = [0.4, 0.5, 0.1]  # define vector
result = argmax(vector)  # get argmax
print('arg max of %s: %d' % (vector, result))
>>arg max of [0.4, 0.5, 0.1]: 1  #1[0th,1th,2th]중 두번째값(0.5)이 젤 크다는뜻
probs = asarray([[0.4, 0.5, 0.1], [0.0, 0.0, 1.0], [0.9, 0.0, 0.1], [0.3, 0.3, 0.4]])
print(probs.shape)
result = argmax(probs, axis=1)
print(result)
>>(4, 3)[1 2 0 2] 

참조 : https://deeplizard.com/learn/video/K3lX3Cltt4c

  • AssignAddVariableOp

변수에 현재값을 추가

tf.raw_ops.AssignAddVariableOp(resource, value, name=None)

  • Device_BiasAdd

bias 와 value 를 더해준다.

-scope: A Scope object

-value: Any number of dimensions.

-bias: 1-D with size the last dimension of value.

tf.raw_ops.BiasAdd(value, bias, data_format='NHWC', name=None)

  • BiasAddGrad

The backward operation for "BiasAdd" on the "bias" tensor.

tf.raw_ops.BiasAddGrad(out_backprop, data_format='NHWC', name=None)

  • Device_Cast

x.values를 dtype으로 변환

tf.cast(x, dtype, name=None)
x = tf.constant([1.8, 2.2], dtype=tf.float32)
tf.dtypes.cast(x, tf.int32)

# float32 -> int32로 변환해주었다.

  • Device_Conv2D
Conv2D(32, (5, 5), padding='valid', input_shape=(28, 28, 1), activation='relu')

순서대로, 필터수, (행,열) , padding:경계처리방법

'valid'는 유효한 영역만 출력 / 'same' 출력 이미지 사이즈가 입력 이미지 사이즈와 동일

input_shape : 샘플수를 제외한 입력형태를 정의, 첫 레이어일떄만 정의해주면됨 (행,열,채널수)

activation : 활성화 함수 설정

‘linear’ : 디폴트 값, 입력뉴런과 가중치로 계산된 결과값이 그대로 출력으로 나옴 / ‘relu’ : 은닉층에 주로 쓰임 / ‘sigmoid’ : 이진 분류 문제에서 출력층에 주로 쓰임 / ‘softmax’ : 다중 클래스 분류 문제에서 출력층에 주로 쓰임

  • Device_Conv2DBackpropFilter

필터 에 대한 컨볼루션의 gradients를 구함

tf.raw_ops.Conv2DBackpropFilter(
    input, filter_sizes, out_backprop, strides, padding, use_cudnn_on_gpu=True,
    explicit_paddings=[], data_format='NHWC', dilations=[1, 1, 1, 1],
    name=None
)

input : 텐서! [배치,인풋높이, 인풋너비, 인풋채널] 이런 모양이어야한다.

filter_sizes : int32모양의 정수벡터여야함, [높이,너비,인풋채널,출력채널]

out_backprop : 텐서 [배치.출력높이,출력너비,출력채널] 모양

strides : 필터가 이동할간격

padding : "SAME", "VALID", "EXPLICIT"

use_cudnn_on_gpu : optional. true가 디폴트

explicit_paddings : 앞에서 패딩이 EXPLICIT 일때, the list of explicit padding amounts

data_format : NHWC가 디폴트

# NHWC
output[b, i, j, k] = sum_{di, dj, q} input[b, strides[1] * i + di, strides[2] * j + dj, q] * filter[di, dj, q, k]
  • Device_Conv2DBackpropInput

input 에 대한 컨볼루션의 gradients를 구함

tf.raw_ops.Conv2DBackpropInput(
    input_sizes, filter, out_backprop, strides, padding, use_cudnn_on_gpu=True,
    explicit_paddings=[], data_format='NHWC', dilations=[1, 1, 1, 1],
    name=None)
  • Device_DivNoNan

리턴값 : The z tensor.

tf.raw_ops.DivNoNan(x, y, name=None)
  • Device_DynamicStitch

데이터로부터 텐서를 단일 텐서로 interleave해준다

**interleave : http://www.terms.co.kr/interleave.htmhttp://www.terms.co.kr/interleave.htm

성능을 높이기 위해서 데이터가 서로 인접하지 않도록 배열하는바업.

tf.raw_ops.DynamicStitch(indices, data, name=None)
  • Device_Equal

x,y 가 같은지 리턴해줌

tf.math.equal(x, y, name=None)
  • Device_FusedBatchNormGradV3

배치 정규화를 위한 기울기

4D Tensor의 크기는 "NHWC"또는 "NCHW"로 정의한다 (data_format)

tf.raw_ops.FusedBatchNormGradV3(
    y_backprop, x, scale, reserve_space_1, reserve_space_2, reserve_space_3,
    epsilon=0.0001, data_format='NHWC', is_training=True, name=None)
  • Device_FusedBatchNormV3

배치 정규화

tf.raw_ops.FusedBatchNormV3(x, scale, offset, mean, variance, epsilon=0.0001, exponential_avg_factor=1,data_format='NHWC', is_training=True, name=None)
  • Device_LogicalAnd

x and y 의 truth을 리턴함

  • Device_MatMul

dot이랑 비슷하다. 곱셈을 의미함


  • Device_MaxPool

  • Device_MaxPoolGrad

맥스풀링함수에서의 gradients를 계산함

tf.raw_ops.MaxPoolGrad(orig_input, orig_output, grad, ksize, strides, padding, explicit_paddings=[],data_format='NHWC', name=None)
  • Device_AvgPool

  • Device_AvgPoolGrad

average pooling functino 에서 gradients를 구한다


  • Device_Mul

곱셈 x * y 값을 리턴

  • Device_RealDiv

x/y 값을 리턴함


  • Device_Relu

Same shape as the input.

tf.keras.layers.ReLU(max_value=None, negative_slope=0, threshold=0, **kwargs)
  • Device_ReluGrad
tf.raw_ops.ReluGrad(gradients, features, name=None)
  • Device_ResourceApplyGradientDescent

알파와 델타를 뺴고 var을 업데이트한다.

  • Device_Softmax

활성화함수, 입력받은 값을 출력으로 0-1사이의 값을 모두 정규화하며,출력값들의 총합은 항상1

  • Device_SoftmaxCrossEntropyWithLogits

소프트맥스 교차 엔트로피의 cost와 gradients 를 계산하여 역전파한다.

tf.raw_ops.SoftmaxCrossEntropyWithLogits(features, labels, name=None)

  • Device_Sum

텐서 차원에서 모든 요소들의 합을 계산한다.

tf.raw_ops.Sum(input, axis, keep_dims=False, name=None)
  • Device_Tile

주어진 텐서를 타일링하여 새 텐서를 만들어낸다

e.g. tf.tile([a,b,c,d]) → [a,b,c,d,a,b,c,d] 이런 텐서를 얻을수가 있다.

  • Device_Unknown

unknown shpae ⇒ TensorShape(None), TensorShape([None, 256]) ....

  • Device__FusedConv2D

Conv2D의 data_format 속성은이 작업에서 지원되지 않으며 대신 'NHWC'순서가 사용됨. 내부적으로이 작업은 그래프 당 단일 스크래치 버퍼를 사용하므로 여러 버전이 병렬로 실행되는 경우 차단된다. 이것은이 연산자가 주로 메모리 사용을 최소화하기위한 최적화이기 때문이다.

  • Device__HostRecv
  • Host_FlushSummaryWriter
tf.summary.flush(writer=None, name=None)
  • Host_IteratorGetNext

주어진 Iterator에서다음 출력을 가져옴

tf.raw_ops.IteratorGetNext(iterator, output_types, output_shapes, name=None)
  • Host_LogicalAnd

Device_LogicalAnd 과 곂침

  • Host_WriteSummary

텐서의 summary를 적는다.

tf.raw_ops.WriteSummary(writer, step, tensor, tag, summary_metadata, name=None)
  • Device_Square

x안에 있는 요소들을 제곱으로 만들어준다

tf.math.square([-2., 0., 3.])[4., 0., 9.]
  • Device_Mean

평균을 구해준다. 예를들어서, 만약 value들이 [1, 3, 5, 7] 라고 하면 mean 은 4

  • Device_BroadcastTo

산술연산을 위해 호환되는 모양을 갖도록 배열을 만드는 프로세스.

x = tf.constant([1, 2, 3]) 
y = tf.broadcast_to(x, [3, 3]) 
print(y)
>> tf.Tensor( [[1 2 3] [1 2 3] [1 2 3]], shape=(3, 3), dtype=int32)

< 시도해본 차원축소 방법 리스트 >

  • pca
  • kernal pca
  • svd
  • isomap
  • mds
  • t-sne

 

차원축소를 해주는 이유

— 차원의 저주문제 (오버피팅)

— 데이터 압축

— 계산비용축소

 

차원축소 접근방법 2가지

(1) 투영 (projection) — PCA /SVD/

(2) 매니폴드학습 / 대부분 but 항상 통하지는 않는다.— Kernal PCA / Isomap / T-SNE /

e.g. 스위스롤 ( 다 펼치면 2d , 하지만 3차원으로 말려있다)

 

→ 전자는 매니폴드 학습방법이 더 효율적 , 후자는 비효율적

⇒ 모델을 학습전 학습 데이터셋 차원축소를 시도하면 항상 모델의 성능은 항상 더 낫거나 간단한 모델이 되는 것은 아니다

 

** 매니폴드란!

일반적으로 거리를 구하는 공식 (지금까지 배워온 방식) = 유클리디안 방식

매니폴드(manifold)란, 두 점 사이의 거리 혹은 유사도가 근거리에서는 유클리디안(Euclidean metric, 직선 거리) 을 따르지만 원거리에서는 그렇지 않은 공간을 말합니다.

그림처럼, 조그만 유클리디안 공간 조각들(육면체 하나를 근거리에서 정의된 유클리디안 공간이라고 생각하시면 됩니다)이 다닥다닥 붙어 이루어져서 전체적으로 보면 비유클리디안(non-Euclidean)이 되는 공간을 뜻합니다. 아래 그림은 각각 2차원과 3차원 매니폴드를 나타냅니다.

 

[PCA]

PCA : 차원을 줄이되 정보손실을 최소화한다

  • 원래 공간에서 데이터가 퍼져 있는 정도를 축소된 공간에서 얼마나 잘 유지하느냐를 척도로 삼음
  • 이를 잘 유지하냐는 변환된 공간에서의 데이터의 '분산'으로 측정
  • 변환된 공간에서 데이터의 분산을 최대로 할 수 있는 좌표축을 찾아야함 ( 즉 데이터가 분산되어 있는 주요한 방향(Principal direction)을 찾아준다

step1 데이터투영(projection)하기

원래 2차원이였다면 1차원으로 투영해버리기

 

step2: 투영된 공간에서 분산 측정하기

평균과 분산을 정규화 해준다. 정규화 해주면 각각의 attribute의 평균이 0이되고, 분산이 1이 되기 때문에 ( 즉 같은 scale을 같는다) attribute간의 비교가 가능해진다. 아래 그림을 살펴보면 분산이 최대가 되어야 데이터가 많이 보존됨을 알수있다. (제일 첫번째 그림에서 c1)

e.g. 첫번째 그림은 주성분이 1개일때(c1) / 두번째 그림은 주성분이 3개일때 (e1,e2,e3 순서대로 분산이큼)

 

step3: 분산의 최대치는 어떻게 찾는가

투영된 공간에서 분산을 최대화 해 줄 수 있는 벡터 u를 찾아야한다. u는 방향이 중요하다. (계산할때 라그랑지 승수를 사용한다)

 

**

공분산행렬

이란? (뒤에서 SVD 와 비교할때도 사용됨)

  • 다음 그림과같이 공분산 행렬은 각 속성에 대해서 두개의 속성(특징쌍)의 변동이 얼마나 닮았는가 ( = 얼마만큼이나 함께 변하는가를 행렬로 나타내준다. 이때 정방행렬이라는것에 주목해야한다( 뒤에 svd와 비교 )
  • 공분산행렬에서 고유값과 고유벡터를 구할수 있다.
  • 이렇게 구한 고유값 목록에서 주성분을 뽑아낼수 있다.

 

#주성분을 2개로 지정해주었을때, 
#위의 결과의 의미는 원 데이터셋 분산의 99.5%가 첫 번째 주성분 축에 놓여 있고, 
# 0.3%가 두 번째 주성분 축에 놓여 있다는 것을 말합니다. 

> pca.explained_variance_ratio_
array([0.99541373, 0.00338148])
> sum(pca.explained_variance_ratio_)
0.9987952108914363
# 두속성이 전체 변화량의 99%를 차지

한마디로 PCA는 데이터의 분산을 최대한 보존하면서 서로 직교하는 새 축(새 기저)를 찾아, 고차원 공간의 표본들을 저차원 공간으로 변환하는 기법이다 / 데이터 하나 하나에 대한 성분을 분석하는 것이 아니라, 여러 데이터들이 모여 하나의 분포를 이룰 때 이 분포의 주 성분(=데이터들의 분산이 가장 큰 방향벡터)을 분석해 주는 방법이다.

 

[Kernal PCA]

pca 는 차원축소를 위한 선형 변환 기법을 이용하기 떄문에 선형으로 분리 불가능한 데이터에 대해서는 적당하지 않다. 이를 극복하기 위해 커널 pca 를 사용할수 있다.

  • 아래 그램에서 첫번째 선형적인 데이터에서는 pca가 잘 작동하지만 2,3 번째 데이터처럼 비선형적인 데이터의 경우 적용하기 곤란하다.

 

코드 (아래) -(1)(2) 예제

http://203.246.113.170:8800/notebooks/Yoonseo/kernal pca 예제 비선형데이터셋.ipynb

 

(1) e.g. 반달 데이터셋 사용! (make_moon)

  • 아래 그림에서 (좌) pca 적용 (우) kernal PCA 적용

 

(2) 나선형 데이터 사용 (make_circles)

  • 두번째 그림이 pca 적용 / 세번째 그림이 kernal pca 사용

 

 

(3) 그외 여러가지 비선형 데이터에서 PCA vs KPCA 비교분석된 좋은 자료

https://rpubs.com/sandipan/197468

[SVD]

특이값 분해라고도 한다

특이값 분해는 고유값 분해 처럼 행렬을 대각화하는 한 방법이다. 그런데, 특이값 분해가 유용한 이유는 행렬이 정방행렬이든 아니든 관계없이 모든 m x n 행렬에 대해 적용 가능하기 때문.

앞서서 PCA 는 고유값 분해는 기본적으로 정방행렬을 반드시 필요로하며, 새로운 축을 만들어 고유벡터의 새로운 관점으로 바라보는것이였다면, SVD 는 정방행렬이 아니라 직사각형 행렬일떄 사용한다.

직사각행렬에 연산을 취했을때 벡터의 방향만 변하고 양(길이)는 변하지 않는다.

https://commons.wikimedia.org/wiki/File%3ASingular_value_decomposition.gif (움직이는 모양 확인)

 

[MDS]

MDS 는 1964 년에 제안된, 매우 오래된 임베딩 방법. MDS 기법은 numeric 변수로만 이루어 졌을 때에만 사용이 가능하다.

낮은 차원에서의 자료들이 거리가 멀리 떨어져 위치한다는 것은 비유사성이 높다는 뜻이고, 자료가 가까울수록 비유사성이 낮다 (즉 유사성이 높다)는 뜻이 된다. MDS를 이용하여 데이터를 시각화 하는 방법의 가장 큰 장점은 바로 데이터들의 유사도를 확인할 수 있다는 점이다. (비슷한 변수값을 가지는 데이터들은 가까이 있다)

한마디로 개체들을 2차원 또는 3차원 공간상에 점으로 표현하여 개체들 사이의 집단화를 시각적으로 표현하는 분석 방법. 군집분석은 개체들간의 비유사성을 이용하여 동일한 그룹들로 분류하는것이 목적인것에 반해 mds는2,3차원위에 점으로 표현하고 시각화하는것이 주 목적. pca 와 비교하면, 원데이를 최대한 보존한다.

 

분석 과정

(1) 자료수집

n개의 개체들을 대상으로 p개의 특성을 측정한다

(2) 유사성 / 비유사성 측정

mds 에서는 유사성이아니라 비유사성 측정방법을 사용함 ( 이유 - 유사성 대신에 비유사성(또는 거리)를 이용하는 이유는 유사성의 경우 대각선원소의 값을 정의하기 어렵기 때문이라고 한다)

(3) 2차원, 3차원 공간상에 개체를 표현

개체들 사이의 *유클리디안 거리(직선거리 계산방법) 를 비유사성 행렬을 이용해서 개체들을 2차원 공간상 점으로 표현한다.

**비유사성 행렬 = m개 객체로 구성된 데이터 세트의 경우, 데이터 세트에 m*(m – 1)/2개 쌍이 있다.

(4) 최적 표현의 결정

s-stress 를 사용해서 최적위치의 적합성을 측정한다.

오른쪽은 stress 구하는 방식 (dij 는 점i 부터 점 j 까지의 실제 유클리디안거리, ^dij는 프로그램에 의해서 추정된 거리)

 

[ISOMAP]

이는 kernal pca 처럼 비선형 데이터를 다룰때 유리하다

이는 MDS + PCA 각각의 특징을 합친 방법이다.

e.g. 스위스롤

앞선 방식 MDS를 사용하면 아래 그림에서 두점사이의 거리는 매우 짧다. 하지만 isomap에서는 다른 방식을 사용한다. 거리를 측정할때 인접지점을 고려한다. 한마디로 쭉 이어져야한다.

e.g. 지구에서 나라별 거리 계산방식과 같다. 각 나라별로 거리를 측정할때 mds 방식으로 유클리디안 방식으로 측정하면 내핵을 뚫고 들어가야한다. 하지만 실제로 계산할땐, 지구의 표면을 따라 거리를 계산한다 (=isomap)

I

[T-SNE]

 

 

 

 아래는 발표 피피티 ( 여기없는건 발표자료에 있음)

https://docs.google.com/presentation/d/1ajWFe_v5EUz-y70otmEQLzr-vn47PXSh3npDBiYV6Hs/edit?usp=sharing 

 

차원축소_발표

차원 축소 개념과 이해 발표자 허윤서

docs.google.com

 

+ Recent posts