
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 ]])
'''