Data_study/Deep Learning

[Deep_learning] Artificial Neurons 구현

onsemiro 2022. 1. 18. 16:56

저번 게시글에서 배운 Artificial Neurons이 실제로 어떻게 구현이 되는지 파이썬을 통해 구현해보자.

Artificial Neurons는 Affine Funtion 과 Activation Funtion으로 이루어져있다고 했다.

Affine Funtion 과 Activation Funtion을 먼저 구현해보고 Artificial Neurons를 진행해보겠다.

 

가장 중요하게 봐야할 것은 분석되는 과정에서 데이터의 차원, weight의 차원, bias의 차원을 확인해야한다.

왜냐하면, 나중에 거대한 데이터를 다룰 때, 모델이 잘 구동되고 있는지는 shape로 밖에 확인할 수 없기 때문이다.

 

Affine Function

Artificial Neurons를 구현할 때, Affine Function은 weight 값과 bias값을 할당시켜, 연산할 수 있는 식을 만드는 과정이다.

Affine function 을 구현하고 danse 메소드가 잘 실행되는 지 weight 값과 bias 값을 확인해보자.

 

import tensorflow as tf
from tensorflow.keras.layers import Dense

x = tf.random.uniform(shape =(1,10),minval=0,maxval=10)

우선 위 코드와 같이 Dense 패키지를 tensforlfow.keras.layers에서 불러오고, 입력 데이터 x를 tf.random.uniform을 활용해서 0과 10사이 값으로 구성된 (1행, 10열)형태의 데이터 셋을 만들어봤다.

 

dense = Dense(units=1)

y_tf = dense(x) #Dense에서 w,b가 몇개 필요한지 말하지 않아도 dense를 통과하면 자기 스스로 w와 b가 몇개 필요한지 확인해서 초기화 시킨다.

그후 Dense 메소드를 활용하여 실행시킨다.

 

여기서 Dense 메소드는 하나의 neuron연산을 실행 시켜주는 것으로, activation 파라미터를 따로 지정을 하지 않으면, activation function을 실행시키지 않은 neuron 연산이라고 생각하면 된다.

 

 

그럼 이제 weight 값과 bias값이 잘 할당되어 실행됐는지 확인해보자.

그리고 직접 할당된 weight 값과 bias값으로 우리가 직접 계산한 결과가 동일한 지도 확인해보자.

 

W,B = dense.get_weights() #초기화 시켜서 할당한 W와 B를 꺼내서

y_man = tf.linalg.matmul(x,W)+B #matmul를 활용해 직접 계산한다.

#print results
print("===== Input/Weight/Bias=====")
print("x:{}\n{}\n".format(x.shape,x.numpy()))
print("W:{}\n{}\n".format(W.shape,W))
print("B:{}\n{}\n".format(B.shape,B))

print("===== Outputs =====")
print("y(Tensorflow): {}\n{}\n".format(y_tf.shape,y_tf.numpy()))
print("y(Manual): {}\n{}\n".format(y_man.shape,y_man.numpy()))

결과를 보면..

Dense()와 직접 계산한 menual값의 비교

X값의 shape가 (1,10)의 형태로 구성된 것을 볼 수 있다.

Weight값은 X값의 shape에 맞게, (10,1)로 행렬의 곱을 할 수 있도록, 할당되었다.

Bias값은 아직 layer에 neurons가 한개이기 때문에, 실수 차원으로 할당되었다.

 

dense.get_weights()를 통해, weight 값과 bias값을 꺼내 matmul()로 직접 계산해봤다.

그 결과, y(tensorflow) 와 y(menual)값은 shape과 값 모두 동일함을 알 수 있다.

 

 

Activation Function

위 affine function으로 계산된 결과를 Activation Function을 통해, 비선형 시스템으로 변형시켜준다.

변형시켜주는 함수들은 대표적으로, Sigmoid, Tanh, Relu 가 있다.

 

Activation Function은 어떻게 구현하는지 알아보자.

 

 

우선 Activation 패키지를 가져오고, activation function을 직접 연산해보기 위해, exp와 maximum 패키지도 가져오자.

그리고, X 데이터 셋도 만들자.

import tensorflow as tf

from tensorflow.math import exp, maximum
from tensorflow.keras.layers import Activation #activation 식을 layer로 가져왔다.

activation = input("which do you want activation Function?")
#activation ="sigmoid"
#activation ="tanh"
#activation = 'relu'

x = tf.random.uniform(shape=(1,10)) #input setting

sigmoid와 tanh, relu들의 식을 통해 구현해보자.

 

dense = Dense(units=1,activation = activation) #imp.. an affine + activation

y_tf = dense(x)
W,b = dense.get_weights()
print("W:{}\n{}\n".format(W.shape,W))
print("b:{}\n{}\n".format(b.shape,b))

#calculate activation value manually
y_man = tf.linalg.matmul(x,W)+b
if activation =="sigmoid":
    y_man_activation = 1/(1+exp(-y_man))
elif activation == "tanh":
    y_man_activation = (exp(y_man)-exp(-y_man))/(exp(y_man)+exp(-y_man))
elif activation == "relu":
    y_man_activation = maximum(y_man,0)
    
print("\nActivation:",activation)
print("y_tf: {}\n{}\n".format(y_tf.shape,y_tf.numpy()))
print("y_man: {}\n{}\n".format(y_man_activation.shape,y_man_activation.numpy()))

 

activation function을 구현하기 위해서는 affine function을 거쳐야하기 때문에, dense에서 affine을 거쳐 activation 파라미터를 통해 activation function도 실행되고 있음을 볼 수 있다.

 

activation function을 그냥 Dense 메소드로 실행해도 되겠지만, activation이 어떻게 실행되는지 확인을 하는 습관은 중요하다.

다른 분석을 할 때도, 패키지만 믿는 것보다는 하나하나 어떻게 진행되는지 확인해보고 검증해보는 습관을 갖자!

 

아래는 각 function들을 실행시킨 결과다.

Activation Function : sigmoid
Activation Function : tanh
Activation Function : relu

 

Minibatches

 

대량의 데이터 셋을 affine function에 넣고 ativation function을 거쳐 대량의 결괏값이 나오는 것을 말한다.

코딩으로 구현해보자.

 

여기서 부터는 데이터셋의 크기가 커지므로, shape의 중요성이 더 커진다.

 

import tensorflow as tf
from tensorflow.keras.layers import Dense

N, n_feature = 32000,10 #set input params
x = tf.random.normal(shape=(N,n_feature)) #minibatch 생성 x는 matrix형태로 이론에서 공부했던, (x)T형태의 모형이다.

dense = Dense(units = 1, activation = "relu") #imp. an AN
y = dense(x) #forward propagation

W, b = dense.get_weights() #get weight/bias

#print resluts
print("Shape of x: ",x.shape)
print("Shape of W: ",W.shape)
print("Shape of b: ",b.shape)
print("Shape of y: ",y.shape)

 

Activation function은 relu를 택했다.

x, W, b, y들의 각 shape를 보면서, Dense 메소드가 어떻게 진행되는지 보자.

 

Dense는 어느 때와 같이 Weight와 bias를 할당한다.

보통 자주 사용되는 relu function을 활용했다.

결과를 보면,

minibatch relu shape

minibatch이기 때문에, 입력데이터의 행의 수가 큼을 알 수 있다.

하지만, weight값과 bias값은 영향을 받지 않는다는 사실을 확인할 수 있었다.

 

 

weight값은 x 입력 데이터의 features와 neurons의 개수에 영향을 받고,

bias 값은 한 layer에 속한 neuron의 개수에 영향을 받는다.

(다음 게시글에서 설명할 dense layer에서 설명하겠다.)

 

그렇게 해서 마지막 결괏값인 y를 보면 x 데이터의 행개수와 neuron의 개수를 통해,

(32000,1)의 shape를 갖음을 알 수 있다.

 

결론! - x의 샘플개수와 상관없이 weight와 bias 값은 변함이 없다.

 

마무리

어떤 모델을 구축할 때, 모델이 어떻게 작동되는지 확인하고 검토하는 습관이 중요하다는 것을 알게 되었다.

군대에서 선형대수학과, 미적분, 다변수미적분을 따로 공부해놨었는데, 많은 도움이 되었다.

반응형