huginn muninn

[ABAE] 삽질 끝에 에러 해결하기..(final) 본문

자연어 처리/ABAE

[ABAE] 삽질 끝에 에러 해결하기..(final)

_maddy 2023. 3. 9. 19:48

 

진짜 일주일 내내 똥 쌌다. 

 

주말에도 연구실가서 코드만 쳐다보고, 스택오버플로우 하루종일 뒤지고 먼지 쌓인 옛날 블로그 글도 읽었다....

그리고 ChatGPT한테도 엄청 물어봄..

 

나는 귀여운 강쥐><

 

거의 저 짤 지금 내 상태.

코드 한번 돌릴 때마다 기도 한 번씩 올렸다. 거의 100번은 넘게 기도 올린 것 같은데,, 

쨋든 내가 어떻게 에러를 해결했는지 정리해보려고 한다. 고친 코드가 너무너무 많지만... 일단 정리해 보는 걸로.. 

 


 

내가 사용하려고 하는 코드는 ACL2017에 실린 "An unsupervised neural attention model for aspect extraction" 논문에서 쓰인 코드. 이 분들이 구현하신 코드에서 원하는 환경은 requirements.txt에서 볼 수 있다. 

 

keras==1.2.1
theano==0.9.0
numpy==1.13.3
scikit-learn
gensim==0.12.4
tqdm
h5py

 

아무리그래도 keras 1.2.1 버전하고 numpy 1.13.3 은 너무한 거 아니냐고🤯. tensor flow 최신 버전이 2.6.0으로 알고 있는데... 쨋든 이 모델 심상치 않다. 꽤나 구식 버전을 사용하고 있다는 건 고쳐야 할게 산더미란 말이다.....

예를 들어 옛날에는 tf.dot을 사용했지만 지금은 tf.matmul을 사용하는 것처럼.

 

가상환경 구축 후에 requirements.txt대로 설치해야 하지만 이미 나는 많은 시도와 가상환경 구축 끝에 저대로 환경을 구현하면 모델을 돌릴 수 없겠다는 결론에 도달했다.

 

그래서 그냥 최신 버전으로 설치해버렸다. 미래의 내가 코드를 고칠 수 있다고 생각했다(고치긴 했지만 너무너무 힘들었음)

 

내가 설치한 것들과 버전은 다음과 같다.

python==3.6.13
tensorflow==2.6.2
keras==2.6.0
numpy==1.19.5
scikit-learn==0.24.2
gensim==4.0.1
tqdm==4.63.0
h5py==3.1.0
nltk==3.4.5

이외에도 conda list로 내가 가상환경에 설치한 게 뭐가 있는지 확인해 보면 다른 것들도 많은데 내가 직접 설치해 준 것은 이것들 뿐이다.. 

 

 

최신버전으로 설치 후 model.py와 my_layers.py에 임포트하는 모델들을 좀 고쳐주었다. 

 

my_layers.py

#import keras.backend as K
#from keras.engine.topology import Layer

import tensorflow as tf
from tensorflow.keras.layers import Layer, InputSpec
from tensorflow.keras import initializers, regularizers, constraints
#from tensorflow.keras import backend as K

#from keras import initializations
#from keras import regularizers
#from keras import constraints
import numpy as np
#import theano.tensor as T

주석 처리된게 기존에 있던 것들이고 나머지가 새로 생긴 것들... 

 

model.py

import logging

#import keras.backend as K
#from tensorflow.keras import backend as K

from tensorflow.keras.layers import Dense, Activation, Embedding, Input
from tensorflow.keras.models import Model
from my_layers import Attention, Average, WeightedSum, WeightedAspectEmb, MaxMargin
import tensorflow as tf

기존에 from keras import 어쩌고 하는 것들은 tensorflow.keras 로 바꾸어주었다. 

 


 

에러를 일으킨 것들

1. theano

그리고 도저히 theano(처음 보는 것;;)로 모델을 돌릴 수 없을 것 같아서, 이분들이 구현한 모델을 새롭게 tensorflow로 고쳐주기로 했다 ㅠㅜ 흑흑... 그래서 계속해서 문제를 일으켰던 theano는 안녕... 

 

theano 얘가 진짜 문제가 많았다🤬. 케라스랑도 안 맞고,, 문법도 안 맞아서 도대체 theano 얘가 뭔가 싶어서 찾아봤더니 tensorflow랑 비슷하게 대규모 머신러닝, 딥러닝 모델을 구현하는 데 사용되는 것으로 2017년 이후로 업데이트가 중단되었다고 한다. 그래서 theano를 tensorflow로 바꾸는 과정에서 일부 구문을 수정한 것들이 많다. 

 

theano를 tensorflow로 바꾸면서 수정한 문법들

  • Theano를 Tensorflow로 교체
import tensorflow as tf
from tensorflow.keras.layers import Layer, InputSpec
from tensorflow.keras import initializers, regularizers, constraints
from tensorflow.keras import backend as K

 

  • 초기화
    Theano는 초기화를 keras.backend 대신 keras.initializations를 사용, 
    Tensorflow 에서는 keras.initializations가 없으며 대신 keras.initializers를 사용한다.
# Theano
self.init = initializations.get('glorot_uniform')

# TensorFlow
self.init = initializers.glorot_uniform()

 

  • InputSpec
    • Theano는 InputSpec을 지원하지 않는다.
    • TensorFlow에서는 InputSpec이 필요.
    • 따라서 InputSpec을 다음과 같이 가져와야 함
from tensorflow.keras.layers import InputSpec

 

  • 다른 일부 라이브러리의 이름 변경
    • 일부 라이브러리의 이름이 TensorFlow에서 변경
    • 예를 들어, Theano에서는 keras.backend를 사용했지만, TensorFlow에서는 tensor flow.keras.backend을 사용해야함.
    • Theano에서는 keras.regularizers를 사용하지만, TensorFlow에서는 tensorflow.keras.regularizers를 사용
    • 따라서 다음과 같이 코드를 수정
# Theano
from keras import regularizers

# TensorFlow
from tensorflow.keras import regularizers

 

  • "get_output_shape_for" 메소드를 "compute_output_shape"으로 변경
    • TensorFlow에서는 "get_output_shape_for" 메소드 대신 "compute_output_shape" 메소드를 사용
    • 따라서 다음과 같이 코드를 수정
# Theano
def get_output_shape_for(self, input_shape):
    return (input_shape[0], input_shape[0][-1])

# TensorFlow
def compute_output_shape(self, input_shape):
    return (input_shape[0], input_shape[0][-1])

 

  • 사용하지 않는 import 제거
    • Theano에서 사용한 keras.backend 및 keras.engine.topology 라이브러리를 TensorFlow에서 사용하지 않으므로 제거
    • 따라서 다음과 같은 코드를 제거
# Theano
import keras.backend as K
from keras.engine.topology import Layer

# TensorFlow
# 라이브러리 import 삭제
 

2. numpy, gensim

넘파이도 시키는 대로 설치했더니 또 gensim이랑 충돌... 아무리 문법 고치고 뭘 해도 import numpy, import gensim이 안되니 시작도 할 수 없었다. 그래서 싹 다 갈아엎고 다시 최신 버전으로 설치. 그리고 버전이 바뀌어 문법이 안 맞는 것들도 모두 수정. 

 

  • gensim의 Word2Vec 모델 객체에는 vocab 속성이 없다. 대신에, wv.vocab 속성을 사용하기.
def __init__(self, emb_path, emb_dim=None):

        logger.info('Loading embeddings from: ' + emb_path)
        self.embeddings = {}
        emb_matrix = []
       
        model = gensim.models.Word2Vec.load(emb_path)
        self.emb_dim = emb_dim
        for word in model.wv.vocab: # model.vocab 대신에 model.wv.vocab 사용
            self.embeddings[word] = list(model.wv[word]) # model.wv[word] 사용
            emb_matrix.append(list(model.wv[word])) # model.wv[word] 사용

        if emb_dim is not None: # != 대신에 is not None 사용
            assert self.emb_dim == len(self.embeddings['nice'])
            
        self.vector_size = len(self.embeddings)
        self.emb_matrix = np.asarray(emb_matrix)

        logger.info('  #vectors: %i, #dimensions: %i' % (self.vector_size, self.emb_dim))
  • gensim 4.0.0 이상에서는 KeyedVectors 클래스에서 vocab 속성이 제거되었다.
    대신 key_to_index 딕셔너리와 index_to_key 리스트를 사용해야 함.
    • model.vocab을 model.wv.key_to_index로 변경
    • vocab.iteritems()를 vocab.items()로 변경

3. Keras, Tensorflow

Keras를 임포트 했더니 텐서플로우가 안 깔려 있어서 깔라는... 근데 또 Tensorflow는 특정 파이썬 버전에서만 작동되어서 conda 가상환경에서 3.6 버전으로 설치한 후 모든 버전을 최신으로 설치했음. 

기존 코드는 tensorflow 1.x에서 작성되었기 때문에 내 가상환경에 설치된 버전인 tensorflow 2.X버전에서 돌아가려면 문법 몇 개를 수정해야 한다. 

  • TensorFlow 2.x에서는 tf.floatx()가 지원되지 않으므로 tf.keras.backend.floatx()로 대체
  • tf.sum 함수가 tf.reduce_sum 으로 변경
  • tf.dot()->tf.matmul로 수정
  • 'tf.repeat_elements'를 'tf.repeat'로 변경
  • tf.keras.backend.epsilon() 대신 tf.keras.backend.epsilon()를 사용

4. TypeError: add_weight() got multiple values for argument 'name'

이게 가장 문제가 많았다. 스택오버플로우랑 옛날 블로그글 봐도 고쳐지지 않던 지독한 에러... my_layers.py에 있는 attention class에 build 함수가 문제를 일으킨 것이다. 

class Attention(tf.keras.layers.Layer):#두개의 입력 텐서를 받아 가중치를 입력 masking함. 
    def __init__(self,
                W_regularizer=None,
                b_regularizer=None,
                W_constraint=None,
                b_constraint=None,
                bias=True, **kwargs):
        """
        Keras Layer that implements an Content Attention mechanism.
        Supports Masking.
        """
        self.supports_masking = True
        self.init = initializers.glorot_uniform()#수정

        self.W_regularizer = regularizers.get(W_regularizer)
        self.b_regularizer = regularizers.get(b_regularizer)
        self.W_constraint = constraints.get(W_constraint)
        self.b_constraint = constraints.get(b_constraint)

        self.bias = bias
        super(Attention, self).__init__(**kwargs)
        #self.input_spec = [InputSpec(ndim=3), InputSpec(ndim=3)]#추가

    def build(self, input_shape):
        assert type(input_shape) == list
        #assert len(input_shape) == 3
        assert len(input_shape) == 2


        self.steps = input_shape[0][1]

        self.W = self.add_weight(shape=(input_shape[0][-1], input_shape[1][-1]),
                                    initializer=self.init,
                                    name='{}_W'.format(self.name),
                                    regularizer=self.W_regularizer,
                                    constraint=self.W_constraint)
        if self.bias:
            self.b = self.add_weight(shape=(1,),
                                     initializer='zero',
                                     name='{}_b'.format(self.name),
                                     regularizer=self.b_regularizer,
                                     constraint=self.b_constraint)
        self.built = True

이 에러는 class Attention(Layer)->class Attention(tf.keras.layers.Layer)로 고쳐주기. attention class에 Layer 들어간 건 다 고쳐주었다.   
https://foxtrotin.tistory.com/527 여기서 해결방법 얻었다.. 감사합니다.... 

 

5. TypeError: ('Keyword argument not understood:', 'input')

#기존
model = Model(input=[sentence_input, neg_input], output=loss)

#바꾸기
model = Model(inputs=[sentence_input, neg_input], outputs=loss)

 

6. 'Embedding' object has no attribute 'W'

model.get_layer('word_emb').W와 같은 형태로 Embedding 레이어의 가중치를 찾을 수 없기 때문에 발생....

        #model.get_layer('word_emb').W.set_value(emb_reader.get_emb_matrix_given_vocab(vocab, model.get_layer('word_emb').W.get_value()))
        #아래 코드로 수정
        word_emb_layer = model.get_layer('word_emb')#수정한 코드
        weights = word_emb_layer.get_weights()[0]#수정한 코드
        new_weights = emb_reader.get_emb_matrix_given_vocab(vocab, weights)#수정한 코드
        word_emb_layer.set_weights([new_weights])#수정한 코드

 

7. AttributeError: 'ResourceVariable' object has no attribute 'set_value'

set_value가 더 이상 지원되지 않는다고 한다. 대신 assign() 메서드를 사용하면 된다. 

 

8. AttributeError: 'generator' object has no attribute 'next'

sen_gen.next() 는 Python 2에서 사용되는 코드이며, Python 3에서는 next(sen_gen)으로 변경

 

9. AttributeError: 'int' object has no attribute 'eval'

TensorFlow 버전 문제.. TensorFlow 버전 2.0 이상에서는 TensorShape 객체의 eval()메서드가 제거되었다. 따라서 eval()을 사용하는 부분을 수정

 

10. AttributeError: 'Embedding' object has no attribute 'W'

'Embedding' 객체에는 'W' 속성이 없다. 대신 'weights' 속성을 사용하여 임베딩 레이어의 가중치를 가져올 수 있다. 

 #기존
 'model.get_layer('word_emb').W.get_value()'
 
 #수정
 word_emb = model.get_layer('word_emb').get_weights()[0]

 

 

 

이 외에도 고친 게 많지만.. 일단 대략적으로 버전이나 라이브러리와 관련된 에러는 모두 정리했다... 

이제 train.py도 돌아가고 evaluation.py도 돌아간다..

이제 연구해야지