Рассматривая документацию, это довольно простая функция, которую довольно легко написать в 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, хотя, с или без потоков (мне не хватает файла заголовка, необходимого для компиляции результата).
Распознавание речи в речь - это * невероятно широкое поле. Есть целые компании, которые выделяют миллиарды в капитале только на это. Если вы не можете предоставить некоторые конкретные реализации/части, где вы застряли, подождите некоторое время, пока вы не зададите этот вопрос. Он слишком широк. – Makoto
@ Makoto: Я думаю, что они указали конкретную часть, где они застревают: им нужен эквивалент функции 'quantiz' MATLAB. – icktoofay