回归预测1:机器学习处理共享单车数据集

使用线性回归、随机森林处理共享单车预测问题,数据集中包含了缺失值,我们使用随机森林先对缺失值进行预测,并且该数据集是和时间序列相关,但是我们将时间特征拆分为多个特征,将问题转换为了回归预测问题。

1 介绍

kaggle数据集介绍:https://www.kaggle.com/competitions/bike-sharing-demand/code?competitionId=3948&sortBy=voteCount
特征:

  • datetime:时间,我们后面会对其进行拆分,拆分为:年月日小时等;
  • season:季节
  • holiday:是否是假期
  • workingday:是否是工作日
  • weather :天气情况
  • temp :温度
  • atemp:体感温度
  • humidity:相对湿度
  • windspeed :风速
  • count -总出租数量(预测值

2 导入工具箱

import numpy as np
import pandas as pd
from datetime import datetime
import warnings
import calendar
pd.options.mode.chained_assignment = None
warnings.filterwarnings("ignore", category=DeprecationWarning)
import matplotlib.pyplot as plt
import seaborn as sn

3 数据探索

3.1 分析数据相关系数

data = pd.read_csv("train.csv")

# 相关性分析
corrMatt = data[["temp", "atemp", "casual", "registered", "humidity", "windspeed", "count"]].corr()
mask = np.array(corrMatt)
mask[np.tril_indices_from(mask)] = False
fig, ax = plt.subplots()
fig.set_size_inches(20, 10)
sn.heatmap(corrMatt, mask=mask, vmax=.8, square=True, annot=True)
plt.show()

在这里插入图片描述

3.2 分析时间和数量的关系

data["date"] = data.datetime.apply(lambda x : x.split()[0])
data["hour"] = data.datetime.apply(lambda x : x.split()[1].split(":")[0])
data["weekday"] = data.date.apply(lambda dateString : calendar.day_name[datetime.strptime(dateString,"%Y-%m-%d").weekday()])
data["month"] = data.date.apply(lambda dateString : calendar.month_name[datetime.strptime(dateString,"%Y-%m-%d").month])
data["season"] = data.season.map({1: "Spring", 2 : "Summer", 3 : "Fall", 4 :"Winter" })

fig, (ax1, ax2, ax3, ax4) = plt.subplots(nrows=4)
fig.set_size_inches(12, 20)
sortOrder = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October",
             "November", "December"]
hueOrder = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

monthAggregated = pd.DataFrame(data.groupby("month")["count"].mean()).reset_index()
monthSorted = monthAggregated.sort_values(by="count", ascending=False)
sn.barplot(data=monthSorted, x="month", y="count", ax=ax1, order=sortOrder)
ax1.set(xlabel='Month', ylabel='Avearage Count', title="Average Count By Month")

hourAggregated = pd.DataFrame(data.groupby(["hour", "season"], sort=True)["count"].mean()).reset_index()
sn.pointplot(x=hourAggregated["hour"], y=hourAggregated["count"], hue=hourAggregated["season"], data=hourAggregated,
             join=True, ax=ax2)
ax2.set(xlabel='Hour Of The Day', ylabel='Users Count', title="Average Users Count By Hour Of The Day Across Season",
        label='big')

hourAggregated = pd.DataFrame(data.groupby(["hour", "weekday"], sort=True)["count"].mean()).reset_index()
sn.pointplot(x=hourAggregated["hour"], y=hourAggregated["count"], hue=hourAggregated["weekday"], hue_order=hueOrder,
             data=hourAggregated, join=True, ax=ax3)
ax3.set(xlabel='Hour Of The Day', ylabel='Users Count', title="Average Users Count By Hour Of The Day Across Weekdays",
        label='big')

hourTransformed = pd.melt(data[["hour", "casual", "registered"]], id_vars=['hour'], value_vars=['casual', 'registered'])
hourAggregated = pd.DataFrame(hourTransformed.groupby(["hour", "variable"], sort=True)["value"].mean()).reset_index()
sn.pointplot(x=hourAggregated["hour"], y=hourAggregated["value"], hue=hourAggregated["variable"],
             hue_order=["casual", "registered"], data=hourAggregated, join=True, ax=ax4)
ax4.set(xlabel='Hour Of The Day', ylabel='Users Count', title="Average Users Count By Hour Of The Day Across User Type",
        label='big')
plt.show()

在这里插入图片描述

4 数据预处理

4.1 日期拆分,将datetime拆分为年月日等

data = pd.read_csv("train.csv")
# 日期数据拆分
data["date"] = data.datetime.apply(lambda x: x.split()[0])
data["hour"] = data.datetime.apply(lambda x: x.split()[1].split(":")[0]).astype("int")
data["year"] = data.datetime.apply(lambda x: x.split()[0].split("-")[0])
data["weekday"] = data.date.apply(lambda dateString: datetime.strptime(dateString, "%Y-%m-%d").weekday())
data["month"] = data.date.apply(lambda dateString: datetime.strptime(dateString, "%Y-%m-%d").month)

4.2 windspeed列有0值,使用随机森林对0值进行填充

print(len(data[data["windspeed"] == 0]))
print(len(data[data["windspeed"] != 0]))
# 2 填充数据,Windspeed有好多0列,我们使用随机森林进行预测,将预测值进行填充
from sklearn.ensemble import RandomForestRegressor

dataWind0 = data[data["windspeed"] == 0]
dataWindNot0 = data[data["windspeed"] != 0]
rfModel_wind = RandomForestRegressor()
windColumns = ["season", "weather", "humidity", "month", "temp", "year", "atemp"]
rfModel_wind.fit(dataWindNot0[windColumns], dataWindNot0["windspeed"])

wind0Values = rfModel_wind.predict(X=dataWind0[windColumns])
dataWind0["windspeed"] = wind0Values
data = dataWindNot0.append(dataWind0)
data.reset_index(inplace=True)
data.drop('index', inplace=True, axis=1)

print(len(data[data["windspeed"] == 0]))
print(len(data[data["windspeed"] != 0]))
原来0值的数量:1313
现在0值的数量:0

4.3 类别变量处理

categoricalFeatureNames = ["season", "holiday", "workingday", "weather", "weekday", "month", "year", "hour"]
for var in categoricalFeatureNames:
    data[var] = data[var].astype("category")

4.4 分割出类别变量

yLabels = data["count"]

4.5 删除不需要的变量

dropFeatures = ['casual', "count", "datetime", "date", "registered"]
data = data.drop(dropFeatures, axis=1)

5 构建目标函数

在这里插入图片描述

def rmsle(y, y_, convertExp=True):
    if convertExp:
        y = np.exp(y),
        y_ = np.exp(y_)
    log1 = np.nan_to_num(np.array([np.log(v + 1) for v in y]))
    log2 = np.nan_to_num(np.array([np.log(v + 1) for v in y_]))
    calc = (log1 - log2) ** 2
    return np.sqrt(np.mean(calc))

6 预测

from sklearn.linear_model import LinearRegression

lModel = LinearRegression()
yLabelsLog = np.log1p(yLabels)
lModel.fit(X=data, y=yLabelsLog)
preds = lModel.predict(X=data)
print("RMSLE Value For Linear Regression: ", rmsle(np.exp(yLabelsLog), np.exp(preds), False))

from sklearn.ensemble import RandomForestRegressor

rfModel = RandomForestRegressor(n_estimators=100)
yLabelsLog = np.log1p(yLabels)
rfModel.fit(data, yLabelsLog)
preds = rfModel.predict(X=data)
print("RMSLE Value For Random Forest: ", rmsle(np.exp(yLabelsLog), np.exp(preds), False))
RMSLE Value For Linear Regression:  0.9779011300976505
RMSLE Value For Random Forest:  0.1025119847901103
通过结果我们看出随机森林效果很好。
待完善:超参数调优。
关注公众号:AI学习部 ,获取更多数据分析相关知识。
<think>好的,我现在需要帮助用户构建或了解用于共享单车预测的随机森林回归模型。用户提到了数据处理、参数调优以及模型实现,我需要详细考虑这些方面。 首先,数据处理部分。共享单车的数据通常包括时间、天气、温度、湿度、风速、季节等信息,还有节假日和工作日的影响。数据预处理的步骤可能包括缺失值处理、异常值检测、特征编码(比如将类别变量如季节、天气转换为独热编码)、时间特征分解(比如从日期中提取小时、星期几、月份等)。还需要标准化或归一化连续变量,如温度、湿度,这对树模型可能影响不大,但最好确认一下。另外,可能需要对目标变量(租赁数量)进行对数转换,特别是如果数据存在偏态分布的话。 然后是特征工程。可能需要创建新特征,比如区分工作日和周末,或者高峰时段。另外,天气状况可能与温度、湿度有关联,可以考虑交互项。时间序列特征也很重要,比如滑动窗口的平均租赁量,但随机森林本身不处理时间序列,可能需要将滞后特征作为输入。 接下来是模型实现。随机森林回归模型可以使用Scikit-learn库中的RandomForestRegressor。需要导入相应的库,准备训练集和测试集,可能需要时间序列的分割,比如按时间划分,而不是随机划分,以避免数据泄漏。然后初始化模型,设置参数,比如n_estimators、max_depth、min_samples_split等,进行训练。 参数调优部分,通常使用网格搜索(GridSearchCV)或随机搜索(RandomizedSearchCV)来调整超参数。重要的参数包括n_estimators(树的数量)、max_features(每次分裂考虑的特征数)、max_depth(树的最大深度)、min_samples_split(分裂所需最小样本数)、min_samples_leaf(叶节点的最小样本数)。交叉验证时需要注意时间序列数据的特殊性,可能需要使用TimeSeriesSplit来避免未来信息泄露。 评估指标方面,回归问题常用MAE、MSE、RMSE、R²等。需要解释这些指标的意义,比如RMSE对较大误差更敏感,而MAE更平均。R²分数表示模型解释的方差比例。 参考用户提供的引用,引用[3]提到Kaggle自行车租赁预测项目,可能涉及类似的数据处理和模型应用。引用[2]中的XGBoost和随机森林的比较,可以建议用户尝试不同模型,但这里用户明确需要随机森林。引用[1]中的回归应用场景,如预测租赁数量属于回归任务,可以结合分类模型预测是否会有高峰时段等。 可能需要注意的问题包括过拟合,通过参数调优和交叉验证来缓解。特征重要性分析可以帮助理解哪些因素影响租赁量,比如温度、时间等。另外,时间序列预测可能需要考虑季节性,随机森林是否能捕捉到这些模式,或者是否需要加入滞后特征。 用户可能还需要了解如何部署模型,或者如何解释模型结果。不过根据问题描述,重点在实现、数据处理和调优,因此需要详细说明这些步骤,并提供代码示例,确保代码正确,比如数据预处理的具体操作,特征工程的步骤,模型训练和评估的流程。 总结步骤应该是:数据加载与探索、数据预处理、特征工程、数据集划分、模型训练、参数调优、模型评估、特征重要性分析。每个步骤需要简要解释,并给出代码示例。同时,注意引用相关参考文献,比如引用[3]的Kaggle项目可能提供了类似的方法。</think>### 共享单车租赁预测的随机森林回归模型实现指南 #### 一、数据处理流程 1. **数据加载与探索** ```python import pandas as pd data = pd.read_csv('bike_sharing.csv') print(data.describe()) print(data.isnull().sum()) # 检查缺失值[^3] ``` 2. **特征处理** - **时间特征分解** $$ \text{小时} = \text{提取datetime字段的小时部分} $$ $$ \text{星期类型} = \text{映射为0-6的类别变量} $$ ```python data['hour'] = pd.to_datetime(data['datetime']).dt.hour data['weekday'] = pd.to_datetime(data['datetime']).dt.weekday ``` - **类别变量编码** 对季节(season)、天气(weather)等字段使用独热编码: ```python data = pd.get_dummies(data, columns=['season','weather']) ``` - **标准化处理** 对温度(temp)、湿度(humidity)等连续变量进行归一化: ```python from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() data[['temp','humidity']] = scaler.fit_transform(data[['temp','humidity']]) ``` #### 二、模型构建与训练 ```python from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split X = data.drop(['datetime','count'], axis=1) y = data['count'] # 按时间顺序划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) rf = RandomForestRegressor(n_estimators=100, random_state=42) rf.fit(X_train, y_train) ``` #### 三、参数调优方法 使用网格搜索优化关键参数: ```python from sklearn.model_selection import GridSearchCV param_grid = { 'n_estimators': [100, 200], 'max_depth': [None, 10, 20], 'min_samples_split': [2, 5] } grid_search = GridSearchCV(estimator=rf, param_grid=param_grid, cv=5) grid_search.fit(X_train, y_train) print(f"最优参数: {grid_search.best_params_}") ``` #### 四、模型评估指标 1. **回归评估指标** ```python from sklearn.metrics import mean_absolute_error, r2_score y_pred = grid_search.best_estimator_.predict(X_test) print(f"MAE: {mean_absolute_error(y_test, y_pred)}") print(f"R²: {r2_score(y_test, y_pred)}") ``` 2. **特征重要性分析** ```python import matplotlib.pyplot as plt plt.barh(X.columns, grid_search.best_estimator_.feature_importances_) plt.title('特征重要性排序') plt.show() ``` #### 五、实践建议 1. **时间序列处理**:建议添加滞后特征如`前3小时租赁量`,增强时间相关性捕捉能力 2. **异常值处理**:对极端天气情况下的租赁量进行截断处理 3. **模型集成**:可结合XGBoost等梯度提升树进行模型融合[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王小葱鸭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值