ABOUT ME

Today
Yesterday
Total
  • Harmonizers Transformer 논문 코드 재현
    CS/논문 리뷰 2024. 4. 14. 19:33

    지난번에 Translating Melody to Chord: Structured and Flexible Harmonization of Melody with Transformer라는 논문을 살펴보면서 공부했는데, 코드를 직접 돌려보면서 구조를 봐야 더 잘 알것같아 깃허브에 있는 코드를 가지고 전체적인 구조를 살펴보았다.

     

    코드는 다음링크에서 볼 수 있다.

    https://github.com/rsy1026/harmonizers_transformer

     

    GitHub - rsy1026/harmonizers_transformer: This repository is for an implementation of the published paper "Translating Melody to

    This repository is for an implementation of the published paper "Translating Melody to Chord: Structured and Flexible Harmonization of Melody with Transformer" - rsy1026/harmonizers_trans...

    github.com

     


    Part 1. 코드 구조

     

    일단 전체적인 파일의 구조는 다음과 같다.

     

    파일의 개수도 많고, 각 파일마다 코드 수가 500줄은 가뿐히 넘어서 구조를 파악하기 정말 힘들었다.

    일단 내가 파악한 구조를 대략적으로 설명하면, 세 개의 파일이 메인이라고 볼 수 있다.

     

    코드를 돌려서 파일을 생성해보고자 할 때, 접근해야할 파일은 그림에 스티커로 표현해 놓은 것처럼 총 3개이다.


    1. process_data.py

    하는 역할 : 

    CMD폴더에 저장해논 Data set을 모델이 학습할 수 있는 형태로 인코딩해준다.

    코드를 실행하면 총 세 종류의 결과를 얻을 수 있다.

     

    1. npy 형식으로 저장되는 parsed features. 

    2. train, val, test batches.

    3. train, val, test  h5py dataset 

     

    코드를 분석해본 결과, 모델 학습에 3번 데이터를 사용하고 테스트에 2번 데이터를 사용하더라.

     

    실행 방법 :

    python process_data.py --dataset [dataset]

    위 명령어를 터미널에서 실행해주면 된다.

     

    [dataset] 부분에는 CMD나 HSLD의 파라미터를 입력하여 사용할 데이터셋을 지정해주면 된다.

     

    실행하기 전에 CMD/dataset 폴더에 CMD 데이터셋을 저장해주어야 한다.


     

    2. train.py

    하는 역할 : 

    학습된 모델의 파라미터, loss 체크포인트를 ./trained/STHarm_CMD와 같은 형식으로 저장해준다.

    h5py 확장자로 저장해놓은 데이터셋을 이용하며, 엄청나게 오래걸린다..

     

    실행 방법 :

    python trainer.py [dataset] [model]

    위 명령어를 터미널에서 실행해주면 된다.

     

    dataset과 학습시킬 모델을 파라미터로 지정해주면 된다.

    3. test.py

    생성된 MIDI형식의 파일이 저장된다. .mid 확장자로 생성되는데, 윈도우 미디어 플레이어로 재생이 된다.


    Part 2. Dependency

    아래는 내가 초반에 겪은 오류이다.

    CMD 폴더에 있는 데이터셋을 파싱해서 인코딩을 해야하는데, 그 단계에서부터 object has no attribute라는 에러가 발생했다. 재밌는 점은 기존 코드에서 이미 생성된 h5py파일이 저장되어있어서 데이터를 파싱하지 못했음에도 CMD batches는 생성이 된다..

     

    처음에는 코드의 문제인줄 알고 정말 하루 종일 붙잡고 있었는데, 결국 파이썬을 다운그레이드 하면서 일단 이 문제는 해결되었다.

     

    xml.etree.ElementTree.Element used to have a method called getchildren(), so you'll see existing code that uses it. It was deprecated in version version 3.2 and then removed in 3.9

    -> xml.etree...Element가 getchildren() 함수를 가지고 있었지만, 파이썬 3.9부터는 삭제되었다고 한다..

     

    Dependency와 관련된 오류를 처음 겪어봐서 해결하는데 오래걸렸는데, 다운그레이드 한번으로 해결되니 좀 허무했다..

     

    <KW, python = 3.11>

     

    K:\paper\harmonizers_transformer-master\harmonizers_transformer-master>C:/Users/A/anaconda3/envs/KW/python.exe k:/paper/harmonizers_transformer-master/harmonizers_transformer-master/process_data.py --dataset CMD

    ---------- START PARSING CMD DATASET ----------

      File "K:\paper\harmonizers_transformer-master\harmonizers_transformer-master\./utils\musicxml_parser.py", line 1237, in parse_notations
        notations = self.xml_notations.getchildren()
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getchildren'
    ---------- END PARSING CMD DATASET ----------

    ---------- START SAVING CMD BATCHES ----------
    saved xml data for a_smooth_one/a
    ...
    saved xml data for anthropology/gs
    Saving batches...
    saved batches for anthropology as --> inp size: (48, 89) / oup size: (6, 72)
    ...
    saved batches for along_came_betty fs --> inp size: (32, 89) / oup size: (4, 72)
    ---------- END SAVING CMD BATCHES ----------

    ---------- SAVED H5 DATASET -> READY TO TRAIN ----------

     

    ------------------------------------------------------------------------------------------------------------------

     

    이후에도 dependency 관련 문제는 계속해서 발생했다..

    numpy와 matplotlib, pytorch의 버전을 계속해서 변경하며 돌려본 결과 결국 코드가 정상적으로 돌아가는 설정을 찾았다.

     

    < STHarm , python = 3.8>

    K:\paper\harmonizers_transformer-master\harmonizers_transformer-master>K:/Anaconda_envs/STHarm/python.exe k:/paper/harmonizers_transformer-master/harmonizers_transformer-master/process_data.py --da
    taset CMD

    ---------- START PARSING CMD DATASET ----------
    Traceback (most recent call last):
      File "CMD_parser_features.py", line 400, in <module>
        save_features()
      File "CMD_parser_features.py", line 51, in save_features
        np.save(os.path.join(save_filename,
      File "<__array_function__ internals>", line 200, in save
      File "K:\Anaconda_envs\STHarm\lib\site-packages\numpy\lib\npyio.py", line 521, in save
        arr = np.asanyarray(arr)
    ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.
    ---------- END PARSING CMD DATASET ----------

    ---------- START SAVING CMD BATCHES ----------
    saved xml data for a_smooth_one/a
    ... 
    saved xml data for anthropology/gs
    Saving batches...
    saved batches for anthropology as --> inp size: (48, 89) / oup size: (6, 72)        
    ...       
    saved batches for anthropology gs --> inp size: (48, 89) / oup size: (6, 72)     

       
    Traceback (most recent call last):
      File "K:\Anaconda_envs\STHarm\lib\site-packages\numpy\lib\npyio.py", line 441, in load
        return pickle.load(fid, **pickle_kwargs)
    EOFError: Ran out of input

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      File "k:/paper/harmonizers_transformer-master/harmonizers_transformer-master/process_data.py", line 1346, in <module>
        save_batches_CMD()
      File "k:/paper/harmonizers_transformer-master/harmonizers_transformer-master/process_data.py", line 849, in save_batches_CMD
        features = np.load(piece, allow_pickle=True).tolist()
      File "K:\Anaconda_envs\STHarm\lib\site-packages\numpy\lib\npyio.py", line 443, in load
        raise pickle.UnpicklingError(
    _pickle.UnpicklingError: Failed to interpret file '.\\CMD\\exp\\train\\raw\\a_smooth_one\\features.a_smooth_one.a.npy' as a pickle

    K:\paper\harmonizers_transformer-master\harmonizers_transformer-master>

     

     

    혹시 다시 참고할 일이 생길까 싶어서 dependency 설정의 최종본을 올려본다.

     

    코드를 제공할 때, 사용자의 환경 리스트를 표기하는 것이 얼마나 고맙고, 또 중요한 포인트인지 절실히 깨달았다..

     


     

    한 가지 더 배운 점이 있는데, 우분투와 윈도우의 디렉토리를 나타내는 슬레시가 다르다는 점이다.

    '\\'와 '/'의 차이를 찾지 못하고 한참 헤매었기 때문에, 머릿속에 고이 박혀 절대 잊지 않을것 같다.

     

     

    빈 파일이 반환되어 리스트에 아무것도 담기지 않는 현상이 일어났고, 빈 리스트의 인덱스를 참조하려고 하니 인덱스 범위 초과 오류가 발생하였는데, 파일을 못찾은것인줄은 꿈에도 모르고 다른쪽에서 헤메다가 print문으로 찍어보고서야 눈치챘다..

     

     


    그리고,

    처음으로 모델을 학습하면서 GPU를 써봤다.

    LSTM모델은 특성상 GPU를 사용하지 못하였는데, 드디어 랩실에서 제공받은 GPU를 돌려보니 기분이 새로웠다! ㅎㅎ

    CUDA와 CUDNN 설치해서 연결해놓은게 3달도 더되었는데, 이제야 써보다니.. 흙흙

     

Designed by Tistory.