Shared Weight AutoEncoder 구현해보기

2020. 2. 24. 21:20분석 Python/Tensorflow

광고 한 번씩 눌러주세요. 블로그 운영에 큰 힘이 됩니다 :)

아래는 AutoEncoder의 구조를 나타냈다.
AutoEncoder는 기본적으로 encoder르 차원 축소 후 decoder로 다시 원래대로 복원할 수 있게 하여 학습시킨다.

원래 기존 구조는 w1, w2, w3, w4 weight를 각각 만들어서 다시 X를 복원한다.

기존 구조 AutoEncoder

하지만 이런 구조에서 생각해보면 굳이 w3, w4가 필요하지 않다. 네트워크의 목적은 다시 X를 복원하는 것이므로
최적화하는 파라미터의 수를 줄이기 위해서 w1 , w2를 transpose를 통해서 구할 수 있다.

네트워크 구조는 아래와 같다.

Sharing Parameter AutoEncoder

이런 식의 구조를 활용하면 parameter의 수를 줄여서 더 빠르게 학습시킬 수 있을 것이라고 했던 것 같다.
암튼 나는 개인적으로 중간에 있는 Code를 쓰는 것이 핵심이기 때문에, W1, W2, W3, W4보다는 최소한의 파라미터(W1, W2)로 세팅하여 최소한의 학습을 하게 한다.
그래서 개인적으로 기대하는 것은 Weight에 의해서 데이터가 잘 복원되긴 보다는, 데이터를 잘 표현한 Code를 통해서 같은 Weight라 할지라도 잘 학습되는 것을 기대한다.

Tensorflow Code는 다음과 같다.

row , dim = Train_X_np.shape
print(row,dim)
target_n = 2 
tf.reset_default_graph()
X = tf.placeholder(tf.float32, shape = [ None , dim])
TOTAL_DIM , h_dim , h_dim2 = dim , 20 , 10
Weight1 =get_weight_variable(shape = [TOTAL_DIM , h_dim], 
                            name=f"W1",type='he_normal', regularize=True)
Weight2 =get_weight_variable(shape = [h_dim , h_dim2], 
                            name=f"W2",type='he_normal', regularize=True)
                            
# encoder
encodelayer1 = tf.matmul(X ,Weight1)
code = tf.matmul(encodelayer1, Weight2)

# decoder
## transpose
decodelayer1 = tf.matmul(code, Weight2 , transpose_a=False , transpose_b=True )
trans_x = tf.matmul(decodelayer1, Weight1 , transpose_a=False , transpose_b=True )

loss = tf.reduce_mean(tf.square(X - trans_x))
vars = tf.trainable_variables()

w1과 w2 만 학습시키는 구조를 얻을 수 있다.

solver = tf.train.AdamOptimizer(learning_rate= 1e-4).minimize(loss ,var_list = vars )
Epoch = 10000
mb_size = 1000
config=tf.ConfigProto(log_device_placement=True)
config.gpu_options.allow_growth = True
sess = tf.Session(config = config)
init = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
sess.run(init)
_Loss_ = []
_Epoch_ = []
print("Train")
for epoch in range(Epoch) :
    print(epoch , end = "\r")
    idx = np.random.permutation(len(Train_X_np))
    XX = Train_X_np[idx , : ]
    batch_iter = int(len(XX) / mb_size)
    batchLoss = 0
    for idx in range(batch_iter) :
        X_mb = XX[idx*mb_size:(idx+1)*mb_size]
        Feed = {X : X_mb }
        _ , LOSS  = sess.run([solver , loss] , feed_dict= Feed)
        batchLoss += LOSS
    batchLoss /= batch_iter
    _Loss_.append(batchLoss)
    _Epoch_.append(epoch)
    if epoch % 100 == 0 :
        clear_output()
        plt.plot(_Epoch_ , _Loss_ )
        select= np.argmin(_Loss_)
        msg = f"Epoch : {epoch}, Loss : {batchLoss:.3f}, minimum : {_Loss_[select]:.3f}"
        plt.title(msg)
        plt.show()

https://www.quora.com/Is-weight-sharing-required-for-an-autoencoder

 

Is weight sharing required for an autoencoder?

Answer (1 of 3): Short answer: no Longer answer: one specific kind of autoencoder requires weight sharing. Specifically, if you apply score matching to some kinds of RBMs, it gives you an autoencoder loss function, and the equation says the decoder weights

www.quora.com

전체 코드는 아래 Github 주소에 있다.

https://github.com/sungreong/TIL/blob/master/FrameWork%20Tensorflow/200224_ColumnTransformer%20%2B%20Shared%20AutoEncoder.ipynb

 

sungreong/TIL

Today I Learned. Contribute to sungreong/TIL development by creating an account on GitHub.

github.com

 

728x90