728x90

오늘 포스트 할 내용은 flac 데이터셋을 wav로 변환하여 진행하는 것이다.

 

일반적으로 음성 처리 분야에서 22.5kHz, 16kHz를 많이 사용하는데,

 

TIDIGITS 데이터셋 같은 경우 20kHz로 되어 있다.

 

또한 flac 확장자로 되어 있는데, 이번 포스팅의 목표는 1) convert flac to wav, 2) downsampling 20kHz -> 16kHz 이다.

 

 

먼저 저장할 경로를 설정해주고, flac 음성을 불러온다.

그 뒤 음성의 path와 file id를 얻는다.

file id 는 file.flac 으로 되어 있기 때문에 [:-5]로 name만 얻어오는 작업을 하고,

soundfile 의 read 함수를 이용하여 data부분을 get한다.

 

그 뒤에 1단계인 flac -> wav 로 저장을 진행한다.

 

이 데이터셋은 20000Hz이기 때문에 2번째로 해야 할 일은 librosa로 wav를 read 한 뒤 16000으로 downsampling을 진행한다.

 

전체 코드는 아래와 같다.

import soundfile as sf
import librosa
import os
save_dir = '/mnt/junewoo/speech/TIDIGITS/tidigits_flac/' # save dir

w_flac = '/mnt/junewoo/speech/TIDIGITS/tidigits_flac/data/adults/train/woman/sp/o31oa.flac' # read file
m_flac = '/mnt/junewoo/speech/TIDIGITS/tidigits_flac/data/adults/train/man/st/ooo5a.flac'

_, w_id = os.path.split(w_flac) # get dir, file name for saving
_, m_id = os.path.split(m_flac)

w_id = w_id[:-5] # change name o31oa.flac -> o31oa
m_id = m_id[:-5] # change name ooo5a.flac -> ooo5a

w_data, w_sr = sf.read(w_flac) # data, sampling rate divide
m_data, m_sr = sf.read(m_flac)


sf.write(save_dir + w_id + '.wav', w_data, w_sr, format='WAV', endian='LITTLE', subtype='PCM_16') # file write for wav
sf.write(save_dir + m_id + '.wav', m_data, m_sr, format='WAV', endian='LITTLE', subtype='PCM_16')

w, sr = librosa.load(save_dir+w_id+'.wav', sr=20000)
m, _ = librosa.load(save_dir+m_id+'.wav', sr=20000)

g_sr = 16000 # goal sampling rate

w_resample = librosa.resample(w, sr, g_sr)
m_resample = librosa.resample(m, sr, g_sr)

sf.write(save_dir + w_id + '_resample16k.wav', w_resample, g_sr, format='WAV', endian='LITTLE', subtype='PCM_16') # file write for wav
sf.write(save_dir + m_id + '_resample16k.wav', m_resample, g_sr, format='WAV', endian='LITTLE', subtype='PCM_16')

 

데이터 크기는 아래의 사진과 같다.

 

o31oa.wav 의 size는 73인데, 20kHz 에서 16kHz로 즉 20%만큼 downsampling을 해버렸기 때문에

73 * 0.8  = 58.4 ==> 58kB의 크기를 갖는다.

 

그러나 실제로 음성을 들어보면 큰 차이가 없음을 알 수 있다.

728x90
728x90

tensorboard 안될 때 해결법에 대해서 얘기하고자한다.

 

1. tf-nightly

 

나는 위 라이브러리를 설치하면서 tensorboard가 안되었다. 

또한 train code를 돌려도 gpu 메모리 할당이 안되고, cpu로 돌아가는 현상이 있었다.

 

그래서 tf-nightly 를 삭제했는데, 완전 삭제도 안되고 tensorboard도 안됐다.

 

이건 꼭 필요한 이유가 아니면 설치하지말자...

 

 

2. grpcio 문제

pkg_resources.VersionConflict: (grpcio 1.24.1 (dir), Requirement.parse('grpcio>=1.24.3')

 

위의 문제가 생겼을 때, pip로 grpcio를 지우고 하여도 안된다.

 

Duplicate plugins for name projector 라는 에러가 생기면서 안된다.

 

3. 완전 삭제가 안됨

tensorflow-gpu, tensorboard 를 지우고, 재설치하여도 안될때가 있다.

 

 

** 해결법

아래의 코드를 그대로 복사하여 하나의 .py 로 만들고, 실행하면 다음과 같은 step을 알려준다.

 

# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Self-diagnosis script for TensorBoard.

Instructions: Save this script to your local machine, then execute it in
the same environment (virtualenv, Conda, etc.) from which you normally
run TensorBoard. Read the output and follow the directions.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# This script may only depend on the Python standard library. It is not
# built with Bazel and should not assume any third-party dependencies.
import collections
import errno
import functools
import hashlib
import inspect
import logging
import os
import pipes
import shlex
import socket
import subprocess
import sys
import tempfile
import textwrap
import traceback


# A *check* is a function (of no arguments) that performs a diagnostic,
# writes log messages, and optionally yields suggestions. Each check
# runs in isolation; exceptions will be caught and reported.
CHECKS = []


# A suggestion to the end user.
#   headline (str): A short description, like "Turn it off and on
#     again". Should be imperative with no trailing punctuation. May
#     contain inline Markdown.
#   description (str): A full enumeration of the steps that the user
#     should take to accept the suggestion. Within this string, prose
#     should be formatted with `reflow`. May contain Markdown.
Suggestion = collections.namedtuple("Suggestion", ("headline", "description"))


def check(fn):
  """Decorator to register a function as a check.

  Checks are run in the order in which they are registered.

  Args:
    fn: A function that takes no arguments and either returns `None` or
      returns a generator of `Suggestion`s. (The ability to return
      `None` is to work around the awkwardness of defining empty
      generator functions in Python.)

  Returns:
    A wrapped version of `fn` that returns a generator of `Suggestion`s.
  """
  @functools.wraps(fn)
  def wrapper():
    result = fn()
    return iter(()) if result is None else result
  CHECKS.append(wrapper)
  return wrapper


def reflow(paragraph):
  return textwrap.fill(textwrap.dedent(paragraph).strip())


def pip(args):
  """Invoke command-line Pip with the specified args.

  Returns:
    A bytestring containing the output of Pip.
  """
  # Suppress the Python 2.7 deprecation warning.
  PYTHONWARNINGS_KEY = "PYTHONWARNINGS"
  old_pythonwarnings = os.environ.get(PYTHONWARNINGS_KEY)
  new_pythonwarnings = "%s%s" % (
      "ignore:DEPRECATION",
      ",%s" % old_pythonwarnings if old_pythonwarnings else "",
  )
  command = [sys.executable, "-m", "pip", "--disable-pip-version-check"]
  command.extend(args)
  try:
    os.environ[PYTHONWARNINGS_KEY] = new_pythonwarnings
    return subprocess.check_output(command)
  finally:
    if old_pythonwarnings is None:
      del os.environ[PYTHONWARNINGS_KEY]
    else:
      os.environ[PYTHONWARNINGS_KEY] = old_pythonwarnings


def which(name):
  """Return the path to a binary, or `None` if it's not on the path.

  Returns:
    A bytestring.
  """
  binary = "where" if os.name == "nt" else "which"
  try:
    return subprocess.check_output([binary, name])
  except subprocess.CalledProcessError:
    return None


def sgetattr(attr, default):
  """Get an attribute off the `socket` module, or use a default."""
  sentinel = object()
  result = getattr(socket, attr, sentinel)
  if result is sentinel:
    print("socket.%s does not exist" % attr)
    return default
  else:
    print("socket.%s = %r" % (attr, result))
    return result


@check
def autoidentify():
  """Print the Git hash of this version of `diagnose_tensorboard.py`.

  Given this hash, use `git cat-file blob HASH` to recover the relevant
  version of the script.
  """
  module = sys.modules[__name__]
  try:
    source = inspect.getsource(module).encode("utf-8")
  except TypeError:
    logging.info("diagnose_tensorboard.py source unavailable")
  else:
    # Git inserts a length-prefix before hashing; cf. `git-hash-object`.
    blob = b"blob %d\0%s" % (len(source), source)
    hash = hashlib.sha1(blob).hexdigest()
    logging.info("diagnose_tensorboard.py version %s", hash)


@check
def general():
  logging.info("sys.version_info: %s", sys.version_info)
  logging.info("os.name: %s", os.name)
  na = type("N/A", (object,), {"__repr__": lambda self: "N/A"})
  logging.info("os.uname(): %r", getattr(os, "uname", na)(),)
  logging.info(
      "sys.getwindowsversion(): %r",
      getattr(sys, "getwindowsversion", na)(),
  )


@check
def package_management():
  conda_meta = os.path.join(sys.prefix, "conda-meta")
  logging.info("has conda-meta: %s", os.path.exists(conda_meta))
  logging.info("$VIRTUAL_ENV: %r", os.environ.get("VIRTUAL_ENV"))


@check
def installed_packages():
  freeze = pip(["freeze", "--all"]).decode("utf-8").splitlines()
  packages = {line.split(u"==")[0]: line for line in freeze}
  packages_set = frozenset(packages)

  # For each of the following families, expect exactly one package to be
  # installed.
  expect_unique = [
      frozenset([
          u"tensorboard",
          u"tb-nightly",
          u"tensorflow-tensorboard",
      ]),
      frozenset([
          u"tensorflow",
          u"tensorflow-gpu",
          u"tf-nightly",
          u"tf-nightly-2.0-preview",
          u"tf-nightly-gpu",
          u"tf-nightly-gpu-2.0-preview",
      ]),
      frozenset([
          u"tensorflow-estimator",
          u"tensorflow-estimator-2.0-preview",
          u"tf-estimator-nightly",
      ]),
  ]

  found_conflict = False
  for family in expect_unique:
    actual = family & packages_set
    for package in actual:
      logging.info("installed: %s", packages[package])
    if len(actual) == 0:
      logging.warning("no installation among: %s", sorted(family))
    elif len(actual) > 1:
      logging.warning("conflicting installations: %s", sorted(actual))
      found_conflict = True

  if found_conflict:
    preamble = reflow(
        """
        Conflicting package installations found. Depending on the order
        of installations and uninstallations, behavior may be undefined.
        Please uninstall ALL versions of TensorFlow and TensorBoard,
        then reinstall ONLY the desired version of TensorFlow, which
        will transitively pull in the proper version of TensorBoard. (If
        you use TensorBoard without TensorFlow, just reinstall the
        appropriate version of TensorBoard directly.)
        """
    )
    packages_to_uninstall = sorted(
        frozenset().union(*expect_unique) & packages_set
    )
    commands = [
        "pip uninstall %s" % " ".join(packages_to_uninstall),
        "pip install tensorflow  # or `tensorflow-gpu`, or `tf-nightly`, ...",
    ]
    message = "%s\n\nNamely:\n\n%s" % (
        preamble,
        "\n".join("\t%s" % c for c in commands),
    )
    yield Suggestion("Fix conflicting installations", message)


@check
def tensorboard_python_version():
  from tensorboard import version
  logging.info("tensorboard.version.VERSION: %r", version.VERSION)


@check
def tensorflow_python_version():
  import tensorflow as tf
  logging.info("tensorflow.__version__: %r", tf.__version__)
  logging.info("tensorflow.__git_version__: %r", tf.__git_version__)


@check
def tensorboard_binary_path():
  logging.info("which tensorboard: %r", which("tensorboard"))


@check
def addrinfos():
  sgetattr("has_ipv6", None)
  family = sgetattr("AF_UNSPEC", 0)
  socktype = sgetattr("SOCK_STREAM", 0)
  protocol = 0
  flags_loopback = sgetattr("AI_ADDRCONFIG", 0)
  flags_wildcard = sgetattr("AI_PASSIVE", 0)

  hints_loopback = (family, socktype, protocol, flags_loopback)
  infos_loopback = socket.getaddrinfo(None, 0, *hints_loopback)
  print("Loopback flags: %r" % (flags_loopback,))
  print("Loopback infos: %r" % (infos_loopback,))

  hints_wildcard = (family, socktype, protocol, flags_wildcard)
  infos_wildcard = socket.getaddrinfo(None, 0, *hints_wildcard)
  print("Wildcard flags: %r" % (flags_wildcard,))
  print("Wildcard infos: %r" % (infos_wildcard,))


@check
def readable_fqdn():
  # May raise `UnicodeDecodeError` for non-ASCII hostnames:
  # https://github.com/tensorflow/tensorboard/issues/682
  try:
    logging.info("socket.getfqdn(): %r", socket.getfqdn())
  except UnicodeDecodeError as e:
    try:
      binary_hostname = subprocess.check_output(["hostname"]).strip()
    except subprocess.CalledProcessError:
      binary_hostname = b"<unavailable>"
    is_non_ascii = not all(
        0x20 <= (ord(c) if not isinstance(c, int) else c) <= 0x7E  # Python 2
        for c in binary_hostname
    )
    if is_non_ascii:
      message = reflow(
          """
          Your computer's hostname, %r, contains bytes outside of the
          printable ASCII range. Some versions of Python have trouble
          working with such names (https://bugs.python.org/issue26227).
          Consider changing to a hostname that only contains printable
          ASCII bytes.
          """ % (binary_hostname,)
      )
      yield Suggestion("Use an ASCII hostname", message)
    else:
      message = reflow(
          """
          Python can't read your computer's hostname, %r. This can occur
          if the hostname contains non-ASCII bytes
          (https://bugs.python.org/issue26227). Consider changing your
          hostname, rebooting your machine, and rerunning this diagnosis
          script to see if the problem is resolved.
          """ % (binary_hostname,)
      )
      yield Suggestion("Use a simpler hostname", message)
    raise e


@check
def stat_tensorboardinfo():
  # We don't use `manager._get_info_dir`, because (a) that requires
  # TensorBoard, and (b) that creates the directory if it doesn't exist.
  path = os.path.join(tempfile.gettempdir(), ".tensorboard-info")
  logging.info("directory: %s", path)
  try:
    stat_result = os.stat(path)
  except OSError as e:
    if e.errno == errno.ENOENT:
      # No problem; this is just fine.
      logging.info(".tensorboard-info directory does not exist")
      return
    else:
      raise
  logging.info("os.stat(...): %r", stat_result)
  logging.info("mode: 0o%o", stat_result.st_mode)
  if stat_result.st_mode & 0o777 != 0o777:
    preamble = reflow(
        """
        The ".tensorboard-info" directory was created by an old version
        of TensorBoard, and its permissions are not set correctly; see
        issue #2010. Change that directory to be world-accessible (may
        require superuser privilege):
        """
    )
    # This error should only appear on Unices, so it's okay to use
    # Unix-specific utilities and shell syntax.
    quote = getattr(shlex, "quote", None) or pipes.quote  # Python <3.3
    command = "chmod 777 %s" % quote(path)
    message = "%s\n\n\t%s" % (preamble, command)
    yield Suggestion("Fix permissions on \"%s\"" % path, message)


@check
def source_trees_without_genfiles():
  roots = list(sys.path)
  if "" not in roots:
    # Catch problems that would occur in a Python interactive shell
    # (where `""` is prepended to `sys.path`) but not when
    # `diagnose_tensorboard.py` is run as a standalone script.
    roots.insert(0, "")

  def has_tensorboard(root):
    return os.path.isfile(os.path.join(root, "tensorboard", "__init__.py"))
  def has_genfiles(root):
    sample_genfile = os.path.join("compat", "proto", "summary_pb2.py")
    return os.path.isfile(os.path.join(root, "tensorboard", sample_genfile))
  def is_bad(root):
    return has_tensorboard(root) and not has_genfiles(root)

  tensorboard_roots = [root for root in roots if has_tensorboard(root)]
  bad_roots = [root for root in roots if is_bad(root)]

  logging.info(
      "tensorboard_roots (%d): %r; bad_roots (%d): %r",
      len(tensorboard_roots),
      tensorboard_roots,
      len(bad_roots),
      bad_roots,
  )

  if bad_roots:
    if bad_roots == [""]:
      message = reflow(
          """
          Your current directory contains a `tensorboard` Python package
          that does not include generated files. This can happen if your
          current directory includes the TensorBoard source tree (e.g.,
          you are in the TensorBoard Git repository). Consider changing
          to a different directory.
          """
      )
    else:
      preamble = reflow(
          """
          Your Python path contains a `tensorboard` package that does
          not include generated files. This can happen if your current
          directory includes the TensorBoard source tree (e.g., you are
          in the TensorBoard Git repository). The following directories
          from your Python path may be problematic:
          """
      )
      roots = []
      realpaths_seen = set()
      for root in bad_roots:
        label = repr(root) if root else "current directory"
        realpath = os.path.realpath(root)
        if realpath in realpaths_seen:
          # virtualenvs on Ubuntu install to both `lib` and `local/lib`;
          # explicitly call out such duplicates to avoid confusion.
          label += " (duplicate underlying directory)"
        realpaths_seen.add(realpath)
        roots.append(label)
      message = "%s\n\n%s" % (preamble, "\n".join("  - %s" % s for s in roots))
    yield Suggestion("Avoid `tensorboard` packages without genfiles", message)


# Prefer to include this check last, as its output is long.
@check
def full_pip_freeze():
  logging.info("pip freeze --all:\n%s", pip(["freeze", "--all"]).decode("utf-8"))


def set_up_logging():
  # Manually install handlers to prevent TensorFlow from stomping the
  # default configuration if it's imported:
  # https://github.com/tensorflow/tensorflow/issues/28147
  logger = logging.getLogger()
  logger.setLevel(logging.INFO)
  handler = logging.StreamHandler(sys.stdout)
  handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
  logger.addHandler(handler)


def main():
  set_up_logging()

  print("### Diagnostics")
  print()

  print("<details>")
  print("<summary>Diagnostics output</summary>")
  print()

  markdown_code_fence = "``````"  # seems likely to be sufficient
  print(markdown_code_fence)
  suggestions = []
  for (i, check) in enumerate(CHECKS):
    if i > 0:
      print()
    print("--- check: %s" % check.__name__)
    try:
      suggestions.extend(check())
    except Exception:
      traceback.print_exc(file=sys.stdout)
      pass
  print(markdown_code_fence)
  print()
  print("</details>")

  for suggestion in suggestions:
    print()
    print("### Suggestion: %s" % suggestion.headline)
    print()
    print(suggestion.description)

  print()
  print("### Next steps")
  print()
  if suggestions:
    print(reflow(
        """
        Please try each suggestion enumerated above to determine whether
        it solves your problem. If none of these suggestions works,
        please copy ALL of the above output, including the lines
        containing only backticks, into your GitHub issue or comment. Be
        sure to redact any sensitive information.
        """
    ))
  else:
    print(reflow(
        """
        No action items identified. Please copy ALL of the above output,
        including the lines containing only backticks, into your GitHub
        issue or comment. Be sure to redact any sensitive information.
        """
    ))


if __name__ == "__main__":
  main()

 

이대로 따라한 뒤 다시 설치하면 잘 되는것을 볼 수 있다.

 

결과사진

 

 

reference: https://github.com/pytorch/pytorch/issues/22676

728x90
728x90

최근 tensorflow 2.0이 release 된 이후로, cuda 설치가 매우 간단해졌다.

(저는 cuda+cudnn 설치하는 시간 5분 걸렸습니다.)

 

Ubuntu 16.04 (CUDA 10) + cudnn + driver 설치

 

# Add NVIDIA package repositories
# Add HTTPS support for apt-key
sudo apt-get install gnupg-curl
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_10.0.130-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu1604_10.0.130-1_amd64.deb
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
sudo apt-get update
wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64/nvidia-machine-learning-repo-ubuntu1604_1.0.0-1_amd64.deb
sudo apt install ./nvidia-machine-learning-repo-ubuntu1604_1.0.0-1_amd64.deb
sudo apt-get update

# Install NVIDIA driver
# Issue with driver install requires creating /usr/lib/nvidia
sudo mkdir /usr/lib/nvidia
sudo apt-get install --no-install-recommends nvidia-driver-418
# Reboot. Check that GPUs are visible using the command: nvidia-smi

# Install development and runtime libraries (~4GB)
sudo apt-get install --no-install-recommends \
    cuda-10-0 \
    libcudnn7=7.6.2.24-1+cuda10.0  \
    libcudnn7-dev=7.6.2.24-1+cuda10.0


# Install TensorRT. Requires that libcudnn7 is installed above.
sudo apt-get install -y --no-install-recommends libnvinfer5=5.1.5-1+cuda10.0 \
    libnvinfer-dev=5.1.5-1+cuda10.0

 

Ubuntu 16.04 (CUDA 9.0 for TensorFlow < 1.13.0) + cudnn + driver 설치

# Add NVIDIA package repository
sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
sudo apt install ./cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64/nvidia-machine-learning-repo-ubuntu1604_1.0.0-1_amd64.deb
sudo apt install ./nvidia-machine-learning-repo-ubuntu1604_1.0.0-1_amd64.deb
sudo apt update

# Install the NVIDIA driver
# Issue with driver install requires creating /usr/lib/nvidia
sudo mkdir /usr/lib/nvidia
sudo apt-get install --no-install-recommends nvidia-410
# Reboot. Check that GPUs are visible using the command: nvidia-smi

# Install CUDA and tools. Include optional NCCL 2.x
sudo apt install cuda9.0 cuda-cublas-9-0 cuda-cufft-9-0 cuda-curand-9-0 \
    cuda-cusolver-9-0 cuda-cusparse-9-0 libcudnn7=7.2.1.38-1+cuda9.0 \
    libnccl2=2.2.13-1+cuda9.0 cuda-command-line-tools-9-0

# Optional: Install the TensorRT runtime (must be after CUDA install)
sudo apt update
sudo apt install libnvinfer4=4.1.2-1+cuda9.0

위에는 cuda-10.0, 아래는 cuda-9.0 인데, 2개 모두 동시 설치 가능하다.

 

본인 계정 -> basrhc 에 들어가서 아래와 같이 사용할 버전을 typing 한다.

 

vi ~/.bashrc

export PATH=/mnt/junewoo/bin:/mnt/junewoo/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin 

# Path for cuda-9.0
export PATH=$PATH:/usr/local/cuda-9.0/bin



# Path for cuda-10.0

#export PATH=$PATH:/usr/local/cuda-10.0/bin



# Path for cudnn with cuda-9.0
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/junewoo/utils/cuda-9.0/lib64



# Path for cudnn with cuda-10.0
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:/mnt/junewoo/utils/cuda-10.0/lib64

 

만약 특정 폴더에 cudnn이 있을 경우(하지만 위의 명령어대로 설치할 경우 usr/local/cuda-n.m에 설치된다.

# Path for cudnn with cuda-10.0
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:/where/your_dir/cuda-10.0/lib64

그 뒤,

source ~/.bashrc



nvcc -V

 

확인해보면 설치된 cuda version 체크할 수 있다.

진짜 5분만에 설치할 수 있다 매우 간단...

 

ref: https://www.tensorflow.org/install/gpu?hl=ko

728x90
728x90

오늘은 Matlab에서의 Stft(short time fourier transform)와 python library인 librosa의 stft의 dimension 결과 및 각 vector값의 차이에 대해서 알아보겠다.

 

실제로 나는 Matlab에서 DTW 알고리즘으로 테스트할 것이 있어서 stft로 변환해본 뒤 python 결과와 비교해보았는데 dimension 크기가 달랐었다. 그리하여 그 이유를 정리하여 여기에 올리겠다.

 

우선 Matlab에서 spectrogram 을 변환하기 위한 코드는 아래와 같다.

 

>> [y, Fs] = audioread("filename1.wav");
>> [x, Fs] = audioread("filename2.wav");

 

음성은 16kHz 이고, nfft=512, hop=256으로 진행하겠다 ==> frame length를 32ms, 겹치는 hop을 16ms로 진행

 

>> s1 = spectrogram(x, 512, 256);
>> s2 = spectrogram(y, 512, 256);

 

matlab data 결과

 

첨부한 그림처럼,

s1: (257, 271)

s2: (257, 256) 으로, s1이 s2보다 길이가 크다고 볼 수 있다.

 

이번에는 python에서 librosa를 사용해서 진행하겠다.

 

nfft=512

hop_length=256

wavfile_male = '경로'

wavfile_female = '경로'

male_stft = librosa.stft(y_male, n_fft=nfft, hop_length=hop_length)
female_stft = librosa.stft(y_female, n_fft=nfft, hop_length=hop_length)
print("male_stft shape {} female_stft shape {}".format(np.shape(male_stft), np.shape(female_stft)))

 

첨부한 그림처럼

male(s1): 257, 273

female(s2): 257, 258

으로 나온다. s1이 s2보다 크다.

 

근데 여기서 차원이 다르다.

 

정확히 말하면 matlab 결과물이 python librosa 결과물보다 크다. 왜 그럴까?

 

계속 찾던 도중, 잘 설명해주는 글을 발견했다.

https://stackoverflow.com/questions/55474581/difference-between-output-of-python-librosa-core-stft-and-matlab-spectrogramx

 

요약하자면, matlab은 spectrogram의 마지막 window를 생략하면서, 각 window 가운데에 해당하는 시간 벡터를 출력한다. 예를 들어 3샘플 윈도우와 1개의 겸칩(overlap) 샘플을 갖는 10개의 샘플 길이의 신호는 다음과 같은 4개의 윈도우를 생성한다.

1:3

3:5

5:7

7:9,

m:n은 n번째 샘플을 포함하여 m에서 n까지의 샘플을 포함하는 윈도우를 나타낸다. 그러므로 window의 center가 2,4,6,8이다.

matlab은 (윈도우 크기-1) * 홉 길이 + 윈도우 사이즈 <= 샘플들의 개수로 되는 최대의 윈도우 크기를 필요로 하기 때문이다.

 

 

반면 python librosa stft 각 프레임의 첫 번째 샘플이 시간이고, 프레임은 입력 신호보다 많은 부분을 다룬다.

 

위의 matlab의 공식에 반해, librosa는

윈도우의 개수 * 홉 길이 > 샘플개수에 되는 최소한의 윈도우 크기를 요구한다.

 

정리

- MATLAB은 최대한의 윈도우 크기 요구

- Librosa는 최소한의 윈도우 크기 요구

 

그럼 MATLAB과 동일한 차원을 갖고 싶다면?

librosa.stft(y, nfft=, hop=, center=False)

위의 코드처럼 맨 뒤에 center=False를 해주면 된다.

 

자세한 내용은 librosa 공식 사이트를 확인해보자 

https://librosa.github.io/librosa/generated/librosa.core.stft.html

 

center:boolean

  • If True, the signal y is padded so that frame D[:, t] is centered at y[t * hop_length].
  • If False, then D[:, t] begins at y[t * hop_length]

위의 center=False로 돌려보면,

(257, 271) (257, 256) 으로 Matlab과 동일한 차원을 갖는 Spectrogram이 나오게 된다.

 

하지만 Matlab과 librosa의 각 spectrogram의 벡터값들이 모두 같진 않다.

얼핏 보기엔 유사하지만 같지 않다.

아무래도 각 팀들에서 Nomalize등의 기법을 다르게 하여 그런 것 같다.

 

 

 

Matlab 코드

[y, Fs] = audioread("filename1.wav"); #여자
[x, Fs] = audioread("filename2.wav"); #남자

s1 = spectrogram(x, 512, 256); 
s2 = spectrogram(y, 512, 256);

Python 코드

import numpy as np

nfft=512
hop_length=256
male_name = 'masch0'
female_name = 'fekmh0'
import pickle
import scipy
from scipy.spatial.distance import euclidean

wavfile_female = '/mnt/junewoo/speech/KAIST_wav/new_Korean_Voice_DB/public/falhj0/PBSG001.wav'

wavfile_male = '/mnt/junewoo/speech/KAIST_wav/new_Korean_Voice_DB/public/masch0/PBSG001.wav'

y_female, sr = librosa.load(wavfile_female, sr=16000)
y_male, sr = librosa.load(wavfile_male, sr=16000)
male_stft = librosa.stft(y_male, n_fft=nfft, hop_length=hop_length, center=False)
female_stft = librosa.stft(y_female, n_fft=nfft, hop_length=hop_length, center=False)
print("male_stft shape {} female_stft shape {}".format(np.shape(male_stft), np.shape(female_stft)))
print('Done')
728x90
728x90

딥러닝을 이용하여 음성 인식, 음성 처리, 화자 인식, 감정 인식 등에서 많이 쓰이는 음성의 특징 추출 방법은 1.Mel-Spectrogram, 2. MFCC가 있다. 오늘은 Mel-Spectrogram에 대하여 어떻게 추출하여 쓸 수 있는지 적어보겠다.

 

사용할 라이브러리는 librosa 이다.

https://librosa.github.io/librosa/generated/librosa.feature.melspectrogram.html

 

librosa.feature.melspectrogram — librosa 0.6.3 documentation

Parameters: y : np.ndarray [shape=(n,)] or None audio time-series sr : number > 0 [scalar] sampling rate of y S : np.ndarray [shape=(d, t)] spectrogram n_fft : int > 0 [scalar] length of the FFT window hop_length : int > 0 [scalar] number of samples betwee

librosa.github.io

위 사이트에서 자세히 설명이 나와있다. 그대로 따라해도 되지만, 이왕 하는김에 조금 자세히 알아보자.

사이트의 doc 을 보면 아래처럼 설명이 있다.

 

Parameters:Returns:

y:np.ndarray [shape=(n,)] or None

audio time-series

sr:number > 0 [scalar]

sampling rate of y

S:np.ndarray [shape=(d, t)]

spectrogram

n_fft:int > 0 [scalar]

length of the FFT window

hop_length:int > 0 [scalar]

number of samples between successive frames. See librosa.core.stft

power:float > 0 [scalar]

Exponent for the magnitude melspectrogram. e.g., 1 for energy, 2 for power, etc.

kwargs:additional keyword arguments

Mel filter bank parameters. See librosa.filters.mel for details.

S:np.ndarray [shape=(n_mels, t)]

Mel spectrogram

1. y

Mel-Spectrogram을 뽑기 위해서는 librosa.load 로 음성 데이터를 load하여 얻은 y를 넣으면 된다. 이렇게 나머지를 지정하지 않고 추출하였을 경우 default 값으로 추출이된다.

2. sr

y, sr = librosa.load(음성데이터) 를 하게 될 경우, 음성의 sr을 얻을 수 있다. 단 여기에서 중요한 것은, sr을 따로 설정해주지 않으면 librosa는 default인 22050을 주게 된다. 나는 이러한 이유로 soundfile을 사용하여 처음 보는 음성 데이터에 대하여 sr을 체크한 뒤, 그대로 아래처럼 설정해서 sr을 얻는 방법을 사용한다.

y, sr = librosa.load(wav_file, sr=16000)

3. S

S는 librosa.stft(y)를 하면 얻을 수 있다. 즉 Short-Time Fourier Transform을 하여 얻어진 magnitude 와 phase의 값인 것이다. 그렇지만 S는 사용하지 않고 음성 데이터인 y만 넣어도 되므로 pass하겠다.

 

4. n_fft

우리가 보유한 음성 데이터는 현재 time-magnitude domain이다. 이걸 왜 frequency로 바꾸냐면, 주파수 관점에서 바라보았을 때 얻을 수 있는 정보가 많기 때문이다.

음성은 연속적인 신호이다. 그러므로 연속적인 신호를 우리는 frequency로 바꿔야 한다.

 

n_fft는 이 때 사용되는데, 음성의 길이를 얼마만큼으로 자를 것인가? 라고 이해하면 될 것 같다. 이를 window라고 부른다.

사람의 목소리는 대부분 16kHz안에 포함이 된다. 만약 n_fft를 512라고 가정해보겠다. 이렇게 될 경우 1개의 n_fft는 16000/512 = 약 31.25가 된다. 이것이 자연수로 떨어지기 위해 올림을 해주어 32로 설정해준다. 총 음성 데이터의 길이가 500이라고 가정하면, 32만큼 잘라서 1칸을 그리겠다는 것으로 이해하면 된다. 

보유한 음성 데이터의 Sampling Rate가 16000이고, 우리는 n_fft를 512개만 사용할 것이라면, 아래의 공식을 이용하여 구할 수 있다.

 

input_nfft = int(round(sr*frame_length))
frame_length = input_nfft/sr

2번 째 줄을 보면 되겠다.

 

frame_length = 512/16000 = 0.032 => 32ms가 나온다.

 

즉 1개의 window의 크기를 32ms로 잡으면 되고, 이것을 window_length 라고도 부른다.

 

5. hop_length

hop_length는 음성의 magnitude를 얼만큼 겹친 상태로 잘라서 칸으로 보여줄 것인가? 라고 생각하면 편할 것 같다. 즉 window_length - frame_stride 만큼 겹쳐서 1칸을 뽑겠다는 뜻이다. 

 

예를 들어 우리가 보유한 데이터가 7초이고, window_length를 0.025초, frame_stride를 0.010초(10ms)단위로 뽑는다고 가정하면, 1칸은 0.015초(15ms)가 겹치도록 하여 총 700칸을 얻을 수 있다.

 

6. 7은 넘어가도록 하겠다.

 

 

자 그럼 이제 실제로 코드를 돌려서 결과를 얻어 볼 것이다.

 

나는 window length 를 0.025로 두고, stride는 0.010로 진행하여 0.01초마다 frequency를 뽑을 것이다.

 

frame_length = 0.025
frame_stride = 0.010

def Mel_S(wav_file):
    # mel-spectrogram
    y, sr = librosa.load(wav_file, sr=16000)

    # wav_length = len(y)/sr
    input_nfft = int(round(sr*frame_length))
    input_stride = int(round(sr*frame_stride))

    S = librosa.feature.melspectrogram(y=y, n_mels=40, n_fft=input_nfft, hop_length=input_stride)
    
    print("Wav length: {}, Mel_S shape:{}".format(len(y)/sr,np.shape(S)))

 

아래처럼 함수를 선언하였다. 여기에서 중요한 것은, n_mels이다. 만약 16kHz를 Mel_S로 뽑는다면 약 8kHz에 해당하는 주파수를 얻을 수 있다. 이때, 8kHz를 n_mels 크기 만큼으로 나눠준다. 즉 1개의 n_mels의 height는 0.4kHz를 포함하고 있다. 

 

음성 데이터의 길이와 얻은 Mel_Spectrogram의 크기를 출력해보면 다음과 같다.

 

총 길이는 3.35초이고, 0.01 단위에서 올림을하여 3.36이 된다. 그리고 0.01에 1칸이므로 336칸을 얻는다.

 

이렇게 Mel_Spectrogram을 얻었고, 이것을 그려보도록 하겠다. 아래의 코드를 복사하면 된다.


    plt.figure(figsize=(10, 4))
    librosa.display.specshow(librosa.power_to_db(S, ref=np.max), y_axis='mel', sr=sr, hop_length=input_stride, x_axis='time')
    plt.colorbar(format='%+2.0f dB')
    plt.title('Mel-Spectrogram')
    plt.tight_layout()
    plt.savefig('Mel-Spectrogram example.png')
    plt.show()

얻을 Mel_Spectrogram 그림은 아래와 같다.

 

 

전체코드는 아래와 같다.

 

# -*- coding: utf-8 -*-
import librosa
import librosa.display
import numpy as np
import matplotlib.pyplot as plt

frame_length = 0.025
frame_stride = 0.010

def Mel_S(wav_file):
    # mel-spectrogram
    y, sr = librosa.load(wav_file, sr=16000)

    # wav_length = len(y)/sr
    input_nfft = int(round(sr*frame_length))
    input_stride = int(round(sr*frame_stride))

    S = librosa.feature.melspectrogram(y=y, n_mels=40, n_fft=input_nfft, hop_length=input_stride)

    print("Wav length: {}, Mel_S shape:{}".format(len(y)/sr,np.shape(S)))


    plt.figure(figsize=(10, 4))
    librosa.display.specshow(librosa.power_to_db(S, ref=np.max), y_axis='mel', sr=sr, hop_length=input_stride, x_axis='time')
    plt.colorbar(format='%+2.0f dB')
    plt.title('Mel-Spectrogram')
    plt.tight_layout()
    plt.savefig('Mel-Spectrogram example.png')
    plt.show()

    return S
man_original_data = '/mnt/junewoo/workspace/transform/test_wav/man_wav1.wav'
mel_spec = Mel_S(man_original_data)
728x90
728x90

음성 처리를 하다 보면 음성 데이터를 Down Sampling 하거나, Up sampling 할 경우가 있다.

예를 들어 보유한 데이터의 Sampling rate가 44.1kHz 인데, n_fft가 너무 크기 때문에 모든 것을 다 함축하여 Mel scale log spectrogram으로 담지 못할 경우가 있다.

이럴 때 자주 사용하는 것이 Down sampling이라고 한다.

오늘은 librosa 라이브러리를 이용하여 down sampling을 해보겠다.
우선 librosa 라이브러리를 설치해야 한다.

설치하였다고 가정하고,  함수를 하나 만들어서 진행하겠다. 함수 이름은 def down_sample이다.

def down_sample(input_wav, origin_sr, resample_sr):
    y, sr = librosa.load(input_wav, sr=origin_sr)
    resample = librosa.resample(y, sr, resample_sr)
    print("original wav sr: {}, original wav shape: {}, resample wav sr: {}, resmaple shape: {}".format(origin_sr, y.shape, resample_sr, resample.shape))

이 함수에서는 wav 파일과 기존 original sr, resample 할 sr을 받고 있다.

보유한 데이터의 음성은 16kHz이므로, original_sr = 16000, resample_sr = 8000으로 진행한다.

 

음성 처리에 있어서 librosa 라이브러리가 정말 잘 지원해주고 있다. resample을 하기 위해서는 3번째 줄의 resample = librosa.resample(y, sr, resample_sr)을 해주면 된다.

 

그 아래의 print 한 결과는 다음과 같다.

 

즉 기존의 y data는 53720이고, 그의 절반으로 하였기 때문에 26860으로 출력이 된다.

 

이렇게만 보면 이해하기가 어렵다. 아래의 코드를 활용하여 직접 그림을 그려보자.

 

    plt.figure(figsize=(10, 4)) # 10,4 크기로 그림
    plt.subplot(2, 1, 1) # 2개를 그릴건데, (총 개수, 가로, 세로) 순서로 그림
    time1 = np.linspace(0, len(y) / sr, len(y)) # 음성의 데이터를 이용하여 음성 총 길이를 구함
    plt.plot(time1, y) # 음성 flot
    plt.title('Original Wav')

    plt.subplot(2, 1, 2)
    time2 = np.linspace(0, len(resample) / resample_sr, len(resample))
    plt.plot(time2, resample)
    plt.title('Resampled Wav')

    plt.tight_layout()
    plt.savefig('compare_16k_vs_8k.png') # 저장

위의 코드에 자세히 주석을 달아놓았다. 위의 코드처럼 입력을 하면 다음의 그림을 얻을 수 있다.

 

 

코드에서 subplot은 2,1,1 -> 총 2개의 사진 중 맨 위를, 2,1,2 -> 총 2개의 사진 중 맨 아래에 그림을 그리겠다는 뜻이다.

 

육안으로 보았을 때 magnitude나 phase의 변화는 없다. 다만 자세히 들여다보면 data의 magnitude가 2개 중 1개씩 비어있다. 즉, 데이터가 총 100개면, resample 하였을 경우 (1/2로 하였기 때문에) 50개의 데이터만 남아있다. 이때, 데이터의 위치는 변화하지 않고 중간중간만 비어지는 것이다.

 

이제 음성 데이터를 저장하여 들어보겠다.

 

    sf.write('./' + '16k.wav' , y, origin_sr, format='WAV', endian='LITTLE', subtype='PCM_16')
    sf.write('./' + '8k.wav', resample, resample_sr, format='WAV', endian='LITTLE', subtype='PCM_16')

 

아래 글에 작성한 것처럼, sf.write를 사용하여 현재 directory에서 16k.wav 라고 저장하는 코드이다. 

 

실제로 음성 첨부를 하여 들어보면,

 

 

 

8kHz

 

16kHz

 

육안으로 들었을 때, 두 데이터의 차이는 크지 않다.

 

저장되는 크기는 어떨까? 예상한 것처럼, 절반으로 resampling 하였기 때문에 데이터의 크기 또한 절반으로 reduce 된다.

 

 

전체 코드는 아래와 같다.

import librosa
import numpy as np
import soundfile as sf
import matplotlib.pyplot as plt

def down_sample(input_wav, origin_sr, resample_sr):
    y, sr = librosa.load(input_wav, sr=origin_sr)
    resample = librosa.resample(y, sr, resample_sr)
    print("original wav sr: {}, original wav shape: {}, resample wav sr: {}, resmaple shape: {}".format(origin_sr, y.shape, resample_sr, resample.shape))

    plt.figure(figsize=(10, 4))
    plt.subplot(2, 1, 1)
    time1 = np.linspace(0, len(y) / sr, len(y))
    plt.plot(time1, y)
    plt.title('Original Wav')

    plt.subplot(2, 1, 2)
    time2 = np.linspace(0, len(resample) / resample_sr, len(resample))
    plt.plot(time2, resample)
    plt.title('Resampled Wav')

    plt.tight_layout()
    plt.savefig('compare_16k_vs_8k.png')

    sf.write('./' + '16k.wav' , y, origin_sr, format='WAV', endian='LITTLE', subtype='PCM_16')
    sf.write('./' + '8k.wav', resample, resample_sr, format='WAV', endian='LITTLE', subtype='PCM_16')

man_original_data = '/mnt/junewoo/workspace/transform/test_wav/man_wav1.wav'
down_sample(man_original_data, 16000, 8000)

 

728x90
728x90

Keras를 사용하다보면, 간단하게 구현된 라이브러리를 사용할 때가 있다.

그래서 더 사랑을 받는게 아닐까. 너무 간결하고 간단한 라이브러리들이 많다.


최근에 사용했던 간단한 라이브러리 Transformer 모델의 Self-Attention이다.


이 Function을 사용하기 위해서는 따로 import를 해줘야하는데 아래와 같이 하면 된다.


from keras_self_attention import SeqSelfAttention


자 이제 CNN 몇개와 RNN 몇개를 쌓고, 그 아래에 Self-Attention을 쌓았다고 가정해보자.


이 모델을 Fine-tune 하기 위해 일정 learning rate로 돌려놓고, 어느정도 loss를 깎은 다음 일정 이상 loss가 떨어지지 않으면 early stopping을 하여 learning rate를 기존보다 0.1배 정도로 낮춰서 fine-tune 할 예정이다. 이를 위해 모델을 save해야한다.


그럼 모델을 load할 때 종속성 문제가 생길 수 있다. 위의 SeqSelfAttention 인식을 못 할 수 있는 것이다.


내가 안되었던 경우는 다음과 같다. 

from keras.models import load_model, Model
import tensorflow as tf
import os
import time
from keras_self_attention import SeqSelfAttention
global graph, model
graph = tf.get_default_graph()
### GPU Setting : Not Using GPU
os.environ["CUDA_VISIBLE_DEVICES"]="-1"

# Load Model
model = load_model('/data/Auditory_Emotion_Recognition/model_attention/fianl_emotion_model.h5')


코드를 보면 단지 model을 load하는데, Unknown layer라고 뜬다. 아래의 사진은 그 현상을 얘기한다.


즉 SeqSelfAttention을 import 하였는데도 이러한 문제가 생긴다.



이를 해결 하기 위해 model load시 다음과 같은 줄을 선언해주면 쉽게 해결할 수 있다.


model = load_model('/data/Auditory_Emotion_Recognition/model_attention/fianl_emotion_model.h5',custom_objects={'SeqSelfAttention':SeqSelfAttention})


custom_objects={'name':import_library_name}


위와 같이 custom_objects 를 선언해주면 사용 가능하다.




728x90
728x90

음성 데이터를 resampling 해야 할 경우가 있다. 


예를 들어 44.1kHz 에서 16000으로 변경을 해준다던지, 16000에서 22050으로 변경하여 음성 처리를 해줄 때가 있다.(Downsampling)


python에서 librosa 라이브러리를 이용하여 resampling을 간단히 해줄 수 있는데, 이 때 우분투에서 작업하던 음성 파일이 resampling 되고나서 librosa를 이용하여 그대로 저장을 하고 윈도우에서 그 음성을 다운받아서 확인해볼 때 읽히지 않을때가 있다.


결론적으로 말하자면, librosa 로 resample 이후에 soundfile의 write를 사용하여 저장하면 이 문제를 해결할 수 있다.



librosa.output.write_wav(output_dir+'.wav', data, sr) # 깨지는 현상 존재
sf.write(output_dir, data, sr, format='WAV', endian='LITTLE', subtype='PCM_16') # 깨지지 않음


위의 soundfile write내의 내용을 librosa write_wav의 내용을 그대로 넣어주면 된다.


728x90
728x90

음성 데이터(Speech, Sound 등)를 python을 이용하여 처리하여(sampling rate나 일정 부분을 자는 것 등) 저장하는 것을 해보려 한다.


사용하는 라이브러리는 librosa


우선 음성을 저장된 디렉토리로부터 불러온다. 

아래의 코드를 사용하여 불러오면 file_dir와 file_id가 출력이 된다.

wav = '/data/dataset/IEMOCAP_wavonly/IEMOCAP_Wavonly/Wav/Ses01F_impro01/Ses01F_impro01_F005.wav'
(file_dir, file_id) = os.path.split(wav)
print("file_dir:", file_dir)
print("file_id:", file_id)

- 결과

file_dir: /data/dataset/IEMOCAP_wavonly/IEMOCAP_Wavonly/Wav/Ses01F_impro01

file_id: Ses01F_impro01_F005.wav

Process finished with exit code 0



그 다음 이 음성 파일을 librosa로 불러올 것이다.

librosa는 별도로 sr(sampling rate)를 설정하지 않으면 default sr이 22500으로 되어있다.

내가 불러올 음성 파일은 이미 16000 sr이므로 반드시 sr=16000을 붙여주도록 한다.


y, sr = librosa.load(wav, sr=16000)
time = np.linspace(0, len(y)/sr, len(y)) # time axis

fig, ax1 = plt.subplots() # plot
ax1.plot(time, y, color = 'b', label='speech waveform')
ax1.set_ylabel("Amplitude") # y 축
ax1.set_xlabel("Time [s]") # x 축
plt.title(file_id) # 제목
plt.savefig(file_id+'.png')
plt.show()

이 음성 파일을 plot하여 그린 그림은 아래와 같다.




약 4초정도의 길이를 갖는 음성파일이다.


이 음성 파일의 절반만을 가져오고 다시 저장하는 단계를 해보겠다.


우선 아래의 코드를 통해 음성 신호를 절반만을 가져오고, 절반을 그려보도록 하자.


half = len(y)/2
y2 = y[:round(half)]
time2 = np.linspace(0, len(y2)/sr, len(y2))
fig2, ax2 = plt.subplots()
ax2.plot(time2, y2, color = 'b', label='speech waveform')
ax1.set_ylabel("Amplitude") # y 축
ax1.set_xlabel("Time [s]") # x 축
plt.title('cut '+file_id)
plt.savefig('cut_half '+file_id+'.png')
plt.show()


이 부분의 결과는 아래의 그림과 같다. 약 절반정도가 잘렸다.




이제 이 음성을 저장할건데, librosa 라이브러리를 사용하여 쉽게 저장할 수 있다. 


librosa.output.write_wav('cut_file.wav', y2, sr)


아래에서 기존 음성과 자른 부분의 음성을 비교해볼 수 있다.


Original 음성:  




절반 Cut 한 음성: 




전체 코드

import librosa
import os
import numpy as np
import matplotlib.pyplot as plt


wav = '/data/dataset/IEMOCAP_wavonly/IEMOCAP_Wavonly/Wav/Ses01F_impro01/Ses01F_impro01_F005.wav'
(file_dir, file_id) = os.path.split(wav)
print("file_dir:", file_dir)
print("file_id:", file_id)

# original
y, sr = librosa.load(wav, sr=16000)
time = np.linspace(0, len(y)/sr, len(y)) # time axis
fig, ax1 = plt.subplots() # plot
ax1.plot(time, y, color = 'b', label='speech waveform')
ax1.set_ylabel("Amplitude") # y 축
ax1.set_xlabel("Time [s]") # x 축
plt.title(file_id) # 제목
plt.savefig(file_id+'.png')
plt.show()
librosa.output.write_wav('original_file.mp3', y, sr) # original wav to save mp3 file

# cut half and save
half = len(y)/2
y2 = y[:round(half)]
time2 = np.linspace(0, len(y2)/sr, len(y2))
fig2, ax2 = plt.subplots()
ax2.plot(time2, y2, color = 'b', label='speech waveform')
ax1.set_ylabel("Amplitude") # y 축
ax1.set_xlabel("Time [s]") # x 축
plt.title('cut '+file_id)
plt.savefig('cut_half '+file_id+'.png')
plt.show()
librosa.output.write_wav('cut_file.mp3', y2, sr) # save half-cut file



728x90
728x90

오늘은 Keras로 구축해놓은 모델을 png나 jpg인 그림 포멧으로 저장하는 법에 대해 써볼까 한다.



우선 Keras 공식 홈페이지를 들어가서 plot_model library를 검색해본다.


https://keras.io/visualization/


들어가보면 맨 윗창에 Model Visualization이라고 나와 있다. 뜻 그대로 모델을 시각화 하겠다라는 뜻일듯.


예제에 나와 있는 것 처럼 그림으로 보고 싶은 모델을 불러온 뒤 예제처럼 코딩을 하면 저장이 된다.


나의 코드는 다음과 같다.


from keras.utils import plot_model


from keras.models import load_model
from keras_self_attention import SeqSelfAttention

model = load_model('/data/Auditory_Emotion_Recognition/model_attention/4emotions_auditory_cnn_model_self_GAP_pati50_epoch200_dropout0.2,relu_lr1e-05_8conv5dim+1GRU2FC_Zscore_lrdecay5.4e-08_acc:0.5498_test:_57.42.h5',custom_objects={'SeqSelfAttention':SeqSelfAttention})
plot_model(model, to_file='./model.png')


from keras.utils import plot_model: keras에서 모델을 그리기 위해 필요한 라이브러리 import


from keras.models import load_model: 저장된 모델을 불러오기 위한 라이브러리 import

from ~ SeqSelfAttention: SelfAttention을 보기 위한 라이브러리 import


model ~ -> 불러올 모델의 위치를 load_model을 통해 불러온 뒤 model로 선언


plot_model(model, to_file='./model.png'): model 을 그림으로 그리는 건데, 이 때 ./ 는 코드상의 디렉토리에 model.png 로 저장하겠다는 뜻이다.


저장된 모델은 다음과 같다.


728x90

+ Recent posts