如何用python實現含有虛擬自變數的迴歸

2021-03-10 01:49:57 字數 8656 閱讀 7664

1樓:匿名使用者

利用python進行線性迴歸

線性迴歸也被稱為最小二乘法迴歸(linear regression, also called ordinary least-squares (ols) regression)。它的數學模型是這樣的:

y = a+ b* x+e

其中,a 被稱為常數項或截距;b 被稱為模型的迴歸係數或斜率;e 為誤差項。a 和 b 是模型的引數。

當然,模型的引數只能從樣本資料中估計出來:

y'= a' + b'* x

我們的目標是選擇合適的引數,讓這一線性模型最好地擬合觀測值。擬合程度越高,模型越好。

那麼,接下來的問題就是,我們如何判斷擬合的質量呢?

這一線性模型可以用二維平面上的一條直線來表示,被稱為迴歸線。

模型的擬合程度越高,也即意味著樣本點圍繞迴歸線越緊密。

如何計算樣本點與迴歸線之間的緊密程度呢?

高斯和勒讓德找到的方法是:被選擇的引數,應該使算出來的迴歸線與觀測值之差的平房和最小。用函式表示為:

這被稱為最小二乘法。最小二乘法的原理是這樣的:當**值和實際值距離的平方和最小時,就選定模型中的兩個引數(a 和 b)。

這一模型並不一定反映解釋變數和反應變數真實的關係。但它的計算成本低;相比複雜模型更容易解釋。

模型估計出來後,我們要回答的問題是:

我們的模型擬合程度如何?或者說,這個模型對因變數的解釋力如何?(r2)

整個模型是否能顯著**因變數的變化?(f 檢驗)

每個自變數是否能顯著**因變數的變化?(t 檢驗)

首先回答第一個問題。為了評估模型的擬合程度如何,我們必須有一個可以比較的基線模型。

如果讓你**一個人的體重是多少?在沒有任何額外資訊的情況下,你可能會用平均值來**,儘管會存在一定誤差,但總比瞎猜好。

現在,如果你知道他的身高資訊,你的**值肯定與平均值不一樣。額外資訊相比平均值更能準確地**被**的變數的能力,就代表模型的解釋力大小。

上圖中,ssa 代表由自變數 x 引起的 y 的離差平方和,即迴歸平方和,代表迴歸模型的解釋力;sse 代表由隨機因素引起的 y 的離差平方和,即剩餘平方和,代表迴歸模型未能解釋的部分;sst 為總的離差平方和,即我們僅憑 y 的平均值去估計 y 時所產生的誤差。

用模型能夠解釋的變異除以總的變異就是模型的擬合程度:

r2=ssa/sst=1-sse

r2(r 的平方)也被稱為決定係數或判定係數。

第二個問題,我們的模型是否顯著**了 y 的變化?

假設 y 與 x 的線性關係不明顯,那麼 ssa 相對 sse 佔有較大的比例的概率則越小。換句話說,在 y 與 x 無線性關係的前提下,ssa 相對 sse 的佔比越高的概率是越小的,這會呈現一定的概率分佈。統計學家告訴我們它滿足 f 分佈,就像這樣:

如果 ssa 相對 sse 佔比較大的情況出現了,比如根據 f 分佈,這個值出現的概率小於 5%。那麼,我們最好是拒絕 y 與 x 線性關係不顯著的原始假設,認為二者存在顯著的線性關係較為合適。

第三個問題,每個自變數是否能顯著**因變數的變化?換句話說,迴歸係數是否顯著?

迴歸係數的顯著性檢驗是圍繞回歸係數的抽樣分佈(t 分佈)來進行的,推斷過程類似於整個模型的檢驗過程,不贅言。

實際上,對於只有一個自變數的一元線性模型,模型的顯著性檢驗和迴歸係數的檢驗是一致的,但對於多元線性模型來說,二者就不能等價了。

利用 stat**odels 進行最小二乘迴歸

#匯入相應模組

in [1]: import numpy as np

in [2]: import pandas as pd

in [3]: import stat**odels.api as **

#將資料匯入 pandas 的 dataframe 物件,第一列(年份)作為行標籤

in [4]: df=pd.read_csv('/users/xiangzhendong/downloads/vincentarelbundock-rdatasets-1218370/csv/datasets/longley.

csv', index_col=0)

#檢視頭部資料

in [5]: df.head()

out[5]:

gnp.deflator      gnp  unemployed  armed.forces  population  year  \

1947          83.0  234.289       235.6         159.0     107.608  1947

1948          88.5  259.426       232.5         145.6     108.632  1948

1949          88.2  258.054       368.2         161.6     109.773  1949

1950          89.5  284.599       335.1         165.0     110.929  1950

1951          96.2  328.975       209.9         309.9     112.075  1951

employed

1947    60.323

1948    61.122

1949    60.171

1950    61.187

1951    63.221

#設定**變數和結果變數,用 gnp ** employed

in [6]: y=df.employed #結果變數

in [7]: x=df.gnp #**變數

#為模型增加常數項,即迴歸線在 y 軸上的截距

in [8]: x=**.add_constant(x)

#執行最小二乘迴歸,x 可以是 numpy array 或 pandas dataframe(行數等於資料點個數,列數為**變數個數),y 可以是一維陣列(numpy array)或 pandas series

in [10]: est=**.ols(y,x)

使用 ols 物件的 fit() 方法來進行模型擬合

in [11]: est=est.fit()

#檢視模型擬合的結果

in [12]: est.summary()

out[12]:

#檢視最終模型的引數

in [13]: est.params

out[13]:

const    51.843590

gnp       0.034752

dtype: float64

#選擇 100 個從最小值到最大值平均分佈(equally spaced)的資料點

in [14]: x_prime=np.linspace(x.gnp.min(), x.gnp.max(),100)[:,np.newaxis]

in [15]: x_prime=**.add_constant(x_prime)

#計算**值

in [16]: y_hat=est.predict(x_prime)

in [17]: plt.scatter(x.gnp, y, alpha=0.3) #畫出原始資料

#分別給 x 軸和 y 軸命名

in [18]: plt.xlabel("gross national product")

in [19]: plt.ylabel("total employment")

in [20]: plt.plot(x_prime[:,1], y_hat, 'r', alpha=0.9) #新增迴歸線,紅色

多元線性迴歸(**變數不止一個)

我們用一條直線來描述一元線性模型中**變數和結果變數的關係,而在多元迴歸中,我們將用一個多維(p)空間來擬合多個**變數。下面表現了兩個**變數的三維圖形:商品的銷量以及在電視和廣播兩種不同媒介的廣告預算。

數學模型是:

sales = beta_0 + beta_1*tv + beta_2*radio

圖中,白色的資料點是平面上的點,黑色的資料點事平面下的點。平面的顏色是由對應的商品銷量的高低決定的,高是紅色,低是藍色。

利用 stat**odels 進行多元線性迴歸

in [1]: import pandas as pd

in [2]: import numpy as np

in [3]: import stat**odels.api as **

in [4]: df_adv=pd.read_csv('g.csv',index_col=0)

in [6]: x=df_adv[['tv','radio']]

in [7]: y=df_adv['sales']

in [8]: df_adv.head()

out[8]:

tv  radio  news*****  sales

1  230.1   37.8       69.2   22.1

2   44.5   39.3       45.1   10.4

3   17.2   45.9       69.3    9.3

4  151.5   41.3       58.5   18.5

5  180.8   10.8       58.4   12.9

in [9]: x=**.add_constant(x)

in [10]: est=**.ols(y,x).fit()

in [11]: est.summary()

out[11]:

你也可以使用 stat**odels 的 formula 模組來建立多元迴歸模型

in [12]: import stat**odels.formula.api as **f

in [13]: est=**f.ols(formula='sales ~ tv + radio',data=df_adv).fit()

處理分類變數

性別或地域都屬於分類變數。

in [15]: df= pd.read_csv('httd.

edu/~tibs/elemstatlearn/datasets/saheart.data', index_col=0)

in [16]: x=df.copy()

利用 dataframe 的 pop 方法將 chd 列單獨提取出來

in [17]: y=x.pop('chd')

in [18]: df.head()

out[18]:

sbp  tobacco   ldl  adiposity  famhist  typea  obesity  alcohol  \

row.names

1          160    12.00  5.73      23.11  present     49    25.30    97.20

2          144     0.01  4.41      28.61   absent     55    28.87     2.06

3          118     0.08  3.48      32.28  present     52    29.14     3.81

4          170     7.50  6.41      38.03  present     51    31.99    24.26

5          134    13.60  3.50      27.78  present     60    25.99    57.34

age  chd

row.names

1           52    1

2           63    1

3           46    0

4           58    1

5           49    1

in [19]: y.groupby(x.famhist).mean()

out[19]:

famhist

absent     0.237037

present    0.500000

name: chd, dtype: float64

in [20]: import stat**odels.formula.api as **f

in [21]: df['famhist_ord']=pd.categorical(df.famhist).labels

in [22]: est=**f.ols(formula="chd ~ famhist_ord", data=df).fit()

分類變數的編碼方式有許多,其中一種編碼方式是虛擬變數編碼(dummy-encoding),就是把一個 k 個水平的分類變數編碼成 k-1 個二分變數。在 stat**odels 中使用 c 函式實現。

in [24]: est=**f.ols(formula="chd ~ c(famhist)", data=df).fit()

in [26]: est.summary()

out[26]:

處理互動作用

隨著教育年限(education)的增長,薪酬 (wage) 會增加嗎?這種影響對男性和女性而言是一樣的嗎?

這裡的問題就涉及性別與教育年限的互動作用。

換言之,教育年限對薪酬的影響是男女有別的。

#匯入相關模組

in [1]: import pandas as pd

in [2]: import numpy as np

in [4]: import stat**odels.api as **

#匯入資料,存入 dataframe 物件

in [5]: df=pd.read_csv('/users/xiangzhendong/downloads/pydatafromweb/wages.csv')

in [6]: df[['wage','education','***']].tail()

out[6]:

wage  education  ***

529  11.36         18    0

530   6.10         12    1

531  23.25         17    1

532  19.88         12    0

533  15.38         16    0

由於性別是一個二分變數,我們可以繪製兩條迴歸線,一條是 ***=0(男性),一條是 ***=1(女性)

#繪製散點圖

in [7]: plt.scatter(df.education,df.wage, alpha=0.3)

in [9]: plt.xlabel('education')

in [10]: plt.ylabel('wage')

#linspace 的作用是生成從最小到最大的均勻分佈的 n 個數

in [17]: education_linspace=np.linspace(df.

education.min(), df.education.

max(),100)

in [12]: import stat**odels.formula.api as **f

in [13]: est=**f.ols(formula='wage ~ education + ***', data=df).fit()

in [18]: plt.plot(education_linspace, est.

params[0]+est.params[1]education_linspace+est.params[2]0, 'r')

in [19]: plt.plot(education_linspace, est.

params[0]+est.params[1]education_linspace+est.params[2]1, 'g')

以上兩條線是平行的。這是因為分類變數隻影響迴歸線的截距,不影響斜率。

接下來我們可以為迴歸模型增加互動項來探索互動效應。也就是說,對於兩個類別,迴歸線的斜率是不一樣的。

in [32]: plt.scatter(df.education,df.wage, alpha=0.3)

in [33]: plt.xlabel('education')

in [34]: plt.ylabel('wage')

#使用*代表我們的迴歸模型中除了互動效應,也包括兩個變數的主效應;如果只想看互動效應,可以用:代替,但通常不會只看互動效應

in [35]: est=**f.ols(formula='wage ~ ****education', data=df).fit()

in [36]: plt.plot(education_linspace, est.

params[0]+est.params[1]0+est.params[2]education_linspace+est.

params[3]0education_linspace, 'r')

in [37]: plt.plot(education_linspace, est.

params[0]+est.params[1]1+est.params[2]education_linspace+est.

params[3]1education_linspace, 'g')

參考資料:

datarobot | ordinary least squares in python

dataroboe | multiple regression using stat**odels

analyticsvidhya | 7 types of regression techniques you should know!

python畫箭頭圖如何用python畫格點上的箭頭圖

我也遇到了和你相同的問題,我們應該看的是同一本書 機器學習實戰 決策樹部分,目前我也找不到解決的方法,是不是 matplotlib 版本的問題 我用的是1.5.0版本!python 中的 turtle 模組怎麼做到多個箭頭同時作圖。有用必採納 可以考慮使用多程序,產生多個 turtle。python...

如何用Python寫Linux命令

有其中一種方法,可以呼叫os庫 import os os.system ls 這樣就執行了 linux ls 命令了 python指令碼在linux上怎麼執行 如果你的linux安裝了python,按ctrl alt t鍵開啟terminal,輸入指令 python。會出現 這個時候就可以在裡面輸入...

如何用python畫五角星,如何用python畫一個五角星

usr bin env pythonimport turtle import time turtle.forward 100 turtle.right 144 time.sleep 1 turtle.forward 100 turtle.right 144 time.sleep 1 turtle.f...