2013-04-13 3 views
2

Как преобразовать MATLAB's quantiz function (где xd - затухающий сигнал) в python/scipy?Преобразование функции квантования в python

Я пытаюсь реализовать алгоритм, который я разработал в MATLAB для обработки речи в программном пакете с использованием python и библиотек, таких как scipy, numpy, pygtk и matplotlib, чтобы преобразовать алгоритм в полный пакет.

Я использую SciPy для разработки алгоритмов, но я не могу найти подходящую функцию «квантование сигнала» в Python:

[I,xq] = quantiz(xd,1:step:1-step, -1:step:1); 

Как я пишу это в Python?

+0

Распознавание речи в речь - это * невероятно широкое поле. Есть целые компании, которые выделяют миллиарды в капитале только на это. Если вы не можете предоставить некоторые конкретные реализации/части, где вы застряли, подождите некоторое время, пока вы не зададите этот вопрос. Он слишком широк. – Makoto

+0

@ Makoto: Я думаю, что они указали конкретную часть, где они застревают: им нужен эквивалент функции 'quantiz' MATLAB. – icktoofay

ответ

2

Рассматривая документацию, это довольно простая функция, которую довольно легко написать в Python. Я переименовал функцию, чтобы добавить отсутствующий ‘ e ’, потому что это меня раздражало. В любом случае:

def quantize(signal, partitions, codebook): 
    indices = [] 
    quanta = [] 
    for datum in signal: 
     index = 0 
     while index < len(partitions) and datum > partitions[index]: 
      index += 1 
     indices.append(index) 
     quanta.append(codebook[index]) 
    return indices, quanta 

Попытка это на примере в документации:

>>> index, quants = quantize([3, 34, 84, 40, 23], range(10, 90, 10), range(10, 100, 10)) 
>>> index 
[0, 3, 8, 3, 2] 
>>> quants 
[10, 40, 90, 40, 30] 

Для немного более эффективным, но менее гибкий вариант, мы можем обойти диапазоны и просто использовать математику:

from __future__ import division 
import math 

def opt_quantize(signal, num_quanta, partition_start, partition_step, 
       codebook_start, codebook_step): 
    indices = [] 
    quanta = [] 
    for datum in signal: 
     index = int(math.floor((datum - partition_start)/partition_step + 1)) 
     if index < 0: 
      index = 0 
     if index >= num_quanta: 
      index = num_quanta - 1 
     indices.append(index) 
     quanta.append(codebook_start + codebook_step * index) 
    return indices, quanta 

Пробуя его на примере в документации:

>>> index, quants = opt_quantize([3, 34, 84, 40, 23], 9, 10, 10, 10, 10) 
>>> index 
[0, 3, 8, 4, 2] 
>>> quants 
[10, 40, 90, 50, 30] 

Таким образом, результаты представляют собой небольшую разницу в бит в случае, когда базовая точка находится именно на участке из-за ошибки с плавающей запятой, но она работает, если ничего нет в разделе.


Так что сокращает время работы, где п длина сигнала и т есть число перегородок из О (млн) до O (N). Это должно дать вам значительное повышение производительности. Мы можем сделать лучше?

Да. С нашим новой математикой на основе подхода, код легко векторный, и мы можем сделать Numpy делать тяжелую работу:

import numpy as np 

def np_quantize(signal, num_quanta, partition_start, partition_step, 
       codebook_start, codebook_step): 
    signal = np.asarray(signal, dtype=float) 
    indices = np.empty_like(signal, dtype=int) 
    np.floor_divide((signal - partition_start + partition_step), \ 
        partition_step, indices) 
    np.clip(indices, 0, num_quanta - 1, indices) 
    quanta = np.asarray(indices, dtype=float) * codebook_step + codebook_start 
    return indices, quanta 

я, случайно, эталоном это, и кажется, что каждый из моих оптимизаций сделал это медленнее, так что либо я делаю что-то ужасно неправильно, либо я не тестирую данные, достаточно большие, чтобы амортизировать константу.

~$ python -m timeit -s 'from quantize import orig_quantize' 'orig_quantize([-3, -2, -1, 0, 1, 2, 3], [-0.5, 0.5], [-1, 0, 1])' 
100000 loops, best of 3: 8.58 usec per loop 
~$ python -m timeit -s 'from quantize import opt_quantize' 'opt_quantize([-3, -2, -1, 0, 1, 2, 3], 3, -0.5, 1, -1, 1)' 
100000 loops, best of 3: 10.8 usec per loop 
~$ python -m timeit -s 'from quantize import np_quantize' 'np_quantize([-3, -2, -1, 0, 1, 2, 3], 3, -0.5, 1, -1, 1)' 
10000 loops, best of 3: 57.4 usec per loop 

Для пинков, я попытался с помощью Cython, а также Numpy:

cimport cython 
cimport numpy as np 

cdef extern from "math.h": 
    float floorf(float) 


@cython.boundscheck(False) 
def cynp_quantize(np.ndarray[float, ndim=1] signal, int num_quanta, 
        float partition_start, float partition_step, 
        float codebook_start, float codebook_step): 
    cdef int i 
    cdef int index 
    cdef np.ndarray[np.int_t, ndim=1] indices = np.empty_like(signal, dtype=int) 
    cdef np.ndarray[float, ndim=1] quanta = np.empty_like(signal) 
    for i in range(signal.shape[0]): 
     index = <int>floorf((signal[i] - partition_start) 
          /partition_step + 1.0) 
     if index < 0: 
      index = 0 
     if index >= num_quanta: 
      index = num_quanta - 1 
     indices[i] = index 
     quanta[i] = codebook_start + index * codebook_step 
    return indices, quanta 

Из того, что я понимаю, Cython экспериментально поддерживает OpenMP, которые позволили бы это сделать все с несколькими потоками. Я не смог проверить производительность этого решения Cython, хотя, с или без потоков (мне не хватает файла заголовка, необходимого для компиляции результата).

+0

Большое спасибо icktoofay, но я немного смущен этими сущностями «1: step: 1-step, -1: step: 1». как его встроенная функция в Matlab, я точно не знаю, как она выполняется на сигнале. поэтому, хотя его просто функция имеет встроенную логику, которую мне трудно реализовать. –

+0

@MaheshGalgalikar: Так вы делаете диапазоны в MATLAB. Грубо, вы можете перевести 'a: b: c' в [' range (a, c, b) '] (http://docs.python.org/3.3/library/stdtypes.html#typesseq-range). – icktoofay

+0

в функции квантизации, которую я использую в matlab, занимает шаг = 0.0078 , но в python он не примет значение float. все значения должны быть целыми .. –

Смежные вопросы