线性回归案例分析

article/2025/8/17 23:58:07

本案例是kaggle共享单车的比赛案例,先对数据集介绍

Instant 记录号

Dteday:日期

Season:季节 1=春天 2=夏天 3=秋天 4=冬天

yr:年份,(0: 2011, 1:2012)

mnth:月份( 1 to 12)

hr:小时 (0 to 23)

holiday:是否是节假日

weekday:星期中的哪天,取值为 0~6

workingday:是否工作日 1=工作日 (非周末和节假日)0=周末

weathersit:天气 1:晴天,多云 2:雾天,阴天 3:小雪,小雨 4:大雨,大雪,大雾

temp:气温摄氏度

atemp:体感温度

hum:湿度

windspeed:风速

casual:非注册用户个数(非会员)

registered:注册用户个数(会员)

cnt:给定日期(天)时间(每小时)总租车人数,响应变量 y

关于线性回归知识请回顾往期两篇文章:

线性回归之原理介绍

线性回归建模思路与模型诊断(附代码)

下面直接上代码操作。

1.导入相关模块

import pandas as pd
import numpy as np
import seaborn as sns
from scipy import stats
import matplotlib.pyplot as pltfrom jupyterthemes import jtplot
jtplot.style(theme='onedork') #选择一个绘图主题
jtplot.style(ticks=True, grid=False, figsize=(6,4))plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

2.加载数据并作描述性统计分析

data = pd.read_excel(r'D:\MLearn\共享单车\共享单车.xlsx')for i in ['season','yr','mnth','holiday','weekday','workingday','weathersit']:data[i] = data[i].astype(object) #声明离散型变量data.drop(['instant','dteday','casual','registered'],axis=1).describe(include='object')des = data.drop(['instant','casual','cnt','registered'],axis=1).describe().T
des['极差'] = des['max'] - des['min']
des['离散系数'] = des['std']/des['mean']
des.T.round(decimals=3)

观察结果:

离散型变量一共7个:季节、年份、月份、是否节假日、是否周末、是否工作日和天气

数据无缺失,都是731条数据记录。

连续型变量有4个,气温摄氏度(temp),体感温度(atemp),湿度(hum)和风速(windspeed)

从数据集中趋势看,中位数与均值基本持平,说明数据分布比较集中,

从数据离散程度看,湿度的变异程度最大,但离散系数最低,波动幅度最低;而风速的变异程度低,但波动幅度大。

3.对目标变量进行正态性检验

from scipy.stats import norm, skewa = data['cnt']sns.distplot(a, fit=norm)
(mu, sigma) = norm.fit(a)
print(mu, sigma)
print('Kurtosis: %f' % a.kurt())
print('Skewness: %f' % a.skew())fig = plt.figure()
res = stats.probplot(a, plot=plt)
plt.show()

结果如下:

拟合的均值为4500,方差1935。蓝色线不完全分布在红色上,峰度值为-0.8,偏度-0.04,表明数据呈现轻微低峰态的左偏分布。

再研究一下目标变量:看看时间跟租赁量的走势图:

data['year_month'] = data.dteday.dt.strftime('%Y-%m') #年月日转换为年月# 做每天租赁散点图和每月均值
group_month = data.groupby('year_month')['cnt'].mean()
group_month.index = pd.to_datetime(group_month.index)
plt.figure(figsize=(16,5))
plt.plot(data.dteday, data.cnt, '-', color = 'b', label = '每天租赁数量', alpha=0.5)
plt.plot(group_month.index, group_month.values, '-o', color='orange', label = '每月租赁数量均值')
plt.legend()
plt.show()

1.共享单车的租赁情况2012年整体比2011年有所增长;

2.租赁数量随月份波动且每年波动幅度相似;

3.有很多局部波峰波谷值且2012年波动情况比2011年大

4.对影响租赁量因素做整体探索

sns.pairplot(data ,x_vars=['holiday','workingday','weathersit','season','weekday', 'temp','atemp','hum','windspeed'] ,y_vars=['casual','registered','cnt'] , plot_kws={'alpha': 0.5})plt.show()

结果如下,就是变量与目标的散点图分布:

1.会员在工作日出行量多,非工作日少,非会员则相反;

2.无论是会员还是非会员,节假日出行量多于非节假日;

3.租赁数量随天气等级上升而减少;

4.一季度出行量低于其他季度出行量

5.会员在星期一~星期五的出行量多于周六、周日,而非会员相反

6.租赁数量随风速增大而减少;

7.温度、湿度对非会员影响比较大,对会员影响较小

8.总体租赁量随着温度升高而升高

5.探索特征与目标之间的关系

对于离散变量,列举季节、月份对目标的影响,其余变量同理操作。

sns.violinplot(data=data[['season','cnt']],x="season",y="cnt")
plt.show()

能看出来每个季节骑行量的分布不同 barplot利用矩阵条的高度反映数值变量的集中趋势

fig,ax = plt.subplots()
sns.barplot(data=data[['mnth', 'cnt']], x="mnth",y="cnt")
ax.set(title="Monthly distribution of counts")
plt.show()

可以看出,一年12月份,单车投放量先上升后下降,峰值出现再6~8月份

对于连续变量,由于变量不多,直接给出相关关系图查看:

corrmatt = data[['temp','atemp','hum','windspeed','cnt']].corr()
plt.subplots(figsize=(6,4))
mask = np.array(corrmatt)
mask[np.tril_indices_from(mask)] = False
heatmap = sns.heatmap(corrmatt,annot=True,mask=mask,cmap="Blues")
plt.show()

1.气温摄氏度、体感温度与骑行量的相关性大于0.5,而湿度、风速与骑行量的相关性很低

2.气温摄氏度与体感温度的相关性高达0.99

再进一步挖掘,

#按温度取租赁额平均值
data['temp_group'] = pd.cut(data['temp'], bins=[0.05*i for i in range(21)],right=False)
temp_rentals = data.groupby(['temp_group'], as_index=True).agg({'casual':'mean', 'registered':'mean','cnt':'mean'})
temp_rentals .plot(title = 'The average number of rentals initiated per hour changes with the temperature')
# plt.xticks(rotation=45)
plt.show()


随着温度的上升,租赁量也增加,在0.7附近达到最高峰,之后随着温度升高,租赁量开始缓慢下降

6.假设检验

对于双样本,这里展示年份对目标影响的显著性检验,其余操作同理。

arg = []
li = [2011,2012]
for i in data['yr'].value_counts().index:arg.append(data[data['yr'] == i]['cnt'])sns.boxplot(data=arg,palette='deep') #箱线图,设置6种颜色;调色板
plt.show()# stats.f_oneway(*arg)
des = data['cnt'].groupby(data['yr']).describe()
des['cov'] = des['std']/des['mean']
des

箱线图如下图:

可见2011和2012骑行量均值有很大差别,下面进一步从统计学上验证该差异显著

#方差齐性检验 H0:两组数据方差相同
year2011 = data[data['yr'] == 0]['cnt']
year2012 = data[data['yr'] == 1]['cnt']
leveneTestRes = stats.levene(year2011, year2012, center='median')
print('w-value=%6.4f, p-value=%6.4f' %leveneTestRes)

检验结果:

p小于0.05,拒绝原假设,即两组数据方差不相同,有显著差异。因此不能采用t检验,要采取大样本u检验

from scipy.stats import normdes['S'] = des['std']**2  #总体方差的无偏估计,describe内置的std分母是n-1
des[['count','mean','S']]
u = (des['mean'][0]-des['mean'][1])/np.sqrt(np.sum(des['S']/des['count'])) #检验统计量
p = norm.cdf(u,0,1) #概率密度函数在 负无穷 到 u上的积分,也就是概率print('u-value=%6.4f, p-value=%6.4f' % (u,2*p)) #双侧检验,乘以2

检验结果p远小于0.05,因此可以认为均值有显著差异。

对于多样本检验,也就是要进行方差分析,这里以季节为例:

arg = []
li = []
for i in data['season'].value_counts().index:li.append(i)arg.append(data[data['season'] == i]['cnt'])sns.set_style('whitegrid') #箱线图,观察异常值
jtplot.style(theme='onedork') #选择一个绘图主题
jtplot.style(ticks=True, grid=False, figsize=(10, 8))
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=Falsesns.boxplot(data=arg,palette='deep') #箱线图,设置6种颜色;调色板
# plt.xticks(range(16),li,rotation=90)
plt.show()print('单因素方差分析:',stats.f_oneway(*arg))

箱线图与检验结果如下:

p值远小于0.05,因此,季节对均值有显著影响。

注:除了单因素方差分析,我们还有多因素方差分析,就是考虑两个变量交互作用的影响,以下代码实现了这个过程(本节的建模不考虑这种影响)

import statsmodels.formula.api as smf
import statsmodels.api as smli = ['season','mnth','weathersit']for n,i in enumerate(li):for j in li[n+1:]:# smf:最小二乘法,构建线性回归模型anal = smf.ols('cnt ~ C({}) + C({}) + C({})*C({})'.format(i,j,i,j), data=data).fit()# anova_lm:多因素方差分析re = sm.stats.anova_lm(anal)re = pd.DataFrame(re)if list(re['PR(>F)'])[2] > 0.01:print('{}和{}交互作用对单车投放量影响无显著差别,考虑无交互作用的情况'.format(i,j))#考虑无交互作用的方差分析anal = smf.ols('cnt ~ C({}) + C({})'.format(i,j), data=data).fit()# anova_lm:多因素方差分析re = sm.stats.anova_lm(anal)else:print('{}和{}交互作用对单车投放量影响有差别'.format(i,j))print(re)print('********************************************************')

7.特征工程

基于前面步骤的分析,我们可以筛选、构造一些特征。然后做一定的特征工程处理,离散变量需要连续化,一般采用one-hot编码(独热编码)

feature_col = ['season','mnth','weathersit','yr']
for feature in feature_col:data[feature] = data[feature].astype('object')season_di = {1:'spring',2:'summer',3:'autumn',4:'winter'}
month_di = {1:'Jan',2:'Feb',3:'Mar',4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'}
weather_di = {1:'sunny',2:'fog',3:'rain',4:'snow'}
year_di = {0:2011,1:2012}data_cat = data[feature_col]
data_cat['season'] = data_cat['season'].replace(season_di)
data_cat['mnth'] = data_cat['mnth'].replace(month_di)
data_cat['weathersit'] = data_cat['weathersit'].replace(weather_di)
data_cat['yr'] = data_cat['yr'].replace(year_di).astype(object)data_cat = pd.get_dummies(data_cat) #独热编码

如有需要,还要进行归一化处理,以后会专门出一起关于归一化的问题,利用下面代码可以进行归一化处理。本次建模做了均值标准差归一化处理。

from sklearn.preprocessing import MinMaxScaler #线性函数归一化
from sklearn.preprocessing import StandardScaler #均值与标准差归一化

8.模型建立与调参

采用L2正则进行建模,利用网格搜索寻找最优超参数,本次建模采取r2评价指标(也就是可决系数)

from sklearn.linear_model import RidgeCV
from sklearn.linear_model import LassoCV
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.metrics import make_scorer,log_loss,r2_score,mean_squared_error #评价指标,损失函数

切分训练测试集,这里二八分:

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=0)

首先,随机挑选几个超参数:

alphas= [0.1,1,5,10]model = RidgeCV(alphas=alphas,fit_intercept=True,scoring=None, cv=5)model.fit(X_train,y_train)y_pred = model.predict(X_test)
# print('train of mean_squared_error is:',mean_squared_error(y_train,model.predict(X_train)))
# print('test of mean_squared_error is:',mean_squared_error(y_test,y_pred))
print(model.alpha_)
print('train of R2 is:',r2_score(y_train,model.predict(X_train)))
print('test of R2 is:',r2_score(y_test,y_pred))

结果如下:

然后从1~10之间利用网格搜索逐步寻找最佳的超参数,笔者一共迭代了4次,最终找到了合适的超参数C=4.213

第一轮迭代:

alphas= np.linspace(1,10,21)
model = RidgeCV(alphas=alphas,fit_intercept=False,scoring=None, cv=5)
model.fit(X_train,y_train)
y_pred = model.predict(X_test)
print(model.alpha_)
print('train of R2 is:',r2_score(y_train,model.predict(X_train)))
print('test of R2 is:',r2_score(y_test,y_pred))

第二轮迭代:

alphas= np.linspace(3.7 ,4.6,21)
model = RidgeCV(alphas=alphas,fit_intercept=False,scoring=None, cv=5)
model.fit(X_train,y_train)
y_pred = model.predict(X_test)
print(model.alpha_)
print('train of R2 is:',r2_score(y_train,model.predict(X_train)))
print('test of R2 is:',r2_score(y_test,y_pred))

第三轮迭代:

alphas= np.linspace(4.15 ,4.24,21)
model = RidgeCV(alphas=alphas,fit_intercept=False,scoring=None, cv=5)
model.fit(X_train,y_train)
y_pred = model.predict(X_test)
print(model.alpha_)
print('train of R2 is:',r2_score(y_train,model.predict(X_train)))
print('test of R2 is:',r2_score(y_test,y_pred))

第四轮迭代:

alphas= np.linspace(4.2085 ,4.2175,21)
model = RidgeCV(alphas=alphas,fit_intercept=False,scoring=None, cv=5)
model.fit(X_train,y_train)
y_pred = model.predict(X_test)
print(model.alpha_)
print('train of R2 is:',r2_score(y_train,model.predict(X_train)))
print('test of R2 is:',r2_score(y_test,y_pred))

可见,第四轮后,训练集和测试集的R2没有变化了,且两者都是0.8369.说明超参数已经最优了。

9.诊断方差与偏差

绘制学习曲线和验证曲线去观察偏差与方差,先来看学习曲线:

from sklearn.linear_model import Ridge
from sklearn.model_selection import learning_curve #学习曲线,方差与偏高的诊断
from sklearn.model_selection import ShuffleSplitcv = ShuffleSplit(n_splits=10, test_size=0.3, random_state=0)li = np.linspace(0.1,1,10)
train_sizes, train_loss, test_loss = learning_curve(Ridge(alpha=4.213,fit_intercept=False,random_state=0),X, y, cv=cv, scoring ='r2',train_sizes=li)train_score = np.mean(train_loss,axis=1)
test_score = np.mean(test_loss,axis=1)
plt.figure()
plt.plot(li,train_score,'o-',color = 'b',label = 'Training')
plt.plot(li,test_score,'o-',color = 'r',label = 'Testing')
# plt.plot(li,[0.115 for i in range(len(li))],'--',color = 'g',label = 'Desired')
plt.legend(loc='best')
plt.title('learning curve')
plt.xlabel('traing set size')
plt.ylabel('R2')
plt.show()

注:这里做了10折交叉验证,利用ShuffleSplit模块实现的,举一个例子解释它的工作原理

假设参数输入如下:

ShuffleSplit(n_splits=5, test_size=0.2, random_state=0)

利用20%数据集作为验证集,80%作为训练集,对同一份数据集做重复5次这样的过程。然后训练时,5次采样都建模,最后用采样的5次验证集的平均结果作为最终的输出结果。

注意,这里与我们常说的交叉验证不太一样,因为每次的验证集样本可能有重复的,而我们的交叉验证的每次的测试集都是不一样的。源码也给出了解释。

严格的交叉验证是下面这样的(估计大家这张图不陌生,利用模块kflod可以实现)

好了,回到正题,我们解读我们模型的学习曲线:

解读学习曲线:一开始,训练集样本只有10%的时候,模型严重过拟合,训练集R2表现比测试集的好了很多,随着样本增加,观察到,训练集R2指标降低,测试集上升,模型过拟合效果逐渐被改善,当用完所有样本进行训练时,二者的R2已经非常接近了,模型拟合效果良好。

再来看验证曲线的表现,

from sklearn.model_selection import validation_curvecv = ShuffleSplit(n_splits=10, test_size=0.3, random_state=0)
li = np.linspace(0.1,10,21)train_loss, test_loss = validation_curve(Ridge(fit_intercept=False,random_state=0),X, y, cv=cv,scoring ='r2',param_name='alpha',param_range=li)train_score = np.mean(train_loss,axis=1)
test_score = np.mean(test_loss,axis=1)
plt.figure()
plt.plot(li,train_score,'o-',color = 'b',label = 'Training')
plt.plot(li,test_score,'o-',color = 'r',label = 'Testing')
plt.legend(loc='best')
plt.title('validation curve')
plt.xlabel('value of C')
plt.ylabel('R2')
plt.show()

刚开始看起来,好像训练集测试集的R2相差很大,但是我们注意到纵坐标的刻度,其实误差已经在0.01范围了。解读这个验证曲线:

一开始,对超参数惩罚很低时,模型过拟合,随着惩罚的增加,训练集效果一直下降,而测试集先上升后下降,说明模型过拟合效果减轻,当达到一定程度后,继续加大惩罚,训练集和测试集效果都下降。这就说明超参数的调节对于最优模型的选择是多么的重要了。

最后我们看看拟合出来特征系数:

# Plot important coefficients
coefs = pd.Series(model.coef_, index = X_train.columns)
print("Ridge picked " + str(sum(coefs != 0)) + " features")#系数值变量排序
imp_coefs = pd.concat([coefs.sort_values()])
imp_coefs.plot(kind = "barh")
plt.title("Coefficients in the OLS Model")
plt.show()

关于回归诊断更多的内容,比如残差独立性检验等。这里不再展示了,代码已在另外一篇文章给出。

关于线性回归的建模实操案例分享到这。最后强调一句,实际业务的建模,如果采用R2作为评价指标,达到0.4以上已经是一个不错的模型了。具体情况还需结合业务进一步分析。


http://chatgpt.dhexx.cn/article/4xqesKFJ.shtml

相关文章

【SPSS】回归分析详细操作教程(附案例实战)

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

案例:回归分析-R实现

作者 | 结实 来源 | DATA江湖 1)业务需求: 某牙膏制造企业为了更好的拓展产品市场,有效管理库存,董事会要求销售部门根据市场调查,找出公司生产牙膏销售量与销售价格以及广告投入等之间的关系,从而预测出在…

SPSS回归分析案例

SPSS回归分析案例 1.应用最小二乘法求经验回归方程 1.1数据导入 首先将数据导入SPSS如下: 1.2线性回归条件的验证 我们需要验证线性回归的前提条件: 线性(散点图,散点图矩阵)独立性正态性(回归分析的过…

回归分析——简单线性回归实例讲解(SPSS)

什么是回归分析? 回归分析是研究自变量与因变量之间数量变化关系的一种分析方法,它主要是通过因变量Y与影响它的自变量Xi(i1,2,3…)之间的回归模型,衡量自变量Xi对因变量Y的影响能力的,进而可以用来预测因…

多分类logit回归案例分析

在研究X对Y的影响时,因变量Y有时是分类变量,这时如果还想分析影响关系可以使用logit回归,常见的logit回归包括,二元logit回归(二项logit回归)、多分类logit回归以及有序logit回归。三者的区别如下&#xff…

超详细机器学习-线性回归案例(正规方程、梯度下降、岭回归)

一、线性回归 定义 线性回归通过一个或者多个自变量与因变量之间之间进行建模的回归分析。其中特点为一个或多个称为回归系数的模型参数的线性组合。 分类 一元线性回归:涉及到的变量只有一个。 多元线性回归:涉及到的变量两个或两个以上。 公式 图例…

回归分析方法应用实例1

在制定运动员选材标准时,理论上要求先对不同年龄的运动员,各测试一个较大的样本,然后,计算出各年龄的平均数、标准差,再来制定标准。 有时尽管各年龄组的样本含量n都较大,但是,计算出的各年龄…

回归分析案例分析全流程

一、案例说明 1.案例数据 在“工资影响因素”的调查问卷中,调查了每个人的起始工资、工作经验、受教育年限、受雇月数、职位等级以及当前工资六个方面。 2.分析目的 目的是建立以当前工资为因变量的回归模型,并得出结论。[案例来源于:SPS…

1.1 一元线性回归分析案例

#将pyplot字体转化成中文 matplotlib.rcParams[font.family] Microsoft YaHei plt.rcParams[font.size] 12 # 设置字体大小 plt.rcParams[axes.unicode_minus] False # 设置正常显示负号案例背景:寻找房屋面积与价格的关系并进行预测图 #需要的包 import matp…

Spring WebFlux (6): RSocket 服务实现

RSocket官网:https://rsocket.io/ RSocket是一种二进制协议,可用于字节流传输,例如TCP,WebSockets和Aeron。 提供了四中交互模式: request/response (stream of 1) 请求/响应(单响应)大多数请…

HTTP协议的挑战者:RSocket

点击蓝色“程序猿DD”关注我 回复“资源”获取独家整理的学习资料! 1. 简介 RSocket是一种二进制的点对点通信协议,是一种新的网络通信第七层协议。旨在用于分布式应用程序中。从这个意义上讲,RSocket是HTTP等其他协议的替代方案。它是一种基…

使用 RSocket——服务端主动调用客户端方法

1. 编写客户端接收请求的逻辑 我们可以在初始化 Rsocket 实例的时候指定客户端可以被调用的方法,使用 acceptor() 指定可被调用的方法和方法使用的通信模型类型: 通信类型为 RequestResponse 时: .acceptor(SocketAcceptor.forRequestRespo…

RSocket 与 gRPC性能对比

几乎每次我向观众介绍RSocket时,都会有人问这个问题:“ RSocket与gRPC相比如何?” 今天我们要找出答案。 搭建平台 插座 RSocket在应用程序网络上实现反应式语义。它是一种网络协议,可端对端实施反压力和其他反应流概念。 gR…

浅谈RSocket与响应式编程

简介: RSocket是高效一个二进制的网络通讯协议,能够满足很多场景下使用。另外,RSocket也是一个激进的响应式捍卫者,激进到连API都跟响应式无缝集成。本文我们将和大家分享RSocket与响应式编程。 作者 | 素渡 来源 | 阿里技术公众号…

阿里雷卷:RSocket从入门到落地,RSocket让AJP换发青春

考虑很久,决定还是写一下这篇文章,主要是 AJP 技术太老,我只能说 Long long ago ,估计我在用这个技术的时候,很多同学小学还没有毕业。但是没有问题,这篇文章只是一个架构启发,不会浪费你时间让…

云原生实践之 RSocket 从入门到落地:Servlet vs RSocket

技术实践的作用在于:除了用于构建业务,也是为了验证某项技术或框架是否值得大规模推广。 本期开始,我们推出《RSocket 从入门到落地》系列文章,通过实例和对比来介绍RSocket。主要围绕RSocket如何实现Polyglot RPC、Service Regi…

RSocket 基于消息传递的反应式应用层网络协议

下面基于RSocket的一些主要特性分别做一下介绍,并和HTTP之类的常见协议进行比较: Multiplexed, Binary Protocol 多路复用的二进制协议Bidirectional Streaming 双向流Flow Control 流控制Socket Resumption 连接恢复Message passing 消息传递模型Trans…

RSocket 从入门到落地:两种微服务对比

✏️ Pic by Alibaba Tech on Facebook 技术实践的作用在于:除了用于构建业务,也是为了验证某项技术或框架是否值得大规模推广。 这是《RSocket 从入门到落地》系列文章的第三篇,来一起对比下开发微服务应用和微服务之间的网络通讯。该系列文…

开源的技术底座技术中台spring cloud Rsocket 微服务

一、项目背景 企业对新技术、用户体验、需求响应、交互协作提出了新的要求 1、应用新技术: 物联网、人工智能、大数据挖掘和分析、机器人、自动化等 2、重用核心能力: 使组织能够在其ERP核心解决方案的基础上进行构建,并为“下一步做什么”铺…

spring响应式编程13 RSocket:一种新的高性能网络通信协议

前面几讲我们讨论了如何使用 WebFlux 构建响应式 Web 服务的实现方案。WebFlux 和 WebMVC 一样,都是基于 HTTP 协议实现请求-响应式的交互方式。这种交互方案很简单,但不够灵活,也无法应对所有的响应式应用场景。那么,有没有在网络…