카테고리 없음

FullyConnected, Convolution1D, 2D practice

oogieon_n_on 2023. 5. 26. 12:27

 

 

1D Fully Connected Layer

output_activation[j] = sum(input_activation[i] * weights[i][j])

 

import numpy as np

def FC1D(num_inputs, num_outputs, input_acts, weights):
    '''
    Args:
    num_inputs : int -> num input nodes
    num_outputs : int -> num output nodes
    input_acts: List[int] -> list of input activations 
    weights: 2dList[float] -> 2dim array of weights  

    input_act[i] * weights[i][j] = output_act[j]
    
    ex) input_neurons=2, output_neurons=3

        input_acts.shape = (1,2)
        weights.shape = (2,3)
        output_acts.shape = (1,3)

        output_act[0] 
        = input_act[0] * weights[0][0] + input_act[1] * weights[1][0]
        output_act[1] 
        = input_act[0] * weights[0][1] + input_act[1] * weights[1][1]
    
    '''
    
    output_acts = []
    for j in range(num_outputs):
        out = 0
        for i in range(num_inputs):
            out += input_act[i] * weights[i][j]
            '''
            j = 0, i = 0 -> out += inp[0] * w[0][0]
            j = 0, i = 1 -> out += inp[1] * w[1][0]
            ...
            j = 2, i = 1 -> out += inp[1] * w[1][2]
            '''
        output_acts.append(out)
    
    return output_acts
num_inputs = 3
num_outputs = 4
input_act = np.random.randint(0,10,num_inputs)
weights = np.random.randn(num_inputs,num_outputs)

input_act, weights

# out
'''
(array([1, 1, 7]),
array([[ 0.3012766 ,  1.48312907,  0.94917185,  0.84476744],
        [ 0.0348986 , -1.95834217,  0.20735562, -0.79946693],
        [ 1.27588699,  0.38829428, -1.03022798, -1.15678384]]))
'''

FC1D(num_inputs, num_outputs, input_acts, weights)

#out
'''
[9.267384104784183, 2.242846889855965, -6.055068361681301, -8.052186350764629]
'''

1D Convolution Layer

def Conv1D(num_inputs, input_acts, filter_size, stride, weights):
    
    output_len = (num_inputs - filter_size)//stride + 1
    
    output_acts = []
    for j in range(output_len):
        out = 0
        for k in range(filter_size):
            out += input_acts[j*stride + k] * weights[k]
        output_acts.append(out)
    return output_acts




#<or>


def Conv1D(num_inputs, input_acts, filter_size, stride, weights):
    '''
    Args:
    num_inputs : int 
    input_acts : 1d array 
    filter_size : int
    stride : int
    weights: 1d array 
    '''


    output_acts = []
    for i in range(0, num_inputs - filter_size + 1, stride):
        
        sliced_input = input_acts[i:i+filter_size]
        
        output = 0
        for j in range(len(sliced_input)):
            output += sliced_input[j] * weights[j]
        
        '''
        <or>
        output = np.sum(sliced_input * weights)
        '''
        
        output_acts.append(output)
    
    return output_acts
num_inputs = 5
input_acts = np.random.randint(0,10,num_inputs)
filter_size = 3
stride = 1
weights = np.random.rand(filter_size)

num_inputs, weights

#out
'''
(5, array([0.55246091, 0.5921884 , 0.33748386]))
'''

Conv1D(num_inputs, input_acts, filter_size, stride, weights)
#out
'''
[10.239410161317394, 10.72210701920207, 8.221155691785725]
'''

 

# 2 dim Convolution 
def Conv2D(input_acts, weights, stride):
    '''
    Args:
    input_acts: 2d array (input_h, input_w)
    stride : int 
    weights : 2d array(filter_h, filter_w)
    '''
    
    input_h, input_w = input_acts.shape
    filter_h, filter_w = weights.shape
    output_h, output_w = (input_h - filter_h)//stride + 1, (input_w - filter_w)//stride + 1
    
    output_act = np.zeros((output_h, output_w))
    for i in range(0, input_h - filter_h + 1, stride):
        for j in range(0, input_w - filter_w + 1, stride):
            
            sliced_input = input_acts[i:i+filter_h, j:j+filter_w]

            output = 0
            for k in range(len(sliced_input[0])):
                for l in range(len(sliced_input[1])):
                    output += sliced_input[k,l] * weights[k,l]

            output_act[i//stride, j//stride] = output

            '''
            <or>
            output_act[i//stride, j//stride] = np.sum(sliced_input * weights)


            # ! wrong !
            # output_act[i//stride, j//stride] = np.sum(np.dot(weights.T, sliced_input))
            # !       !   
            '''    
    return output_act
# contains input channel 
def Conv2D_w_C(input_acts, weights, stride):
    '''
    Args:
    input_acts: 3d array (input_channels, input_h, input_w)
    stride : int 
    weights : 4d array (num_filters, input_channels, filter_h, filter_w)
    num_filters: int (개별 입력 채널에 대한 필터의 개수) == output_channels
    '''

    input_c, input_h, input_w = input_acts.shape
    num_filters, input_c, filter_h, filter_w = weights.shape

    output_h = (input_h - filter_h)//stride + 1
    output_w = (input_w - filter_w)//stride + 1

    output_act = np.zeros((num_filters, output_h, output_w))
    for nf in range(num_filters):
        for h in range(0, input_h - filter_h + 1 , stride):
            for w in range(0, input_w - filter_w + 1, stride):

                sliced_input = input_acts[:, h:h+filter_h, w:w+filter_w]
                output = np.sum(sliced_input * weights[nf])

                output_act[nf, h//stride, w//stride] = output
    
    return output_act

 

2D convolution with padding 

def convolution2D(inputActivations,
                  weights,
                  stride,
                  padding=False):
    '''
    Args:
    inputActivations : 2D numpy array
    weights : 2D numpy array
    stride : int
    padding : int or bool 
    '''
    

    #padding
    if padding:
        inputActivations = inputActivations.tolist()
        num_pad = padding
        c_pad = [0]
        for i in range(len(inputActivations)):
            inputActivations[i] = c_pad*num_pad + inputActivations[i] + c_pad*num_pad

        r_pad = [c_pad * len(inputActivations[0])]
        inputActivations = np.array(r_pad * num_pad + inputActivations + r_pad * num_pad)
        print(inputActivations)
    
    input_h, input_w = inputActivations.shape
    weight_h, weight_w = weights.shape
    
    output_h = (input_h - weight_h)//stride + 1 
    output_w = (input_w - weight_w)//stride + 1
    outputActivations = np.zeros((output_h, output_w))

    # convolution 
    for i in range(output_h):
        for j in range(output_w):

            sliced_input = inputActivations[(i*stride):(i*stride)+weight_h,
                                            (j*stride):(j*stride)+weight_w]
            # out = 0
            # for k in range(sliced_input.shape[0]):
            #     for l in range(sliced_input.shape[1]):
            #         out += sliced_input[k,l] * weights[k,l]


            out = np.sum(sliced_input * weights)
            
            outputActivations[i,j] = out
    
    return outputActivations
inputActivations = np.random.randint(1,10,(5,5))
weights = np.random.randn(3,3)
stride = 2

convolution2D(inputActivations,
              weights,
              stride,
              padding=1)


#out 

'''
inputActivations: 
[[4 3 6 5 2]
 [6 9 4 6 9]
 [5 2 8 9 2]
 [3 2 2 8 6]
 [1 5 2 2 7]]
 
padded_input :
[[0 0 0 0 0 0 0]
 [0 4 3 6 5 2 0]
 [0 6 9 4 6 9 0]
 [0 5 2 8 9 2 0]
 [0 3 2 2 8 6 0]
 [0 1 5 2 2 7 0]
 [0 0 0 0 0 0 0]]
 
outputActivations:
array([[  1.08833448, -11.60591936,   7.24595419],
       [  2.15685504,  -9.90894467,  -1.22822303],
       [ -4.25173809,   2.4089247 ,   0.7006725 ]])
'''