以某种方式期望统计库提供一些通用性的功能,因此如果您追求一个简单的案例,您必须缩小提供的功能。在这里,库函数需要几个因果变量,而不仅仅是一个。此外,它使用向量和矩阵,您可能只需要简单的列表。
为了展示如何使用带有单个因果变量的库,我假设您想要一个只使用普通 Haskell 数据类型的接口,如下所示:
-- [(x0, y0), (x1, y1), , (x2, y2) ... ] -> ((a, b), r2) for y ≃ a + b*x
simpleRegression1 :: [(Double, Double)] -> ((Double, Double), Double)
使用olsRegress 似乎比使用ols 更简单,因为:
- 不需要矩阵数据类型
- 您可以轻松获得 y 截距值(即表示法中的 a)
- 您还可以从同一个调用中获得拟合优度系数
代码可以写成如下:
import qualified Data.List as L
import qualified Data.Vector.Unboxed as DVU
import qualified Statistics.Regression as SR
-- [(x0, y0), (x1, y1), , (x2, y2) ... ] -> ((a, b), r2) for y ≃ a + b*x
simpleRegression1 :: [(Double, Double)] -> ((Double, Double), Double)
simpleRegression1 xyPairs =
let xList = L.map fst xyPairs
yList = L.map snd xyPairs
xVecList = [DVU.fromList xList]
yVec = DVU.fromList yList
(sv, r2) = SR.olsRegress xVecList yVec
[b, a] = DVU.toList sv
in
((a,b), r2)
在我们的例子中,只有一个列向量,所以xVecList 只有一个元素。
正如olsRegress documentation 中提到的,y 截距“a”值是输出向量的最后一个元素。
测试代码:
main = do
let measurements = [(1.0, 1.9999), (2.0, 2.5001), (3.0, 2.9999)]
---- measurements = [(1.0, 2.0), (2.0, 2.5), (3.0, 3.0)]
((a,b), r2) = simpleRegression1 measurements
putStrLn $ "measurements = " ++ (show measurements)
putStrLn $ "a = " ++ (show a) ++ " b = " ++ (show b) ++
" r2 = " ++ (show r2)
let ypList = L.map (\x -> a+b*x) (L.map fst measurements)
diffList = L.zipWith (-) (L.map snd measurements) ypList
putStrLn $ "ypList = " ++ (show ypList)
putStrLn $ "diffList = " ++ (show diffList)
测试输出:
measurements = [(1.0,1.9999),(2.0,2.5001),(3.0,2.9999)]
a = 1.4999666666666656 b = 0.5000000000000006 r2 = 0.9999999466666695
ypList = [1.999966666666666,2.4999666666666664,2.9999666666666673]
diffList = [-6.666666666599319e-5,1.3333333333376274e-4,-6.66666666675475e-5]
注意还有一个LinearRegression module。