在上一篇文章中我们对一元线性回归模型和方程的原理及公式进行了推导,本篇文章将根据实际数据建立一个一元回归模型,代码基于Python
建模应用
首先导入需要用到的Python库:
#一元线性回归
import matplotlib.pyplot as plt #画图库
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression #线性回归库
原始数据为工作时间与收入表,对应有两列数据:工作时间(年)和工资(千),导入数据并查看前10列数据。
#读取数据,
df = pd.read_excel(r"C:\Downloads\工作时间与收入表.xlsx")
df.head(10)
将所有数据绘制散点图,看一下数据的分布
# 绘制散点图
plt.rcParams['font.family'] = 'KaiTi'
plt.scatter(df['工龄'], df['薪水(K)'], c='blue')
# 添加标签和标题
plt.xlabel('workyear')
plt.ylabel('salary')
plt.title('workyear to salary')
# 添加图例
plt.legend()
# 显示图形
plt.show()
从图中可以看出数据是具有线性趋势的,所以考虑使用线性回归模型找出对应关系。这里我们先按照之前说过的原理来自己计算一下回归方程的参数。
首先是最小二乘法:
# 更新k,b(最小二乘法)
k = np.sum(df['薪水(K)'] * (df['工龄'] - df['工龄'].mean())) / (np.sum(df['工龄'] ** 2) - np.sum(df['工龄']) ** 2 / len(df))
b = df['薪水(K)'].mean() - k * df['工龄'].mean()
print(k, b)
首先是计算协方差和方差估计参数:
cov_xy = np.sum((df['工龄'] - df['工龄'].mean()) * (df['薪水(K)'] - df['薪水(K)'].mean()))
var_x = np.sum((df['工龄'] - df['工龄'].mean())**2)
# 计算k和b
k = cov_xy / var_x
b = df['薪水(K)'].mean() - k * df['工龄'].mean()
print(k, b)
实际计算后两种方法得到的参数结果是一致的,将回归方程与数据作图展示一下:
# 绘制散点图
plt.rcParams['font.family'] = 'KaiTi'
plt.scatter(df['工龄'], df['薪水(K)'], c = 'blue', label = 'data')
# 生成一些x值
x_line = np.linspace(0, 5, 100)
# 根据直线方程计算对应的y值
k = np.sum(df['薪水(K)'] * (df['工龄'] - df['工龄'].mean())) / (np.sum(df['工龄'] ** 2) - np.sum(df['工龄']) ** 2 / len(df))
b = df['薪水(K)'].mean() - k * df['工龄'].mean()
y_line = k * x_line + b
# 绘制直线图
plt.plot(x_line, y_line, label = f' y = {k:.2f}x + {b:.2f}', c = 'red')
# 添加标签和标题
plt.xlabel('Workyear')
plt.ylabel('Salary')
plt.title('Workyear to salary')
# 添加图例
plt.legend()
# 显示图形
plt.show()
这样我们就得到了一个一元回归模型的结果,当然我们也可以直接用Python库内置的模型直接建模
#直接通过内置库建模
X = df[['工龄']] #这里的自变量必须写成二维形式,一个因变量可能对应多个自变量
Y = df['薪水(K)']
# 模型搭建
model = LinearRegression()
model.fit(X,Y)
# 模型可视化
plt.scatter(X,Y)
plt.plot(X,model.predict(X),color='red')
plt.xlabel('Workyear')
plt.ylabel('Salary')
plt.show()
#查看系数,截距:线性回归方程构造
model.coef_,model.intercept_
可以得到相同的结果
模型的评价
评价指标
之前通过观察数据分布我们猜测数据符合一元线性回归模型并计算得到回归方程,之后还需要对得到的回归模型进行评估,这里主要以3个值作为评判标准:
R-squared(即统计学中的R方)、Adj.R-squared(即调整后R方)、P值。
其中R-squared和Adj.R-squared用来衡量线性拟合的优劣,P值用来衡量特征变量的显著性。
R-squared和Adj.R-squared的取值范围为0~1,它们的值越接近1,则模型的拟合程度越高;一般情况下R-squared和Adj.R-squared大于0.7表示模型拟合程度很好,R-squared和Adj.R-squared在0.4到0.7之间表示模型拟合程度一般。
P值在本质上是个概率值,其取值范围也为0~1,P值越接近0,则特征变量的显著性越高,即该特征变量真的和目标变量具有更高的相关性,一般当P值小于0.05时,就认为特征变量与目标变量有显著相关性。
R方(R-squared)
R-squared即R方,可记为
R
2
R^2
R2,
R
s
q
R_{sq}
Rsq。要想理解R-squared,得先了解3组概念:
整体平方和TSS(Total Sum of Squares):数据实际值与整个样本均值的差距平方和,可以理解为我们直接用均值作了一个简单粗暴的模型,作为一个基准线
**残差平方和RSS/SSE (Residual Sum of Squares) **:数据实际值与回归曲线得到的值差距平方和,是由误差导致的真实值和估计值之间的偏差平方和(Sum Of Squares Due To Error,SSE),代表的是我们建立的回归模型没有解释的残差部分
**解释平方和ESS/SSR(Explained Sum of Squares) **:整个样本均值与回归曲线得到的值差距平方和,代表的是我们建立的回归模型可以解释的部分(Sum Of Squares Due To Regression,SSR),可以理解为详细建模之后比上面说的简单粗暴的模型更好的部分有多少
它们的关系如下图所示,其中Actual
Y
i
Y_i
Yi为实际值,
Y
f
i
t
t
e
d
Y_{fitted}
Yfitted为预测值,
Y
m
e
a
n
Y_{mean}
Ymean为所有散点平均值。
R方的计算公式为:
R
2
=
1
−
R
S
S
T
S
S
R^2=1-\frac{RSS}{TSS}
R2=1−TSSRSS
所以模型不可以解释的部分RSS越少,也就说明回归方程得到的预测值在每个点都更靠近真实值,回归模型也就越好,反映到R方上就是越靠近1.
调整后R方(Adj.R-squared)
上面说到R方越接近1,模型的拟合程度越高。不过拟合程度也不是越高越好,拟合程度过高可能会导致过拟合现象。
所谓过度拟合(简称过拟合),是指模型在训练样本中拟合程度过高,虽然它很好地贴合了训练集数据,但是却丧失了泛化能力,模型不具有推广性,导致在新的数据集中表现不佳。
过拟合相对的则是欠拟合,欠拟合是指模型拟合程度不高,数据距离拟合曲线较远,或指模型没有很好地捕捉到数据特征,不能够很好地拟合数据
调整后R方是R方的改进版,其目的是为了防止选取的特征变量过多而导致虚高的R方。每新增一个特征变量,线性回归背后的数学原理都会导致R-squared增加,但是这个新增的特征变量可能对模型并没有什么帮助。为了限制过多的特征变量,引入了调整后R方的概念,它在R方的基础上额外考虑了特征变量的数量这一因素,其公式如下。
R
2
‾
=
1
−
(
1
−
R
2
)
(
n
−
1
)
n
−
k
−
1
\overline {R^2}=1-\frac{(1-R^2)(n-1)}{n-k-1}
R2=1−n−k−1(1−R2)(n−1)
其中n为样本数量,k为特征变量数量,可以看到当特征变量数量k越多的时候会对调整后R方产生负影响,从而告告诉我们不要为了追求高R方值而添加过多的特征变量。对于特征变量数量不同的模型之间的比较,调整后R方能更准确地反映线性模型的好坏。
P值
P值涉及统计学里假设检验中的概念,判断特征变量与预测变量有无显著相关性,如果有显著的相关性那么说明对应的特征变量更适合放到回归方程中作为自变量。其原假设为特征变量与预测变量无显著相关性,那么P值就是当原假设为真时当前实际得到的样本结果出现的概率。通常来说,我们会以0.05为阈值,当P值小于0.05时,就认为该特征变量与预测变量显著相关。
评价指标代码
利用statsmodels库可直接输出常用的评价指标
#线性回归模型评估
import statsmodels.api as sm
# add_constant()函数给原来的特征变量X添加常数项,并赋给X2,这样才有y=ax+b中的常数项,即截距b
X2 = sm.add_constant(X)
# 用OLS()和fit()函数对Y和X2进行线性回归方程搭建
est = sm.OLS(Y,X).fit()
est.summary()
可以看到上述建立的模型R方和调整后R方为0.78左右,P值小于0.05,说明这个模型的拟合程度很好。当然在实际应用中,这些评价指标一般不会像这个例子这么理想,需要更加综合的判断。、