线性回归数据_数据科学笔记(三)——线性回归
1. 機(jī)器學(xué)習(xí)眼中的線性回歸
左圖是原始建模數(shù)據(jù),目的是用來尋找玩偶數(shù)量和成本的某種關(guān)系。右圖將數(shù)據(jù)可視化得到散點(diǎn)圖。
第一步 進(jìn)行場景確定
第二步 定義損失函數(shù)
建模的目的:模型預(yù)測值與真實(shí)值之間的差距越小越好。下面有兩種定義損失函數(shù)的方法。帶“帽子”的變量代表預(yù)測值。不帶的表示觀測值。
由于以上兩點(diǎn)原因,所以采用右邊的函數(shù)作為損失函數(shù)。
實(shí)際上使用左面的函數(shù)定義損失函數(shù)也能得到一個(gè)線性模型,只是并不是我們常說的線性回歸模型而已。
所以:損失函數(shù)是機(jī)器學(xué)習(xí)模型的核心。(即使相同的模型形式,不同的損失函數(shù)對應(yīng)著不同模型的效果)。
第三步 特征提取
原始數(shù)據(jù)比較干凈,所以并不需要進(jìn)行數(shù)據(jù)清洗。在本題中玩偶個(gè)數(shù)可以作為特征直接使用。
第四步 確定模型形式和參數(shù)估計(jì)
第五步 評估模型效果
對于回歸問題,常用的模型評估指標(biāo)有兩個(gè):
均方差(MSE):預(yù)測值與真實(shí)值的平均差距。L指的是上面定義的損失函數(shù)。
決定系數(shù)(R2):數(shù)據(jù)變化被模型解釋的比例。
第一個(gè)公式為成本變化幅度。即真實(shí)值與真實(shí)值平均值之間的差值的平方和。
第二個(gè)公式是未被模型所解釋的變化幅度。即真實(shí)值與預(yù)測值之間的差值的平方和。從建模的角度來講,我們希望該公式得到的值越小越好。
所以,決定系數(shù)的公式如下:結(jié)果越接近于1,模型的預(yù)測效果越好。
2.? 統(tǒng)計(jì)眼中的線性回歸
2.1 模型的假設(shè)
在機(jī)器學(xué)習(xí)的角度,我們并不太關(guān)心 x 和 y 的數(shù)學(xué)關(guān)系是怎么樣的。整個(gè)的建模過程是機(jī)械化的。我們只是關(guān)心能用什么樣的公式能讓從 x 出發(fā)的預(yù)測值與真實(shí)值 y 之間的關(guān)系最小的可以了。
站在統(tǒng)計(jì)學(xué)的角度出發(fā),我們試圖弄清楚變量 y 與 x 之間的數(shù)學(xué)關(guān)系。
比如 04/01 和 04/02 兩天的玩偶個(gè)數(shù)都是10,但前者成本為7.7,后者成本為9.87.這說明變量 y?似乎帶有某種隨機(jī)性。并且在散點(diǎn)圖中,我們同樣得到 x 與 y 似乎存在某種線性關(guān)系。
在上面公式的基礎(chǔ)上,進(jìn)一步假設(shè)。其中假設(shè)的 第二點(diǎn) 和 第三點(diǎn) 可能與現(xiàn)實(shí)情況沖突。
根據(jù)這三個(gè)假設(shè)我們可以進(jìn)一步來分析為什么會(huì)存在 x 相同而 y 不同的情況。
首先假設(shè)模型的?a, b, σ(假設(shè)1:隨機(jī)擾動(dòng)項(xiàng)服從的正態(tài)分布的方差)是已知的。這時(shí)候我們可以看到 y 是由?ax + b + 隨機(jī)值?構(gòu)成,那么就說明 y 本身就是一個(gè)隨機(jī)值。而且也可以很清楚的證明 yi?是服從 期望為?10a+b?方差為?σ2?的正態(tài)分布。所以,有?相同的玩偶個(gè)數(shù),不同的成本?這種情況出現(xiàn)正是因?yàn)?成本分別是同一正態(tài)分布的兩次獨(dú)立觀測值。
所以,在統(tǒng)計(jì)學(xué)的眼里,我們得到的變量值其實(shí)是一個(gè)隨機(jī)變量的觀測值,它并不是一個(gè)確定的值。因此,統(tǒng)計(jì)學(xué)希望通過這樣一個(gè)隨機(jī)變量的觀測值去挖掘真實(shí)的值是多少。
2.2 參數(shù)估計(jì)公式(最大似然估計(jì)法 Maximum Likelihood Estimation, MLE)
根據(jù)上面的模型假設(shè),可以得到:
由于 y 是隨機(jī)變量,就可以定義參數(shù)的似然函數(shù)(Likelihood function):
這里的似然函數(shù) L 其實(shí)就是 y 的聯(lián)合條件概率。并且 yi?是相互獨(dú)立的,那么就可以將似然函數(shù) L 改寫成每一點(diǎn)概率的乘積的形式。這一點(diǎn)可以極大地方便后面的數(shù)學(xué)處理。
既然 y 是隨機(jī)變量,那么模型參數(shù)估計(jì)的原則就是?y出現(xiàn)的概率達(dá)到最大。
這就是所謂的?最大似然估計(jì)法(Maximum Likelihood Estimation, MLE)。
2.3 最大似然估計(jì)法與機(jī)器學(xué)習(xí)模型參數(shù)估計(jì)公式的關(guān)系
在機(jī)器學(xué)習(xí)中,首先定義了損失函數(shù),也就是模型真實(shí)值與預(yù)測值之間的差距。
在機(jī)器學(xué)習(xí)中,參數(shù)估計(jì)的原則就是使?損失函數(shù)達(dá)到最小值。
而在統(tǒng)計(jì)學(xué)中,我們從 y 是隨機(jī)變量這一點(diǎn)出發(fā),參數(shù)估計(jì)的原則就是使?y出現(xiàn)的概率達(dá)到最大。
將統(tǒng)計(jì)學(xué)中的最大似然估計(jì)法翻譯成公式:
由于 L 這里是乘積的形式:
? 那么為了數(shù)學(xué)上好處理,引入自然對數(shù)函數(shù),也就是以 e為底(2.71828...)的對數(shù)函數(shù)。對于它有以下性質(zhì):
同時(shí),我們也注意到自然對數(shù)函數(shù)本身是一個(gè)增函數(shù),也就是說 L 達(dá)到最大值的時(shí)候 ln(L) 也達(dá)到最大值,因此可以把尋找參數(shù) a, b 的公式改寫為:
? 從之前已經(jīng)證明 yi?服從正態(tài)分布,因此將 lnL 展開,得到如下的式子:
我們可以注意到 前面(一個(gè)紅線)是一個(gè)固定的值,后面(兩個(gè)紅線)才是變量。如果我們想要 lnL 達(dá)到最大值,那么我們就要后面的變量達(dá)到最小值。所以最終的參數(shù)估計(jì)公式也就變成了:
這就與前面機(jī)器學(xué)習(xí)里面的?線性回歸模型(最小二乘法OLS)的參數(shù)估計(jì)公式相同。
在之前機(jī)器學(xué)習(xí)的討論中,我們知道?只要定義一種不同的損失函數(shù),就有一種新的線性回歸模型。那么為什么我們通常使用的就是 最小二乘法(OLS)線性回歸模型呢?
就是因?yàn)樗褂玫膿p失函數(shù)背后有極為強(qiáng)大的數(shù)學(xué)基礎(chǔ)。
由于 最大似然估計(jì)法 與 OLS線性回歸模型 的參數(shù)估計(jì)公式是相同的,所以它們得到的結(jié)果是一樣的。
2.4 置信區(qū)間
根據(jù) 2.3 的討論,我們有了模型參數(shù)估計(jì)值的公式:
根據(jù)模型參數(shù)估計(jì)公式,可以得到參數(shù) a, b 的估計(jì)值。但是,使用不同數(shù)據(jù)訓(xùn)練模型的時(shí)候,會(huì)得到不同的參數(shù)估計(jì)值。(這里的不同的數(shù)據(jù),指的是符合同一規(guī)律的數(shù)據(jù))。
例如:我們采用 04/01,04/02,04/03 和 04/04,04/05,04/06 日期的數(shù)據(jù)分別訓(xùn)練模型可得到兩個(gè)估計(jì)值,而且這兩個(gè)值是不相同的:
這是因?yàn)?模型參數(shù)的估計(jì)值只是一個(gè)隨機(jī)變量,具體數(shù)值依賴于使用的數(shù)據(jù)。而且數(shù)學(xué)上可以證明,參數(shù)估計(jì)值本身是隨機(jī)變量,并且服從正態(tài)分布。
數(shù)學(xué)上的證明較為繁瑣,所以這里就采用一個(gè)實(shí)證的例子:
既然得到的估計(jì)值只是隨機(jī)變量的一次觀測值,那么我們更關(guān)心這個(gè)估計(jì)值離真實(shí)值有多遠(yuǎn)?
在統(tǒng)計(jì)學(xué)里,解決方案就是?定義參數(shù)真實(shí)值的置信區(qū)間。
在上面的證明,我們可以得知估計(jì)值服從以真實(shí)值為期望的正態(tài)分布。參數(shù)的真實(shí)值就是 a 。我們假設(shè)這個(gè)正態(tài)分布的方差為σ2,那么大部分估計(jì)值就會(huì)落在以 真實(shí)值a 為中心,2倍 σ 為半徑的區(qū)間里面。
將其翻譯為數(shù)學(xué)公式,即為:
因此,可以定義參數(shù) a 的 95% 的置信區(qū)間:
所以,95%的置信區(qū)間表示:
重復(fù)100次的模型訓(xùn)練,并按公式得到置信區(qū)間,那么有95次,參數(shù) a 的真實(shí)值將落在這個(gè)區(qū)間里。
也可以 “通俗地” 理解為參數(shù) a 的大概取值范圍。
后面一句話其實(shí)不太嚴(yán)謹(jǐn),因?yàn)橐婚_始 假設(shè) 參數(shù) a 的真實(shí)值是一個(gè)確定的值,但是現(xiàn)在又說大概的范圍,這又將參數(shù) a 作為一個(gè)隨機(jī)值進(jìn)行處理,這前后是矛盾的。不過,依然可以這樣通俗的進(jìn)行理解。
置信區(qū)間就是控制模型結(jié)果隨機(jī)性的一個(gè)工具。也就是說我們得到的參數(shù)的估計(jì)值其實(shí)是一個(gè)隨機(jī)變量。它并不等于真實(shí)值,但是我們可以用置信區(qū)間去控制這個(gè)真實(shí)值大概所在的區(qū)間范圍是多少。
2.5 假設(shè)檢驗(yàn)
除了置信區(qū)間外,還可以使用假設(shè)檢驗(yàn)來得到更有把握的結(jié)果。
具體來說,我們剛剛得到了 a 的估計(jì)值,但是我們不知道 a 的真實(shí)值是多少。那么我們可以做一個(gè)假設(shè),比如我們假設(shè) a = 0 。那么根據(jù)這個(gè)假設(shè),以及 a 的估計(jì)值服從正態(tài)分布,那么我們可以得到在 a = 0 的情況下,也就是在這個(gè)假設(shè)成立的條件下,估計(jì)值大致分布的區(qū)間也就是 0-2σ 到 0+2σ。
這時(shí),我們得到模型估計(jì)值是 0.98 。它沒有落在大致分布的區(qū)間內(nèi),這是概率很小的事情。那么在這個(gè)情況下,我們就可以拒絕之前的假設(shè) a = 0。因?yàn)樵谶@個(gè)假設(shè)成立的條件下,幾乎不可能的事情發(fā)生了。
換個(gè)角度來看,使用剛剛定義的置信區(qū)間,我們得到 0 并沒有在置信區(qū)間內(nèi),根據(jù)這個(gè)我們也可以拒絕 a = 0? 這樣的一個(gè)假設(shè)。
總結(jié)一下:
1. 對于單個(gè)參數(shù)的假設(shè)檢驗(yàn)與置信區(qū)間比較類似,二者相通。
2. 也可以對多個(gè)參數(shù)做組合的假設(shè)檢驗(yàn)。
3. 模型陷阱(過擬合與模型幻覺)
3.1 模型陷阱概述
在現(xiàn)實(shí)生活中,搭建模型主要有兩種用途。
1. 正向運(yùn)用:對未知情況做預(yù)測。(也就是知道 x1, x2, x3.....對 y 值進(jìn)行預(yù)測)
要求準(zhǔn)確度很高,得到的 y 越接近真實(shí)值越好。
易受到過度擬合干擾。
2. 反向運(yùn)用:解釋數(shù)據(jù)之間的聯(lián)動(dòng)效應(yīng)。(也就是目標(biāo)值 y 與什么變量有關(guān))
數(shù)據(jù)驅(qū)動(dòng)的本質(zhì)。不是特別關(guān)心模型的準(zhǔn)確性,而是關(guān)心模型的可靠性。
易受到模型幻覺干擾。(也就是誤以為某個(gè) x 與最終值 y 是有關(guān)系的)
過度擬合?和?模型幻覺?統(tǒng)稱為?模型陷阱。
3.2 過度擬合
同樣以 y=x 為真實(shí)的模型結(jié)果為例。隨著模型更加復(fù)雜,均方差和決定系數(shù)確實(shí)是向更好的方向進(jìn)行發(fā)展。但是實(shí)際上我們知道模型就是最簡單的 y=x 線性模型。這里就是一個(gè)悖論,我們使用評估模型的指標(biāo)并沒有挑選出更真實(shí)的模型,這就是所謂的過度擬合。
對于過度擬合來說
1. 對于已知數(shù)據(jù),模型越復(fù)雜 “效果越好”。
這里有一個(gè)既當(dāng)運(yùn)動(dòng)員又當(dāng)裁判員的問題。歷史數(shù)據(jù)我們用來搭建模型,但也使用它來對模型的效果進(jìn)行評估,這是導(dǎo)致這個(gè)問題的原因。
2. 模型的擴(kuò)展性非常差。
如果我們使用后面三幅圖的模型進(jìn)行預(yù)測,那么結(jié)果是非常不準(zhǔn)確的。
解決方法分為兩類:
1. 數(shù)據(jù)層面
在現(xiàn)實(shí)生活中,模型的使用周期如下圖
由于我們的目的是為了預(yù)測未知數(shù)據(jù),所以我們可以把歷史數(shù)據(jù)集分為兩份。一份是訓(xùn)練集,一份是測試集。首先使用訓(xùn)練集估計(jì)模型的參數(shù),然后采用測試集評估模型效果。
通過這種辦法,就可以把部分歷史數(shù)據(jù)當(dāng)成了未知數(shù)據(jù)。
2. 模型層面
模型層面的解決方法:奧卡姆剃刀原則。
對于訓(xùn)練集來說,通常模型越復(fù)雜,結(jié)果的誤差也就越小(如下圖 藍(lán)線)。但對于測試集來說,當(dāng)模型太復(fù)雜通常會(huì)遇到?過度擬合?的現(xiàn)象,當(dāng)模型太簡單會(huì)遇到?欠擬合?的現(xiàn)象,這兩種現(xiàn)象誤差都會(huì)很大。
我們的目的是選擇?剛剛好的模型復(fù)雜程度使得在測試集上的誤差達(dá)到最小。
但在現(xiàn)實(shí)中,最佳選擇是非常難實(shí)現(xiàn)的。這時(shí)候有一個(gè)很好的解決辦法,就是奧卡姆剃刀原則。
Occam's Razor: 如無必要,切勿假定繁多。
這句話的意思是,如果兩個(gè)模型對于未知數(shù)據(jù)的預(yù)測結(jié)果差不多的時(shí)候,應(yīng)該選擇更加簡單的那個(gè)模型。
3.3 機(jī)器學(xué)習(xí)對于模型幻覺的解決方法(懲罰項(xiàng) L1,L2范數(shù)及網(wǎng)格搜尋)
在現(xiàn)實(shí)中,控制模型復(fù)雜程度的方法主要有兩種:
1. 模型本身的復(fù)雜度。(比如 線性回歸 比 神經(jīng)網(wǎng)絡(luò) 更簡單)。
2. 模型使用的特征,包括個(gè)數(shù)以及特征的復(fù)雜度。( x 的個(gè)數(shù))
第二種方法實(shí)現(xiàn)起來更加容易,但是會(huì)引起 模型幻覺。
模型幻覺 指?不相關(guān)的特征?被加入到模型里,且被認(rèn)為與預(yù)測結(jié)果有相關(guān)性。
3.3.1 懲罰項(xiàng)
回顧一下使用的數(shù)據(jù),x 指的是玩偶個(gè)數(shù),y 指的是生產(chǎn)成本。他們之間的關(guān)系是?y = x + 一個(gè)隨機(jī)變量
這時(shí)我們引入一個(gè)不相關(guān)的變量 z,但是這里假設(shè)我們不知道它是無關(guān)的。這時(shí)的方程就變成了
y = ax + bz + c
但是其實(shí)在這個(gè)模型里參數(shù) b 和 c的真實(shí)值都為 0 。
根據(jù)之前的討論,可以定義 y = ax + bz + c 的損失函數(shù)。在 損失函數(shù)L 中我們希望 讓真實(shí)值等于 0 的 b,c 盡可能的靠近 0 。
解決方案就是?加入懲罰項(xiàng)?。加入懲罰項(xiàng)后,a, b, c 的值越遠(yuǎn)離 0 ,損失函數(shù) L 的值也就越大。這就使得模型的參數(shù)盡可能的靠近 0 。從另外一個(gè)角度來說,如果 b 的估計(jì)值為 0 ,這相當(dāng)于在模型里沒有使用變量 z 通過這種方式,自動(dòng)地限制了模型的復(fù)雜程度。在理想情況下,無論參數(shù) b 的值是多少,都不會(huì)影響原損失函數(shù)的取值,因此這樣的一個(gè)公式會(huì)使?不相關(guān)的 b 和 c 靠近 0?, 而不是讓 a 靠近 0 。
其中?α 被稱為懲罰力度。
上面的懲罰項(xiàng)被稱為?L1懲罰項(xiàng)(L1 范數(shù)),如果加入了 L1懲罰項(xiàng),整個(gè)模型就被稱為?Lasso回歸。
下面的懲罰項(xiàng)被稱為?L2懲罰項(xiàng)(L2 范數(shù)),如果加入了 L2懲罰項(xiàng),整個(gè)模型就被稱為?Ridge回歸。
3.3.2 網(wǎng)格搜尋
首先,看看增加懲罰項(xiàng)后,模型的結(jié)果有什么變化。我們可以看出懲罰力度 α 越大,b 和 c 的估計(jì)值越靠近于 0 ,a 的值就越靠近于 1 。三者越來越靠近它的真實(shí)值。但是這不意味著 懲罰力度?α 總是越大越好。那該如何選擇?懲罰力度?α?呢??
這里需要注意的是,對于 a, b, c 是有數(shù)學(xué)公式來求最優(yōu)值的。但是 懲罰力度?α 是沒有的。能想到的辦法就只有?網(wǎng)格搜尋,也就是一種遍歷的辦法。給定一些 α 的備選值分別去訓(xùn)練模型。最后選擇技術(shù)指標(biāo)最好的 α 作為最終的 α 。
總結(jié)一下,機(jī)器學(xué)習(xí)對于模型幻覺的解決辦法。這里還有一個(gè)問題,如果模型有超參數(shù),那么測試集也出現(xiàn)了既當(dāng)裁判員又當(dāng)運(yùn)動(dòng)員的問題。即超參數(shù)選擇和測試指標(biāo)都用了測試集。這時(shí)候就將數(shù)據(jù)分成三個(gè)集合 訓(xùn)練集,驗(yàn)證集,測試集。這樣就解決了這個(gè)問題。
a,b,c 是模型的參數(shù),懲罰力度?α 是模型的超參數(shù)。
3.4 統(tǒng)計(jì)分析的解決方法(假設(shè)檢驗(yàn))
模型的式子是 y = ax + bz + c,在圖片中我們可以得到?b,c的估計(jì)值都不等于0,但是根據(jù)后面的結(jié)果,我們可以得到?b,c都不顯著。換句話說,并不能拒絕 b,c 的真實(shí)值等于0的假設(shè)。換個(gè)角度看,在 b,c 的95%置信區(qū)間內(nèi)都包含了0,所以依然并不能拒絕 b,c 的真實(shí)值等于0的假設(shè)。所以才實(shí)際操作中,如果模型的參數(shù)不顯著,就可以將其排除。因此?將變量 z 排除出模型,重新建模。參數(shù) c 被稱為截距項(xiàng),是一個(gè)特殊的參數(shù),這里并不排除。
3.5 機(jī)器學(xué)習(xí)和統(tǒng)計(jì)解決模型幻覺的方法比較
機(jī)器學(xué)習(xí)雖然使無關(guān)變量前面的系數(shù)盡可能接近于 0 ,但是仍未能完全排除。而統(tǒng)計(jì)分析可以將無關(guān)的變量完全排除出模型。但這就說明統(tǒng)計(jì)分析需要更多的人為干預(yù),是否排除無關(guān)變量是一個(gè)人為的選擇,隨意性較大。(具體是多少的顯著度是沒辦法量化的,比如 顯著度5%還是1% 就認(rèn)為不顯著)。
目的在于預(yù)測,可以采用機(jī)器學(xué)習(xí)方法。目的在于分析 y 和 x 之間的關(guān)系,盡可能使用統(tǒng)計(jì)方法。
4. 模型的生命周期
模型的一生分為兩個(gè)階段。一是模型的訓(xùn)練(下圖虛線以下部分),二是模型的使用(下圖虛線以上部分)。
連接這兩個(gè)階段的IT工具就是模型的保存和讀取。
如果訓(xùn)練模型和使用模型都是 Python 程序,則可以使用 pickle 來實(shí)現(xiàn)模型的持久化(保存和讀取)。
pickle 是 Python 的一個(gè)標(biāo)準(zhǔn)模塊,它可以將 Python 對象保存為文件,也可以從保存文件里還原相應(yīng)的 Python 對象。
如果訓(xùn)練模型和使用模型分別使用兩種不同的語言,則可以使用 PMML 來實(shí)現(xiàn)模型在不同編程語言之間的保存和讀取。
PMML 是一種描述預(yù)測模型的標(biāo)準(zhǔn),它與使用的編程語言無關(guān)。
PMML 主要記錄三類信息:模型類別、模型變量、模型參數(shù)。
# -*- coding: UTF-8 -*-"""此腳本用于展示使用sklearn搭建線性回歸模型"""import osimport sysimport numpy as npimport matplotlib.pyplot as pltimport pandas as pdfrom sklearn import linear_modeldef evaluateModel(model, testData, features, labels): """ 計(jì)算線性模型的均方差和決定系數(shù) 參數(shù) ---- model : LinearRegression, 訓(xùn)練完成的線性模型 testData : DataFrame,測試數(shù)據(jù) features : list[str],特征名列表 labels : list[str],標(biāo)簽名列表 返回 ---- error : np.float64,均方差 score : np.float64,決定系數(shù) """ # 均方差(The mean squared error),均方差越小越好 error = np.mean( (model.predict(testData[features]) - testData[labels]) ** 2) # 決定系數(shù)(Coefficient of determination),決定系數(shù)越接近1越好 score = model.score(testData[features], testData[labels]) return error, scoredef visualizeModel(model, data, features, labels, error, score): """ 模型可視化 """ # 為在Matplotlib中顯示中文,設(shè)置特殊字體 plt.rcParams['font.sans-serif']=['SimHei'] # 創(chuàng)建一個(gè)圖形框 fig = plt.figure(figsize=(6, 6), dpi=80) # 在圖形框里只畫一幅圖 ax = fig.add_subplot(111) # 在Matplotlib中顯示中文,需要使用unicode # 在Python3中,str不需要decode if sys.version_info[0] == 3: ax.set_title(u'%s' % "線性回歸示例") else: ax.set_title(u'%s' % "線性回歸示例".decode("utf-8")) ax.set_xlabel('$x$') ax.set_ylabel('$y$') # 畫點(diǎn)圖,用藍(lán)色圓點(diǎn)表示原始數(shù)據(jù) # 在Python3中,str不需要decode if sys.version_info[0] == 3: ax.scatter(data[features], data[labels], color='b', label=u'%s: $y = x + \epsilon$' % "真實(shí)值") else: ax.scatter(data[features], data[labels], color='b', label=u'%s: $y = x + \epsilon$' % "真實(shí)值".decode("utf-8")) # 根據(jù)截距的正負(fù),打印不同的標(biāo)簽 if model.intercept_ > 0: # 畫線圖,用紅色線條表示模型結(jié)果 # 在Python3中,str不需要decode if sys.version_info[0] == 3: ax.plot(data[features], model.predict(data[features]), color='r', label=u'%s: $y = %.3fx$ + %.3f'\ % ("預(yù)測值", model.coef_, model.intercept_)) else: ax.plot(data[features], model.predict(data[features]), color='r', label=u'%s: $y = %.3fx$ + %.3f'\ % ("預(yù)測值".decode("utf-8"), model.coef_, model.intercept_)) else: # 在Python3中,str不需要decode if sys.version_info[0] == 3: ax.plot(data[features], model.predict(data[features]), color='r', label=u'%s: $y = %.3fx$ - %.3f'\ % ("預(yù)測值", model.coef_, abs(model.intercept_))) else: ax.plot(data[features], model.predict(data[features]), color='r', label=u'%s: $y = %.3fx$ - %.3f'\ % ("預(yù)測值".decode("utf-8"), model.coef_, abs(model.intercept_))) legend = plt.legend(shadow=True) legend.get_frame().set_facecolor('#6F93AE') # 顯示均方差和決定系數(shù) # 在Python3中,str不需要decode if sys.version_info[0] == 3: ax.text(0.99, 0.01, u'%s%.3f\n%s%.3f'\ % ("均方差:", error, "決定系數(shù):", score), style='italic', verticalalignment='bottom', horizontalalignment='right', transform=ax.transAxes, color='m', fontsize=13) else: ax.text(0.99, 0.01, u'%s%.3f\n%s%.3f'\ % ("均方差:".decode("utf-8"), error, "決定系數(shù):".decode("utf-8"), score), style='italic', verticalalignment='bottom', horizontalalignment='right', transform=ax.transAxes, color='m', fontsize=13) # 展示上面所畫的圖片。圖片將阻斷程序的運(yùn)行,直至所有的圖片被關(guān)閉 # 在Python shell里面,可以設(shè)置參數(shù)"block=False",使阻斷失效。 plt.show()def trainModel(trainData, features, labels): """ 利用訓(xùn)練數(shù)據(jù),估計(jì)模型參數(shù) 參數(shù) ---- trainData : DataFrame,訓(xùn)練數(shù)據(jù)集,包含特征和標(biāo)簽 features : 特征名列表 labels : 標(biāo)簽名列表 返回 ---- model : LinearRegression, 訓(xùn)練好的線性模型 """ # 創(chuàng)建一個(gè)線性回歸模型 model = linear_model.LinearRegression() # 訓(xùn)練模型,估計(jì)模型參數(shù) model.fit(trainData[features], trainData[labels]) return modeldef linearModel(data): """ 線性回歸模型建模步驟展示 參數(shù) ---- data : DataFrame,建模數(shù)據(jù) """ features = ["x"] labels = ["y"] # 劃分訓(xùn)練集和測試集 trainData = data[:15] testData = data[15:] # 產(chǎn)生并訓(xùn)練模型 model = trainModel(trainData, features, labels) # 評價(jià)模型效果 error, score = evaluateModel(model, testData, features, labels) # 圖形化模型結(jié)果 visualizeModel(model, data, features, labels, error, score)def readData(path): """ 使用pandas讀取數(shù)據(jù) """ data = pd.read_csv(path) return dataif __name__ == "__main__": homePath = os.path.dirname(os.path.abspath(__file__)) # Windows下的存儲(chǔ)路徑與Linux并不相同 if os.name == "nt": dataPath = "%s\\data\\simple_example.csv" % homePath else: dataPath = "%s/data/simple_example.csv" % homePath data = readData(dataPath) linearModel(data)"""此腳本用于如何使用統(tǒng)計(jì)方法解決模型幻覺"""# 保證腳本與Python3兼容from __future__ import print_functionimport osimport numpy as npimport statsmodels.api as smimport matplotlib.pyplot as pltimport pandas as pddef generateRandomVar(): """ """ np.random.seed(4873) return np.random.randint(2, size=20) def evaluateModel(res): """ 分析線性回歸模型的統(tǒng)計(jì)性質(zhì) """ # 整體統(tǒng)計(jì)分析結(jié)果 print(res.summary()) # 用f test檢測x對應(yīng)的系數(shù)a是否顯著 print("檢驗(yàn)假設(shè)z的系數(shù)等于0:") print(res.f_test("z=0")) # 用f test檢測常量b是否顯著 print("檢測假設(shè)const的系數(shù)等于0:") print(res.f_test("const=0")) # 用f test檢測a=1, b=0同時(shí)成立的顯著性 print("檢測假設(shè)z和const的系數(shù)同時(shí)等于0:") print(res.f_test(["z=0", "const=0"]))def trainModel(X, Y): """ 訓(xùn)練模型 """ model = sm.OLS(Y, X) res = model.fit() return resdef confidenceInterval(data): """ """ features = ["x"] labels = ["y"] Y = data[labels] _X = data[features] # 加入新的隨機(jī)變量,次變量的系數(shù)應(yīng)為0 _X["z"] = generateRandomVar() # 加入常量變量 X = sm.add_constant(_X) res = trainModel(X, Y) evaluateModel(res) def generateData(): """ 生成模型數(shù)據(jù) """ np.random.seed(5320) x = np.array(range(0, 20)) / 2 error = np.round(np.random.randn(20), 2) y = 0.05 * x + error # 新加入的無關(guān)變量z恒等于1 z = np.zeros(20) + 1 return pd.DataFrame({"x": x, "z": z, "y": y})def wrongCoef(): """ 由于新變量的加入,正效應(yīng)變?yōu)樨?fù)效應(yīng) """ features = ["x", "z"] labels = ["y"] data = generateData() X = data[features] Y = data[labels] # 沒有多余變量時(shí),x系數(shù)符號估計(jì)正確,為正 model = sm.OLS(Y, X["x"]) res = model.fit() print("沒有加入新變量時(shí):") print(res.summary()) # 加入多余變量時(shí),x系數(shù)符號估計(jì)錯(cuò)誤,為負(fù) model1 = sm.OLS(Y, X) res1 = model1.fit() print("加入新變量后:") print(res1.summary())def readData(path): """ 使用pandas讀取數(shù)據(jù) """ data = pd.read_csv(path) return dataif __name__ == "__main__": homePath = os.path.dirname(os.path.abspath(__file__)) # Windows下的存儲(chǔ)路徑與Linux并不相同 if os.name == "nt": dataPath = "%s\\data\\simple_example.csv" % homePath else: dataPath = "%s/data/simple_example.csv" % homePath data = readData(dataPath) print("***************************************************") # 在Windows下運(yùn)行此腳本需確保Windows下的命令提示符(cmd)能顯示中文 print("加入不相關(guān)的新變量,新變量的系數(shù)被錯(cuò)誤估計(jì)為不等于0") print("***************************************************") confidenceInterval(data) print("**********************************************") print("加入不相關(guān)的新變量,舊變量系數(shù)的符號被錯(cuò)誤估計(jì)") print("**********************************************") wrongCoef()參考資料:
1、《精通數(shù)據(jù)科學(xué):從線性回歸到深度學(xué)習(xí)》
2、https://www.cnblogs.com/xzt6/p/13379038.html
總結(jié)
以上是生活随笔為你收集整理的线性回归数据_数据科学笔记(三)——线性回归的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python连接spark_python
- 下一篇: 动词ing基本用法_动词ing形式的用法