在 python 浮点数中刷新为零和/或有效数字

Posted

技术标签:

【中文标题】在 python 浮点数中刷新为零和/或有效数字【英文标题】:Flush to zero and/or significant digits in python floats 【发布时间】:2016-09-21 17:22:35 【问题描述】:

我正在尝试使用音频文件 (.wavs) 执行 ICA 应用程序。使用 scipy wavfile 时,我注意到使用 cprofile 时,我的 load_wav 函数的性能很差。以 4.5 Ghz 的 CPU 速度处理一个 44100 立体声 .wav 文件需要 30 分钟。请记住,.wav 文件的持续时间只有 10 秒。这是我的参考功能:

def load_wav(filename,samplerate=44100):

    # load file
    rate, data = wavfile.read(filename)

    # convert stereo to mono
    if len(data.shape) > 1:
        data = data[:,0]/2 + data[:,1]/2

    # re-interpolate samplerate    
    ratio = float(samplerate) / float(rate)
    data = resample(data, len(data) * ratio)

    return samplerate, data.astype(np.int16)

这主要是需要永远的重新插值部分。我研究了我能做的事情,似乎并不是所有的计算机都擅长处理大量的浮点数。一些浮点数可能接近于零,但不完全是。在我的音频示例中,这可能是一个人讲话中停顿的结果,或者可能发生在文件的开头或结尾,并且列表还在继续。

所以要深入了解它,有人可以在 Python 中分享类似这种 c++ 解决方法的东西吗?他们将此问题称为“非规范化”,并建议将其刷新为零。

http://blog.audio-tk.com/2016/09/20/audio-toolkit-handling-denormals/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+eifelle%2FCPPV+%28Matt%27s+blog%29

知道零是否是唯一需要警惕的数字也会让人安心。也许,我应该为所有数字设置有效数字?这会对音频应用产生影响吗?如果是这样,那在 Python 中会是什么样子?显然,我们可能希望避免过度使用,比如只使用整数,这可能会导致很多声音退化。

无论如何,我想你已经明白我的问题了,我希望计算速度在合理范围内,但仍然能够获得 .wav 的一半体面的 numpy 表示。

如果可以的话,请帮忙,

谢谢

导入如下:

import numpy as np
from scipy.io import wavfile
from scipy.signal import resample

另外,如果您想查看 jupyter notebook 以查看整个 ICA 应用程序,您可以在此处进行: http://web.archive.org/web/20150314223948/http://shogun-toolbox.org/static/notebook/current/bss_audio.html

**该链接使用 Python 2.7,我使用的是 Python 3.5,因此可能会略有不同。

--编辑

嗯。对困惑感到抱歉。为什么 X 的形状会发生变化的答案是因为示例笔记本采用点积的方式与我习惯的方式不同。他们使用S=(np.c_[s1,s2,s3]).T 然后np.dot(A,S)。我通常使用S=np.c_[s1,s2,s3] 然后np.dot(S,A.T)。所以我所要做的就是改变一些东西来获得所需的 X 形状。经典案例,在我跳跃之前不看。我错误地指责 np.delete(data,-1) 造成了这种形状事故。它已被证明可以处理素数,保证数据是偶数。我将删除一些不必要的 cmets 以恢复我的帖子的清晰度。

就音频处理代码效率而言,仍无法确定是否刷新到零/有效数字阈值。我希望我的问题的这个特定方面很快会被重新审视。在那之前,我将使用np.delete(data,-1) 作为处理大数/质数时快速而肮脏的解决方案。

【问题讨论】:

len(data) * ratio的值是多少? 对于我的特定 .wav 来说,它是 441263。这是一个“大”数字,但又不是天文数字,所以它引出了一个问题,是旅程还是目的地损害了计算的可行性。 请您出示您的进口商品。 resample 是从哪里来的?来自scipy.signal? @ArashHowaida:来自文档:“如前所述,resample 使用 FFT 转换,如果输入或输出样本的数量很大且素数,这可能会非常慢;请参阅 scipy.fftpack.fft。” 441263 既大又素。 【参考方案1】:

正如 AndyG 已经评论的那样,the documentation for scipy.signal.resample 警告你

... resample 使用 FFT 变换,如果输入样本的数量很大且是素数,这可能会非常慢,请参阅scipy.fftpack.fft

441263 既大又素数。

如果你的 scipy 版本 >= 0.18.0,你可以试试resample_poly

当样本数量很大且为素数时,或者当样本数量很大并且上下共享较大的最大公分母时,这种多相方法可能会比 scipy.signal.resample 中的傅里叶方法更快。

例如:

import numpy
from scipy.signal import resample, resample_poly

x = np.random.randn(441263)

%timeit resample(x, x.shape[0] // 4)
# 1 loop, best of 3: 2min 18s per loop

%timeit resample_poly(x, 10, 40)
# 100 loops, best of 3: 9.05 ms per loop

【讨论】:

我会尝试这种多相方法,我现在对事情很乐观。不过我有一个问题,零刷新或有效数字仍然会影响这种计算的性能吗? resample_poly 和 resample 都会受益吗?或者是大/素数方面淹没了“非正规”。只是想知道“非规范化”是否仍然是一个因素。 请不要将代码放入 cmets。如果您需要添加说明,则应改为编辑您的问题。

以上是关于在 python 浮点数中刷新为零和/或有效数字的主要内容,如果未能解决你的问题,请参考以下文章

输入一个点坐标(两个浮点数),输出其到坐标原点的距离(保留2位有效数字)

Python输入验证 - 接受正浮点数或int

浮点数的有效数字位数

浮点数 (IEEE-754)

float double

C语言如何实现输出浮点数小数点两位(四舍五入法),但若小数点最后位为零则舍去??