Kaggle共享单车—可视化分析与单车用量预测

1.项目介绍

1.1项目说明

自行车共享系统是租借自行车的一种手段,通过这些系统,人们可以从任意地点租借一辆自行车,到达目的地后归还。
自行车共享系统明确记录了旅行时间,出发地点,到达地点和时间。因此,其可用于研究城市中的移动性。
在本项目中,要求将历史使用模式与天气数据结合起来,以预测华盛顿特区的自行车租赁租赁需求。

1.2数据来源

数据来自kaggle:kaggle共享单车数据

数据提供了跨越两年的每小时租赁数据,包含天气信息和日期信息,

训练集由每月前19天的数据组成,测试集是每月第20天到当月底的数据。

2.理解数据

2.1变量说明

datetime(日期) - 年 、月、 日+ 整点时刻
season(季节) - 1 =春, 2 = 夏, 3 = 秋, 4 = 冬
holiday(是否假日) - 是否是节假日
workingday(是否工作日) - 是否是工作日
weather(天气等级) -
1. 清澈,少云,多云。
2. 雾+阴天,雾+碎云、雾+少云、雾
3. 小雪、小雨+雷暴+散云,小雨+云
4. 暴雨+冰雹+雷暴+雾,雪+雾
temp(温度) - 摄氏温度
atemp(体感温度) - 感觉摄氏温度
humidity(相对湿度) - 相对湿度
windspeed(风速) - 风速
casual(临时租赁数量) - 非用户租赁数量
registered(会员租赁数量) - 会员租赁数量
count(总租赁数量) - 租赁总量

2.2导入数据

#导入数据包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
# 导入数据
data = pd.read_csv(r'C:\Users\ThinkPad\Desktop\bike-share\train.csv')
# 查看数据变量
data.head()
image.png

3.数据预处理

先观察数据

data.info()
image.png
data.describe()
image.png

3.1 数据变换

首先观察到datetime包含了从年到小时的信息,这里我们想把他拆开,便于之后的分析。

data['datetime'] = data['datetime'].astype(str)
data['datetime'] = data['datetime'].apply(lambda x:datetime.strptime(x,'%Y-%m-%d %H:%M:%S'))
# 提取年、月、日、小时、星期日数,并以列的形式添加到data数据中
data['year'] = data['datetime'].apply(lambda x: x.year)
data['month'] = data['datetime'].apply(lambda x: x.month)
data['day'] = data['datetime'].apply(lambda x: x.day)
data['hour'] = data['datetime'].apply(lambda x: x.hour)
data['weekday'] = data['datetime'].apply(lambda x: x.strftime('%a'))
# 调整列标题顺序,方便理解数据
columns = ['datetime', 'year', 'month', 'day', 'hour', 'weekday',
           'season', 'holiday', 'workingday', 
           'weather', 'temp', 'atemp', 'humidity', 'windspeed', 
           'casual', 'registered', 'count',]
data = data[columns]
data.head()

3.2 数据类型转换

季节,节假日,工作日,星期日数等列数据目前都是int类型,为了便于进行数据可视化,可以使用map()和pd.Categorical()将这些列的数据转换成分类数据。例如季节数据1代表春天,可以将数值型数据1转换成文本型数据Spring,再转换成带顺序的分类型数据,这样在数据可视化时会自动保留Spring--Summer--Fall--Winter的季节顺序。

对于一年中任意一天,它只能是工作日或者非工作日,其中非工作日又分为节假日和周末,因此,任意一天的日期类型只能是workingday,或者weekend,或者holiday,因此可以用一列由这三者组成的数据替代workingday和holiday两列的数据。

data1 = data.copy()
#定义day_type()函数,用来判断日期类型
def day_type(row):
    if row['holiday'] == 1:
        return 2
    elif row['workingday'] == 0 and row['holiday'] == 0:
        return 1
    else:
        return 0
# 添加一列day_type,值为日期的日期类型
data1['day_type'] = data1.apply(day_type,axis=1)
# 使用map()函数转换数值为文本型
data1['season'] = data1['season'].map({1:'Spr',2:'Sum',3:'Aut',4:'Win'})
data1['day_type'] = data1['day_type'].map({0:'Workingday',1:'Weekend',2:'Holiday'})
# 将文本型数据转换成分类数据
data1['season'] = pd.Categorical(values = data1['season'],ordered = True,categories = ['Spr','Sum','Aut','Win'])
data1['day_type'] = pd.Categorical(values = data1['day_type'],ordered = True,categories = ['Workingday','Weekend','Holiday'])
data1['weekday'] = pd.Categorical(values = data1['weekday'],ordered = True,categories = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'])
data1.set_index('datetime',inplace = True)
data1.head()
image.png

这里就可以把holiday,workingday删除掉了,因为已经归并到day_type中了

data1 = data1.drop(columns=['holiday','workingday'])

3.3 数据清洗

通过检查没有重复值,之前查看info的是时候也知道是没有缺失值的,所以接下来来检查有没有数据异常

# 数值型数据分布分析
fig,axes = plt.subplots(3,2,figsize = (16,14))
sns.distplot(data1['temp'],ax=axes[0,0])
sns.distplot(data1['atemp'],ax=axes[0,1])
sns.distplot(data1['humidity'],ax=axes[1,0])
sns.distplot(data1['windspeed'],ax=axes[1,1])
sns.distplot(data1['casual'],ax=axes[2,0])
sns.distplot(data1['registered'],ax=axes[2,1])
image.png

风速0-10中存在异常值,这里使用随即森林进行填充。

#对风速中的0值进行替换
#了解对产生风速影响的因素
corrDf = data.corr() 
heatmap = sns.heatmap(corrDf)
plt.show()
corrDf['windspeed'].sort_values(ascending =False)
image.png

image.png
from sklearn.ensemble import RandomForestRegressor
# 将数据分成风速等于0和不等于两部分
wind_0 = data[data['windspeed']==0]
wind_1 = data[data['windspeed']!=0]

#选定模型
Model_wind = RandomForestRegressor(n_estimators=1000,random_state=42)

# 选定特征值
windspeed_X = wind_1[['hour','count','season','month','humidity']]

# 选定标签值
windspeed_y = wind_1['windspeed']

#选定预测特征值
windspeedpre_X = wind_0[['hour','count','season','month','humidity']]

# 将风速不等于0的数据作为训练集,fit到RandomForestRegressor之中
Model_wind.fit(windspeed_X, windspeed_y)

#通过训练好的模型预测风速
wind_0prevalues = Model_wind.predict(windspeedpre_X)

#将预测的风速填充到风速为零的数据中
wind_0.loc[:,'windspeed'] = wind_0prevalues

wind_0和wind_1分别为:


image.png
#连接两部分数据
data = pd.concat([wind_1,wind_0],join='inner').sort_values('datetime')
data.reset_index(inplace=True)
data.drop('index',inplace=True,axis=1)
data.head()

再看一下现在的风速分布

# 风速分布

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

fig.set_size_inches(6,5)
sns.distplot(data['windspeed'])

ax.set(xlabel='windspeed',title='windspeed_scatter diagram')
image.png
#将data的windspeed字段复制给已经整理好的data1
data1['windspeed']=data['windspeed']

4.可视化与分析

#设置作图风格
plt.style.use('ggplot')

4.1 2011年至2012年的共享单车总租赁量情况

total = data1[['casual','registered','count']].resample('M').sum().reset_index()
total.head()
image.png
# 计算注册用户租车量比例
total['rate'] = total['registered']/total['count']
# 将月份数据转换成文本型
total['month'] = total['datetime'].apply(lambda x: x.strftime('%b\n%Y') if x.strftime('%b') == 'Jan' else x.strftime('%b'))
# 设定作图尺寸
fig, ax1 = plt.subplots(figsize=(15,10))
x = np.arange(24)
y1 = total['casual']
y2 = total['registered']
ax1 = plt.bar(x, y1, label='Casual', bottom=total['registered'],alpha=0.7)
ax2 = plt.bar(x, y2, label='Registered',alpha=0.7)
plt.title('Monthly Bike Rental in 2011-2012')
plt.xlim(-1,24)
plt.ylim(0, 150000)
plt.legend(loc='center left')
plt.xticks(np.arange(24), total['month'], rotation=0)

# 根据注册用户租车比例作图
ax3 = plt.twinx()
y3 = total['rate']
ax3 = plt.plot(np.arange(24), y3, label='2011',color='green')
# 美化图表
plt.ylim(0,1.1)
plt.yticks([0.5, 0.75, 0.875, 1], ['50%', '75%', '87.5%', '100%'])
plt.grid(b=None)
plt.text(x=20, y=0.96, s='Registered Rental %', color='black', weight='bold', rotation=0, backgroundcolor='#f0f0f0')

# 添加水印
plt.text(x = -1.5, y = -0.2,
    s = '   ©Cuijian                                                              Data Source: Kaggle',
    fontsize = 14, color = 'grey')  

# 添加数值标签
for a,b in zip(x,y3):
    plt.text(a, b+0.02, '%.1f%%' %(b*100), ha='center', va= 'bottom', fontsize = 7)
image.png
  • 2011年至2012年,租车数量总体呈现上升趋势,但是受季节因素影响显著,其中,春季最少,夏季秋季最多,冬季租车量要高于春季。(这里回答了开头提出的第二个问题。)
  • 注册用户是租车主力,租车比例基本每月都在75%以上。
  • 注册用户在夏季和秋季的租车比例(80%)低于春季和冬季(90%)。也就是说非注册用户夏秋租车占比高于春冬,即非注册用户更倾向于在天气情况较为暖和的夏季和秋季租车。

4.2 工作日,节假日的租车量有何不同?

# 获取包含日期数据的每日租车数据
daily_rental = data1.groupby(['year', 'month', 'day','weekday','day_type'])['count'].sum().reset_index()
daily_rental.head()

# 获取最低和最高的单日租车量值
daily_min = daily_rental['count'].min()
daily_max = daily_rental['count'].max()
print(daily_min,daily_max)
fig,(ax1,ax2) = plt.subplots(1,2,figsize = (15,12))
# 根据星期日数作每日租车量的箱线图
sns.boxplot(x = 'weekday', y = 'count', data = daily_rental, ax = ax1)
# day_type三个类型的箱线图
sns.boxplot(x = 'day_type', y = 'count', data = daily_rental, ax = ax2)

# 美化图表
ax1.set_title('Daily Bike Rental by Weekday', fontsize=18)
ax2.set_title('Daily Bike Rental by day_type', fontsize=18)
ax1.axhline(daily_min, xmin=0, xmax=16, linewidth=1, linestyle='--', alpha=0.7)
ax2.axhline(daily_max, xmin=0, xmax=16, linewidth=1, linestyle='--', alpha=0.7)
image.png
  • 没有异常值出现,数据相对合理可信。
  • 每周各天的平均租车量差距不大,在4500次上下范围波动,星期六的平均租车量相对最高,最高租车量也是在星期六。星期日的平均租车量相对最低
  • 星期五的最低租车量接近1500次,明显高于其他天数(<=1000)。
  • 就日期类型而言,工作日,周末和节假日的平均租车量较为接近,节假日的租车量波动范围较小,节假日租车量中位数明显高于工作日和周末。可以判断用户更倾向在节假日租车。

然后我们进一步下钻,探索注册用户和非注册用户的在不同天数下的租车情况

daily_casual_rental = data1.groupby(['year', 'month', 'day','weekday','day_type'])['casual'].sum().reset_index()
daily_registered_rental = data1.groupby(['year', 'month', 'day','weekday','day_type'])['registered'].sum().reset_index()

# 合并数据
daily_user_rental = daily_casual_rental
daily_user_rental['registered'] = daily_registered_rental['registered']
daily_user_rental.head()
image.png
# 使用pd.melt将casual, registered两列变成user_type一列
daily_user_rental = daily_user_rental.melt(id_vars=['year', 'month', 'day', 'weekday', 'day_type'], 
                                           value_vars=['casual', 'registered'], var_name='user_type', 
                                           value_name='rental')
daily_user_rental.head()
image.png
# 设定图表
fig, (ax5, ax6) = plt.subplots(1, 2, figsize = (16,8))
fig.suptitle('Daily Bike Rental by Casual& Registered Users',fontsize = 24)
# 不同星期日数下的每日租车量箱线图
sns.boxplot(x="weekday", y="rental", hue="user_type", ax=ax5,data=daily_user_rental,
            showmeans=True,meanprops=dict(marker='o', markerfacecolor='yellow', markeredgecolor='yellow'))
sns.boxplot(x="day_type", y="rental", hue="user_type", ax=ax6,
            data=daily_user_rental, showmeans=True, palette=['pink', 'green'], linewidth=1,
            meanprops=dict(marker='o', markerfacecolor='yellow', markeredgecolor='yellow'))
image.png

由上图可见:

  • 出现4个异常值,分别分布在周一,周二,周三,数量很少,其中三个超过上限的异常值很可能是因为当天是节假日造成的。
  • 注册用户更倾向在工作日租车,在周末的租车量(约3000/日)明显低于工作日(约4000/日),在节假日的租车量总体介于工作日和周末租车量之间。
  • 非注册用户在工作日租车量少(平均值低于1000/日),所占比例很低,在周末租车量(约1500/日)明显提高,但仍低于注册用户租车量。

4.3 每天哪个时段的租车量较高?

fig,ax7 = plt.subplots(figsize=(16,8))
# 注册用户不同时间段和日期类型的租车量作图
ax7 = data1.groupby(['hour', 'day_type'])['registered'].sum().unstack().plot(ax=ax7,marker='o')

# 非注册用户不同时间段和日期类型的租车量作图
ax8 = data1.groupby(['hour', 'day_type'])['casual'].sum().unstack().plot(ax=ax7,linestyle='--',
                                                                       color=['green','orange','pink'],marker='o')
#美化
plt.xticks(np.arange(24))
ax7.legend(['Workingday Registered', 'Weekend Registered', 'Holiday Registered', 
            'Workingday Casual', 'Weekend Casual', 'Holiday Casual'], fontsize=12)
plt.suptitle('registered&casual count in time of day_type ')
image.png

从上图可知:

  • 工作日时的早7-8点和晚5-6点是注册用户的使用高峰时段,换一句话说,注册用户有很大一部分需求是由于早晚的通勤用车。而非注册用户在工作日则没有明显的高峰时段,说明非注册用户有可能多数是无需上班通勤的大龄人群或者不需要使用自行车的人群。
  • 再来看节假日,注册用户和非注册用户的曲线表现相似,均是从早上8点开始逐渐增多,当中午12点和13点左右时达到一天的最大值,但是注册用户的最大值平均能达到37000,但是非注册用户只有20000左右,13点之后使用量逐渐递减。
  • 节假日用车数非常少,两条曲线表现相近,可以看出无论是注册用户还是非注册用户,都很少子节假日用车。

4.4 天气情况对租车量的影响如何?

天气数据包含weather, temp, atemp, windspeed, humidity,下面逐一作图分析。

4.4.1 不同天气状况下的租车量分析

weather_rental=data1[['weather','casual','registered','count']]
weather_rental['weather']=weather_rental['weather'].map({1:'Clear,Partly cloudy',2:'Mist + Cloudy',3:'Light Snow, Light Rain',
                              4:'Heavy Rain,snow'})
weather_rental.head()
image.png
weather_rental_gb=weather_rental.groupby('weather').agg({'weather':'count','count':sum}).rename(columns={'weather':'weather_count',
                                                                                                        'count':'rental'}).reset_index().sort_values('rental',ascending=False)
weather_rental_gb['average hourly rental']= weather_rental_gb['rental']/weather_rental_gb['weather_count']
weather_rental_gb.head()
image.png
fig,ax9 = plt.subplots(figsize=(10,6))
ax9=plt.bar(weather_rental_gb['weather'],weather_rental_gb['rental'],color='sandybrown')
plt.twinx()
ax10=plt.plot(weather_rental_gb['weather'],weather_rental_gb['average hourly rental'],color='gray',marker='o')

# 添加数值标签
x=weather_rental_gb['weather']
y1=weather_rental_gb['rental']
y2=weather_rental_gb['average hourly rental']
plt.legend()
for a,b in zip(x,y2):
    plt.text(a, b+2, '%.1f' %b, ha='center', va= 'bottom', fontsize =12)
image.png

由天气状况-租车数据图可见:

天气状况好时的租车量高于天气状况差的时候。晴天/少云和多云/薄雾天气下的租车量明显高于雨雪天气时。暴雨/大学天气只出现了一次,因此平均租车数据不具参考性。
晴天/少云天气下的总租车量大大超过其他天气状况,可以判断华盛顿特区气候宜人,天气多以晴天/少云为主。

4.4.2 不同风速下的租车量分析

data.set_index('datetime',inplace = True)
windspeed_rental=data[['windspeed','casual','registered','count']]
#把风速变为整形
list_windspeed=windspeed_rental['windspeed']
list_windspeed=round(list_windspeed)
list_windspeed=list_windspeed.astype(int)
windspeed_rental.loc[:,'windspeed']=list_windspeed
#对风速进行groupby
windspeed_rental_gb=windspeed_rental.groupby('windspeed').agg({'windspeed':'count',
                                                               'casual':'sum',
                                                               'registered':'sum',
                                                               'count':'sum'})
windspeed_rental_gb.rename(columns={'windspeed':'wd_count',
                          'casual':'casual_rental',
                          'registered':'registered_rental',
                          'count':'sum_rental'},inplace=True)
windspeed_rental_gb.reset_index()
windspeed_rental_gb['avg_casual_rental']=round(windspeed_rental_gb['casual_rental']/windspeed_rental_gb['wd_count'])
windspeed_rental_gb['avg_registered_rental']=round(windspeed_rental_gb['registered_rental']/windspeed_rental_gb['wd_count'])
windspeed_rental_gb['wd_rate']=windspeed_rental_gb['wd_count']/sum(windspeed_rental_gb['wd_count'])
windspeed_rental_gb['wd_rate_total']=np.cumsum(windspeed_rental_gb['wd_rate'])
windspeed_rental_gb=windspeed_rental_gb.reset_index()
image.png
#风度对总租借量的影响
fig,(ax10,ax11)=plt.subplots(1,2,figsize=(20,6))
sns.barplot(x="windspeed",y="sum_rental",data=windspeed_rental_gb,ax=ax10)
sns.lineplot(x="windspeed",y="wd_rate_total",data=windspeed_rental_gb,ax=ax11)
image.png

左图其实并不能够说明什么问题,因为有的风速分布是极少的,所以这一风速所对应的使用量也是极少的,即我们不能够说某一风速下使用量少,因为受很有可能这一风速出现的概率很小的影响。


image.png

其实最好能做出上面这个图,但是这个图的做法还在探索中。。。汗~

#两种客户在不同风速下的平均租借量
fig=plt.figure(figsize=(15,6))
sns.lineplot(x="windspeed",y="avg_casual_rental",data=windspeed_rental_gb,label='avg_casual_rental')
sns.lineplot(x="windspeed",y="avg_registered_rental",data=windspeed_rental_gb,label='avg_registered_rental')
fig.legend()
image.png
  • 超过80%的时间段风速在20以下,另外接近20%的时段风速在20-40区间,40以上的风速的时间段极少。鉴于风速大于30m/s已经属于飓风级别,因此推断风速单位是km/h。40km/h的风速已经相当于6级强风。
  • 从平均租借量来看的话,35km/h以上的风级开始平均租借量下降明显。

4.4.3 不同体感温度下的租车量分析

atemp_rental=data[['atemp','casual','registered','count']]
atemp_rental.head()

list_atemp=atemp_rental['atemp']
list_atemp=round(list_atemp)
list_atemp=list_atemp.astype(int)
atemp_rental.loc[:,'atemp']=list_atemp

atemp_rental_gb=atemp_rental.groupby('atemp').agg({'atemp':'count',
                                                   'casual':'sum',
                                                   'registered':'sum',
                                                   'count':'sum'})
atemp_rental_gb.rename(columns={'atemp':'atemp_count',
                                'casual':'casual_rental',
                                'registered':'registered_rental',
                                'count':'sum_rental'},inplace=True)
atemp_rental_gb.reset_index()
atemp_rental_gb['avg_casual_rental']=round(atemp_rental_gb['casual_rental']/atemp_rental_gb['atemp_count'])
atemp_rental_gb['avg_registered_rental']=round(atemp_rental_gb['registered_rental']/atemp_rental_gb['atemp_count'])
atemp_rental_gb['atemp_rate']=atemp_rental_gb['atemp_count']/sum(atemp_rental_gb['atemp_count'])
atemp_rental_gb['atemp_rate_total']=np.cumsum(atemp_rental_gb['atemp_rate'])
atemp_rental_gb=atemp_rental_gb.reset_index()

#体感温度对总租借量的影响
fig,(ax12,ax13)=plt.subplots(1,2,figsize=(20,6))
sns.barplot(x="atemp",y="sum_rental",data=atemp_rental_gb,ax=ax12)
sns.lineplot(x="atemp",y="atemp_rate_total",data=atemp_rental_gb,ax=ax13)
image.png
#两种客户在不同atemp下的平均租借量
fig=plt.figure(figsize=(15,6))
sns.lineplot(x="atemp",y="avg_casual_rental",data=atemp_rental_gb,label='avg_casual_rental')
sns.lineplot(x="atemp",y="avg_registered_rental",data=atemp_rental_gb,label='avg_registered_rental')
fig.legend()
image.png
  • 体感温度主要分布在5到40摄氏度,分布相对平均。
  • 5到40摄氏度的区间,无论是注册用户还是非注册用户,平均租车量基本都随着温度的上升而明显提高。

4.4.3 不同湿度下的租车量分析

思路和4.4.2是一样的,这里就直接分析结论:

  • 湿度主要集中在20至100区间,分布相对平均。
  • 湿度20-100的时候,注册用户和非注册用户的平均租车量都随着湿度的升高而显著下降。湿度20的时候租车量最高。

5.随机森林预测

5.1 数据准备

train=data.reset_index()
#训练集数据
train = train[['datetime','season','holiday','workingday','weather','temp','atemp','humidity','windspeed','count']] #风速是用随机森林模拟过的
#测试数据集
test  = pd.read_csv(r'C:\Users\ThinkPad\Desktop\bike-share\test.csv')
#了解数据集总数
print ('训练数据集:',train.shape,'测试数据集:',test.shape)
image.png
#训练集去除3倍方差以外数据
train_std = train[np.abs(train['count']-
                        train['count'].mean())<=(3*train['count'].std())] 
train_std.shape

5.2 数据预处理

先将训练集和测试集进行合并

train_std_y=np.log(train_std.pop('count'))
#将train_std、test 合并,便于修改
full = train_std.append( test , ignore_index = True )
print ('合并后的数据集:',full.shape)
full.info()
image.png

选定特征year,month,weekday,hour,season,holiday, weather, temp, humidity, windspeed

full['datetime'] = full['datetime'].astype(str)
full['datetime'] = full['datetime'].apply(lambda x:datetime.strptime(x,'%Y-%m-%d %H:%M:%S'))
# 提取年、月、小时、星期日数,并以列的形式添加到数据中
full['year'] = full['datetime'].apply(lambda x: x.year)
full['month'] = full['datetime'].apply(lambda x: x.month)
full['hour'] = full['datetime'].apply(lambda x: x.hour)
full['weekday'] = full['datetime'].apply(lambda x: x.strftime('%a'))
#选择需要的特征
columns = ['year','month','weekday','hour',
           'season','holiday', 'weather', 'temp', 'humidity', 'windspeed']
full_feature = full[columns]
full_feature.head()
image.png
#将多类别型数据使用one-hot转化成多个二分型类别
dummies_year = pd.get_dummies(full_feature['year'],prefix='year')
dummies_month = pd.get_dummies(full_feature['month'], prefix= 'month')
dummies_weekday = pd.get_dummies(full_feature['weekday'],prefix='weekday')
dummies_hour = pd.get_dummies(full_feature['hour'],prefix='hour')
dummies_season = pd.get_dummies(full_feature['season'],prefix='season')
dummies_holiday = pd.get_dummies(full_feature['holiday'],prefix='holiday')
dummies_weather = pd.get_dummies(full_feature['weather'],prefix='weather')
full_feature=pd.concat([full_feature,dummies_year,dummies_month,dummies_weekday,
                        dummies_hour,dummies_season,dummies_holiday,dummies_weather],axis=1)
#删除原有列
dropFeatures = ['season','weather','year','month','weekday','hour','holiday']
full_feature = full_feature.drop(dropFeatures ,axis = 1)
full_feature.head()
image.png

5.3 建模

5.3.1 设置训练集和预测集

train_df=full_feature.loc[train_std.index]
test_df=full_feature.loc[test.index]
#原始数据集有多少行
print('原始数据集有多少行:',train_df.shape[0])

#预测数据集大小
print('预测数据集有多少行:',test_df.shape[0])

train_x=train_df
train_y=train_std_y
test_x=test_df

5.3.2 随机森林算法调参

导入相关函数库,分别对几个重要参数进行调参

from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import GridSearchCV,cross_val_score
###粗调n_estimators参数
ScoreAll = []
for i in range(1,200,10):
    DT = RandomForestRegressor(n_estimators = i,random_state = 42) 
    score = cross_val_score(DT,train_x,train_y,cv=10,scoring='neg_mean_squared_error').mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()
image.png
###粗调max_depth参数
ScoreAll = []
for i in range(1,60,10):
    DT = RandomForestRegressor(n_estimators = 181,random_state = 42,max_depth =i) 
    score = cross_val_score(DT,train_x,train_y,cv=10,scoring='neg_mean_squared_error').mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()
image.png
###调min_samples_split参数
ScoreAll = []
for i in range(4,14):
    RF = RandomForestRegressor(n_estimators = 100,random_state = 42,max_depth =21,min_samples_split = i )
    score = cross_val_score(RF,train_x,train_y,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()
image.png
###调min_samples_leaf参数
ScoreAll = []
for i in range(10,30,2):
    DT = RandomForestRegressor(n_estimators = 100,random_state = 42,max_depth =21,min_samples_leaf = i,min_samples_split = 11 ) 
    score = cross_val_score(DT,train_x,train_y,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()
image.png
#调max_features参数
param_grid = {
    'max_features':np.arange(0.1, 1)}

rfc = RandomForestRegressor(random_state=42,n_estimators = 100,max_depth = 21,min_samples_leaf =16 ,min_samples_split =11 )
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(train_x,train_y)
print(GS.best_params_)
print(GS.best_score_)
image.png

5.3.3 应用模型

Model = RandomForestRegressor(random_state=42,n_estimators = 100,max_depth = 21,min_samples_leaf =16 ,min_samples_split =11 )
Model.fit(train_x , train_y)
pred_value = Model.predict(test_x)
pred_value = np.exp(pred_value)
submission = pd.DataFrame({'count':pred_value},columns=['count'])
submission['count'] = submission['count'].astype(int)
result=pd.concat([test,submission],axis=1)
result=result[['datetime','count']]
result.to_csv(r'C:\Users\ThinkPad\Desktop\bike-share\bike_predictions.csv',index = False)

提交~~~


image.png

结果貌似并不尽如人意,文章先写到这里,后续会持续考虑如何优化改进~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容