簡體   English   中英

如何獲得具有先驗斷點的分段線性回歸?

[英]How can I obtain segmented linear regressions with a priori breakpoints?

我需要詳細解釋這一點,因為我沒有統計的基礎知識可以更簡潔地進行解釋。 在SO中這樣問,因為我正在尋找python解決方案,但是如果更合適的話可以去stats.SE。

我有井下數據,可能有點像這樣:

Rt      T
0.0000  15.0000
4.0054  15.4523
25.1858 16.0761
27.9998 16.2013
35.7259 16.5914
39.0769 16.8777
45.1805 17.3545
45.6717 17.3877
48.3419 17.5307
51.5661 17.7079
64.1578 18.4177
66.8280 18.5750
111.1613    19.8261
114.2518    19.9731
121.8681    20.4074
146.0591    21.2622
148.8134    21.4117
164.6219    22.1776
176.5220    23.4835
177.9578    23.6738
180.8773    23.9973
187.1846    24.4976
210.5131    25.7585
211.4830    26.0231
230.2598    28.5495
262.3549    30.8602
266.2318    31.3067
303.3181    37.3183
329.4067    39.2858
335.0262    39.4731
337.8323    39.6756
343.1142    39.9271
352.2322    40.6634
367.8386    42.3641
380.0900    43.9158
388.5412    44.1891
390.4162    44.3563
395.6409    44.5837

(Rt變量可以視為深度的代理,而T是溫度)。 我還具有“先驗”數據,可提供Rt = 0時的溫度,並且未顯示一些可以用作斷點,引導斷點或至少與發現的斷點進行比較的標記。

這兩個變量的線性關系在某些深度區間受某些過程影響。 一個簡單的線性回歸是

q, T0, r_value, p_value, std_err = stats.linregress(Rt, T)

看起來像這樣,您可以清楚地看到偏差,並且T0的擬合度很低(應該為15):

在此輸入圖像描述

我希望能夠執行一系列線性回歸(在每個段的末端連接),但是我想要做到這一點:(a)通過不指定中斷的數量或位置,(b)通過指定數量和位置休息時間;(c)計算每個分段的系數

我想我可以通過拆分數據並小心一點分別地做(b)和(c),但是我不知道(a),想知道是否有人知道這可以更簡單地完成。

我已經看到了這一點: https : //stats.stackexchange.com/a/20210/9311 ,我認為MARS可能是處理它的好方法,但這僅僅是因為它看起來不錯。 我不太了解 我以盲切粘貼的方式對數據進行了嘗試,並在下面顯示了輸出,但同樣,我也不明白:

在此輸入圖像描述

簡短的答案是,我使用R創建了線性回歸模型來解決了我的問題,然后使用segmented包從線性模型中生成了分段線性回歸。 我能夠使用psi=NAK=n來指定預期的斷點(或結)數n ,如下所示。

長答案是:

R版本3.0.1(2013-05-16)
平台:x86_64-pc-linux-gnu(64位)

# example data:
bullard <- structure(list(Rt = c(5.1861, 10.5266, 11.6688, 19.2345, 59.2882, 
68.6889, 320.6442, 340.4545, 479.3034, 482.6092, 484.048, 485.7009, 
486.4204, 488.1337, 489.5725, 491.2254, 492.3676, 493.2297, 494.3719, 
495.2339, 496.3762, 499.6819, 500.253, 501.1151, 504.5417, 505.4038, 
507.6278, 508.4899, 509.6321, 522.1321, 524.4165, 527.0027, 529.2871, 
531.8733, 533.0155, 544.6534, 547.9592, 551.4075, 553.0604, 556.9397, 
558.5926, 561.1788, 562.321, 563.1831, 563.7542, 565.0473, 566.1895, 
572.801, 573.9432, 575.6674, 576.2385, 577.1006, 586.2382, 587.5313, 
589.2446, 590.1067, 593.4125, 594.5547, 595.8478, 596.99, 598.7141, 
599.8563, 600.2873, 603.1429, 604.0049, 604.576, 605.8691, 607.0113, 
610.0286, 614.0263, 617.3321, 624.7564, 626.4805, 628.1334, 630.9889, 
631.851, 636.4198, 638.0727, 638.5038, 639.646, 644.8184, 647.1028, 
647.9649, 649.1071, 649.5381, 650.6803, 651.5424, 652.6846, 654.3375, 
656.0508, 658.2059, 659.9193, 661.2124, 662.3546, 664.0787, 664.6498, 
665.9429, 682.4782, 731.3561, 734.6619, 778.1154, 787.2919, 803.9261, 
814.335, 848.1552, 898.2568, 912.6188, 924.6932, 940.9083), Tem = c(12.7813, 
12.9341, 12.9163, 14.6367, 15.6235, 15.9454, 27.7281, 28.4951, 
34.7237, 34.8028, 34.8841, 34.9175, 34.9618, 35.087, 35.1581, 
35.204, 35.2824, 35.3751, 35.4615, 35.5567, 35.6494, 35.7464, 
35.8007, 35.8951, 36.2097, 36.3225, 36.4435, 36.5458, 36.6758, 
38.5766, 38.8014, 39.1435, 39.3543, 39.6769, 39.786, 41.0773, 
41.155, 41.4648, 41.5047, 41.8333, 41.8819, 42.111, 42.1904, 
42.2751, 42.3316, 42.4573, 42.5571, 42.7591, 42.8758, 43.0994, 
43.1605, 43.2751, 44.3113, 44.502, 44.704, 44.8372, 44.9648, 
45.104, 45.3173, 45.4562, 45.7358, 45.8809, 45.9543, 46.3093, 
46.4571, 46.5263, 46.7352, 46.8716, 47.3605, 47.8788, 48.0124, 
48.9564, 49.2635, 49.3216, 49.6884, 49.8318, 50.3981, 50.4609, 
50.5309, 50.6636, 51.4257, 51.6715, 51.7854, 51.9082, 51.9701, 
52.0924, 52.2088, 52.3334, 52.3839, 52.5518, 52.844, 53.0192, 
53.1816, 53.2734, 53.5312, 53.5609, 53.6907, 55.2449, 57.8091, 
57.8523, 59.6843, 60.0675, 60.8166, 61.3004, 63.2003, 66.456, 
67.4, 68.2014, 69.3065)), .Names = c("Rt", "Tem"), class = "data.frame", row.names = c(NA, 
-109L))


library(segmented)  # Version: segmented_0.2-9.4

# create a linear model
out.lm <- lm(Tem ~ Rt, data = bullard)

# Set X breakpoints: Set psi=NA and K=n:
o <- segmented(out.lm, seg.Z=~Rt, psi=NA, control=seg.control(display=FALSE, K=3))
slope(o)  # defaults to confidence level of 0.95 (conf.level=0.95)

# Trickery for placing text labels
r <- o$rangeZ[, 1]
est.psi <- o$psi[, 2]
v <- sort(c(r, est.psi))
xCoord <- rowMeans(cbind(v[-length(v)], v[-1]))
Z <- o$model[, o$nameUV$Z]
id <- sapply(xCoord, function(x) which.min(abs(x - Z)))
yCoord <- broken.line(o)[id]

# create the segmented plot, add linear regression for comparison, and text labels
plot(o, lwd=2, col=2:6, main="Segmented regression", res=TRUE)
abline(out.lm, col="red", lwd=1, lty=2)  # dashed line for linear regression
text(xCoord, yCoord, 
    labels=formatC(slope(o)[[1]][, 1] * 1000, digits=1, format="f"), 
    pos = 4, cex = 1.3)

在此輸入圖像描述

從技術上來說,您想要的是樣條插值 ,特別是1階樣條插值(將連接直線段; 2階連接拋物線等)。

關於Stack Overflow的Python樣條曲線插值處理已經存在一個問題,它將對您的問題有所幫助。 這是鏈接 如果您在嘗試這些提示后還有其他疑問,請發回。

本文第30-31頁提供了一種非常簡單的方法(無需迭代,無需初步猜測,無需指定): https : //fr.scribd.com/document/380941024/Regression-par-morceaux-Piecewise-Regression -pdf 結果是:

在此輸入圖像描述

注意:該方法基於積分方程的擬合。 當前例不是一個有利的情況,因為這些點的脫落的分布遠沒有規則(大范圍內沒有點)。 這使數值積分的准確性降低。 但是,分段擬合出奇地不錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM