實驗數據:html
第一步:準備樣本數據並繪製散點圖python
1)代碼及其說明算法
import numpy as np import scipy as sp import matplotlib.pyplot as plt from scipy.optimize import leastsq ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) #身高 Yi=np.array([58,63,57,65,62,66,58,59,62])#體重 #畫樣本點 plt.figure(figsize=(8,6)) ##指定圖像比例: 8:6 plt.scatter(Xi,Yi,color="green",label="樣本數據",linewidth=1) plt.show()
2)結果圖api
3)分析數組
從散點圖能夠看出,樣本點基本是圍繞箭頭所示的直線分佈的。因此先以直線模型對數據進行擬合app
第二步: 使用最小二乘法算法求擬合直線機器學習
1)代碼及其說明函數
import numpy as np import scipy as sp import matplotlib.pyplot as plt from scipy.optimize import leastsq ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) Yi=np.array([58,63,57,65,62,66,58,59,62]) ##須要擬合的函數func :指定函數的形狀 k= 0.42116973935 b= -8.28830260655 def func(p,x): k,b=p return k*x+b ##誤差函數:x,y都是列表:這裏的x,y更上面的Xi,Yi中是一一對應的 def error(p,x,y): return func(p,x)-y #k,b的初始值,能夠任意設定,通過幾回試驗,發現p0的值會影響cost的值:Para[1] p0=[1,20] #把error函數中除了p0之外的參數打包到args中(使用要求) Para=leastsq(error,p0,args=(Xi,Yi)) #讀取結果 k,b=Para[0] print("k=",k,"b=",b) #畫樣本點 plt.figure(figsize=(8,6)) ##指定圖像比例: 8:6 plt.scatter(Xi,Yi,color="green",label="樣本數據",linewidth=2) #畫擬合直線 x=np.linspace(150,190,100) ##在150-190直接畫100個連續點 y=k*x+b ##函數式 plt.plot(x,y,color="red",label="擬合直線",linewidth=2) plt.legend() #繪製圖例 plt.show()
2)結果圖學習
3)分析spa
從圖上看,擬合效果仍是不錯的。樣本點基本均勻的分佈在迴歸線兩邊,沒有出現數據點嚴重偏離迴歸線的狀況。
第三步: 驗證迴歸線的擬合程度—殘差分佈圖
1)代碼及其說明
import numpy as np import matplotlib.pyplot as plt import statsmodels.api as sm from statsmodels.graphics.api import qqplot ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) Yi=np.array([58,63,57,65,62,66,58,59,62]) xy_res=[] ##計算殘差 def residual(x,y): res=y-(0.42116973935*x-8.28830260655) return res ##讀取殘差 for d in range(0,len(Xi)): res=residual(Xi[d],Yi[d]) xy_res.append(res) ##print(xy_res) ##計算殘差平方和:22.8833439288 -->越小擬合狀況越好 xy_res_sum=np.dot(xy_res,xy_res) #print(xy_res_sum) ##若是數據擬合模型效果好,殘差應該聽從正態分佈(0,d*d:這裏d表示殘差) #畫樣本點 fig=plt.figure(figsize=(8,6)) ##指定圖像比例: 8:6 ax=fig.add_subplot(111) fig=qqplot(np.array(xy_res),line='q',ax=ax) plt.show()
2)結果圖
3)分析
上圖爲Q-Q圖,原理:若是兩個分佈類似,則該Q-Q圖趨近於落在y=x線上。若是兩分佈線性相關,則點在Q-Q圖上趨近於落在一條直線上,但不必定在y=x線上。Q-Q圖能夠用來可在分佈的位置-尺度範疇上可視化的評估參數。
從圖上能夠看出,迴歸效果比較理想,但不是最理想的
4)如下代碼能夠一樣實現上述圖示:
import numpy as np import scipy.stats as stats import pylab ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) Yi=np.array([58,63,57,65,62,66,58,59,62]) xy_res=[] ##計算殘差 def residual(x,y): res=y-(0.42116973935*x-8.28830260655) return res ##讀取殘差 for d in range(0,len(Xi)): res=residual(Xi[d],Yi[d]) xy_res.append(res) ##print(xy_res) ##計算殘差平方和:22.8833439288 -->越小擬合狀況越好 xy_res_sum=np.dot(xy_res,xy_res) #print(xy_res_sum) ##若是數據擬合模型效果好,殘差應該聽從正態分佈(0,d*d:這裏d表示殘差) #畫樣本點 stats.probplot(np.array(xy_res),dist="norm",plot=pylab) pylab.show()
第四步: 驗證迴歸線的擬合程度—標準化殘差
1)代碼及其說明
import numpy as np import matplotlib.pyplot as plt ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) Yi=np.array([58,63,57,65,62,66,58,59,62]) xy_res=[] ##計算殘差 def residual(x,y): res=y-(0.42116973935*x-8.28830260655) return res ##讀取殘差 for d in range(0,len(Xi)): res=residual(Xi[d],Yi[d]) xy_res.append(res) ##print(xy_res) ##計算殘差平方和:22.8833439288 -->越小擬合狀況越好 xy_res_sum=np.dot(xy_res,xy_res) ''' 標準殘差: (殘差-殘差平均值)/殘差的標準差 ''' ''' 標準殘差圖: 1.標準殘差是以擬合模型的自變量爲橫座標,以標準殘差爲縱座標造成的平面座標圖像 2.試驗點的標準殘差落在殘差圖的(-2,2)區間之外的機率<=0.05.若某一點落在區間外,可判爲異常點 3.有效標準殘差點圍繞y=0的直線上下徹底隨機分佈,說明擬合狀況良好 4.若是擬合方程本來是非線性模型,但擬合時卻採用了線性模型,標準化殘差圖就會表現出曲線形狀,產生 系統性誤差 ''' ##計算殘差平均值 xy_res_avg=0 for d in range(0,len(xy_res)): xy_res_avg+=xy_res[d] xy_res_avg/=len(xy_res) #殘差的標準差 xy_res_sd=np.sqrt(xy_res_sum/len(Xi)) ##標準化殘差 xy_res_sds=[] for d in range(0,len(Xi)): res=(xy_res[d]-xy_res_avg)/xy_res_sd xy_res_sds.append(res) #print(xy_res_sds) #標準化殘差分佈 plt.figure(figsize=(8,6)) ##指定圖像比例: 8:6 plt.scatter(Xi,xy_res_sds) plt.show() ''' 1.絕大部分數據分佈在(-2,+2)的水平帶狀區間內,所以模型擬合較充分 2.數據點分佈稍均勻,但沒有達到隨機均勻分佈的狀態。此外,部分數據點還呈現某種曲線波動形狀, 有少量系統性誤差。所以可能採用非線性擬合效果會更好 '''
2)結果圖
3)分析
數據點分佈仍是存在必定的變化趨勢的。
第五步:使用曲線模型擬合數據
1)代碼及其說明
import numpy as np import scipy as sp import matplotlib.pyplot as plt from scipy.optimize import leastsq ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) Yi=np.array([58,63,57,65,62,66,58,59,62]) ##須要擬合的函數func :指定函數的形狀 k= 0.860357336936 b= -19.6659389666 def func(p,x): k,b=p return x**k+b ##誤差函數:x,y都是列表:這裏的x,y更上面的Xi,Yi中是一一對應的 def error(p,x,y): return func(p,x)-y #k,b的初始值,能夠任意設定,通過幾回試驗,發現p0的值會影響cost的值:Para[1] p0=[1,20] #把error函數中除了p0之外的參數打包到args中(使用要求) Para=leastsq(error,p0,args=(Xi,Yi)) #讀取結果 k,b=Para[0] print("k=",k,"b=",b) #畫樣本點 plt.figure(figsize=(8,6)) ##指定圖像比例: 8:6 plt.scatter(Xi,Yi,color="green",label="樣本數據",linewidth=2) #畫擬合直線 x=np.linspace(150,190,100) ##在150-190直接畫100個連續點 y=x**k+b ##函數式 plt.plot(x,y,color="red",label="擬合直線",linewidth=2) plt.legend() #繪製圖例 plt.show()
2)結果圖
3)分析
因爲標準化殘差的分佈圖,部分數據的趨勢與冪函數在第一象限的圖像相似, 因此採用了y=xa +b的函數形式,截距b是爲了圖像能夠在Y軸上下移動
第六步:驗證迴歸線的擬合程度—殘差分佈圖
1)代碼及其說明
import numpy as np import matplotlib.pyplot as plt import statsmodels.api as sm from statsmodels.graphics.api import qqplot ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) Yi=np.array([58,63,57,65,62,66,58,59,62]) xy_res=[] ##計算殘差 def residual(x,y): res=y-(x**0.860357336936-19.6659389666) return res ##讀取殘差 for d in range(0,len(Xi)): res=residual(Xi[d],Yi[d]) xy_res.append(res) ##print(xy_res) ##計算殘差平方和:22.8833439288 -->越小擬合狀況越好 xy_res_sum=np.dot(xy_res,xy_res) #print(xy_res_sum) ##若是數據擬合模型效果好,殘差應該聽從正態分佈(0,d*d:這裏d表示殘差) #畫樣本點 fig=plt.figure(figsize=(8,6)) ##指定圖像比例: 8:6 ax=fig.add_subplot(111) fig=qqplot(np.array(xy_res),line='q',ax=ax) plt.show()
2)結果圖
3)分析
從圖上能夠看出,迴歸效果也比較理想
第七步:驗證迴歸線的擬合程度—標準化殘差
1)代碼及其說明
import numpy as np import matplotlib.pyplot as plt ##樣本數據(Xi,Yi),須要轉換成數組(列表)形式 Xi=np.array([160,165,158,172,159,176,160,162,171]) Yi=np.array([58,63,57,65,62,66,58,59,62]) xy_res=[] ##計算殘差 def residual(x,y): res=y-(x**0.860357336936-19.6659389666) return res ##讀取殘差 for d in range(0,len(Xi)): res=residual(Xi[d],Yi[d]) xy_res.append(res) ##print(xy_res) ##計算殘差平方和:22.881076636 -->越小擬合狀況越好 xy_res_sum=np.dot(xy_res,xy_res) #print(xy_res_sum) ''' 標準殘差: (殘差-殘差平均值)/殘差的標準差 ''' ##計算殘差平均值 xy_res_avg=0 for d in range(0,len(xy_res)): xy_res_avg+=xy_res[d] xy_res_avg/=len(xy_res) #殘差的標準差 xy_res_sd=np.sqrt(xy_res_sum/len(Xi)) ##標準化殘差 xy_res_sds=[] for d in range(0,len(Xi)): res=(xy_res[d]-xy_res_avg)/xy_res_sd xy_res_sds.append(res) print(xy_res_sds) #標準化殘差分佈 plt.figure(figsize=(8,6)) ##指定圖像比例: 8:6 plt.scatter(Xi,xy_res_sds) plt.show() ''' 1.絕大部分數據分佈在(-2,+2)的水平帶狀區間內,所以模型擬合較充分 2.數據點分佈稍均勻,但沒有達到隨機均勻分佈的狀態。此外,部分數據點還呈現某種曲線波動形狀, 有少量系統性誤差。所以可能採用非線性擬合效果會更好 '''
2)結果圖
3)分析
數據點分佈趨和直線迴歸方程基本同樣
補充說明:
其實整個實驗過程並無達到預期效果。
1)若是對實驗過程的5-7步使用R語言從新實驗(R語言提供了全部相關函數),第7步的效果以下:
也就說全部的標準化殘差都是落在(-2,+2)區間內的,即曲線方程纔是最佳擬合方程。
2)標準化殘差沒有找到具體的定義,網上對這個定義有多種解釋
3)標準化殘差的計算方式沒有找到相應的python包,只能按照其中某一個定義本身寫代碼計算(估計是浮點數計算產生的偏差)