一.背景
1.1 數(shù)據(jù)源
現(xiàn)有2000年到2019年的數(shù)據(jù),其中y列表示收入,x1~x13表示與收入相關(guān)聯(lián)的13個特征值。
1.2 處理目的
a.分析、識別影響收入y的關(guān)鍵屬性;
b.預(yù)測2020年、2021年的收入;
二. 分析過程
2.1 讀取數(shù)據(jù)
import pandas as pd
import numpy as np
import sys
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('seaborn')#設(shè)置樣式
plt.rcParams['font.sans-serif']=['SimHei']# 支持中文
plt.rcParams['axes.unicode_minus'] = False #正常顯示負(fù)號
import warnings
warnings.filterwarnings('ignore')
data = pd.read_csv('data/data.csv')
2.2 相關(guān)性分析
使用heatmap來畫圖呈現(xiàn)數(shù)據(jù)相關(guān)性。使用mask為得出的相關(guān)性矩陣corr畫遮罩。
corr = data.corr(method='pearson')
corr
plt.figure(figsize=(12,10))
mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True #cmap是設(shè)置熱圖的顏色
cmap = sns.diverging_palette(220, 10, as_cmap=True)
#繪制熱圖
g = sns.heatmap(corr, mask=mask, cmap=cmap, square=True, annot=True, fmt='0.2f')
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
#plt.savefig("corr.png")
plt.show()
最終得出的相關(guān)性矩陣和相關(guān)關(guān)系圖如下。
從上面的相關(guān)性呈現(xiàn)來看,可以得出以下結(jié)論:
a. 特征值x11與收入y的關(guān)系不顯著,呈現(xiàn)負(fù)相關(guān)。
b. 其余屬性與收入呈現(xiàn)高度正相關(guān)。
c. x2,x3,x7與多條屬性存在共線性。
本次分析目的在于找出與收入y顯著相關(guān)的特征值,然而上述結(jié)果顯示,數(shù)十個指標(biāo)與收入y都呈現(xiàn)顯著性相關(guān),這些屬性之間存在著信息的重復(fù),因此接下來需要運用Lasso回歸來對上述特征值做進一步篩選。
2.3 Lasso回歸-選取相關(guān)變量
使用Lasso回歸,處理共線性,有效降維。
from sklearn.linear_model import Lasso
lasso = Lasso(1000) # 調(diào)用Lasso()函數(shù),設(shè)置λ的值為1000
lasso.fit(data.iloc[:,0:13],data['y'])
tar = lasso.coef_ != 0 # 返回一個相關(guān)系數(shù)是否為零的布爾數(shù)組
data_a = data.iloc[:,0:13]
new_reg_data = data_a.iloc[:, tar ] # 返回相關(guān)系數(shù)非零的數(shù)據(jù)
new_reg_data 即為Lasso回歸選中的新的顯著性特征變量X。下圖為Lasso回歸選出的特征值。
對于x1,x3,x4,x5,x6,x7,x8,x13這些新選取的相關(guān)性特征值,y收入值與他們分別的相關(guān)性系數(shù)如下。
2.4 構(gòu)建灰色預(yù)測模型
白色系統(tǒng):指一個系統(tǒng)的的內(nèi)部特征是完全可以認(rèn)知的,即系統(tǒng)的信息完全公開。
黑色系統(tǒng):指一個系統(tǒng)的內(nèi)部信息對外界來說是一無所知的,只能通過它與外界的聯(lián)系來加以觀測研究。
灰色系統(tǒng):一部分的信息是已知的,另一部分是未知的,系統(tǒng)內(nèi)各因素間有不確定的關(guān)系,GM(1,1)就是灰色系統(tǒng),也是最常用的模型系統(tǒng)。
灰色預(yù)測模型(Gray Forecast Model)是通過少量的、不完全的信息,建立數(shù)學(xué)模型并做出預(yù)測的一種預(yù)測方法。對單調(diào)性曲線有較好的預(yù)測。
定義一個灰色預(yù)測函數(shù)
def GM11(x0):
import numpy as np
x1 = x0.cumsum() #1-AGO序列
z1 = (x1[:len(x1)-1] + x1[1:])/2.0 #緊鄰均值(MEAN)生成序列
z1 = z1.reshape((len(z1),1))
B = np.append(-z1, np.ones_like(z1), axis = 1)
Yn = x0[1:].reshape((len(x0)-1, 1))
[[a],[b]] = np.dot(np.dot(np.linalg.inv(np.dot(B.T, B)), B.T), Yn) #計算參數(shù)
f = lambda k: (x0[0]-b/a)*np.exp(-a*(k-1))-(x0[0]-b/a)*np.exp(-a*(k-2)) #還原值
delta = np.abs(x0 - np.array([f(i) for i in range(1,len(x0)+1)]))
C = delta.std()/x0.std()
P = 1.0*(np.abs(delta - delta.mean()) < 0.6745*x0.std()).sum()/len(x0)
return f, a, b, x0[0], C, P #返回灰色預(yù)測函數(shù)、a、b、首項、方差比、小殘差概率
new_reg_data 為上一個步驟選取的特征值。給接下來需要預(yù)測的兩個年份填上空值。
new_reg_data.index = range(2000,2020)
#給接下來兩個年份填上空值
new_reg_data.loc[2020] = None
new_reg_data.loc[2021] = None
l = ['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']
for i in l:
f = GM11(new_reg_data.loc[range(2000,2020),i].values)[0]
new_reg_data.loc[2020,i] = f(len(new_reg_data)-1) # 2020年預(yù)測結(jié)果
new_reg_data.loc[2021,i] = f(len(new_reg_data)) # 2021年預(yù)測結(jié)果
new_reg_data[i] = new_reg_data[i].round(2) # 保留兩位小數(shù)
y = list(data['y'].values) # 提取財政收入列,合并至新數(shù)據(jù)框中
y.extend([np.nan,np.nan])
new_reg_data['y'] = y
new_reg_data_GM11 = new_reg_data
new_reg_data_GM11 為初步預(yù)測的y值。結(jié)果如下圖。
2.5 構(gòu)建支持向量機回歸模型預(yù)測
調(diào)取模型,選取特征值與Y值。
from sklearn.svm import LinearSVR
data_train = new_reg_data_GM11.loc[range(2000,2020)].copy()
#數(shù)據(jù)標(biāo)準(zhǔn)化
data_mean = data_train.mean()
data_std = data_train.std()
data_train = (data_train-data_mean)/data_std
#選取測試集數(shù)據(jù)集
feature =['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']
x_train = data_train[feature].values
y_train = data_train['y'].values
linearsvr.predict(x) ,這是y是預(yù)測后歸一化的值;
這里x,y都做過數(shù)據(jù)的歸一化處理,根據(jù)公式 y歸一值=(y歸一前的值-y.mean())/y.std() ,因此有 y歸一前的值=y歸一值*y.std()+y.mean()
#調(diào)用LinearSVR()
linearsvr = LinearSVR()
linearsvr.fit(x_train,y_train)
# 給所有數(shù)據(jù)做歸一化處理,剛才訓(xùn)練集選取的是2000-2019年數(shù)據(jù),現(xiàn)在是全部數(shù)據(jù)集2000-2021年
x = ((new_reg_data_GM11[feature] - data_mean[feature])/data_std[feature]).values
new_reg_data_GM11['y_pred'] = linearsvr.predict(x) * data_std['y'] + data_mean['y']
最終預(yù)測的結(jié)果表格為new_reg_data_GM11
2.6 比較y-實際值與y-預(yù)測值的差異
畫出預(yù)測結(jié)果圖
fig = new_reg_data_GM11[['y','y_pred']].plot(subplots = True, style=['b-o','r-*']) # 畫出預(yù)測結(jié)果圖
plt.show()
結(jié)果如下