Swift Accelerate用于计算平均值和标准偏差。

7

我正在研究如何在Swift中使用Accelerate计算数组的平均值和标准差。

我能够计算平均值,但我该如何计算标准差?

let rr: [Double] = [ 18.0, 21.0, 41.0, 42.0, 48.0, 50.0, 55.0, 90.0 ]

var mn: Double = 0.0

vDSP_meanvD(rr, 1, &mn, vDSP_Length(rr.count))

print(mn) // prints correct mean as 45.6250

// Standard Deviation should be 22.3155

我认为你可以通过均值和“平方均值”(vDSP_measqvD)来计算它... - Martin R
谢谢Martin!你能给我展示一下vDSP_measqvD是如何工作的吗?该参数有一个星号(*)。我仍然对使用它们感到困惑。 - Pat
vDSP_measqvD的接口与vDSP_meanvD完全相同。 - Martin R
好的,我会尝试。 - Pat
我可能建议的一件事是,基准测试一下加速框架是否对你的数据集有所改进。我曾经花了不少精力来优化带有加速框架的Swift,但在编译器优化后使用mapreduce后发现性能的提高微乎其微。 - Scott H
1
@ScottH:这是一个很好的观点。我的经验不同:在这里https://dev59.com/fJ7ha4cB1Zd3GeqPjnW5#41806438中,加速方法并没有比显式循环更快。但是在这里https://dev59.com/Jp7ha4cB1Zd3GeqPrfvD#42129847中,它快了5倍。这可能也取决于硬件。 - Martin R
2个回答

15
你可以通过计算均值和平方均值来计算标准差(参见https://en.wikipedia.org/wiki/Standard_deviation#Identities_and_mathematical_propertieshttps://en.wikipedia.org/wiki/Algebraic_formula_for_the_variance)。
import Accelerate

let rr: [Double] = [ 18.0, 21.0, 41.0, 42.0, 48.0, 50.0, 55.0, 90.0 ]

var mn: Double = 0.0 // mean value
vDSP_meanvD(rr, 1, &mn, vDSP_Length(rr.count))

var ms: Double = 0.0 // mean square value
vDSP_measqvD(rr, 1, &ms, vDSP_Length(rr.count))

let sddev = sqrt(ms - mn * mn) * sqrt(Double(rr.count)/Double(rr.count - 1))

print(mn, sddev)
// 45.625 22.315513501982

如果您使用的是iOS 9.0或更高版本,或者macOS 10.11或更高版本,则可以选择使用vDSP_normalizeD函数:

var mn = 0.0
var sddev = 0.0
vDSP_normalizeD(rr, 1, nil, 1, &mn, &sddev, vDSP_Length(rr.count))
sddev *= sqrt(Double(rr.count)/Double(rr.count - 1))

print(mn, sddev)
// 45.625 22.315513501982

非常感谢你,马丁!我只是在尝试弄清楚这个公式。 - Pat
@Pat:我已经添加了另一个可能的解决方案。 - Martin R
再次感谢你,马丁! - Pat

4

@Martin R的答案中还有一个附加说明:对于Float/单精度浮点数,也有一个vDSP_normalize函数。

func vDSP_normalize(UnsafePointer<Float>, vDSP_Stride, UnsafeMutablePointer<Float>?, vDSP_Stride, UnsafeMutablePointer<Float>, UnsafeMutablePointer<Float>, vDSP_Length)
//Compute mean and standard deviation and then calculate new elements to have a zero mean and a unit standard deviation. Single precision.

func vDSP_normalizeD(UnsafePointer<Double>, vDSP_Stride, UnsafeMutablePointer<Double>?, vDSP_Stride, UnsafeMutablePointer<Double>, UnsafeMutablePointer<Double>, vDSP_Length)
//Compute mean and standard deviation and then calculate new elements to have a zero mean and a unit standard deviation. Double precision.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接