코딩뚠뚠

[머신러닝 공부] Tiny ML -10 / 음성인식 모델훈련하기 -1 본문

공부/ML&DL

[머신러닝 공부] Tiny ML -10 / 음성인식 모델훈련하기 -1

로디네로 2022. 2. 2. 16:01
반응형

Chapter10. 음성인식(호출어 감지) 모델 훈련하기

 

"
새로운 모델을 만들어보자

"

 

 

목차 :

  • 새로운 모델 훈련
  • 프로젝트에서 모델 사용
  • 모델 작동 방식 -> 다음장
  • 내 데이터로 훈련하기 -> 다음장

 


 

새로운 모델 훈련 : 

 

우선 이 장에서는 yes, no 외의 다른 단어를 인식할 수 있는 모델을 훈련할 것이다.

 

훈련 시 아래와 같은 사항을 고려해야 될 것이다.

  1. 입력 : 기존 스크립트 활용을 위해 데이터의 모양과 형식을 맞춰줘야 한다.
  2. 출력 : 클래스 당 하나의 확률 텐서 타입을 갖는 출력을 맞춰줘야 한다.
  3. 훈련데이터 : 많은 데이터는 정확도를 향상시킨다.
  4. 최적화문제 : 메모리가 극도로 제한된 상태이므로 최적화문제가 있다.

참고한 기존 스크립트 아래 스크립트이다.

 

GitHub - tensorflow/tflite-micro: TensorFlow Lite for Microcontrollers

TensorFlow Lite for Microcontrollers. Contribute to tensorflow/tflite-micro development by creating an account on GitHub.

github.com

  ※ 공부를 계속하며 레포지토리가 계속 최신화 되어 책의 설명과 안맞는 부분이 있는데 위 링크도 그렇다.

최신 코드를 반영한 레포지토리는 아래 링크이다. 

(https://www.tensorflow.org/tutorials/audio/simple_audio)

 

 

 

> 이후 '런타임 - 런타임 유형 변경' 에서 하드웨어 가속을 GPU로 설정해준다.

(6개월 전만 해도 Colab Pro+ 버전에서 백그라운드 실행 같은 기능은 없었던것 같은데.. 너무 혜택이 없어서 그런지 추가해줬나보다.)

 

 

> 해당 주피터노트북을 실행하면 데이터셋을 자동으로 다운받는다.

아래와 같은 wav 데이터들이 학습데이터로 주어진다.

 


 

> 이번엔 yes, no 가 아닌 on, off를 훈련시켜보자.

또한 학습률 0.001로 12000번 학습을, 0.0001로 3000번 학습을 시켜보자.

학습초반엔 높은 학습률로 iter를 수행해 빠르게 수렴을 진행하고 이후엔 가중치와 편향을 미세하게 조정할것이다.

WANTED_WORDS = "on,off"
TRAINING_STEPS = "12000,3000"
LEARNING_RATE = "0.001,0.0001"

 

 

> Environment Setup을 실행하고 훈련을 시작한다.

!python tensorflow/tensorflow/examples/speech_commands/train.py \
--data_dir={DATASET_DIR} \
--wanted_words={WANTED_WORDS} \
--silence_percentage={SILENT_PERCENTAGE} \
--unknown_percentage={UNKNOWN_PERCENTAGE} \
--preprocess={PREPROCESS} \
--window_stride={WINDOW_STRIDE} \
--model_architecture={MODEL_ARCHITECTURE} \
--how_many_training_steps={TRAINING_STEPS} \
--learning_rate={LEARNING_RATE} \
--train_dir={TRAIN_DIR} \
--summaries_dir={LOGS_DIR} \
--verbosity={VERBOSITY} \
--eval_step_interval={EVAL_STEP_INTERVAL} \
--save_step_interval={SAVE_STEP_INTERVAL}

 

 

> tensorboard가 잘 로드되었다면 아래와 같이 훈련중 결과들이 보드에 나타날 것이다.

 

 

> 훈련 중 음성 입력데이터에 대한 스펙트로그램을 IMAGES 탭에서 볼 수 있다.

 

 

> 약 두 시간 후 훈련이 완료된 후의 tensorboard 모습이다.

 

 

> smoothing을 높게 주었을 때 train data에 대한 accuracy 와 cross_entropy 그래프이다.

 

 

> 마찬가지로 smoothing을 높게 주었을 때 validation data에 대한 accuracy 와 cross_entropy 그래프이다.

 

 

> freezing 과정 : 파이썬 스크립트와 체크포인트 파일들을 하나의 모델파일로 통합하여 추론에 사용할 수 있게 한다.

가중치가 고정된 정적인 그래프를 만들어보자.

!python tensorflow/tensorflow/examples/speech_commands/freeze.py \
--wanted_words=$WANTED_WORDS \
--window_stride_ms=$WINDOW_STRIDE \
--preprocess=$PREPROCESS \
--model_architecture=$MODEL_ARCHITECTURE \
--start_checkpoint=$TRAIN_DIR$MODEL_ARCHITECTURE'.ckpt-'{TOTAL_STEPS} \
--save_format=saved_model \
--output_file={SAVED_MODEL}

생성된 파일은 완전히 훈련된 파일로 추론을 실행하는 데 사용할 수 있다.

다만 이는 TFlite 가 아닌 일반 tensorflow 방식이므로 MCU에 이식하기 위해서는 변환이 필요하다.

 


 

> 텐서플로 라이트로 변환하기

- lite로 변환한다는 것은 곧 양자화 한다는 것

optimization 방식, inference input, inference output 의 type, sampling rate 등을 지정해주고 converter를 이용해 변환해준다.

SAMPLE_RATE = 16000
CLIP_DURATION_MS = 1000
WINDOW_SIZE_MS = 30.0
FEATURE_BIN_COUNT = 40
BACKGROUND_FREQUENCY = 0.8
BACKGROUND_VOLUME_RANGE = 0.1
TIME_SHIFT_MS = 100.0

DATA_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/speech_commands_v0.02.tar.gz'
VALIDATION_PERCENTAGE = 10
TESTING_PERCENTAGE = 10
model_settings = models.prepare_model_settings(
    len(input_data.prepare_words_list(WANTED_WORDS.split(','))),
    SAMPLE_RATE, CLIP_DURATION_MS, WINDOW_SIZE_MS,
    WINDOW_STRIDE, FEATURE_BIN_COUNT, PREPROCESS)
audio_processor = input_data.AudioProcessor(
    DATA_URL, DATASET_DIR,
    SILENT_PERCENTAGE, UNKNOWN_PERCENTAGE,
    WANTED_WORDS.split(','), VALIDATION_PERCENTAGE,
    TESTING_PERCENTAGE, model_settings, LOGS_DIR)
with tf.Session() as sess:
  float_converter = tf.lite.TFLiteConverter.from_saved_model(SAVED_MODEL)
  float_tflite_model = float_converter.convert()
  float_tflite_model_size = open(FLOAT_MODEL_TFLITE, "wb").write(float_tflite_model)
  print("Float model is %d bytes" % float_tflite_model_size)

  converter = tf.lite.TFLiteConverter.from_saved_model(SAVED_MODEL)
  converter.optimizations = [tf.lite.Optimize.DEFAULT]
  converter.inference_input_type = tf.lite.constants.INT8
  converter.inference_output_type = tf.lite.constants.INT8
  def representative_dataset_gen():
    for i in range(100):
      data, _ = audio_processor.get_data(1, i*1, model_settings,
                                         BACKGROUND_FREQUENCY, 
                                         BACKGROUND_VOLUME_RANGE,
                                         TIME_SHIFT_MS,
                                         'testing',
                                         sess)
      flattened_data = np.array(data.flatten(), dtype=np.float32).reshape(1, 1960)
      yield [flattened_data]
  converter.representative_dataset = representative_dataset_gen
  tflite_model = converter.convert()
  tflite_model_size = open(MODEL_TFLITE, "wb").write(tflite_model)
  print("Quantized model is %d bytes" % tflite_model_size)

결과적으로 모델의 크기는 18712bytes로 매우 작아졌음을 확인할 수 있다.

 

 

> 양자화 이후 모델의 accuracy를 test 해본다.

성능이 조금은 떨어질 것이라고 생각했지만 이상하게도 accuracy가 더 높게 나왔다. 

 

 

> C 배열 만들기

xxd 커맨드를 이용해 모델을 C배열로 변환하는 작업이다.

이 배열을 MCU에 이식해 동작을 확인해볼 것이다.

# Install xxd if it is not available
!apt-get update && apt-get -qq install xxd
# Convert to a C source file
!xxd -i {MODEL_TFLITE} > {MODEL_TFLITE_MICRO}
# Update variable names
REPLACE_TEXT = MODEL_TFLITE.replace('/', '_').replace('.', '_')
!sed -i 's/'{REPLACE_TEXT}'/g_model/g' {MODEL_TFLITE_MICRO}

명령을 실행한 후 !cat {MODEL_TF_LITE_MICRO} 명령으로 배열을 확인해볼 수 있다.

 

 


 

 

프로젝트에서 모델 사용

 

> 위에서 모델 훈련 후 만들어진 모델을 C배열 형태로 바꾸었으니 MCU에 이식해보자.

 

책에서는 위 C배열을 micro_features/tiny_conv_micro_features_model_data.cc 내용에 붙여넣으라고 하나

 

또! 버전이 다른 관계로 내가 clone 한 버전에서는 micro_features/model.cc로 대체되었다. (자주 버전이 바뀌나보다..)

 

> 그 다음은 label을 업데이트 해 줄 차례이다.

 

micro_features/micro_model_settings.cc를 열어 label을 변경해준다. (yes,no -> on,off)

 

 

> command_responder.cc 업데이트

 

on,off 가 들릴 때 어떤 LED 출력을 낼지에 대한 동작을 정의해 주는 부분이다.

 

tensorflow/lite/micro/examples/micro_speech/sparkfun_edge/command_responder.cc 를 수정한다.

  am_devices_led_toggle(am_bsp_psLEDs, AM_BSP_LED_BLUE);
  am_devices_led_off(am_bsp_psLEDs, AM_BSP_LED_RED);
  am_devices_led_off(am_bsp_psLEDs, AM_BSP_LED_YELLOW);
  am_devices_led_off(am_bsp_psLEDs, AM_BSP_LED_GREEN);
  
  if (is_new_command) {
    TF_LITE_REPORT_ERROR(error_reporter, "Heard %s (%d) @%dms", found_command,
                         score, current_time);
    if (found_command[0] == 'o' && found_command[1] == 'n') {
      am_devices_led_on(am_bsp_psLEDs, AM_BSP_LED_YELLOW);
    }
    if (found_command[0] == 'o' && found_command[1] == 'f') {
      am_devices_led_on(am_bsp_psLEDs, AM_BSP_LED_RED);
    }
    if (found_command[0] == 'u') {
      am_devices_led_on(am_bsp_psLEDs, AM_BSP_LED_GREEN);
    }
  }

 

 

> 역시 한번에 될리는 없다.

make -f tensorflow/lite/micro/tools/make/Makefile TARGET=sparkfun_edge micro_speech_bin

위 명령을 실행해보니

이런 에러가 떴고 model.cc에서 unsigned int g_model_len 을 const int g_model_len 으로 변경하고 make 진행

tensorflow/lite/micro/tools/make/gen/spark~micro/bin/micro_speech.bin

위 경로에 bin 파일이 생성되었다.

 

 

 

> 바이너리 서명

cp tensorflow/lite/micro/tools/make/downloads/AmbiqSuite-Rel2.2.0/tools/apollo3_scripts/keys_info0.py tensorflow/lite/micro/tools/make/downloads/AmbiqSuite-Rel2.2.0/tools/apollo3_scripts/keys_info.py
python3 tensorflow/lite/micro/tools/make/downloads/AmbiqSuite-Rel2.2.0/tools/apollo3_scripts/create_cust_image_blob.py --bin tensorflow/lite/micro/tools/make/gen/sparkfun_edge_cortex-m4_micro/bin/micro_speech.bin --load-address 0xC000 --magic-num 0xCB -o main_nonsecure_ota --version 0x0
python3 tensorflow/lite/micro/tools/make/downloads/AmbiqSuite-Rel2.2.0/tools/apollo3_scripts/create_cust_wireupdate_blob.py --load-address 0x20000 --bin main_nonsecure_ota.bin -i 6 -o main_nonsecure_wire --options 0x1

위 명령으로 main_nonsecure_wire.bin 파일이 생성되었고 이를 플래시 할 것이다.

 

 

 

> 디바이스 연결 및 설정

export DEVICENAME=/dev/ttyUSB0
export BAUD_RATE=921600
sudo chmod 666 /dev/ttyUSB0

 

> 플래싱

python tensorflow/lite/micro/tools/make/downloads/AmbiqSuite-Rel2.2.0/tools/apollo3_scripts/uart_wired_update.py -b ${BAUD_RATE} ${DEVICENAME} -r 1 -f main_nonsecure_wire.bin -i 6

 

on이라고 말하면 노란색 LED가, off를 말하면 빨간색 LED가 켜질 것이다.

 

 


 

Google Colab 외의 다른 방법으로 스크립트를 실행하기

 

colab을 써보신 분이라면 연결이 끊겨 짜증나는 경험을 한번씩 해보셨을것이라 생각한다.

 

이에 아래와 같은 방법들을 사용할 수 있다.

 

로컬 워크스테이션에 도커를 올려 사용하는 방식은 내 GPU가 좋지않아 해보지 못하겠지만 google cloud에서 training 후 inference server와 연동하는 방법은 조만간 배워보려한다.

 

 

- GPU가 있는 클라우드 가상머신

 

Deep Learning VM Image  |  딥 러닝 VM 이미지  |  Google Cloud

딥 러닝 애플리케이션을 위해 사전 구성된 VM입니다.

cloud.google.com

- 로컬 워크스테이션 with 텐서플로 GPU 도커 이미지

 

Docker  |  TensorFlow

Help protect the Great Barrier Reef with TensorFlow on Kaggle Join Challenge Docker Docker는 컨테이너를 사용하여 TensorFlow 설치를 나머지 시스템에서 격리하는 가상 환경을 만듭니다. TensorFlow 프로그램은 호스트 머

www.tensorflow.org

 

 

 

 

 

 

반응형