多元回归分析
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
建模复习
目录
前言
回归分析是数据分析中最基础也是最重要的分析工具。通过研究自变量X和因变量Y的相关关系尝试去解释Y的形成机制进而达到通过X去预测Y的目的。
常见的回归分析有线性回归0-1回归定序回归计数回归和生存回归。其划分的依据是因变量Y的类型。
一、回归的思想
1,介绍
回归分析研究X和Y之间的相关性。
相关性不解释
Y:因变量类型
10-1变量1是好瓜0是坏瓜。
2定序变量Y为a,b,c,d或者为1234....表示不同的水平
3计数变量次数非负整数完成作业的次数
4生产变量产品寿命企业寿命。。。无法将数据具体化的数据
X自变量。指标参数回归分析中通过研究X和Y的相关关系尝试解释Y的形成机制进而达到通过各种指标X预测Y
2回归分析的分类
类别 | 模型 | Y | 例子 |
线性回归 | OLS,GLS(最小二乘) | 连续数值型变量 | GDP与产量收入关系 |
0-1回归 | logistic回归 | 二值变量0-1 | 是否好瓜是否突变 |
定序回归 | probit回归 | 定序变量 | 等级评定优良差 |
计数回归 | 泊松分布 | 计数变量 | 每分钟的车流量 |
生存回归 | cox等比例风险回归 | 生存变量截断数据 | 企业产品寿命 |
3数据类型
数据类型 | 建模方法 |
横截面数据某一时间点收集的不同对象数据 | 多元回归分析 |
时序数据一串时间序列数据 | LSTM,灰色时间预测指数平滑ARIMA,SARIAM,GARCH,VAR,协积 |
面板数据横截数据+时序数据 | 固定效应随机效应静态面板动态面板 |
横截数据在比赛中往往可以使用回归进行建模建立自变量和因变量间的相关分析模型和预测模型
二、一元线性回归
1一元线性函数拟合
设这些样本点为
我们设置拟合曲线为,令拟合值
那么
令现在找k和b,使得L最小。
L为损失函数在回归中也叫作误差平方和
2一元线性回归模型
假设x是自变量y是因变量且满足如下线性关系
是回归系数为无法观测得且满足一定条件得扰动项
令预测值其中
我们称为残差
这部分为建模凑字数部分建模论文写作公式存储
2.线性的理解
假设x是自变量有是因变量且满足如下线性关系
当然线性假定并不是要求初始模型都呈现严格的线性关系。自变量与自变量可以通过变量替换转化成线性模型如
对变量x进行ln操作或平法开方操作是提高模型准确性的一大常用数据预处理当然也容易出现过拟合。。。
3回归系数
1回归系数的解释
是回归系数
假设x为某产品品质评分(1-10之间)y为该产品的销量我们对和y使用一元线性回归模型,如果得到;
评估分析
3.4:在评分为0时该产品的平均销量为3.4
2.3:评分每增加一个单位该产品的平均销量增加2.3
2内生性
(写建模论文严谨的解释)
内生性问题 (endogeneity issue) 是指模型中的一个或多个解释变量与误差项存在相关关系。换言之如果 OLS回归模型中出现 则模型存在内生性问题以致于 OLS 估计量不再是一致估计。
接上个假设假设为某产品品质评分(1-10之间)某产品价格为该产品的销量。那么我们建立多元线性回归模型
得到
评估分析
5.3:在评分为0日价格为0时该产品的平均销量为5.3个(没现实意义)
0.19:在保持其他变量不变的情况下评分每增加一个单位该产品的平均销量增加0.19
-1.74:在保持其他变量不变的情况下价格每增加一个单位该产品的平均销量减少1.74
看见加入新的自变量价格后对回归系数的影响非常大可能原因是产品评分和价格两变量存在相关性所以遗漏变量导致的内生性问题
3完全多重共线性
共线性问题指的是输入的自变量之间存在较高的线性相关度。共线性问题会导致回归模型
的稳定性和准确性大大降低另外过多无关的维度计算也很浪费时间。
计算VIT
解决法子
1向前逐步回归将自变量逐个引入模型每引入一个自变量后都要进行检验显著时才加入回归模型。缺点随着以后其他自变量的引入原来显著的自变量也可能变成不显著的了
2向后逐步回归与向前逐步回归相反先将所有变量均放入模型之后尝试将其中一个自变量从模型中剔除看整个模型解释因变量的 变异是否有显著变化之后将最没有解释力的那个自变量剔除此过程不断迭代 直到没有自变量符合剔除的条件。缺点一开始把全部变量都引入回归方程 这样计算量比较大。若对一些不重要的变量一开始就不引入这样就可以减少 一些计算。当然这个缺点随着现在计算机的能力的提升已经变得不算问题了
3岭回归和lasso回归正则化这两种方法在OLS回归模型的损失函数上加入了不同的惩罚项该惩罚项由回归系数的函数构成一方面加入的惩罚项能够识别出模型中不重要的变量对模型起到简化作用可以看作逐步回归法的升级版另一方面加入的惩罚项能够让模型变得可估计 即使之前的数据不满足列满秩。
4改变特征变量的表现形式有些变量可以改变其表现形式如像网页的浏览次数、点击次数等特征属于长尾分布可以对其进行log变换变换后的变量可以有效的降低变量之间的相关性。
5主成分分析PCA通过主成分分析提取主要的特征从而忽略次要的成分得到相关性很低的特征。
4拟合优度
拟合优度Goodness of Fit 是指回归直线对观测值的拟合程度。度量拟合优度的统计量是可决系数亦称确定系数R²。
- R² 最大值为 1。R² 的值越接近1说明回归直线对观测值的拟合程度越好
- 反之R² 的值越小说明回归直线对观测值的拟合程度越差。
三实验
1变量说明
符号 | 解释 |
未知待估计参数 | |
满足一定条件的误差项 | |
VIF | 方差膨胀因子 |
X | 原始数据矩阵 |
2模型的建立与求解
2.1数据来源
diabetes 是一个关于糖尿病的数据集 该数据集包括442个病人的生理数据及一年以后的病情发展情况。
from sklearn.datasets import load_iris, load_wine, load_diabetes
diabetes = load_diabetes()
data = diabetes['data']
target = diabetes['target']
feature_names = diabetes['feature_names']
df = pd.DataFrame(data, columns=feature_names)
df.head() # 查看前几行数据
该数据集共442条信息特征值总共10项, 如下:
age:年龄
sex:性别
bmi(body mass index):身体质量指数是衡量是否肥胖和标准体重的重要指标理想BMI(18.5~23.9) = 体重(单位Kg) ÷ 身高的平方
(单位m) bp(blood pressure):血压平均血压
s1,s2,s3,s4,s4,s6:六种血清的化验数据是血液中各种疾病级数指针的6的属性值。 s1——tcT细胞一种白细胞
2.2线性假设
已知442个病人的生理数据与年龄性别身体质量指数BMI六种血清的化验数据有关。为了方便探求病人的生理数据与各项生理指标的具体关系假设病人的生理数据因变量与各项生理指标自变量间的关系为线性关系
其中是未知代估参数是无法观测且满足一定条件的误差项
2.3相关性分析建模考虑点
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(15,8))
mask = np.triu(np.ones_like(df.corr(), dtype=bool))
sns.heatmap(df.corr(), annot=True, mask=mask, vmin=-1, vmax=1)
plt.title('Correlation Coefficient Of Predictors')
plt.show()
2.4完全多重共线性建模考虑点
如果数据矩阵X不满秩即存在某一解释变量可以被其他解释变量线性表示出则存在“严格多重共线性”。其表现为不存在总体参数不可识别无法定义最小二乘估计量。
严格多重共线性在现实数据中极少出现,现实中较为常见的是近似(非严格)多重共线性。其具体表现为: 存在第k个解释变量如果将对其他解释变量了进行回归所得到的可决系数较高。在存在近似多重共线性的情况下OSL 依然是最佳线性无偏估计但不意味着 OSL 估计量方差绝对小。其主要负面效果为:单个系数的t检验不显著或系数估计值不合理甚至符号与理论值相反另一种可能情况是增减解释变量会使得系数估计值发生很大的变化。直观来看若两个(或多个)解释变量高度相关则不容易区分它们对被解释变量的单独影响力。
2.5运用VIF法检验多重共线性建模考虑点
VIF 全称为方差膨胀因子(Variance Inflation Factor)其计算方法为:
假设共有k个自变量则第m个自变量的。其中是将第m个自变量作为因变量,对剩下的K-1个自变量回归得到的拟合优度。VIF越大说明第m个自变量与其他自变量的相关性越大。
定义回归模型的。
一个经验规则是若VIF >10则认为该回归方程存在严重的多重共线性
可以看出s1=59.203>10,s2=39.194>10,s3=15.4023>10可以认为该回归方程存在严重的多重共线性
#检验完全多重共线性
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor
import numpy as np
# 当VIF<10,说明不存在多重共线性当10<=VIF<100,存在较强的多重共线性当VIF>=100,存在严重多重共线性
vif = [variance_inflation_factor(df.values, df.columns.get_loc(i)) for i in df.columns]
探究单个变量与结果之间的可决系数进行一元线性回归
plt.figure(figsize=(2*6, 5*5))
for i, col in enumerate(df.columns):
train_X = df.loc[:, col].values.reshape(-1, 1)
# 每一次循环都取出datafram中的一列数据是一维Series数据格式但是线性回归模型要求传入的是一个二维数据因此利用reshape修改其形状
train_Y = target
linearmodel = linear_model.LinearRegression()
reg = linearmodel.fit(train_X, train_Y)
score = reg.score(train_X, train_Y)
axes = plt.subplot(5, 2, i + 1)
plt.scatter(train_X, train_Y)
# 画出每一个特征训练模型得到的拟合直线 y= kx + b
k = linearmodel.coef_ # 回归系数
b = linearmodel.intercept_ # 截距
x = np.linspace(train_X.min(), train_X.max(), 100)
y = k * x + b
# 作图
plt.plot(x, y, c='red')
axes.set_title(col + ' Coefficient of determination:' + str(score))
plt.show()
从中可以看出糖尿病数据集中10的特征对target的影响大小从大到小分别是
[[0.3439237602253803, 'bmi'], [0.32022405096453443, 's5'], [0.19490798886682947, 'bp'], [0.18528968598509687, 's4'], [0.1558585524453051, 's3'], [0.14629361572293453, 's6'], [0.04495353245556555, 's1'], [0.03530218264671636
这个数据有些指标或多或少有点离谱
2.5多元线性回归模型
from sklearn.model_selection import train_test_split
from sklearn import datasets, linear_model
from sklearn.metrics import mean_squared_error, r2_score
train_X, test_X, train_Y, test_Y = train_test_split(data, target, train_size=0.8)
model = linear_model.LinearRegression(copy_X=True, fit_intercept=True, normalize=False)#计算截距
# 3、训练数据
model.fit(train_X, train_Y)
# 4、评估模型
y_pred = model.predict(test_X)
# The coefficients
print("Coefficients: \n", model.coef_)
# The mean squared error
print("MSE:",mean_squared_error(test_Y, y_pred))
# The coefficient of determination: 1 is perfect prediction
print("R2:",r2_score(test_Y, y_pred))
R2的numpy计算方法
from sklearn.metrics import r2_score
import numpy as np
def test(a,b):
# anumpy一维数组形状是(n,)表示标签。
# bnumpy一维数组形状是(n,)表示预测结果。
# print(r2_score(a,b))
return R2(b,a)
def SST(y_tar):
y_mean = np.mean(y_tar)
sst = np.sum((y_tar-y_mean)**2)
return sst
def SSE(y_hat, y_tar):
sse = np.sum((y_hat-y_tar)**2)
return sse
def R2(y_hat, y_tar):#y_hat为预测结果y_tar为标签目标值
sst = SST(y_tar)
sse = SSE(y_hat,y_tar)
rr = 1-sse/sst
return rr
多元线性回归求解推导
MSE
为了最小
。。。。一堆计算之后没必要看
#一些numpy操作
# 矩阵拼接
import numpy as np
#拼接
np.concatenate((a,b), axis=1)
# 矩阵乘法
a.dot(b)
# 矩阵转置
a.T
# 矩阵的逆
aa=np.linalg.inv(aa)
#求方差
np.var(a)
#均值
np.mean(a)
计算:
ones = np.ones([X.shape[0], 1])
X=np.concatenate((X,ones),axis=1)
XT=X.T
XTX=X.T.dot(X)
XTX=XTX.dot(XTX.T)
XTX_1=np.linalg.inv(XTX)
XTY=XT.dot(y)
beta=XTX_1.dot(XTY)
2.6 利用岭回归解决多重共线性问题
from sklearn.linear_model import Ridge
n_alphas = 100
alphas = np.logspace(-5, 0, n_alphas)
coefs = []
for alpha in alphas:
ridge = linear_model.Ridge(alpha=alpha)
ridge.fit(train_X, train_Y)
coefs.append(ridge.coef_)
y_reg_pred = ridge.predict(test_X)
# The coefficients
print("Coefficients: \n", ridge.coef_)
# The mean squared error
print("MSE:",mean_squared_error(test_Y, y_reg_pred))
# The coefficient of determination: 1 is perfect prediction
print("R2:",r2_score(test_Y, y_reg_pred))
ax = plt.gca()
ax.plot(alphas, coefs)
ax.set_xscale('log')
ax.set_xlim(ax.get_xlim())[::-1]
plt.xlabel('alpha')
plt.ylabel('weights')
plt.title('Ridge coefficients as a function of the regularization')
plt.show()
从岭迹图可以看出那些指标对结果显著那些指标不显著
岭回归的数学原理最小化目标从MSE变成MSE+系数平方和
新的目标是
新的结果是
beta = np.linalg.inv(X.T.dot(X) + alpha*I).dot(X.T.dot(y))
2.6多项式回归
改变特征变量的表现形式吧
eg一元一次线性回归变成一元二次线性回归
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(d)
d为多项式次数这是一个改变特征的方法可以解决多重共线性问题。虽然多项式的加入对数据的拟合效果有所提高但是容易出现过拟合或者龙格现象这时候给予模型正则化可适当缓解过拟合现象
例子进行一元线性回归拟合sin
随机数大一点导致过拟合嘿嘿
import numpy as np
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_squared_error
# 用于训练的数据有20个
train_size = 20
# 用于测试的数据有15个
test_size = 15
# 生成用于训练的 X
train_X = np.random.uniform(low=0, high=1.2, size=train_size)
# 生成用于测试的 X
test_X = np.random.uniform(low=0.1, high=1.3, size=test_size)
# 生成用于训练的 y
train_y = np.sin(train_X * 2 * np.pi) + np.random.normal(0, 0.8, train_size)
# 生成用于测试的 y
test_y = np.sin(test_X * 2 * np.pi) + np.random.normal(0, 0.8, test_size)
plt.scatter(train_X, train_y, c="silver")
plt.scatter(test_X, test_y, c='black')
数据转换为多项式
poly = PolynomialFeatures(6) # 次数为6
# 训练数据进行转化
train_poly_X = poly.fit_transform(train_X.reshape(train_size, 1))
# 测试数据进行转换
test_poly_X = poly.transform(test_X.reshape(test_size, 1))
建立线性回归模型
# 1. 建立模型
model = LinearRegression()
# 2. 训练
model.fit(train_poly_X, train_y)
# 3. 预测
train_pred_y = model.predict(train_poly_X)
test_pred_y = model.predict(test_poly_X)
# 4. 评价
print(mean_squared_error(train_pred_y, train_y)) # MSE
print(mean_squared_error(test_pred_y, test_y)) # MSE
说明有些过拟合那多项式就一个一个变试试
polys = [] # 每次循环时要保存一个转换器以便后面调用
models = [] # 每次循环时要保存一个模型以便后面调用
for n in range(1,7):
# 0. 数据准备转换为多项式
polys.append(PolynomialFeatures(n)) # 次数为n的多项式转换
train_poly_X = polys[n-1].fit_transform(train_X.reshape(train_size, 1))
test_poly_X = polys[n-1].transform(test_X.reshape(test_size, 1))
# 1. 建立模型
models.append(LinearRegression())
# 2. 训练
models[n-1].fit(train_poly_X, train_y)
# 3. 预测
train_pred_y = models[n-1].predict(train_poly_X)
test_pred_y = models[n-1].predict(test_poly_X)
# 4. 评价
MSE_train = mean_squared_error(train_pred_y, train_y)
MSE_test = mean_squared_error(test_pred_y, test_y)
print(f"{n}\t{MSE_train:.3f}\t{MSE_test:.3f}")
可以看见多项式为三次时最好
plt.scatter(train_X, train_y, c="silver")
plt.scatter(test_X, test_y, c='black')
n = 3 # 使用6次方模型展示拟合结果
# 准备拟合曲线先从x入手得到一系列的x
xR = np.linspace(-0.05, 1.4, 100)
# 将 x 扩展到 n 次多项式
xR_poly = polys[n-1].transform(xR.reshape(100, 1))
# n次方模型保存在models[n-1]处。用它预测得到拟合结果
yR = models[n-1].predict(xR_poly)
print(models[n-1].intercept_) # n次方模型的参数
print(models[n-1].coef_) # n次方模型的参数
plt.plot(xR, yR, 'r-')
加入岭回归
polys2 = [] # 每次循环时要保存一个转换器以便后面调用
models2 = [] # 每次循环时要保存一个模型以便后面调用
for n in range(1,7):
# 0. 数据准备转换为多项式
polys2.append(PolynomialFeatures(n)) # 次数为n的多项式转换
train_poly_X = polys2[n-1].fit_transform(train_X.reshape(train_size, 1))
test_poly_X = polys2[n-1].transform(test_X.reshape(test_size, 1))
# 1. 建立模型
models2.append(Ridge(alpha=0.1))
# 2. 训练
models2[n-1].fit(train_poly_X, train_y)
# 3. 预测
train_pred_y = models2[n-1].predict(train_poly_X)
test_pred_y = models2[n-1].predict(test_poly_X)
# 4. 评价
MSE_train = mean_squared_error(train_pred_y, train_y)
MSE_test = mean_squared_error(test_pred_y, test_y)
print(f"{n}\t{MSE_train:.3f}\t{MSE_test:.3f}")
画出多项式6次的拟合曲线
多元线性回归的多项式
如果一个n元线性回归模型还要进行PolynomialFeatures(d)的变换最终会得到(含常数项)
例如一元线性回归模型经过PolynomialFeatures(6)的变换会得到7项特征二元线性回归模型经过PolynomialFeatures(2)的变换会得到6项特征。
糖尿病数据进行多项式多元线性回归
from sklearn.preprocessing import PolynomialFeatures
polys2 = []
models2 = []
for n in range(1,7):
poly = PolynomialFeatures(n) # 次数为6
train_poly_X = poly.fit_transform(train_X)
test_poly_X = poly.transform(test_X)
models2.append(Ridge(alpha=0.1))
# 2. 训练
models2[n-1].fit(train_poly_X, train_Y)
# 3. 预测
train_pred_y = models2[n-1].predict(train_poly_X)
test_pred_y = models2[n-1].predict(test_poly_X)
# 4. 评价
MSE_train = mean_squared_error(train_pred_y, train_Y)
MSE_test = mean_squared_error(test_pred_y, test_Y)
R2=r2_score(test_Y, test_pred_y)
print(f"{n}\t{MSE_train:.3f}\t{MSE_test:.3f}\t{R2:.3f}")
pipeline:将一件需要重复做的事情切割成各个不同的阶段每一个阶段由独立的单元负责。所有待执行的对象依次进入作业队列。
from sklearn.pipeline import Pipeline
# 1. 建立模型
p = Pipeline([
('ppp', PolynomialFeatures(6)),
('mm', Ridge(alpha=0.1)),
])
# 2. 训练
p.fit(train_X, train_Y)
# 3. 预测
train_pred_y = p.predict(train_X)
test_pred_y = p.predict(test_X)
# 4. 评价
MSE_train = mean_squared_error(train_pred_y, train_Y)
MSE_test = mean_squared_error(test_pred_y, test_Y)
print(f"{MSE_train:.3f}\t{MSE_test:.3f}")
总结
多重共线性还是用逐步回归好一些,用lasso会比用Ridge好自己感觉