2017년 12월 31일 일요일

Levinson-Durbin recursion

Matlab

levinson : Levinson-Durbin recursion

Syntax
a = levinson(r)
a = levinson(r, n)
[a, e] = levinson(r, n)
[a, e, k] = levinson(r, n)

Description
The Levinson-Durbin recursion is an algorithm for finding an all-pole IIR filter with a prescribed deterministic autocorrelation sequence. It has applications in filter design, coding, and spectral estimation. The filter that levinson produces is minimum phase.

a = levinson(r) finds the coefficients of a length(r)-1 order autoregressive linear process which has r as its autocorrelation sequence. r is a real or complex deterministic autocorrelation sequence. If r is a matrix, levinson finds the coefficients for each column of r and returns them in the rows of a. n=length(r)-1 is the default order of the denominator polynomial A(z); that is, a = [1 a(2) ... a(n+1)]. The filter coefficients are ordered in descending powers of z–1.

H(z) = 1/A(z)
A(z) = 1 + a(2)z^(−1) + ⋯ + a(n+1)z^(−n)

a = levinson(r,n) returns the coefficients for an autoregressive model of order n.
[a,e] = levinson(r,n) returns the prediction error, e, of order n.
[a,e,k] = levinson(r,n) returns the reflection coefficients k as a column vector of length n.

Example
>> data = [2, 2, 0, 0, -1, -1, 0, 0, 1, 1];
>> [r, lg] = xcorr(data, 'biased');
>> r(lg<0) = []
r =
1.2000  0.6000  0.0000  -0.3000  -0.6000  -0.3000  -0.0000  0.2000  0.4000  0.2000
>> [ar, e] = levinson(r, 3)
ar =
1.0000   -0.6250    0.2500    0.1250
e =
0.7875

출처 : <https://kr.mathworks.com/help/signal/ref/levinson.html>

Python

lazy_lpc Module : Linear Predictive Coding (LPC) module

github for AudioLazy : <https://github.com/danilobellini/audiolazy>
AudioLazy 0.6 Docs : <http://pythonhosted.org/audiolazy/index.html>

Module contents
ParCorError Error when trying to find the partial correlation coefficients (reflection
coefficients) and there’s no way to find them.
toeplitz Find the toeplitz matrix as a list of lists given its first line/column.
levinson_durbin Solve the Yule-Walker linear system of equations.
lpc This is a StrategyDict instance object called lpc. Strategies stored: 5.
parcor Find the partial correlation coefficients (PARCOR), or reflection
coefficients, relative to the lattice implementation of a given LTI FIR
LinearFilter with a constant denominator (i.e., LPC analysis filter, or
any filter without feedback).
parcor_stable Tests whether the given filter is stable or not by using the partial
correlation coefficients (reflection coefficients) of the given filter.
Find the Line Spectral Frequencies (LSF) from a given FIR filter.
lsf_stable Tests whether the given filter is stable or not by using the Line
Spectral Frequencies (LSF) of the given filter. Needs NumPy.

levinson_durbin(acdata, order=None)
acdata – Autocorrelation lag list, commonly the acorr function output.
order – The order of the resulting ZFilter object. Defaults to len(acdata) - 1.

Example
>>> data = [2, 2, 0, 0, -1, -1, 0, 0, 1, 1]
>>> acdata = acorr(data)
>>> acdata
[12, 6, 0, -3, -6, -3, 0, 2, 4, 2]
>>> ldfilt = levinson_durbin(acorr(data), 3)
>>> ldfilt
1 - 0.625 * z^-1 + 0.25 * z^-2 + 0.125 * z^-3
    >>> ldfilt.numerator
[1, - 0.625, 0.25, 0.125]
>>> ldfilt.error  # Squared! See lpc for more information about this
7.875


출처 : <http://pythonhosted.org/audiolazy/lazy_lpc.html#audiolazy.lazy_lpc.levinson_durbin>

2017년 12월 22일 금요일

파이썬 변수 명명 규칙 (PEP 8 -- Style Guide for Python Code)

PEP 8을 간단하게 요약하면

피해야 할 이름 :

  • 소문자 l, 대문자 O, 대문자 I하나만 변수의 이름으로 쓰는 것은 권장하지 않습니다. 특정 폰트에서 헷갈릴수도 있기 때문입니다.

패키지와 모듈의 이름 :

  • 모듈 이름은 짧아야 하고, 전부 소문자여야 합니다. 가독성을 위해서라면 밑줄(_)을 쓸 수 있습니다.
  • 패키지 이름 또한 짧아야 하고, 전부 소문자여야 합니다. 밑줄은 권장하지 않습니다

클래스 이름 :

  • 클래스 이름은 CapWords 형식(단어를 대문자로 시작)을 따릅니다

exception의 이름 :

  • exception은 클래스이므로, class와 동일하게 적용됩니다.
  • 다만, 맨 뒤는 "Error"로 끝나야 합니다.

전역변수의 이름 :
(전역 변수는 하나의 모듈 안에서만 쓰인다고 가정합니다)

  • 전역 변수의 이름을 짓는 것은 함수 이름을 짓는 것과 동일합니다.
  • from M import *과 같이 쓰일 모듈에서는 global이 export 될 것을 방지하기 위해 all`메커니즘이나 혹은 맨 앞을 밑줄로 시작해야 합니다.

함수의 이름 :

  • 함수의 이름은 원칙적으로 소문자여야 하고, 가독성을 위해서 밑줄(_)로 단어를 나눌 수 있습니다.
  • 간혹 threading.py같이 이미 대/소문자를 혼용하는 경우는 대/소문자를 같이 쓰는 경우도 있습니다.

함수와 메소드의 인자 :

  • 메소드 인스턴스에 쓰이는 첫 번째 인자는 무조건 self여야 합니다.
  • 클래스 메소드의 첫 번째 인자는 무조건 cls여야 합니다
  • 예약된 키워드(in 등)와 함수의 인자가 겹치는 경우, 변수 이름 맨 뒤에 밑줄 하나를 붙이는 것으로 대체합니다.(ex, class_)

메소드 이름과 인스턴스의 이름 :

  • 함수 이름과 동일합니다.
  • public이 아닌 메소드나 인스턴스의 이름은 밑줄로 시작합니다

상수의 이름 :

  • 상수 이름은 전부 대문자와 밑줄로 쓰는 것을 원칙으로 합니다.


출처: <http://hashcode.co.kr/questions/489/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C-%EB%B3%80%EC%88%98%ED%95%A8%EC%88%98-%EC%9D%B4%EB%A6%84%EC%9D%84-%EC%A7%80%EC%9D%84-%EB%95%8C-%EA%B7%9C%EC%B9%99%EC%9D%B4-%EC%9E%88%EB%82%98%EC%9A%94>

2017년 12월 20일 수요일

필터뱅크와 MFCC

Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What's In-Between

출처: <http://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html


이 글에서는 필터 뱅크와 MFCC에 대해 논의하고 필터 뱅크가 인기를 얻는 이유에 대해 설명한다.
필터뱅크를 계산하는 것과 MFCC를 계산하는 것은 어느 정도 같은 과정을 포함한다. 두 경우 모두 필터뱅크는 계산하여야 하고, 약간의 추가적인 스탭을 거쳐 MFCC를 얻을 수 있다.

간단히 말하면,

  1. pre-emphasis filtering: s1 = pre-emphasis filter(s)
  2. Framing and windowing: s12 = framing(s1), s2 = windowing(s21)
  3. Fourier transform and Power spectrum: s3 = fft(s2), s4 = p_spec(s3)
  4. Computation of the filterbank: s5 = cal_filterbank(s4)
  5. Discrete Cosine Transform: s6 = dct(s5)
  6. mean normalization:
         Filterbank = mean_norm(s5)
         MFCC = mean_norm(s6)


1. pre-emphasis filtering

고주파를 증폭킴으로써 얻을 수 있는 장점:
  1. 고주파 성분은 저주파 성분에 비해 크기가 작기 때문에 이를 통해 주파수 스팩트럼의 밸러스를 맞출 수 있다.
  2. 푸리에 변환 중 발생할 수 있는 수치 문제를 피할 수 있다.
  3. SNR을 개선할 수 있다.
필터 식 : y(t)=x(t)− αx(t−1), 일반적으로 α는 0.95 또는 0.97
파이썬 코드 : 
   pre_emphasis = 0.97
   emphasized_signal = numpy.append(signal[0], signal[1:] - pre_emphasis * signal[:-1])


2. Framing and Windowing
음성 신호는 nonstationary하므로 이를 한꺼번에 푸리에 변환하는 것은 의미가 없다. 일반적으로 음성 처리에서,
  1. 프레임 길이 : 20ms~40ms 
  2. 오버랩 : 50% (+/- 10%)
  3. 해밍윈도우
파이썬 코드:
   frame_size = 0.025   # 25ms
   frame_stride = 0.01  # 10ms hop-size == 15ms overlap
   # Convert from seconds to samples.
   frame_length, frame_step = frame_size * sample_rate, frame_stride * sample_rate  
   signal_length = len(emphasized_signal)
   frame_length = int(round(frame_length))
   frame_step = int(round(frame_step))
   # Make sure that we have at least 1 frame.
   num_frames = int(numpy.ceil(float(numpy.abs(signal_length - frame_length)) / 
                       frame_step))  

   pad_signal_length = num_frames * frame_step + frame_length
   z = numpy.zeros((pad_signal_length - signal_length))
   # Pad Signal to make sure that all frames have equal number of samples without 
   # truncating any samples from the original signal.
   pad_signal = numpy.append(emphasized_signal, z) 
   indices = numpy.tile(numpy.arange(0, frame_length), (num_frames, 1)) +             
                numpy.tile(numpy.arange(0, num_frames * frame_step, frame_step), 
                (frame_length, 1)).T
   frames = pad_signal[indices.astype(numpy.int32, copy=False)]
   # Hamming window
   frames *= numpy.hamming(frame_length)
   # Explicit Implementation **
   # frames *= 0.54 - 0.46 * numpy.cos((2 * numpy.pi * n) / (frame_length - 1))  


3. Fourier transform and Power spectrum
N-point FFT을 적용. 일반적으로 N = 256 또는 512를 사용
Power spectrum (periodogram) = |FFT(x_i)|^2 / N

파이썬 코드:
   NFFT = 512
   mag_frames = numpy.absolute(numpy.fft.rfft(frames, NFFT))  # Magnitude of the FFT
   pow_frames = ((1.0 / NFFT) * ((mag_frames) ** 2))               # Power Spectrum


4. Filterbanks
Mel 스케일의 Trianglar filter (일반적으로 40 filters)를 Power spectrum에 적용

Filterbanks on the Mel-scale
Mel과 Hz의 관계식:
   f = 700(10^(m∕2595)−1)
   m = 2595 log_10⁡(1+f/700)  

Filterbank 식:
Filterbanks equation
파이썬 코드:
   low_freq_mel = 0
   nfilt = 22
   # Convert Hz to Mel
   high_freq_mel = (2595 * numpy.log10(1 + (sample_rate / 2) / 700))  
   # Equally spaced in Mel scale
   mel_points = numpy.linspace(low_freq_mel, high_freq_mel, nfilt + 2)  
   # Convert Mel to Hz
   hz_points = (700 * (10**(mel_points / 2595) - 1))  
   bin = numpy.floor((NFFT + 1) * hz_points / sample_rate)
   fbank = numpy.zeros((nfilt, int(numpy.floor(NFFT / 2 + 1))))
   for m in range(1, nfilt + 1):
      f_m_minus = int(bin[m - 1])   # left
      f_m = int(bin[m])                # center
      f_m_plus = int(bin[m + 1])    # right
      for k in range(f_m_minus, f_m):
         fbank[m - 1, k] = (k - bin[m - 1]) / (bin[m] - bin[m - 1])
      for k in range(f_m, f_m_plus):
         fbank[m - 1, k] = (bin[m + 1] - k) / (bin[m + 1] - bin[m])

   filter_banks = numpy.dot(pow_frames, fbank.T)
   # Numerical Stability
   filter_banks = numpy.where(filter_banks == 0, numpy.finfo(float).eps, filter_banks)  
   filter_banks = 20 * numpy.log10(filter_banks)  # dB


5. Mel-frequency Cepstral Coefficients (MFCCs)
이전 단계에서 계산한 필터 뱅크 계수는 상관도가 매우 높기때문에 머신러닝 알고리듬에서 문제가 될 수도 있다고 알려져있다. 따라서 필터 뱅크 계수의 상관도를 줄이기위해 DCT를 적용한다. 그러면 압축된 필터뱅크의 형태를 얻을 수 있다. 일반적으로 음성 인식에서는 2-13개만 남기고 나머지는 버린다.  이유는 나머지의 계수가 음성 인식에 크게 기여하지 못하기 때문이다. 
                                                                  
파이썬 코드:
   num_ceps = 12
   # Keep 2-13
   mfcc = dct(filter_banks, type=2, axis=1, norm='ortho')[:, 1 : (num_ceps + 1)] 
   (nframes, ncoeff) = mfcc.shape
   n = numpy.arange(ncoeff)
   lift = 1 + (cep_lifter / 2) * numpy.sin(numpy.pi * n / cep_lifter)
   mfcc *= lift  #*

6. Mean Normalization
스팩트럼의 밸런스를 유지하고 SNR을 향상시키기 위한 것으로, 모든 프레임에서 각 계수의 평균을 빼기만하면 된다.
                                                               
파이썬 코드:
   filter_banks -= (numpy.mean(filter_banks, axis=0) + 1e-8)
   mfcc -= (numpy.mean(mfcc, axis=0) + 1e-8)


Filterbanks vs. MFCC

필터뱅크를 계산하는 모든 과정은 음성신호와 인간의 인지에 대한 본성을 동기로 삼는다.
MFCC를 위한 추가적인 계산 과정은 머신러닝 알고리즘의 한계가 동기가 되었다.
MFCC에서 DCT는 필터뱅크 계수간의 상관도를 낮추는 과정으로 화이트닝(whitening)으로 간주된다. GMM-HMM이 유행할 때 MFCC도 유행하였다.
특히 MFCC와 GMMs-HMMs이 공동으로 자동음성인식의 표준기법 발전한 경우 매우 인기가 있었다.
음성인식 시스템에 딥러닝을 적용하는 요즘에는 상관도가 높은 입력에 덜 민감한 딥뉴럴네트워크에 과연 MFCC가 옳은 선택인가를 생각해볼 필요가 있다. 선형 변환인 DCT로 인해 비선형성이 강한 음성의 일부 정보가 사라지는 것은 바라는 바가 아니다.

푸리에 변환도 과연 필요한가?라는 질문도 할 수 있다. 푸리에 변환도 선형 변환이기 때문에 이를 무시하고 시간 영역의 신호를 직접 학습하는 것도 좋을 것이다. 사실 이미 이에 대한 긍정적인 연구 결과가 발표되었다.


결론

머신러닝 알고리즘이 상관도가 높은 입력에 영향을 받지 않는다면 Mel-scaled 필터뱅크를 사용하고,
머신러닝 알고리즘이 상관도가 높은 입력에 영향을 받기 쉬운 환경이라면 MFCC를 사용하라.


2017년 12월 18일 월요일

Tensorboard 사용시 발생할 수 있는 현상

1. No scalar data was found.

텐서보드가 윈도우에서 동작할 때 발생할 수 있는 현상중 logdir과 관련된 것일 수 있다.
디렉토리 경로를 나타내는 ":\"을 정상적으로 인식하지 못하는 경우가 있다고 한다.
이를 해결하기 위한 방법은 2가지가 있는데,
     (1) logdir의 위치에서 텐서플로를 동작시키는 방법
     (2) logdir표기법을 다음과 같이 하는 방법 :
            --logdir foo:D:\some\path (동작한다고 한다.)
            --logdir D:\some\path      (동작하지 않는다고 한다.) 

[참고] Tensorboard has wrong logdir on Windows #54 

위 두 가지 중 한 가지 방법을 사용을 했는데도 해결하지 못했다면 작업 경로를 확인할 필요가 있다. 나의 경우 (1)의 방법을 적용하고 있는데 동작하지 않았다. 그래서 현재 작업 경로를 살펴보았더니 한글이 포함되어있었다. 혹시나 하는 마음으로 영문으로만 된 경로에 파일을 복사하고 실행시켰더니 동작이 되었다.

2. with tf.name_scope로 그룹화 했는데 [GRAPH]에서는 아무것도 보이지 않는다.

난감하네.

2017년 12월 7일 목요일

파이썬에는 switch문이 없다.

파이썬의 조건문에는 C언어의 switch-case문이 없다. 대체할 수 있는 방법은 두 가지이다.
(1) 조건문 if-elif-else문 사용
(2) 딕셔너리(dictionary)를 이용


1. 조건문 if-elif-else문 사용

  (생략)


2. 딕셔너리(dictionary)를 이용

딕셔너리는 키로 색인되는 객체들을 담는 연관 배열 혹은 해시테이블이다. 아래와 같이 값들을 중괄호로 둘러싸서 딕셔너리를 생성한다.

stock = { "name" : "GOOG", "shares" : 100, "price" : 490.10 }

딕셔너리의 요소에 접근하려면 키 색인 연산자를 다음과 같이 사용한다.

name = stock["name"]
value = stock["shares"] * stock["price"]

객체의 추가 및 수정은 다음과 같이 수행한다.

stock["share"] = 75    # 객체 수정
stock["date"] = "June 7, 2007"

딕셔너리의 키는 주로 문자열을 사용하지만, 숫자나 튜플 같은 다른 파이썬 객체도 키로 사용될 수 있다. 다만 리스트나 딕셔너리 같이 그 내용이 바뀔 수 있는 객체는 키로 사용할 수 없다.          출처: <파이썬 완벽 가이드, 인사이트>

딕셔너리의 요소에 접근하는 방법이 switch문과 유사하여 이를 이용하면 간단한 값을 리턴 받는 경우에는 사용이 가능하다.

{1: "First", 2: "Second", 3: "Third"}[number]

위 코드에서 number가 1이면 "First"가 2이면 "Second", 3이면 "Third"가 반환된다.
이렇게 간단한 경우에는 좋지만 각 조건마다 여러 줄의 코드가 수행되어야 하는 경우라면 if-elif-else문이 타당하다. 적어도 난 그렇게 생각한다.

검색해보니 아래와 같이 딕셔너리 객체에 람다식(lambda)을 사용해서 switch의 case문에서 여러 줄의 코드가 수행될 수 있도록 한 경우도 있었다. 머리 좋네.

링크: <https://codingair.wordpress.com/2014/02/11/use-python-to-do-switch-case/>


2017년 12월 6일 수요일

두서없이 써본 파이썬 Numpy functions

reshape(A, (row,col))
     A를 (row,col)사이즈로 변환, row=-1이면 col에 맞게 자동 변환

where(numpy.array == value)
     numpy.array에서 value의 인덱스를 알려준다. list.index와 같은 기능

ramdom.shuffle(array)
     array를 랜덤하게 섞는다. 이 함수는 머신러닝에서 데이터를 학습시킬 때 편향되지 않은 학습을 시키기위해 사용된다.  하나의 array를 랜덤하게 섞을 때는 이 함수를 그대로 사용하면 되지만 두 개의 array을 같은 순서로 섞고자 한다면 각각 섞어서는 안된다.

x = np.array([1, 3, 5, 7, 9])
y = np.array([1, 3, 5, 7, 9])
np.random.shuffle(x)
np.random.shuffle(y)
print("x: ", x, "y: ", y)

(결과)   x:  [9 7 1 3 5] y:  [5 1 9 7 3]

이 경우 아래와 같이 인덱스를 나타내는 array가 하나 더 필요하다.

x = np.array([1, 3, 5, 7, 9])
y = np.array([1, 3, 5, 7, 9])
idx = np.arange(x.shape[0])
np.random.shuffle(idx)
x = x[idx]
y = y[idx]
print("x: ", x, "y: ", y)

(결과)   x:  [9 1 3 7 5] y:  [9 1 3 7 5]

tile(A, reps)
     A를 여러개 반복적으로 만들어 하나의 행렬로 만드는 기능
     A : 반복하고자 하는 값 또는 행렬
     reps : A를 반복하는 횟수

argsort
     오름차순 정렬된 인덱스 반환





File/Directory 다루기

1. 특정 디렉토리의 파일 목록 가져오기

import os

dirPath = "./directory_name/subDirectory_name"    # 파일이 들어있는 디렉토리
fileList = os.listdir(dirPath)    # 해당 디렉토리에 있는 파일 목록을 만든다.

fileList는 해당 디렉토리에 존재하는 파일명을 갖는 리스트이다.


2. 특정 디렉토리 내에 있는 여러 파일들 중에서 특정 문자열을 포함한 파일 목록 가져오기

import glob

dirPath = ".\\directory_name\\subDirectory_name\\"
fileList0 = glob.glob(dirPath + "*")         # 모든 파일 목록
fileList1 = glob.glob(dirPath + "*.txt")     # 확장자가 txt인 파일 목록
fileList2 = glob.glob(dirPath + "*str*.txt") # 이름에 str"을 포함하고 확장자가 txt인 파일
fileList3 = glob.glob("*str*.txt")              # 이름에 str"을 포함하고 확장자가 txt인 파일

fileList0 ~ fileList2는 파일 경로와 파일명을 모두 포함하는 리스트이고 fileList3은 fileList2와 같은 조건이나 파일 경로를 따로 지정하지 않았기 때문에 현재 디렉토리인 경우에 해당한다. 이 경우 fileList3은 현재 디렉토리에 존재하는 파일명만 갖는 리스트이다.


3. 파일 경로가 파일명과 같이 저장된 목록에서 파일명만 뽑아내기

위의 예에서 fileList0 ~ fileList2는 파일 경로와 파일명을 모두 포함하는 리스트이다. 이 경우 파일 이름만 뽑아내기 위해서는 다음과 같이 한다.

filenameList0 = []
for k in range(len(fileList0))
     filenameList.append(os.path.basename(fileList0(k)))


Plotly Python Library를 이용한 plotting


Getting Started with Plotly for Matplotlib

Plotly's Matplotlib graphing library makes interactive, publication-quality graphs online. Examples of how to make line plots, scatter plots, area charts, bar charts, error bars, box plots, histograms, heatmaps, subplots, multiple-axes, polar charts, and bubble charts.



출처: <https://plot.ly/matplotlib/getting-started/> <https://plot.ly/python/>

2017년 12월 5일 화요일

Interpolation in Python

scipy는 간단한 단일변수(univariate)부터 복잡한 복수변수(multivariate)를 망라하는 보간법 함수를 15개 이상 제공한다.

1. 단일 변수

보간법은 두 가지의 기본적인 방법을 사용한다.
(1) 전체 데이터 집합에 단일 함수 적용하는 방법
(2) 여러 개의 함수를 각기 다른 데이터 집합에 적용하는 방법 (스플라인 보간법)

import numpy as np
from scipy.interpolate import interp1d

x = np.linspace(0, 10*np.pi, 20)
y = np.cos(x)

fl = interp1d(x, y, kind = 'linear')
fq = interp1d(x, y, kind = 'quadratic')

xint = np.linspace(x.min(), x.max(), 1000)
yintl = fl(xint)
yintq = fq(xint)

노이즈가 포함된 데이터의 보간법

from scipy.interpolate import UnivariateSpline

sample = 30
x = np.linspace(1, 10*np.pi, sample)
y = np.cos(x) + np.log10(x) + np.random.randn(sample)/10

f = UnivariateSpline(x, y, s=1)

xint = np.linspace(x.min(), x.max(), 1000)
yint = f(xint)

2. 복수 변수

영상 복구에 사용되기도 한다.

from scipy.interpolate import griddata
from scipy.interpolate import SmoothBivrateSpline as SBS

영상에 두 가지 방법을 각각 적용하여 결과를 비교하면 SmoothBivrateSpline이 더 잘 동작하는 것처럼 보일때가 있는데, 코드를 여러번 실행해 비교해 보길 바란다. SmoothBivrateSpline은 표본에 민감해 보간법을 적용한 결과가 이상한 경우도 있다. griddata는 좀 더 안정적이어서 표본 선택과 관계없이 타당한 결과를 얻을 수 있다.


출처: <데이터/수치 분석을 위한 파이썬 라이브러리  SciPy와 NumPy (한빛미디어)>

Matplotlib을 이용한 파이썬 plotting

파이썬에서 그래프를 여러개 그려야할 때
(1) 하나의 창에 여러개의 그래프를 그리는 방법과
(2) 각각의 그래프를 각각의 창에 그리는 경우가 있을 수  있다.


1. 하나의 창에 여러개의 그래프를 그리는 방법 : subplot

import matplotlib.pyplot as plt
import numpy as np

csvData = np.loadtxt(Filename, delimiter=',' )
timeData = csvData[0:len(csvData)]

fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
ax1.plot(timeData, label='sound data')
ax1.legend()

timeData = (timeData - np.mean(timeData))/maxSampleValue

ax2.plot(timeData, label='normalized sound data')
ax2.legend()
fig.show()


2. 각각의 그래프를 각각의 창에 그리는 경우

방법 #1
x = np.arange(5)
y = np.exp(x)
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.plot(x, y)

z = np.sin(x)
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
ax2.plot(x, z)

w = np.cos(x)
ax1.plot(x, w)  # can continue plotting on the first axis

방법 #2
x = arange(5)
y = np.exp(x)
plt.figure(0)
plt.plot(x, y)

z = np.sin(x)
plt.figure(1)
plt.plot(x, z)

w = np.cos(x)
plt.figure(0)   # Here's the part I need
plt.plot(x, w)

Edit: Note that you can number the plots however you want (here, starting from 0) but if you don't provide figure with a number at all when you create a new one, the automatic numbering will start at 1 ("Matlab Style" according to the docs).

출처: <https://stackoverflow.com/questions/6916978/how-do-i-tell-matplotlib-to-create-a-second-new-plot-then-later-plot-on-the-o>


2017년 12월 4일 월요일

UnicodeDecodeError: 'cp949'


data = np.loadtxt('./data.csv', delimiter=',', unpack=True, dtype='float32')

UnicodeDecodeError: 'cp949' codec can't decode byte 0xbf in position 2: illegal multibyte sequence

파이썬 3에서는 ANSI형식으로 저장된 파일만 읽을 수 있다.
open() 함수를 이용하여 파일을 읽어오는 경우라면 다음과 같이 'utf-8'을 추가하여 해결할 수 있다.

fID = open('./data.csv', 'r', 'utf-8')

하지만 numpy의 loadtxt()를 이용하여 읽는 경우는 encoding 옵션이 없기때문에 파일 자체를 ANSI형식으로 저장해야한다.
메모장에서 해당 파일을 열고 > 다른 이름으로 저장하기 > 인코딩을 ANSI로 선택하여 저장한다.

2017년 12월 3일 일요일

checkpoint file

체크포인트 파일(checkpoint file)은 학습된 모델을 저장한 파일을 일컫는다.

1. 체크포인트 파일 저장하기

최적화가 끝난 후 학습된 변수들을 체크포인트 파일에 저장한다.

     save.save(sess, './model/myNetwork.ckpt', global_step = total_step)

두 번째 인수는 체크포인트 파일이 저장될 위치와 체크포인트 파일의 이름을 의미하며, 체크포인트가 저장될 디렉토리(이 경우는 './model')는 미리 만들어져 있어야 한다.
세 번째 인수의 global_step의 값은 텐서 변수 또는 숫자 값을 넣을 수 있으며, 저장할 파일의 이름에 추가로 붙게되어 여러 상태의 체크포인트를 만들 수 있고, 가장 효과적인 모델을 선별하여 사용할 수 있다.

2. 체크포인트 파일 불러오기

./model이라는 디렉토리에 기존에 학습해둔 파일이 있는지 확인한다.

     ckpt = tf.train.get_checkpoint_state('./model')

모델이 있다면 saver.restore() 함수를 이용하여 학습된 값들을 불러오고, 아니면 변수를 새로 초기화한다.

     if ckpt and tf.train.checkpoint_exist(ckpt.model_checkpoint_path):
          saver.restore(sess, ckpt.model_checkpoint_path)
     else:
          sess.run(tf.global_variables_initializer())

3. 주의사항(?)

나만 멍청한 짓을 했나보다. 책을 보고 따라하다보니 체크포인트 파일을 저장하는데는 문제가 없었다. 일단 학습을 끝내고 체크포인트 파일에 저장하니 해당 폴더에 체크포인트 파일이 저장된 것을 확인할 수 있었다. 아래와 같이 첫 번째 실행은 정상적으로 잘 동작하였다.

runfile('C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3/golbin_checkpoint.py', wdir='C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3')
Step: 1 Cost: 0.735
Step: 2 Cost: 0.708
Prediction Value :  [0 1 2 0 0 2]
Target Value :  [0 1 2 0 0 2]
Accuracy : 100.00

이제 저장된 체크포인트 파일을 불러와서 모델을 실행시켜보고자 스크립를 'run'하였다.
스크립트의 두 번째 실행이었다. 아래와 같은 Error가 반겨주었다.

runfile('C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3/golbin_checkpoint.py', wdir='C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3')
INFO:tensorflow:Restoring parameters from ./model\dnn.ckpt-2
Traceback (most recent call last):

  File "<ipython-input-4-b4971a68fef7>", line 1, in <module>
    runfile('C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3/golbin_checkpoint.py', wdir='C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3')
<중략>
  File "C:\Users\Thriving_Zinnias\Anaconda3\envs\TF-35\lib\site-packages\tensorflow\python\client\session.py", line 1152, in _do_call
    raise type(e)(node_def, op, message)

NotFoundError: Key global_step_2 not found in checkpoint
[[Node: save_2/RestoreV2_35 = RestoreV2[dtypes=[DT_INT32], _device="/job:localhost/replica:0/task:0/cpu:0"](_arg_save_2/Const_0_0, save_2/RestoreV2_35/tensor_names, save_2/RestoreV2_35/shape_and_slices)]]

Caused by op 'save_2/RestoreV2_35', defined at:
  File "C:\Users\Thriving_Zinnias\Anaconda3\envs\TF-35\lib\site-packages\spyder\utils\ipython\start_kernel.py", line 241, in <module>
    main()
<중략>
  File "C:\Users\Thriving_Zinnias\Anaconda3\envs\TF-35\lib\site-packages\tensorflow\python\framework\ops.py", line 1269, in __init__
    self._traceback = _extract_stack()

NotFoundError (see above for traceback): Key global_step_2 not found in checkpoint
[[Node: save_2/RestoreV2_35 = RestoreV2[dtypes=[DT_INT32], _device="/job:localhost/replica:0/task:0/cpu:0"](_arg_save_2/Const_0_0, save_2/RestoreV2_35/tensor_names, save_2/RestoreV2_35/shape_and_slices)]]

이것때문에 몇시간을 허비하였다. 문제는 스크립트를 실행시키면 해당 내용이 커널에 계속 남아 있는다는 것이다. 이게 문제일거라고는 생각도 못했다.
커널을 재시작하고, 스크립트를 'run'하였더니 아래와 같이 잘 되었다. 모델을 불러와서 정상적으로 동작하면 화면에 나타나게 했던 'Trained model has been loaded.'가 보인다.

runfile('C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3/golbin_checkpoint.py', wdir='C:/Users/Thriving_Zinnias/AnacondaProjects/spyder-py3')
INFO:tensorflow:Restoring parameters from ./model\dnn.ckpt-2
Trained model has been loaded.
Step: 3 Cost: 0.704
Step: 4 Cost: 0.680
Prediction Value :  [0 1 2 0 0 2]
Target Value :  [0 1 2 0 0 2]
Accuracy : 100.00


CSV 파일 읽기

방법 #1
1.  파이썬에 기본으로 내장된 csv 모듈을 import한다.
2. open() 함수로 csv파일을 연다.
3. csv.reader() 함수로 한 line 단위로 읽어온다.
4. for문을 이용하여 파일 전체를 읽어들인다.

방법 #2
1. numpy를 import한다.
2. numpy.loadtxt() 함수를 이용하여 데이터를 읽어들인다.
   (ex) import numpy as np
         data = np.loadtxt('testdata.csv', delimiter = ',')

"데이터/수치 분석을 위한 파이썬 라이브러리 SciPy와 NumPy" (한빛미디어)를 보다가 알게되었는데, 위 두 방법은 처리해야할 데이터의 크기가 커지면 성능면에서 차이를 보인다고 한다.
책의 내용을 인용하면,

...
이렇게 데이터에 접근하고 기록하는 방식(방법 #1)은 유연하고 빠르지만, 한 가지 단점이 있다. 만일 파일의 크기가 크다면 데이터 접근과 처리가 느릴 수 있다. 이때는 numpy.ndarray로 데이터를 직접 가져오는 것이 가장 좋으며, numpy의 loadtxt함수로 이를 할 수 있다. 데이터가 행과 열로 되어 있으면 값들이 정수나 부동소수 같은 비슷한 형식으로 구성되어 있는 한 아주 잘 동작한다. numpy.savetxt로 numpy.loadtxt와 마찬가지로 쉽고 빠르게 데이터를 저장할 수 있다.
....

2017년 12월 2일 토요일

InvalidArgumentError

데이터를 제대로 feed하지 못하여 발생한 어처구니없는 'InvalidArgumentError'
trainMLP->CrossEntropy->targetClass,predictClass->Layer->inputData
즉, 입력으로 feed해야할 데이터는 inputData, targetClass의 placeholder에 할당되어야 한다.

inputData    = tf.placeholder('float')#, shape = (1,numFeatures))
predictClass = tf.placeholder('float')#, shape = (1,numClass))
targetClass  = tf.placeholder('float')#, shape = (1,numClass))
print(targetClass)

Tensor("Placeholder_17:0", dtype=float32)
...
Layer = tf.add(tf.matmul(inputData, W), b)
predictClass = tf.nn.softmax(Layer)
crossEntropy = -tf.reduce_sum(targetClass * tf.log(predictClass))
optimizer = tf.train.GradientDescentOptimizer(learning_rate = 0.01)
trainMLP = optimizer.minimize(crossEntropy)
...
while True:
    sess.run(trainMLP, feed_dict={inputData: Features, predictClass: Classes})
    if (step+1) % 10 == 0:
        print(step+1, sess.run(crossEntropy, feed_dict={inputData: Features, predictClass: Classes}))
    if step > maxIteration:
        break
    step += 1

---------------------------------------------------------------------------
InvalidArgumentError                      Traceback (most recent call last)
~\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\client\session.py in _do_call(self, fn, *args)
   1138     try:
-> 1139       return fn(*args)
   1140     except errors.OpError as e:

~\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\client\session.py in _run_fn(session, feed_dict, fetch_list, target_list, options, run_metadata)
   1120                                  feed_dict, fetch_list, target_list,
-> 1121                                  status, run_metadata)
   1122 

~\Anaconda3\envs\tf35\lib\contextlib.py in __exit__(self, type, value, traceback)
     87             try:
---> 88                 next(self.gen)
     89             except StopIteration:

~\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\framework\errors_impl.py in raise_exception_on_not_ok_status()
    465           compat.as_text(pywrap_tensorflow.TF_Message(status)),
--> 466           pywrap_tensorflow.TF_GetCode(status))
    467   finally:

InvalidArgumentError: You must feed a value for placeholder tensor 'Placeholder_17' with dtype float
  [[Node: Placeholder_17 = Placeholder[dtype=DT_FLOAT, shape=<unknown>, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

During handling of the above exception, another exception occurred:

InvalidArgumentError                      Traceback (most recent call last)
<ipython-input-41-a95816e42cf9> in <module>()
      1 while True:
----> 2     sess.run(trainMLP, feed_dict={inputData: Features, predictClass: Classes})
      3     if (step+1) % 10 == 0:
      4         print(step+1, sess.run(crossEntropy, feed_dict={inputData: Features, targetClass: Classes}))
      5     if step > maxIteration:

~\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\client\session.py in run(self, fetches, feed_dict, options, run_metadata)
    787     try:
    788       result = self._run(None, fetches, feed_dict, options_ptr,
--> 789                          run_metadata_ptr)
    790       if run_metadata:
    791         proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)

~\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\client\session.py in _run(self, handle, fetches, feed_dict, options, run_metadata)
    995     if final_fetches or final_targets:
    996       results = self._do_run(handle, final_targets, final_fetches,
--> 997                              feed_dict_string, options, run_metadata)
    998     else:
    999       results = []

~\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\client\session.py in _do_run(self, handle, target_list, fetch_list, feed_dict, options, run_metadata)
   1130     if handle is None:
   1131       return self._do_call(_run_fn, self._session, feed_dict, fetch_list,
-> 1132                            target_list, options, run_metadata)
   1133     else:
   1134       return self._do_call(_prun_fn, self._session, handle, feed_dict,

~\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\client\session.py in _do_call(self, fn, *args)
   1150         except KeyError:
   1151           pass
-> 1152       raise type(e)(node_def, op, message)
   1153 
   1154   def _extend_graph(self):

InvalidArgumentError: You must feed a value for placeholder tensor 'Placeholder_17' with dtype float
  [[Node: Placeholder_17 = Placeholder[dtype=DT_FLOAT, shape=<unknown>, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

Caused by op 'Placeholder_17', defined at:
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\ipykernel_launcher.py", line 16, in <module>
    app.launch_new_instance()
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\traitlets\config\application.py", line 658, in launch_instance
    app.start()
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\ipykernel\kernelapp.py", line 477, in start
    ioloop.IOLoop.instance().start()
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\zmq\eventloop\ioloop.py", line 177, in start
    super(ZMQIOLoop, self).start()
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tornado\ioloop.py", line 888, in start
    handler_func(fd_obj, events)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tornado\stack_context.py", line 277, in null_wrapper
    return fn(*args, **kwargs)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\zmq\eventloop\zmqstream.py", line 440, in _handle_events
    self._handle_recv()
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\zmq\eventloop\zmqstream.py", line 472, in _handle_recv
    self._run_callback(callback, msg)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\zmq\eventloop\zmqstream.py", line 414, in _run_callback
    callback(*args, **kwargs)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tornado\stack_context.py", line 277, in null_wrapper
    return fn(*args, **kwargs)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\ipykernel\kernelbase.py", line 283, in dispatcher
    return self.dispatch_shell(stream, msg)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\ipykernel\kernelbase.py", line 235, in dispatch_shell
    handler(stream, idents, msg)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\ipykernel\kernelbase.py", line 399, in execute_request
    user_expressions, allow_stdin)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\ipykernel\ipkernel.py", line 196, in do_execute
    res = shell.run_cell(code, store_history=store_history, silent=silent)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\ipykernel\zmqshell.py", line 533, in run_cell
    return super(ZMQInteractiveShell, self).run_cell(*args, **kwargs)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\IPython\core\interactiveshell.py", line 2728, in run_cell
    interactivity=interactivity, compiler=compiler, result=result)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\IPython\core\interactiveshell.py", line 2850, in run_ast_nodes
    if self.run_code(code, result):
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\IPython\core\interactiveshell.py", line 2910, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-32-6f3ef8777c4a>", line 3, in <module>
    targetClass  = tf.placeholder('float')#, shape = (1,numClass))
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\ops\array_ops.py", line 1530, in placeholder
    return gen_array_ops._placeholder(dtype=dtype, shape=shape, name=name)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\ops\gen_array_ops.py", line 1954, in _placeholder
    name=name)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\framework\op_def_library.py", line 767, in apply_op
    op_def=op_def)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\framework\ops.py", line 2506, in create_op
    original_op=self._default_original_op, op_def=op_def)
  File "C:\Users\Sangjin Cho\Anaconda3\envs\tf35\lib\site-packages\tensorflow\python\framework\ops.py", line 1269, in __init__
    self._traceback = _extract_stack()

InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor 'Placeholder_17' with dtype float
  [[Node: Placeholder_17 = Placeholder[dtype=DT_FLOAT, shape=<unknown>, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

2017년 11월 30일 목요일

두서없이 써본 파이썬 built-in functions

locals()
     현재 범위에서 사용할 수 있는 이름들을 반환한다.

reset -sf
     메모리에 있는 모든 변수를 삭제한다.

pow(a,b)
     a의 b승. a**b와 같다.

run
     ipython console창에서 파이썬 스크립트를 실행시킨다.
     (예) In [1]: run gogoletsgo.py

sorted
     입력값을 오름차순으로 정렬한 후 리스트로 반환

2017년 11월 29일 수요일

파일 입출력

파이썬의 기본 입력 매커니즘은 라인을 기반으로 한다. 데이터를 텍스트 파일에서 프로그램으로 읽어들이면 한 번에 한 라인씩 가져온다.

     data = open('head_first.txt')
     print(data.readline(), end='')
   
open으로 연 파일은 한 라인씩 읽어들이는 것이 기본이고, readline() 메서드로 파일에서 한 라인을 읽어 올 수 있다.
print 함수는 기본적으로 줄바꿈을 수행하지만 줄을 바꾸지 않으려면 end=''을 사용한다.


open() : 파일을 읽고 쓰기위해 아래의 모드를 지정해야 한다.
            r : 읽기 모드. 기본 모드이므로 생략 가능하다.
            w : 쓰기 모드. 기존에 파일이 있었다면 모든 내용이 지워진다.
            w+ : 파일의 내용을 지우지 않고 읽고 쓰기 위한 모드
            a : 파일의 끝에 추가하기 위한 모드
             

print() : 데이터를 파일로 출력하기 위해서 file 인자에 데이터 파일 객체를 지정해야 한다.
           fID = open('data.out', 'w')
           print('Nothing changes unless you change yourself.', file = fID)

문자열 매서드

strip()  문자열 앞뒤의 불필요한 공백을 제거

2017년 11월 28일 화요일

Spectral flatness

Spectral flatness or tonality coefficient,[1][2] also known as Wiener entropy,[3][4] is a measure used in digital signal processing to characterize an audio spectrum. Spectral flatness is typically measured in decibels, and provides a way to quantify how noise-like a sound is, as opposed to being tone-like.[2]

The meaning of tonal in this context is in the sense of the amount of peaks or resonant structure in a power spectrum, as opposed to flat spectrum of a white noise. A high spectral flatness (approaching 1.0 for white noise) indicates that the spectrum has a similar amount of power in all spectral bands — this would sound similar to white noise, and the graph of the spectrum would appear relatively flat and smooth. A low spectral flatness (approaching 0.0 for a pure tone) indicates that the spectral power is concentrated in a relatively small number of bands — this would typically sound like a mixture of sine waves, and the spectrum would appear "spiky".[5]
The spectral flatness is calculated by dividing the geometric mean of the power spectrum by the arithmetic mean of the power spectrum, i.e.:


where x(n) represents the magnitude of bin number n. Note that a single (or more) empty bin yields a flatness of 0, so this measure is most useful when bins are generally not empty.
The ratio produced by this calculation is often converted to a decibel scale for reporting, with a maximum of 0 dB and a minimum of ∞ dB.
The spectral flatness can also be measured within a specified subband, rather than across the whole band.


출처: <https://en.wikipedia.org/wiki/Spectral_flatness

Spectral centroid

The spectral centroid is a measure used in digital signal processing to characterise a spectrum. It indicates where the "center of mass" of the spectrum is. Perceptually, it has a robust connection with the impression of "brightness" of a sound.[1]

It is calculated as the weighted mean of the frequencies present in the signal, determined using a Fourier transform, with their magnitudes as the weights:[2]


where x(n) represents the weighted frequency value, or magnitude, of bin number n, and f(n) represents the center frequency of that bin.


출처: <https://en.wikipedia.org/wiki/Spectral_centroid

람다 표현식 (Lambda expression)

람다 표현식(Lambda expression)  람다 표현식으로 함수를 정의하고, 이를 변수에 할당하여 변수를 함수처럼 사용한다. (1) 람다 표현식       lambda <매개변수> : 수식      ※ 람다식을 실행하...