【pythonでCNN#4】Convolutional層(順伝播)

記事の目的

pythonでCNN(畳み込みニューラルネットワーク)を実装する上で必要になるConvolutional層の順伝播を実装していきます。ここにある全てのコードは、コピペで再現することが可能です。

 

目次

  1. 畳み込み演算
  2. im2col関数
  3. Convolutional層

 

1 畳み込み演算

 

2 im2col関数

# In[1]
import numpy as np

# In[2]
def im2col(x, fil_size, y_size, stride, pad):
    x_b, x_c, x_h, x_w = x.shape
    fil_h, fil_w = fil_size, fil_size
    y_h, y_w = y_size, y_size
    index = -1
    
    x_pad = np.pad(x, [(0, 0), (0, 0), (pad, pad), (pad, pad)], "constant")
    x_col = np.zeros((fil_h*fil_w, x_b, x_c, y_h, y_w))
    
    for h in range(fil_h):
        h2 = h + y_h*stride
        for w in range(fil_w):
            index += 1
            w2 = w + y_w*stride
            x_col[index,:,:,:,:] = x_pad[:,:,h:h2:stride,w:w2:stride]
    x_col = x_col.transpose(2,0,1,3,4).reshape(x_c*fil_h*fil_w, x_b*y_h*y_w)
    
    return x_col

# In[3]
x = np.arange(144).reshape(3,3,4,4)
x_col = im2col(x,3,2,1,0)
x_col.shape

# In[4]
w = np.arange(54).reshape(2,3,3,3)
w_col = w.reshape(2,-1)
w_col

# In[5]
b = np.ones((1,2))
b

# In[6]
y = np.dot(w_col, x_col)
y

# In[7]
y = y.T + b
y

# In[8]
y.reshape(3,2,2,2).transpose(0,3,1,2)

 

3 Convolutional層

# In[9]
class Conv:
    
    def __init__(self, x_c, y_c, fil_size, stride, pad):
        self.x_c, self.y_c = x_c, y_c
        self.fil_h, self.fil_w = fil_size, fil_size
        self.stride, self.pad = stride, pad
        
        self.w = np.arange(54).reshape(2,3,3,3)
        self.b = np.zeros((1,self.y_c))
        #self.w = np.random.randn(self.y_c, self.x_c, self.fil_h, self.fil_w)
        #self.b = np.random.randn(1, self.y_c)
        
    def forward(self, x):
        
        self.x_b, self.x_c, self.x_h, self.x_w = x.shape
        self.y_h = (self.x_h - self.fil_h + 2*self.pad) // self.stride + 1
        self.y_w = (self.x_w - self.fil_w + 2*self.pad) // self.stride + 1
        
        self.x_col = im2col(x, self.fil_h, self.y_h, self.stride, self.pad)
        self.w_col = self.w.reshape(self.y_c, self.x_c*self.fil_h*self.fil_w)
        
        y = np.dot(self.w_col, self.x_col).T + self.b
        self.y = y.reshape(self.x_b, self.y_h, self.y_w, self.y_c).transpose(0,3,1,2)
        
        return self.y

# In[10]
conv = Conv(3,2,3,1,0)
conv.forward(x)