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 |
---|---|
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 연산이 되어 아래의 인덱스 어레이가 생성됨
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 |
---|---|
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]]
반응형
'Education > 새싹 TIL' 카테고리의 다른 글
새싹 AI데이터엔지니어 핀테커스 13주차 (월) - LeNet5 & VGGNet (1) | 2023.11.27 |
---|---|
새싹 AI데이터엔지니어 핀테커스 12주차 (금) - Sobel Filtering 3 & Convolutional Neural Network (0) | 2023.11.24 |
새싹 AI데이터엔지니어 핀테커스 12주차 (수) - Sobel Filtering (1) | 2023.11.22 |
새싹 AI데이터엔지니어 핀테커스 12주차 (화) - Multiclass Classification & MNIST (1) | 2023.11.21 |
새싹 AI데이터엔지니어 핀테커스 12주차 (월) - Pytorch Tutorial2 (Moon & Make Blobs XOR Dataset) (0) | 2023.11.20 |