【数据挖掘案例】财政收入影响因素分析及预测模型

案例来源自《Python 数据分析与挖掘实战》第 13 章:财政收入影响因素分析及预测模型

案例目的:预测财政收入

1 数据的基本描述性分析

数据
在这里插入图片描述
字段含义
社会从业人数(x1 )、 在岗职工工资总额(x2)、社会消费品零售总额(x3)、城镇居民人均可支配收人(x4)、 城镇居民人均消费性支出(x5)、年末总人口(x6)、全社会固定资产投资额(x7)、地区生产总值(x8)、第一产业产值(x9)、税收(x10)、居民消费价格指数(x11)、第三产业与第二产业产值比(x12)地区生产总值(x8)和居民消费水平(x13)。

导包与读取数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from pylab import mpl
# 正常显示中文标签
mpl.rcParams['font.sans-serif'] = ['SimHei']
# 正常显示负号
mpl.rcParams['axes.unicode_minus'] = False
# 禁用科学计数法
pd.set_option('display.float_format', lambda x: '%.2f' % x) 

# 读入数据
data = pd.read_excel('data1.xlsx',index_col=0)

数据的基本情况

data.shape # (20, 14)
data.info()
'''
<class 'pandas.core.frame.DataFrame'>
Int64Index: 20 entries, 1994 to 2013
Data columns (total 14 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   x1      20 non-null     int64  
 1   x2      20 non-null     float64
 2   x3      20 non-null     float64
 3   x4      20 non-null     float64
 4   x5      20 non-null     float64
 5   x6      20 non-null     int64  
 6   x7      20 non-null     float64
 7   x8      20 non-null     float64
 8   x9      20 non-null     float64
 9   x10     20 non-null     float64
 10  x11     20 non-null     float64
 11  x12     20 non-null     float64
 12  x13     20 non-null     int64  
 13  y       20 non-null     float64
dtypes: float64(11), int64(3)
'''
# 描述性分析
data.describe().T

或更简洁一点

r = [data.min(), data.max(), data.mean(), data.std()]
r = pd.DataFrame(r, index=['Min', 'Max', 'Mean', 'STD']).T
r = np.round(r, 2)
r

结果

            Min         Max        Mean         STD
x1   3831732.00  7599295.00  5579519.95  1262194.72
x2       181.54     2110.78      765.04      595.70
x3       448.19     6882.85     2370.83     1919.17
x4      7571.00    42049.14    19644.69    10203.02
x5      6212.70    33156.83    15870.95     8199.77
x6   6370241.00  8323096.00  7350513.60   621341.85
x7       525.71     4454.55     1712.24     1184.71
x8       985.31    15420.14     5705.80     4478.40
x9        60.62      228.46      129.49       50.51
x10       65.66      852.56      340.22      251.58
x11       97.50      120.00      103.31        5.51
x12        1.03        1.91        1.42        0.25
x13     5321.00    41972.00    17273.80    11109.19
y         64.87     2088.14      618.08      609.25

变量的分布情况

from sklearn.preprocessing import MinMaxScaler
#实现归一化
scaler = MinMaxScaler() #实例化
scaler = scaler.fit(data) #fit,在这里本质是生成min(x)和max(x)
data_scale = pd.DataFrame(scaler.transform(data)) #通过接口导出结果
data_scale.columns = data.columns

import joypy
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm
import seaborn as sns
fig, axes = joypy.joyplot(data_scale, alpha=.5, color='#FFCC99')#连续值的列为一个"脊"

在这里插入图片描述

data_scale.plot()

在这里插入图片描述


相关性分析

pear = np.round(data.corr(method = 'pearson'), 2)
pear
plt.figure(figsize=(12,12))
sns.heatmap(data.corr(), center=0,
            square=True, linewidths=.5, cbar_kws={"shrink": .5},annot=True, fmt='.1f')
#设置x轴
plt.xticks(fontsize=15)
#设置y轴
plt.yticks(fontsize=15)
plt.tight_layout()
plt.savefig('a.png')

在这里插入图片描述

由图可知,居民消费价格指数(x11)与财政收入的线性关系不显著,而且呈现负相关。其余变量均与财政收入呈现高度的正相关关系。

2 数据的预处理

变量的筛选

分析方法的选择:以往对财政收入的分析会使用 多元线性回归模型最小二乘估计方法来估计回归模型的系数,通过系数能否通过检验来检验它们之间的关系,但这样的结果对数据依赖程度很大,并且求得的往往只是局部最优解,后续的检验可能会失去应有的意义。因此本案例运用Adaptive-Lasso变量选择方法来研究

对于Lasso,这里参考书中的理论知识

在这里插入图片描述

Lasso全称最小绝对收缩和选择算子,和岭回归一样,Lasso是被创造来作用于多重共线性问题的算法,不过Lasso使用的是系数 β \beta β 的L1范式(L1范式则是系数 β \beta β 的绝对值)乘以正则化系数

不太严谨说法是,Lasso与岭回归非常相似,都是利用正则项来对原本的损失函数形成一个惩罚,以此来防止多重共线性。

Lasso 虽然是为了限制多重共线性被创造出来的,但其实并不使用它来抑制多重共线性,反而接受了它在其他方面的优势,

由于,L2正则化只会将系数压缩到尽量接近0,但L1正则化主导稀疏性,因此会将系数压缩到0。

因此,Lasso成为了线性模型中的特征选择工具首选

Lasso回归的特点是在拟合广义线性模型的同时进行变量筛选和复杂度调整。 因此,不论目标因变量是连续的,还是二元或者多元离散的,都可以用Lasso回归建模然后预测。

这里的变量筛选是指不把所有的变量都放入模型中进行拟合,而是有选择的把变量放入模型从而得到更好的性能参数。
在这里插入图片描述

—关于Adaptive-Lasso变量选择方法(参考书籍)

Adaptive_lasso算法是近些年来被广泛应用于参数估计于变量选择的方法之一。Adaptive_Lasso算法能够解决最小二乘法和逐步回归局部最优解的不足,这是它的优点之一。


Adaptive_lasso算法计算出某变量的特征值非零,则表示该变量对预测变量存在较大影响,而如果某变量的特征值为零,则表示该变量对预测变量影响很小。


Lasso变量选择模型

这里没有找到AdaptiveLasso这个函数,用Lasso代替

from sklearn.linear_model import Lasso
model = Lasso(alpha=0.1, max_iter=100000)
model.fit(data.iloc[:, 0:13], data['y'])
q=model.coef_#各特征的系数
q=pd.DataFrame(q,index=data.columns[:-1])
q
'''
        0
x1  -0.00
x2  -0.59
x3   0.44
x4  -0.13
x5   0.17
x6   0.00
x7   0.27
x8   0.03
x9  -7.56
x10 -0.09
x11  3.38
x12  0.00
x13 -0.01
'''

计算出某变量的特征值非零,则表示该变量对预测变量存在较大影响,而如果某变量的特征值为零,则表示该变量对预测变量影响很小。

调整参数值(参照:https://blog.csdn.net/weixin_43746433/article/details/100047231)

from sklearn.linear_model import Lasso
lasso = Lasso(1000)  #调用Lasso()函数,设置λ的值为1000
lasso.fit(data.iloc[:,0:13],data['y'])
print('相关系数为:',np.round(lasso.coef_,5))  #输出结果,保留五位小数
## 计算相关系数非零的个数
print('相关系数非零个数为:',np.sum(lasso.coef_ != 0))
mask = lasso.coef_ != 0  #返回一个相关系数是否为零的布尔数组
print('相关系数是否为零:',mask)

new_reg_data = data.iloc[:,:13].iloc[:,mask]  #返回相关系数非零的数据
new_reg_data = pd.concat([new_reg_data,data.y],axis=1)
new_reg_data.to_excel('new_reg_data.xlsx')
相关系数为:
 [-1.8000e-04 -0.0000e+00  1.2414e-01 -1.0310e-02  6.5400e-02  1.2000e-04
  3.1741e-01  3.4900e-02 -0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00
 -4.0300e-02]
相关系数非零个数为: 8
相关系数是否为零: [ True False  True  True  True  True  True  True False False False False  True]

根据非零的系数,最终通过Lasso筛选出的变量如下
在这里插入图片描述

变量筛选好之后,接下来的开始建模

3 建立财政收入预测模型

这里使用的预测方法是,灰色预测 + 神经网络预测 的组合模型

基本思路是

(1)首先是在前面的变量选择结果基础上,对单个选定的影响因素建立灰色预测模型,得到它们在2014年及2015年的预测值。

(2)然后,通过神经网络对历史数据( X 1994 − 2003 X_{1994-2003} X19942003 Y 1994 − 2003 Y_{1994-2003} Y19942003)建立训练模型。

(3)把 X 1994 − 2003 X_{1994-2003} X19942003以及灰色预测的数据结果 X 2004 − 2005 X_{2004-2005} X20042005一并代人训练好的模型中,得到预测值。


灰色预测模型

灰色模型学习资料(自己推荐自己*-*)

灰色预测函数

def GM11(x0): #自定义灰色预测函数
    import numpy as np
    x1 = x0.cumsum() # 生成累加序列
    z1 = (x1[:len(x1)-1] + x1[1:])/2.0 # 生成紧邻均值(MEAN)序列,比直接使用累加序列好,共 n-1 个值
    z1 = z1.reshape((len(z1),1))
    B = np.append(-z1, np.ones_like(z1), axis = 1)    # 生成 B 矩阵
    Y = x0[1:].reshape((len(x0)-1, 1))    # Y 矩阵
    [[a],[u]] = np.dot(np.dot(np.linalg.inv(np.dot(B.T, B)), B.T), Y)    #计算参数
    f = lambda k: (x0[0]-u/a)*np.exp(-a*(k-1))-(x0[0]-u/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, u, x0[0], C, P #返回灰色预测函数、a、b、首项、方差比、小残差概率

data.index = range(1994, 2014)
data.loc[2014] = None
data.loc[2015] = None
# 模型精度评价
# 被lasso筛选出来的6个变量
l = ['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']
for i in l:
    GM = GM11(data[i][list(range(1994, 2014))].values)
    f = GM[0]
    c = GM[-2]
    p = GM[-1]
    data[i][2014] = f(len(data)-1)
    data[i][2015] = f(len(data))
    data[i] = data[i].round(2)
    if (c < 0.35) & (p > 0.95):
        print('对于模型{},该模型精度为---好'.format(i))
    elif (c < 0.5) & (p > 0.8):
        print('对于模型{},该模型精度为---合格'.format(i))
    elif (c < 0.65) & (p > 0.7):
        print('对于模型{},该模型精度为---勉强合格'.format(i))
    else:
        print('对于模型{},该模型精度为---不合格'.format(i))

data[l+['y']].to_excel('data2.xlsx')
对于模型x1,该模型精度为---好
对于模型x3,该模型精度为---好
对于模型x4,该模型精度为---好
对于模型x5,该模型精度为---好
对于模型x6,该模型精度为---好
对于模型x7,该模型精度为---好
对于模型x8,该模型精度为---好
对于模型x13,该模型精度为---

在这里插入图片描述

预测值如下:
在这里插入图片描述


神经网络预测模型

下面用历史数据建立神经网络模型

其参数设置为误差精度107,学习次数10000次,神经元个数为Lasso变量选择方法选择的变量个数8。

'''神经网络'''
data2 = pd.read_excel('data2.xlsx', index_col=0)
# 提取数据
feature = list(data2.columns[:len(data2.columns)-1]) # ['x1', 'x2', 'x3', 'x4', 'x5', 'x7']
train = data2.loc[list(range(1994, 2014))].copy()
mean = train.mean()
std = train.std() 
train = (train - mean) / std    # 数据标准化,这里使用标准差标准化
x_train = train[feature].values
y_train = train['y'].values

# 建立神经网络模型 
from keras.models import Sequential
from keras.layers.core import Dense, Activation

model = Sequential()
model.add(Dense(input_dim=8, units=12))
model.add(Activation('relu'))
model.add(Dense(input_dim=12, units=1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(x_train, y_train, epochs=10000, batch_size=16)
model.save_weights('net.model')

训练好模型后,将 X 1994 − 2005 X_{1994-2005} X19942005全部带入模型中作预测,结果如下:

# 将整个变量矩阵标准化
x = ((data2[feature] - mean[feature]) / std[feature]).values
# 预测,并还原结果
data2['y_pred'] = model.predict(x) * std['y'] + mean['y']
data2.to_excel('data3.xlsx')

预测结果
在这里插入图片描述

绘制真实值与预测值之间的折线图

import matplotlib.pyplot as plt
p = data2[['y', 'y_pred']].plot(style=['b-o', 'r-*'])
p.set_ylim(0, 2500)
p.set_xlim(1993, 2016)
plt.show()

从结果中,比较预测值与真实值基本高度吻合
在这里插入图片描述

为了与神经网络预测结果有一个对比,下面使用其他预测模型查看其结果如何

from sklearn.linear_model import LinearRegression # 线性回归
from sklearn.neighbors import KNeighborsRegressor # K近邻回归
from sklearn.neural_network import MLPRegressor # 神经网络回归
from sklearn.tree import DecisionTreeRegressor # 决策树回归
from sklearn.tree import ExtraTreeRegressor # 极端随机森林回归
from xgboost import XGBRegressor # XGBoot
from sklearn.ensemble import RandomForestRegressor # 随机森林回归
from sklearn.ensemble import AdaBoostRegressor  # Adaboost 集成学习
from sklearn.ensemble import GradientBoostingRegressor # 集成学习梯度提升决策树
from sklearn.ensemble import BaggingRegressor # bagging回归
from sklearn.linear_model import ElasticNet

from sklearn.metrics import explained_variance_score,\
mean_absolute_error,mean_squared_error,\
median_absolute_error,r2_score

models=[LinearRegression(),KNeighborsRegressor(),MLPRegressor(alpha=20),DecisionTreeRegressor(),ExtraTreeRegressor(),XGBRegressor(),RandomForestRegressor(),AdaBoostRegressor(),GradientBoostingRegressor(),BaggingRegressor(),ElasticNet()]
models_str=['LinearRegression','KNNRegressor','MLPRegressor','DecisionTree','ExtraTree','XGBoost','RandomForest','AdaBoost','GradientBoost','Bagging','ElasticNet']


data2 = pd.read_excel('data2.xlsx', index_col=0)
# 提取数据
feature = ['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']
train = data2.loc[list(range(1994, 2014))].copy()
mean = train.mean()
std = train.std() 
train = (train - mean) / std    # 数据标准化,这里使用标准差标准化
x_train = train[feature].values
y_train = train['y'].values
# 将整个变量矩阵标准化
x = ((data2[feature] - mean[feature]) / std[feature]).values


for name,model in zip(models_str,models):
    print('开始训练模型:'+name)
    model=model   #建立模型
    a = 'y_pred_'+ name
    data2[a] = model.fit(x_train,y_train).predict(x) * std['y'] + mean['y']
    df=data2[:-2]
    print('平均绝对误差为:',mean_absolute_error(df['y'].values,df[a].values))
    print('均方误差为:',mean_squared_error(df['y'],df[a]))
    print('中值绝对误差为:',median_absolute_error(df['y'],df[a]))
    print('可解释方差值为:',explained_variance_score(df['y'],df[a]))
    print('R方值为:',r2_score(df['y'],df[a]))
    print('*-*'*15)

结果

开始训练模型:LinearRegression
平均绝对误差为: 32.624948062446734
均方误差为: 1596.8011348674995
中值绝对误差为: 29.89818813145061
可解释方差值为: 0.9954717568606967
R方值为: 0.9954717568606967
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:KNNRegressor
平均绝对误差为: 63.916899999999984
均方误差为: 17521.95548179999
中值绝对误差为: 26.000000000000043
可解释方差值为: 0.9517094362717755
R方值为: 0.950310860278652
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:MLPRegressor
平均绝对误差为: 235.42036857561698
均方误差为: 76090.58720607273
中值绝对误差为: 196.3296364219621
可解释方差值为: 0.7845740946711923
R方值为: 0.7842206697141109
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:DecisionTree
平均绝对误差为: 2.7711166694643907e-14
均方误差为: 1.0551803468236254e-26
中值绝对误差为: 0.0
可解释方差值为: 1.0
R方值为: 1.0
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:ExtraTree
平均绝对误差为: 2.7711166694643907e-14
均方误差为: 1.0551803468236254e-26
中值绝对误差为: 0.0
可解释方差值为: 1.0
R方值为: 1.0
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:XGBoost
平均绝对误差为: 0.5735757446289022
均方误差为: 0.5008986120857999
中值绝对误差为: 0.6280151367187159
可解释方差值为: 0.9999985795409094
R方值为: 0.9999985795408995
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:RandomForest
平均绝对误差为: 24.30998000000009
均方误差为: 2541.844172424009
中值绝对误差为: 8.976250000000078
可解释方差值为: 0.9932099301805153
R方值为: 0.9927917834076989
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:AdaBoost
平均绝对误差为: 13.087633333333354
均方误差为: 386.4120509666666
中值绝对误差为: 7.9691666666666805
可解释方差值为: 0.9991155201544625
R方值为: 0.9989042043617541
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:GradientBoost
平均绝对误差为: 0.023211721877213876
均方误差为: 0.0014299207277676446
中值绝对误差为: 0.011657245535729999
可解释方差值为: 0.9999999959449999
R方值为: 0.9999999959449999
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:Bagging
平均绝对误差为: 34.284249999999986
均方误差为: 4470.224954049998
中值绝对误差为: 7.295999999999992
可解释方差值为: 0.9874093338106849
R方值为: 0.9873232395460447
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*
开始训练模型:ElasticNet
平均绝对误差为: 294.6018692079905
均方误差为: 118127.42764924551
中值绝对误差为: 249.10992216728664
可解释方差值为: 0.665011689849139
R方值为: 0.6650116898491392
*-**-**-**-**-**-**-**-**-**-**-**-**-**-**-*

在这里插入图片描述

注:存在严重的过拟合问题

看一下,线性回归、XGBoost 预测值对比图

线性回归
在这里插入图片描述

XGBoost

在这里插入图片描述
这里做法存在一定的问题,没有划分训练集和测试集,存在严重过拟合,模型失效。

下面试一下

线支持向量机线性回归(LinearSVR)

from sklearn.svm import LinearSVR
linearsvr = LinearSVR().fit(x_train,y_train)  #调用LinearSVR()函数
# 预测,并还原结果
data2['y_pred_linearsvr'] = linearsvr.predict(x) * std['y'] + mean['y']

在这里插入图片描述
相比其他回归模型,神经网络预测模型在这里效果更好一点

至此。

  • 33
    点赞
  • 358
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值