线性回归 - Swift 中的加速框架
Linear regression - accelerate framework in Swift
我在 Whosebug 的第一个问题...希望我的问题足够具体。
我在 Swift 中有一个数组,其中包含特定日期的测量值。喜欢:
var myArray:[(day: Int, mW: Double)] = []
myArray.append(day:0, mW: 31.98)
myArray.append(day:1, mW: 31.89)
myArray.append(day:2, mW: 31.77)
myArray.append(day:4, mW: 31.58)
myArray.append(day:6, mW: 31.46)
有些日子不见了,我只是没有测量...所有的测量应该在一条线上,或多或少。所以我想到了线性回归。我找到了 Accelerate 框架,但是文档丢失了,我也找不到示例。
对于缺失的测量值,我想要一个函数,输入一个缺失的日期,输出一个基于其他测量值的最佳猜测。
func bG(day: Int) -> Double {
return // return best guess for measurement
}
感谢您的帮助。
一月
我的回答没有专门讨论 Accelerate Framework,但我认为这个问题很有趣,我想尝试一下。根据我收集到的信息,您基本上是在寻找一条最适合的线,并从中插入或推断 mW
的更多值。为此,我使用了最小二乘法,详见此处:http://hotmath.com/hotmath_help/topics/line-of-best-fit.html 并在 Playgrounds 中使用 Swift:
实现了此方法
// The typealias allows us to use '$X.day' and '$X.mW',
// instead of '$X.0' and '$X.1' in the following closures.
typealias PointTuple = (day: Double, mW: Double)
// The days are the values on the x-axis.
// mW is the value on the y-axis.
let points: [PointTuple] = [(0.0, 31.98),
(1.0, 31.89),
(2.0, 31.77),
(4.0, 31.58),
(6.0, 31.46)]
// When using reduce, [=10=] is the current total.
let meanDays = points.reduce(0) { [=10=] + .day } / Double(points.count)
let meanMW = points.reduce(0) { [=10=] + .mW } / Double(points.count)
let a = points.reduce(0) { [=10=] + (.day - meanDays) * (.mW - meanMW) }
let b = points.reduce(0) { [=10=] + pow(.day - meanDays, 2) }
// The equation of a straight line is: y = mx + c
// Where m is the gradient and c is the y intercept.
let m = a / b
let c = meanMW - m * meanDays
上面的代码a
和b
参考了网站上的以下公式:
a
:
b
:
现在您可以创建函数,该函数使用最适合 interpolate/extrapolate mW
:
的线
func bG(day: Double) -> Double {
return m * day + c
}
并像这样使用它:
bG(3) // 31.70
bG(5) // 31.52
bG(7) // 31.35
如果你想在 Swift 中进行快速线性回归,我建议使用 Upsurge 框架。它提供了许多包装 Accelerate 库的简单函数,因此您可以在 iOS 或 OSX 上获得 SIMD 的好处
无需担心 vDSP 调用的复杂性。
要使用基本的 Upsurge 函数进行线性回归很简单:
let meanx = mean(x)
let meany = mean(y)
let meanxy = mean(x * y)
let meanx_sqr = measq(x)
let slope = (meanx * meany - meanxy) / (meanx * meanx - meanx_sqr)
let intercept = meany - slope * meanx
这基本上就是 linregress 函数中实现的内容。
您可以将它与 [Double] 数组、其他 类(例如 RealArray(Upsurge 附带))或您自己的对象(如果它们可以公开连续内存)一起使用。
因此满足您需求的脚本如下所示:
#!/usr/bin/env cato
import Upsurge
typealias PointTuple = (day: Double, mW:Double)
var myArray:[PointTuple] = []
myArray.append((0, 31.98))
myArray.append((1, 31.89))
myArray.append((2, 31.77))
myArray.append((4, 31.58))
myArray.append((6, 31.46))
let x = myArray.map { [=11=].day }
let y = myArray.map { [=11=].mW }
let (slope, intercept) = Upsurge.linregress(x, y)
func bG(day: Double) -> Double {
return slope * day + intercept
}
(我留在了附加部分而不是使用文字,因为如果它很长,您可能会以编程方式添加到您的数组中)
和完全免责声明:我贡献了 linregress 代码。我希望在将来的某个时候也可以添加确定系数。
我在 Whosebug 的第一个问题...希望我的问题足够具体。
我在 Swift 中有一个数组,其中包含特定日期的测量值。喜欢:
var myArray:[(day: Int, mW: Double)] = []
myArray.append(day:0, mW: 31.98)
myArray.append(day:1, mW: 31.89)
myArray.append(day:2, mW: 31.77)
myArray.append(day:4, mW: 31.58)
myArray.append(day:6, mW: 31.46)
有些日子不见了,我只是没有测量...所有的测量应该在一条线上,或多或少。所以我想到了线性回归。我找到了 Accelerate 框架,但是文档丢失了,我也找不到示例。
对于缺失的测量值,我想要一个函数,输入一个缺失的日期,输出一个基于其他测量值的最佳猜测。
func bG(day: Int) -> Double {
return // return best guess for measurement
}
感谢您的帮助。 一月
我的回答没有专门讨论 Accelerate Framework,但我认为这个问题很有趣,我想尝试一下。根据我收集到的信息,您基本上是在寻找一条最适合的线,并从中插入或推断 mW
的更多值。为此,我使用了最小二乘法,详见此处:http://hotmath.com/hotmath_help/topics/line-of-best-fit.html 并在 Playgrounds 中使用 Swift:
// The typealias allows us to use '$X.day' and '$X.mW',
// instead of '$X.0' and '$X.1' in the following closures.
typealias PointTuple = (day: Double, mW: Double)
// The days are the values on the x-axis.
// mW is the value on the y-axis.
let points: [PointTuple] = [(0.0, 31.98),
(1.0, 31.89),
(2.0, 31.77),
(4.0, 31.58),
(6.0, 31.46)]
// When using reduce, [=10=] is the current total.
let meanDays = points.reduce(0) { [=10=] + .day } / Double(points.count)
let meanMW = points.reduce(0) { [=10=] + .mW } / Double(points.count)
let a = points.reduce(0) { [=10=] + (.day - meanDays) * (.mW - meanMW) }
let b = points.reduce(0) { [=10=] + pow(.day - meanDays, 2) }
// The equation of a straight line is: y = mx + c
// Where m is the gradient and c is the y intercept.
let m = a / b
let c = meanMW - m * meanDays
上面的代码a
和b
参考了网站上的以下公式:
a
:
b
:
现在您可以创建函数,该函数使用最适合 interpolate/extrapolate mW
:
func bG(day: Double) -> Double {
return m * day + c
}
并像这样使用它:
bG(3) // 31.70
bG(5) // 31.52
bG(7) // 31.35
如果你想在 Swift 中进行快速线性回归,我建议使用 Upsurge 框架。它提供了许多包装 Accelerate 库的简单函数,因此您可以在 iOS 或 OSX 上获得 SIMD 的好处 无需担心 vDSP 调用的复杂性。
要使用基本的 Upsurge 函数进行线性回归很简单:
let meanx = mean(x) let meany = mean(y) let meanxy = mean(x * y) let meanx_sqr = measq(x) let slope = (meanx * meany - meanxy) / (meanx * meanx - meanx_sqr) let intercept = meany - slope * meanx
这基本上就是 linregress 函数中实现的内容。
您可以将它与 [Double] 数组、其他 类(例如 RealArray(Upsurge 附带))或您自己的对象(如果它们可以公开连续内存)一起使用。
因此满足您需求的脚本如下所示:
#!/usr/bin/env cato import Upsurge typealias PointTuple = (day: Double, mW:Double) var myArray:[PointTuple] = [] myArray.append((0, 31.98)) myArray.append((1, 31.89)) myArray.append((2, 31.77)) myArray.append((4, 31.58)) myArray.append((6, 31.46)) let x = myArray.map { [=11=].day } let y = myArray.map { [=11=].mW } let (slope, intercept) = Upsurge.linregress(x, y) func bG(day: Double) -> Double { return slope * day + intercept }
(我留在了附加部分而不是使用文字,因为如果它很长,您可能会以编程方式添加到您的数组中)
和完全免责声明:我贡献了 linregress 代码。我希望在将来的某个时候也可以添加确定系数。