2015-04-16 27 views
5

'de hızlandırma çerçevesi Buradaki ilk sorum Stackoverflow ... umarım sorusu yeterince spesifiktir.Lineer regresyon - Swift

Swift'de belirli tarihlerdeki ölçümlerle bir dizi var. Gibi:

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) 

Bazı günler eksik, sadece bir ölçüm almadı ... Tüm ölçümler bir satırda olmalıdır, az ya da çok. Bu yüzden doğrusal regresyon hakkında düşündüm. Accelerate çerçevesini buldum, ancak belgeler eksik ve örnekleri bulamıyorum.

Eksik ölçümler için, diğer ölçümlere dayanarak, girdi eksik bir gün ve çıktı olarak en iyi tahminde bulunmak gibi bir fonksiyona sahip olmak istiyorum.

func bG(day: Int) -> Double { 
    return // return best guess for measurement 
} 

Yardımlarınız için teşekkürler. Jan

cevap

10

Cevabım özellikle Accelerate Framework hakkında konuşmuyor, ancak sorunun ilginç olduğunu düşündüğümde bir bıçak gibi verebileceğimi düşündüm. Topladığım şeyden, temel olarak, en iyi uyum çizgisini oluşturmak ve bu değerden mW daha fazla değer elde etmek veya daha fazla değer vermek istiyorsunuz. Ben En Küçük Kareler Yöntemi kullanılan yapmak için burada ayrıntılı: http://hotmath.com/hotmath_help/topics/line-of-best-fit.html ve Swift kullanarak Playgrounds bu uygulamaya: a Yukarıdaki kodda

// 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, $0 is the current total. 
let meanDays = points.reduce(0) { $0 + $1.day }/Double(points.count) 
let meanMW = points.reduce(0) { $0 + $1.mW }/Double(points.count) 

let a = points.reduce(0) { $0 + ($1.day - meanDays) * ($1.mW - meanMW) } 
let b = points.reduce(0) { $0 + pow($1.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 

ve b web sitesinden aşağıdaki formüllere bakınız:

a : enter image description here

b: enter image description here

func bG(day: Double) -> Double { 
    return m * day + c 
} 

Ve böylece gibi kullanmak:: Artık arasına sokmak için en uygun çizgisini kullanan bir işlev oluşturabilirsiniz/mW tahmin

bG(3) // 31.70 
bG(5) // 31.52 
bG(7) // 31.35 
+0

Kodunuz için çok teşekkürler (ve benim sorularımda yaptığınız düzenlemeler), ABakerSmith! Bundan çok memnun kaldım ... Btw, Stackoverflow'ta yeniyim dediğim gibi ... senin için başka bir rozete oy vermem mi gerekiyor? Mutlu olurdum ... :-) – arakweker

+0

Harika, yardım ettiğine sevindim! Eğer cevabınızı sorununuzu çözdüyseniz, soldaki onay işaretine basarak doğru şekilde işaretleyebilirsiniz. Ayrıca oylama sorularını cevaplayabilirsiniz, ancak bunun için 15 puana ihtiyacınız olduğuna inanıyorum. – ABakerSmith

+0

Bu arada Yığın Taşmasına Hoş Geldiniz! – ABakerSmith

3

Eğer Swift hızlı doğrusal regresyon yapmak istiyorsanız, Upsurge çerçevesini kullanmanızı öneriyorum. Accelerate kütüphanesini sarmalayan bir dizi basit işlev sunar ve böylece vDSP çağrılarının karmaşıklığı konusunda endişelenmenize gerek kalmadan iOS veya OSX 'da SIMD'nin avantajlarından yararlanabilirsiniz.

baz yükselişe fonksiyonları ile doğrusal regresyon yapmak için basitçe:

 
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 

Bu linregress fonksiyonu uygulanan ne aslında.

Bir [Double] dizisi, RealArray (Upsurge ile birlikte gelir) gibi diğer sınıflar veya bitişik belleği gösterebilirse kendi nesnelerinizle kullanabilirsiniz.

 
#!/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 { $0.day } 
let y = myArray.map { $0.mW } 

let (slope, intercept) = Upsurge.linregress(x, y) 

func bG(day: Double) -> Double { 
    return slope * day + intercept 
} 

(ı ekler sol olasılıkla programlı diziye ekliyoruz gibi önemli uzunlukta ise yerine değişmezleri kullanma yerine)

: gibi

Yani ihtiyaçlarını karşılamak için bir komut dosyası olmazdı

ve tam sorumluluk reddi beyanı: linrogress koduna katkıda bulundum. Gelecekte bir noktada kararlılığın eş-etkinliğini de eklemeyi umuyorum.