11강
#11-1
(i)
- 두 번쨰 사진이 출력되기 위해선 기존의 사진을 transpose해주면 된다.
- 다음과 같이 코드를 변형해주면된다. (img.T)
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.image import imread
img = imread('dataset/lena_gray.png').T
plt.imshow(img,cmap = plt.cm.gray)
plt.axis('off')
plt.show()
(ii)
- 3번째 사진은 1번째 사진을 좌우반전해준것과 같다.
- 즉 좌우반전을 한다는건 Columns을 Reverse해준것과 같다고 생각하면 된다.(역행으로 연산)
- 즉 img[:,::-1]을 해주면 된다.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.image import imread
img = imread('dataset/lena_gray.png')
plt.imshow(img[:,::-1],cmap = plt.cm.gray)
plt.axis('off')
plt.show()
#11-2
( i )
- transpose(0,1,2,3) --> transpose(a,b,c,d) 에서 a,b,c,d를 추론하는 문제이다.
- 해당 문제를 가장 빨리 풀기 위한 방법은 다음과 같다.
i) transpose하기 전 a를 기준으로 axis= 0,1,2,3 에 만나는 즉, 같은 축에 있는 원소들을 표기한다.
ex) i(axis= 0),e(axis= 1),c(axis= 2),b(axis= 3)
ii) transpose하고 난 후 a를 기준으로 axis = 0,1,2,3에 만나는 즉, 같은 축에 있는 원소들을 표기한다.
ex) e(axis=0),i(axis=1), c(axis=2), b(axis=3)
i),ii)에서 구한 원소들을 비교하여 바뀐 위치가 곧 transpose한 위치와 동일하다.
i,e,c,b --> e,i,c,b
transpose(1,0,2,3)을 적용했음을 알 수 있음.
조금 더 직관적으로 판단하기 위해서 i,e,c,b를 각각 0,1,2,3 이라고 치환하고 생각해보자.
0,1,2,3 --> 1,0,2,3 이 된다.
즉 1,0,2,3 그대로 적어주면 구하고자 하는 transpose를 구할 수 있는 것이다.
(ii)
이를 코드를 구현해서 한번 알아보자.
#11-3
(i)
#11-2과 마찬가지의 원리를 이용하여 계산해보자.
i) transpose하기 전 : i,e,c,b
ii) transpose한 후 : i,e,b,c
(0,1,2,3) --> (0,1,3,2) ==> transpose(0,1,3,2)를 사용함을 알 수 있음
(ii)
- 코드로 검산해보자.
#11-4
- 해당 문제는 axis=0,1,2,3일 때, 각각의 축에 어떤 원소들이 들어가 있는지를 알아야 풀 수 있는 문제이다.
- 교수님 풀이로 대체하고자 한다.
#11-5
- 해당 문제를 효율적으로 풀어내기위해서, 일일히 Tensor를 4개나 그려서 transpose한 결과를 나타내지 말고,
- 최종적으로 변하는 transpose를 구해서 한번만 적용해야한다.
- 각 축을 (a,b,c,d)라고 두자. 이걸 3가지의 transpose를 적용하면 다음과 같다.
(a,b,c,d) ---> (a,c,d,b) ---> (c,a,b,d) ---> (b,a,c,d)
- 즉, (a,b,c,d) ---> (b,a,c,d)해주는 transpose와 같다.
- 따라서, transpose(1,0,2,3)과 동일하다. (#11-2와 동일하기 때문에 이후의 풀이는 생략한다.)
#11-6
(iii)와 (iv)는 중복이니까 생략한다.
(i)
- RGB Image의 Shape는 (Height, Width, Channel)라는 점을 인지하고 있어야 한다.
(ii)
- RGB채널을 분리하기 위해선 하나만 생각하자, R을 선택하면 나머지 G,B를 0으로 바꿔준다.
ex)
red = china.copy()
red[:,:,1] = 0
red[:,:,2] = 0
plt.imshow(red)
plt.show()
green = china.copy()
green[:,:,0] = 0
green[:,:,2] = 0
plt.imshow(green)
plt.show()
blue = china.copy()
blue[:,:,0] = 0
blue[:,:,1] = 0
plt.imshow(blue)
plt.show()
12강
#12-1
- 해당 문제를 풀기위해 plt.show()가 나타내는 코드블럭 3개를 따로따로 봐보도록하자.
i) First Code Block
img=np.zeros((100,100))
img[:50,:50]=1.
plt.imshow(img, cmap=plt.cm.gray)
plt.show()
- 이 이미지를 출력하면 제이사분면이 흰색으로 칠해진 이미지가 나오게 된다.
cf) 0 : Black, 1 : White 이다. (1이 흰색인 이유는 빛의 삼원색에 의해, 모든 빛을 받았을 땐 흰색으로 나타나기 때문이라고 생각하자.)\
ii) Second Code Block
w1=np.array([[[[1,2,1],[0,0,0],[-1,-2,-1]]]])
b=0
conv_layer1 = Convolution(w1, b)
img = img.reshape(1, 1, *img.shape)
out = conv_layer1.forward(img)
out = out.reshape(out.shape[2], out.shape[3])
plt.imshow(out, cmap=plt.cm.gray)
plt.show()
- 해당 ConV Layer에서 사용된 필터가 어떤 필터인지 파악하는 것이 중요하다.
- 사용된 필터는 수평 Sobel Filter인데,
- 이 Filter를 통해 나오게 되는 Feature Map은 기존에 있었던 Image의 수평선 라인을 1로 따주고, 나머지를 0으로 따준다.
- 그래서 결과는 다음과 같아진다.
iii) Third Code Block
w2=np.array([[[[1,0,-1],[2,0,-2],[1,0,-1]]]])
conv layer2 = Convolution(w2, b)
out = conv layer2.forward(img)
out = out.reshape(out.shape[2], out.shape[3])
plt.imshow(out, cmap=plt.cm.gray)
plt.show()
- 해당 ConV Layer에서 사용된 필터는 수직 Sobel 필터이다.
- 이는 수직선을 Detection해준다.
#12-2
- 문제를 간단하게 요약하면 다음과 같다.
- 'Image --- ConV---> Feature Map'
- Image와 Feature Map의 Shape가 동일할 때, padding값을 구하시오. (stride = 1)
- ConV_Layer를 통해 나오는 Feature Map의 Shape를 알기 위해선, 공식을 외워도 괜찮고, 그림을 그려서 판단해도 좋다.
- 개인적으로, 그림을 그려서 판단하는게 좀 더 실수 안하고 좋겠지만, 빠른 연산을 위해서 공식을 한번 외워보자.
- 공식은 다음과 같다.
''' Feature Map Shape = abs((Input_data.shape- Filter.shape + 2*Padding) / Stride + 1) '''
cf) 공식 외우는 팁은, (P + I + P - F) / S + 1 로 외우는게 좋다.
- 해당문제는 다음과 같이 풀린다.
25 = (P + 25 + P - 5) / 1 + 1 = 2P +21
P = 2
- 따라서 Padding 값은 2가 된다.
#12-3
(i)
china = load_sample_image('china.jpg')
china = china.mean(axis=2)
plt.imshow(china,cmap=plt.cm.gray)
plt.show()
(ii)
Sobel_filter =np.array([[[[1,2,1],[0,0,0],[-1,-2,-1]]]])
b = 0
conv_layer = Convolution(Sobel_filter,b)
img = china.reshape(1,1,*china.shape)
out = conv_layer.forward(img)
out = out.reshape(out.shape[2],out.shape[3])
plt.imshow(out,cmap=plt.cm.gray)
plt.show()
(iii)
Sobel_filter = np.array([[[[1,0,-1],[2,0,-2],[1,0,-1]]]])
b = 0
conv_layer = Convolution(Sobel_filter,b)
img = china.reshape(1,1,*china.shape)
out = conv_layer.forward(img)
out = out.reshape(out.shape[2],out.shape[3])
plt.imshow(out,cmap=plt.cm.gray)
plt.show()
#12-4
(i)
출력될 4개의 값을 확인하기 위해 print(),plt.show()를 기준으로 Code Block을 4개로 나눠서 4가지 Case를 함께 알아보자.
i) First Code Block
w=np.array([[[[0,1,0],[1,-4,1],[0,1,0]]]])
b=0
conv layer = Convolution(w, b)
img=np.zeros((10,10))
img[:5,:]=1.
img = img.reshape(1, 1, *img.shape)
out = conv layer.forward(img)
out = out.reshape(out.shape[2], out.shape[3])
print(out)
- 우선 img는 위쪽 절반은 흰색, 아랫쪽 절반은 검정색인 img가 나올것이다.
- 이걸 대충 Conv_Layer를 통해 계산한다면 다음과 같을 것이다. (실제로 계산해보거나, 머리속으로 연산해도 간단히 가능하다.)
ii) Second Code Block
plt.imshow(out, cmap=plt.cm.gray)
plt.show()
- 위의 Matrix을 출력하면 중간의 선을 제외한 나머지 부분은 회색이고,
중간의 선은 위쪽은 검정, 아래쪽은 흰색인 Feature map이 나올것이다.
iii) Third Code Block,...
... 부터는 transpose한거랑 같기 때문에 생략한다.
(ii) Blur Filter의 Feature Map
- 자세한 서술은 하지 안겠지만, 여기서의 Blur Filter는 Averge Pooling과 같은 역할을 한다는 것만 기억하자.
(iii) 생략
13강
#13-1
(i)
- 답을 구하기 보단, 풀이 과정만 보여주고자 한다.
- 사실상, Tensor처리 하는방법만 알면 그 뒤는 12강과 동일하기 때문이다.
A B
C D
- 다음과 같이 합성곱한 결과가 Blocked Matrix 형태로 나오게 될텐데(정확힌 4차원 Tensor),
A : 첫번째 데이터와 첫번째 필터의 합성곱 결과
B : 첫번째 데이터와 두번째 필터의 합성곱 결과
C : 두번째 데이터와 첫번째 필터의 합성곱 결과
D : 두번째 데이터와 두번째 필터의 합성곱 결과
--> 라고 생각하면 된다.
- 즉, 데이터가 하나씩 순차적으로 모든 필터를 걸치고 나서 그 다음 데이터가 ConvL에 지나간다는 것만 알아두자.
- 즉, 하나의 데이터가 모든 필터를 지나야만, 그 다음 데이터를 사용할 수 있다는 것이다.
(ii) 코드구현
X = np.array([[[[1,0,1],[0,1,0],[1,0,1]],[[1,1,1],[1,0,1],[1,1,1]]],[[[1,1,1],[1,0,0],[1,0,0]],[[0,0,1],[0,0,1],[1,1,1]]]])
W = np.array([[[[1,0],[1,0]],[[1,1],[0,0]]],[[[0,1],[0,1]],[[0,0],[1,1]]]])
b=0
conv_layer = Convolution(W, b)
out = conv_layer.forward(X)
print(out)
------------------------------------------------------------------------------------------------------------
[[[[3. 3.]
[2. 2.]]
[[2. 2.]
[3. 3.]]]
[[[2. 2.]
[2. 1.]]
[[1. 2.]
[2. 2.]]]]
#13-2
#13-1과 동일하기 때문에 생략한다.
#13-3
(i)
(FN,C,FH,FW) ---> (FH,FW,C,FN) 로 변환하는 과정이 있어야 한다.
따라서, transpose(2,3,1,0) 을 적용하면 된다.
(ii)
역과정이므로
(2,3,1,0) -->(0,1,2,3) 으로 변환해준다고 생각하면 된다.
따라서, transpose(3,2,0,1) 을 적용하면 된다.
#13-4
(i)
image = np.zeros((30,30,3))
# R
image[:15,:,0] = 1
#G
image[:,:10,1] = 1
#B
image[:,20:,2] = 1
plt.imshow(image,cmap=plt.cm.gray)
plt.show()
(ii)
image = np.zeros((30,30,3))
# R
image[:15,:,0] = 1
#G
image[:,:10,1] = 1
#B
image[:,20:,2] = 1
W = np.array([[[[1,0,-1],[2,0,-2],[1,0,-1]], [[1,0,-1],[2,0,-2],[1,0,-1]], [[1,2,1],[0,0,0],[-1,-2,-1]]]])
conv_layer = Convolution(W,0)
image = image.reshape(1,30,30,3)
image = image.transpose(0,3,1,2)
out = conv_layer.forward(image)
out = out[0].transpose(1,2,0)
plt.imshow(out,cmap=plt.cm.gray)
plt.show()
- 결과를 보기전에 생각해보자,
#Red
- Red 채널을 통과하는 필터는 수직 Sobel 필터이다, 근데 Image의 Red 필터에 속하는 행렬은 수평이다.
- 따라서 전부 0인 Matrix가 나온다.
#Greed
- Greed 채널을 통과하는 필터는 수직 Sobel 필터이다, 근데 Image의 Green 필터에 속하는 행렬은 수직이다.
- 따라서, 수직인 부분 즉 image[:,9:10,1] 부분만 1이고 나머지는 0인 Matrix가 나온다.
#Blue
- Blue 채널을 통과하는 필터는 수평 필터이다, 근데 Image의 Blue 필터에 속하는 행렬은 수직이다.
- 따라서 전부 0인 Matrix가 나온다.
- 필터를 거쳐서 나오게되는 Feature Map은 Gray Scale(흑백사진)으로 나올것이고,
다음과 같을것(Green Filter의 Feature Map)이다.
#13-5
(i)
image = np.zeros((30,30,3))
# R
image[:20,:20,0] = 1
#G
image[:20,10:,1] = 1
#B
image[10:,:20,2] = 1
plt.imshow(image,cmap=plt.cm.gray)
plt.show()
(ii)
- 해상도가 줄지않도록, 합성곱을 하기위해선 여러 방법이 존재하지만, 1 x 1 ConVL을 사용해도 괜찮다.
- 이를 사용하면 해상도가 줄지않도록 합성곱을 실행시켜준다.
- 이러한 필터를 3개를 사용하여 R,G,B를 분리시켜야 하는데 이는 다음과 같이 해주면 된다.
R만 추출하는 필터 : [[[1]],[[0]],[[0]]]
G만 추출하는 필터 : [[[0]],[[1]],[[0]]]
B만 추출하는 필터 : [[[0]],[[0]],[[1]]]
- 코드로 구현해보지.
image = np.zeros((30,30,3))
# R
image[:20,:20,0] = 1
#G
image[:20,10:,1] = 1
#B
image[10:,:20,2] = 1
W = np.array([[[[1]],[[0]],[[0]]],[[[0]],[[1]],[[0]]],[[[0]],[[0]],[[1]]]])
conv_layer = Convolution(W,0)
image = image.reshape(1,30,30,3)
image = image.transpose(0,3,1,2)
out = conv_layer.forward(image)
out = out.transpose(0,2,3,1)
plt.imshow(out[0,:,:,0],cmap=plt.cm.gray)
plt.show()
plt.imshow(out[0,:,:,1],cmap=plt.cm.gray)
plt.show()
plt.imshow(out[0,:,:,2],cmap=plt.cm.gray)
plt.show()
#13-6
(i)
from sklearn.datasets import load_sample_image
china = load_sample_image('china.jpg')
flower = load_sample_image('flower.jpg')
data_set = np.array([china,flower])
data_set = data_set.transpose(0,3,1,2)
(ii)
w1=np.array([[1,2,1],[0,0,0],[-1,-2,-1]])
w_h = np.array([w1,w1,w1])
w2=np.array([[1,0,-1],[2,0,-2],[1,0,-1]])
w_v = np.array([w2,w2,w2])
W = np.array([w_h,w_v])
(iii)
b=0
conv_layer = Convolution(W, b)
out = conv_layer.forward(data_set)
print(out.shape)
------------------------------------------------------------
Output
(2, 2, 425, 638)
(iv)
plt.figure(figsize=(15,10))
for i in (0,1):
for j in (0,1):
plt.subplot(2,2,2*i+j+1)
plt.imshow(out[i,j,:,:], cmap='gray')
plt.xticks([])
plt.yticks([])
plt.show()
#13-7
- 생략
14강
#14-1
from common.layers import Pooling
X = np.array([[[[0,1,2],[3,7,4],[5,6,8]],[[8,0,1],[2,7,3],[4,5,6]]],[[[5,1,4],[2,0,3],[8,6,7]],[[5,6,7],[3,8,4],[0,1,2]]]])
pool_layer = Pooling(2,2,1)
out = pool_layer.forward(X)
print(out)
----------------------------------------------------------------
[[[[7. 7.]
[7. 8.]]
[[8. 7.]
[7. 7.]]]
[[[5. 4.]
[8. 7.]]
[[8. 8.]
[8. 8.]]]]
#14-2
- #14-1과 일치(생략)
#14-3
- ConV Layer는 한번 거칠때마다 점점 나오게 되는 feature map이 Input Data에 비해 사이즈가 작아지게 된다.
- 이는 즉, Input Data를 Down-sampling하는 효과를 가지고 있고,
- Down-Sampling은 상대적으로 크기가 큰 데이터를 상대적으로 크기가 작은 데이터로 압축시키는 역할을 하게 되는데,
- 결국, ConV Layer을 거치면 거칠수록 Local한 특징에서 Global한 특징을 찾아내게 된다.
#14-4
- 코드 구현은 하지 않겠지만, 중요한 핵심만 딱 정리하면 다음과 같다.
- ii)에선 3x3, stride = 3, 이고, iv)에선 5x5, stride = 5이다.
- 여기서 max Pooling을 하는데, 이 Max-pooling의 window size가 커지면 커질수록 해상도는 더더욱 감소하게 된다.
cf) 단, Overlapping Pooling은 고려하지 않는다.
15강
#15-1
(i)
i) col = im2col(x,FH,FW,self.stride, self.pad) 을 먼저 보자.
- im2col() 함수는 "기존의 input_data와 filter가 만나서 합성곱하는 위치"의 input_data를 flatten해서 위에서 부터 열로 들어가게 된다.
- 이를 나타내면 다음과 같다.
ii) col_W = self.W.reshape(FN,-1).T
- 각 필터를 flatten해서 행렬의 열에 채워 넣는것과 같다.
iii)
out = np.dot(col,col_W) + self.b
iv) out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)
- iii)의 out을 재배열해주면 된다. 이를 하나씩 차근히 봐보자.
- reshape(N,out_h,out_w,-1)을 보면 다음과 같이 간단하게 알 수 있다.
- transpose(0,3,1,2)를 한번 봐보자. 이를 바로 transpose(0,3,1,2)를 하지말고 이를 분리해서 생각해보자.
- transpose(0,1,3,2) --> transpose(0,2,1,3) 을 두번 해준것과 같은 결과 라는 것을 알 수 있다.
- transpose(0,1,3,2)는 작은행렬 4개에 대하여 전부 transpose 한것과 같고,
-transpose(0,2,1,3)은 다음과 같이 위치를 바꿔주면 된다.
- 이걸 종합적으로 보면 다음과 같은 결과가 나온다.
#15-2
- #15-1과 동일한 문제이기 때문에 생략한다.
#15-3
- naive한 코드 구현
out = np.zeros((N, FN, out_h, out_w))
for i in range(N):
for j in range(FN):
for k in range(out_h):
h_start = k * stride
h_end = h_start + FH
for l in range(out_w):
w_start = l * stride
w_end = w_start + FW
out[i,j,k,l] = np.sum(input[i,:, h_start:h_end, w_start:w_end] * filters[j])
- 해당 문제에서 가져갈 것은 4중 for문 작성하는 법과 im2col이 더 빠르다 라는 것만 알고 가자.
16강
#16-1
- 빨강색으로 체크한 건 첫번째 필터에 대한 가중치이고 거기에 대해 나오게 되는 Out Node는 곧 1번째 필터에 대한 Feature Map이 된다.
- 파란색으로 체크한 건 두번째 필터에 대한 가중치이고 거기에 대해 나오게 되는 Out Node는 곧 2번째 필터에 대한 Feature Map이 된다.
- 가중치 행렬, 편향벡터... 뒷부분은 중복이기에 생략한다.
#16-2
i) dout = dout.transpose(0,2,3,1).reshape(-1,FN)
- 이 dout은 8*2로 이루어진 모든원소가 1인 행렬이 나올 것이다.
ii) self.db = np.sum(dout.axis=0)
- [8,8] 이 나올 것이다.
iii) self.dW = np.dot(self.col.T,dout)
- self.col : im2col한 데이터를 의미한다. 그래서 다음과 같이 연산이 가능하다.
iv) self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH,FW)
v) dcol = np.dot(dout,self.col_W.T)
vi) dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad)
cf) im2col 역전파 문제는 나중에 기출풀면서 자세히 서술하겠다.
#16-3
- transpose(0,3,1,2)의 역전파는 다시 0,1,2,3으로 돌려두는 transpose와 같다.(재배열)
- 따라서 transpose(0,2,3,1) 이 된다.
17강
#17-1
i) col = im2col(x,self.pool_h,self.pool_w,self.stride,self.pad)
ii) col = col.reshape(-1,self.pool_h*self.pool_w)
iii) out = np.max(col,axis=1)
[8,9,7,7,7,8,7,5,8,4,8,8,8,7,8]
iv) out = out.reshape(N, out h, out w, C).transpose(0, 3, 1, 2)
#17-2
18강
#18-1
- 총 8개의 파란 화살표에 대해서 data의 shape를 구해보자
i) input_data shape
- shape : 100 x 3 x 50 x 50
ii) 1- ConV
- Feature map의 크기 = (P + I + P -F) / S + 1 = (50 - 7)/1 + 1 = 44
- shape : (100 x 40) x 44 x 44
iii) 1- ReLU
- shape : 100 x 40 x 44 x 44 (변함 없음)
iv) PoolingLayer
- Featue map의 크기 = (P + I + P - F) / S + 1 = (3 + 44 + 3 - 5)/5 + 1 = 10
- shape : 100 x 40 x 10 x 10
v) 1 - Affine
- 가중치 행렬 : 4000 * 50
- 100 * 50
vi) ReLU
- 100 * 50
vii) 2- Affine
- 100 * 10
viii) Softmax
- 1
#18-2
- #18-1과 동일 생략
#18-3
- 2번문제가 아닌 1번문제라고 생각하고 풀이를 나아가겠다. (합성곱층 필터의 분포만 풀이)
- He Initialization : ~N(0,(2 / N_in))
- 합성곱층 필터의 N_in은 Input_data를 im_2_col한 결과의 가로 크기가 된다.
- input_data를 im2col하면
가로 크기 : FW * FH * C
세로 크기 : N * ((P + I + P - FW)/S+1)**2
- 즉, 3x7x7이 된다.
따라서 ~N(0,2/147) 을 따른다.
#18-4
- 생략 (앞선 단원들을 복습하는 것과 같기 때문)
#18-5
- 생략
#18-6
- 생략