【问题标题】:Convert quantiz function to python将 quantiz 函数转换为 python
【发布时间】:2013-04-13 03:42:18
【问题描述】:

如何转换MATLAB's quantiz function (其中 xd 是 desimated 信号)到 python/scipy 中?

我正在尝试将我在 MATLAB 中开发的用于语音处理的算法实现到使用 python 和 scipy、numpy、pygtk 和 matplotlib 等库的软件包中,以便将算法转换为完整的包。

我正在使用 scipy 进行算法开发,但我在 python 中找不到合适的函数来“量化信号”:

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

我将如何在 python 中编写这个?

【问题讨论】:

  • 语音转语音识别是一个难以置信广泛的领域。仅此一项就投入了数十亿资金的整个公司。除非您可以提供一些您遇到困难的具体实现/部分,否则请稍等片刻,直到您提出这个问题。它太宽泛了。
  • @Makoto:我认为他们确实指定了他们卡住的具体部分:他们需要与 MATLAB quantiz 函数等效的部分。

标签: python matlab signal-processing


【解决方案1】:

查看文档,这是一个非常简单的函数,在 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]

因此,由于浮点错误导致数据恰好在分区上,结果会略有不同,但如果分区上没有任何内容,则它可以工作。


这样可以减少运行时间,其中 n 是信号的长度,m 是从 O(mn) 到 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 解决方案的性能(我缺少编译结果所需的头文件)。

【讨论】:

  • 非常感谢 icktoofay,但我对这些实体“1:step:1-step,-1:step:1”有点困惑。作为 Matlab 中的一个内置函数,我不完全知道它是如何在信号上执行的。所以虽然它只是一个功能,但它有一个内置的逻辑,我发现它很难实现。
  • @MaheshGalgalikar:这就是您在 MATLAB 中处理范围的方式。大致上,您可以将a:b:c 翻译成range(a, c, b)
  • 在我在 matlab 中使用的 quantiz 函数中,采用 step=0.0078 但在 python 中它不会接受浮点值。所有值都必须是整数..
  • @MaheshGalgalikar:见this question。如果您是第一个答案中的函数,您可能需要使用list(frange(...)) 而不仅仅是range(...)。 Numpy arange 不需要任何特殊的 list 东西。
  • @icktoofay : 非常感谢会让你知道进度
猜你喜欢
  • 1970-01-01
  • 2015-09-28
  • 2014-03-05
  • 1970-01-01
  • 2022-01-04
  • 2018-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多