[NIA sound event detection]#2 모델의 예측 결과를 label-studio에 올리기

Clay Ryu's sound lab·2022년 8월 23일
0

Projects

목록 보기
15/43

Introduction

모델의 예측이 어떻게 나오는지를 확인하고 나서 해야하는 작업은 어노테이터들에게 모델의 예측을 제공하여 음원의 event를 체크하도록 하는 것이다. 이 작업을 위해서는 예측 결과를 확인하고 수정할 수 있는 frontend 웹 페이지가 필요하며 label-studio를 활용하기로 했다.

label-studio

https://labelstud.io/
label-studio는 open source data labeling tool로서 서버에서 구현이 가능한 frontend 사이트를 제공한다. 우리에게는 외부에서 접속이 가능한 ip와 label-studio를 구동할 docker가 있는 상황이었다.

Obstacles & Walkthrough

Model Prediction to json

model의 prediction은 label-studio를 구동한 서버의 local storage와 연동을 해야하며 sqlite로 만들어지는 data 또한 연동을 해주어야 한다. 이를 위해서 우선 model prediction을 label-studio에서 읽을 수 있는 json파일의 형식으로 바꿔주어야 한다.
코드는 슈퍼맨 교수님께서 정리해주셨다.

if __name__ == "__main__":
  parser = argparse.ArgumentParser("sed_inference")
  parser.add_argument('--path', type=str, default='/home/clay/label_studio_files/data_v4/01/',
                      help='directory path to the dataset')
  parser.add_argument('--vocab_path', type=str, default='vocab.json',
                      help='directory path to the dataset')
  parser.add_argument('--threshold', type=float, default=0.1,
                      help='sound event detection threshold value')
  parser.add_argument('--batch_size', type=int, default=8,
                      help='data batch size')

  args = parser.parse_args()

  dataset = OnFlyAudio(args.path)
  meta_manager = MetaCreator(args.vocab_path)

  data_loader = DataLoader(dataset, batch_size=args.batch_size, collate_fn=pad_collate, pin_memory=True, num_workers=2, drop_last=False)

  # load panns model
  sed = SoundEventDetection(checkpoint_path=None, device='cuda')

  smoother = Smoother() # 적분
  pred = []

  for i, batch in tqdm(enumerate(data_loader)):
    audio, lens = batch
    framewise_output = sed.inference(audio)
    # framewise_output.shape = (batch_size, seq_len, num_tags), where seq_len is the length of the audio in 10ms step
    smoothed_output = smoother(framewise_output)

    pred += quantize_prediction(smoothed_output, lens, shifted_index= i * data_loader.batch_size, threshold=args.threshold)

  jsonified_pred = jsonify(pred, dataset, meta_manager)
  with open(f"prediction_threshold{str(args.threshold)}.json", "w") as json_file:
    json.dump(jsonified_pred, json_file, ensure_ascii=False)
  print(pred)

간단하게 과정을 요약하면 함께 제공 받은 metadata를 정리 + 모델의 예측 중 on, offset 부분을 label-studio에서 원하는 형태에 집어넣는 것이다.

def jsonify(event_labels, dataset, meta_manager:MetaCreator):
  '''
  event_labels (list of list of dict):
    each item has {'data_id': int, 'label': str, 'onset': float, 'offset': float}

  dataset (NeutuneSet)
  
  '''
  json_list = [] # list of dictionary. Each dictionary item is annotation/data-path to a single data sample

  for piece_event in event_labels:
    # piece_event는 list of dict
    event_id = piece_event[0]['data_id']
    #sample_path = dataset.wav_list[event_id].relative_to(dataset.path) # dataset path 안에서 wav sample의 상대 경로
    sample_path = dataset.mp3_list[event_id].relative_to(dataset.path) # mp3 sample의 상대 경로
    sample_path = '/data/local-files/?d=data_v4/01/' + str(sample_path)

    annotations =[{'id': 1,
                    'result': [{ #"value"의 key는 label-studio에서 인식되는 key들이라 변경하면 안됨
                                "value":{"start":event['onset'],"end":event['offset'],"labels":[event['label']],"score":float(event["confidence"])},
                                "from_name":"label",
                                "to_name":"audio",
                                "type":"labels",
                              } for event in piece_event]}]
    json_event = {'id':event_id, 'predictions': annotations, 'data': {'audio': sample_path, 'text': meta_manager.get_class_name_and_title(dataset.wav_list[event_id])}}
    json_list.append(json_event)

  return json_list

Path Connection

시간이 정말 오래 걸렸던 부분은 label-studio에 알려준 path와 local의 path를 연결하는 작업이었다. 이 문제는 사실 label-studio에서 제공하는 guide를 미리 보았더라면 바로 해결이 가능했는데 우리는 어노테이터들이 수정할 수 없도록 settings ui를 삭제한 상태였기 때문에 이걸 인지하는데에 꽤 길고 많은 시행착오 과정이 필요했다.
https://labelstud.io/guide/storage.html#Local-storage

컨테이너를 몇번을 팠는지 모르겠다.

sudo docker run -it -p 40001:8080 -v /home/maler/label_studio_serve/data/:/label-studio/data -v /home/maler/label_studio_serve/files/data_v4/:/label-studio/files heartexlabs/label-studio:latest

시행착오를 좀 살펴보자면 우선 local storage와 host에서 label-studio에 제공하는 storage를 똑같이 맞춰주기 위해서 local을 작업하는 docker를 다시 파는 작업을 했다. 그래도 해결이 되지 않았기 때문에 label-studio의 버젼을 맞춰주는 작업도 시도를 했다. 결국 settings를 발견하므로 해결이 되었다.

profile
chords & code // harmony with structure

0개의 댓글