728x90

2023-11-23 56th Class

Correlation

#️⃣ Correlation 이란

Filter -1 1 -1
Data -1 0 -1 0 0 1 -1 1 -1 -1
-1 0 -1 x -1 1 -1 2
0 -1 0 x -1 1 -1 -1
-1 0 0 x -1 1 -1 1
0 0 1 x -1 1 -1 -1
0 1 -1 x -1 1 -1 2
1 -1 1 x -1 1 -1 -3
-1 1 -1 x -1 1 -1 3
1 -1 -1 x -1 1 -1 -1

Correlation이란 Data를 filter로 window만큼 이동하면서 1)원소곱 2)합을 하는 연산

  • 원소별로 곱해서 더하는 연산
  • correlation은 dot product랑 다름

#️⃣ 1-Dimensional Correlation

[1] for loop ver.

def one_dim_correlation():  
    filter = np.array([-1, 1, -1])  
    data = np.array([-1, 0, -1, 0, 0, 1, -1, 1, -1, -1])  
  
    window_size = 3  
    n_window = len(data) - window_size +1  
    correlated = np.array([np.dot(data[i:i+window_size], filter) for i in range(n_window)])  
    print(f"{correlated=}")

'''
for loop ver
correlated=array([ 2, -1,  1, -1,  2, -3,  3, -1])
'''

[2] numpy broadcasting ver.1

def one_dim_corr_np1():  
    np.random.seed(0)  
    data = np.random.randint(-1, 2, (10,))  
    filter_ = np.array([-1, 1, -1])  
    print(f"{data=}")  
    print(f"{filter_=}")  
    L = len(data)  
    F = len(filter_)  
  
    L_ = L - F + 1  
    filter_idx = np.tile(np.arange(F), reps=[L_, 1])  
    window_idx = np.arange(L_).reshape(-1, 1)  
    idx_arr = filter_idx + window_idx  
    print("idx_arr")  
    print(idx_arr)  
    sliding_window = data[idx_arr]  
    hadamard = sliding_window * filter_  
    summation = np.sum(hadamard, axis=1)  
    print(f"{summation=}")
numpy broadcasting ver. 1
data=array([-1,  0, -1,  0,  0,  1, -1,  1, -1, -1])
filter_=array([-1,  1, -1])
idx_arr
[[0 1 2]
 [1 2 3]
 [2 3 4]
 [3 4 5]
 [4 5 6]
 [5 6 7]
 [6 7 8]
 [7 8 9]]
summation=array([ 2, -1,  1, -1,  2, -3,  3, -1])
filter_idx window_idx
Pasted image 20231123180757.png Pasted image 20231123180853.png
filter_idx = [[0 1 2], [0 1 2], [0 1 2], [0 1 2], [0 1 2], [0 1 2], [0 1 2], [0 1 2]]
window_idx = [[0], [1], [2], [3], [4], [5], [6], [7]]
  • filter_idx: n, n+1, n+2 인 row를 L_=8개 만큼 생성
  • window_idx: L_=8줄짜리 세로 vector 생성
  • filter_idx + window_idx를 하면 numpy broadcasting 연산이 되어 아래의 인덱스 어레이가 생성됨

Pasted image 20231123181008.png

idx_arr = [[0 1 2], [1 2 3], [2 3 4], [3 4 5], [4 5 6], [5 6 7], [6 7 8], [7 8 9]]
  • data에 이 index array로 인덱싱하게되면 (data[idx_arr])
  • window 길이만큼의 데이터를 column으로 가진 sliding window가 만들어짐
  • 참고 data = [-1 0 -1 0 0 1 -1 1 -1 -1]
sliding_window hadamard
Pasted image 20231123181337.png Pasted image 20231123181403.png
sliding_window = [[-1  0 -1], [ 0 -1  0], [-1  0  0], [ 0  0  1], [ 0  1 -1], [ 1 -1  1], [-1  1 -1], [ 1 -1 -1]]
hadamard = [[ 1  0  1], [ 0 -1  0], [ 1  0  0], [ 0  0 -1], [ 0  1  1], [-1 -1 -1], [ 1  1  1], [-1 -1  1]]
  • sliding window와 filter를 원소곱하면 -> hadamard
  • hadamard product 결과를 가로방향으로 summation하면 -> 최종 correlation 계산이 완료됨
  • 위 hadamard및 sum 과정은 matmul로 대체 가능함

최종 1d correlation 결과

summation = [ 2 -1  1 -1  2 -3  3 -1]

[2] numpy broadcasting ver.2

def one_dim_corr_np2():  
    # 교안 코드  
    np.random.seed(0)  
    data = np.random.randint(-1, 2, (10,))  
    filter_ = np.array([-1, 1, -1])  
    print(f"{data=}")  
    print(f"{filter_=}")  
    L = len(data)  
    F = len(filter_)  
    L_ = L - F + 1  
  
    filter_idx = np.arange(F).reshape(1, -1)  
    window_idx = np.arange(L_).reshape(-1, 1)  
    idx_arr = filter_idx + window_idx  
    print("idx_arr")  
    print(idx_arr)  
    window_mat = data[idx_arr]  
    multiplied = np.matmul(window_mat, filter_)  
    print(f"{multiplied=}")
data=array([-1,  0, -1,  0,  0,  1, -1,  1, -1, -1])
filter_=array([-1,  1, -1])
idx_arr
[[0 1 2]
 [1 2 3]
 [2 3 4]
 [3 4 5]
 [4 5 6]
 [5 6 7]
 [6 7 8]
 [7 8 9]]
multiplied=array([ 2, -1,  1, -1,  2, -3,  3, -1])
  • tile로 늘리지 않고, (1, 3) + (8, 1) 형태로 broadcasting 연산하면
  • (8, 3)으로 idx_arr을 만들 수 있음
filter_idx = [[0 1 2]] (1, 3)
window_idx = [[0], [1], [2], [3], [4], [5], [6], [7]] (8, 1)
idx_arr = [[0 1 2], [1 2 3], [2 3 4], [3 4 5], [4 5 6], [5 6 7], [6 7 8], [7 8 9]] (8, 3)

#️⃣ 2-Dimensional Correlation

def two_dim_correlation():  
    rows = np.arange(1, 6).reshape(-1, 1)  
    cols = np.arange(7)  
    data = (rows + cols) * 10  
  
    window_size = 3  
    height, width = data.shape  
    n_window_height = height - window_size + 1  
    n_window_width = width - window_size + 1  
  
    filter = np.array([  
        [1, 2, 5],  
        [-10, 2, -2],  
        [5, 1, -4]  
    ])  
  
    # data에서 window로 추출한 (3,3)과 filter (3,3)을 원소곱(hadamard product)  
    # 2차원부터는 np.dot()을 하면 행렬곱을 계산하기 때문에 사용할 수 없고  
    # * 연산으로 hadamard product한 후 np.sum()을 해야 함  
    hadamard_product = lambda row, col: data[row:row + window_size, col:col + window_size] * filter  
    extracted = np.array([[hadamard_product(row, col) for col in range(n_window_width)] for row in range(n_window_height)])  
    # extracted = (3, 5, 3, 3) -> (3, 3)인 원소곱한 결괏값이 3x5=15개  
    print("after hadamard")  
    print(extracted[0, 0])  
  
    correlated = np.sum(extracted, axis=(2, 3))  
    print(f"correlated = {correlated.shape} \n{correlated}")
after hadamard
[[  10   40  150]
 [-200   60  -80]
 [ 150   40 -200]]
correlated = (3, 5) 
[[-30 -30 -30 -30 -30]
 [-30 -30 -30 -30 -30]
 [-30 -30 -30 -30 -30]]
반응형