在先前的模型预测过程中,我们已经初步优化了模型的算法,使得预测效果更好了一些,接下来,我们可以通过特征工程构建,进一步优化模型的预测效果。

  先对数据进行数据集转化,将一些特征标准化,方便后续操作,首先对时间特征进行统一,在我们的数据集中,时间特征有:date、hour、weekday、month、year。我们利用pandas库里的apply函数对数据进行分割。

  

DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)

  解释:  

  1.该函数起作用的是第一个参数,提供一个函数,实现函数的功能。

  2.这个函数需要自己实现,函数的传入参数根据axis来定,比如axis = 1,就会把一行数据作为Series的数据结构传入给自己实现的函数中,我们在函数中实现对Series不同属性之间的计算,返回一个结果,则apply函数会自动遍历每一行DataFrame的数据,最后将所有结果组合成一个Series数据结构并返回。

  lambda函数,它是只有一个表达式的函数:

lambda arg: (操作表达式,一般包含arg)

  split()函数,通过指定分隔符对字符串进行切片,如果参数num有指定值,则分隔num+1个子字符串

  

str.split( str="", num = string.count (str) )

  参数介绍:

  str — 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。

  num — 分割次数,默认为-1,即分割所有。

  返回值是分割后的字符串列表。

  下面对数据进行处理:

from datetime import datetime
dataDaily["date"] = dataDaily.datetime.apply(lambda x: x.split()[0])
dataDaily["hour"] = dataDaily.datetime.apply(lambda x: x.split()[1].split(":")[0]).astype("int")
dataDaily["year"] = dataDaily.datetime.apply(lambda x: x.split()[0].split("-")[0])
dataDaily["weekday"] = dataDaily.date.apply(lambda x: datetime.strptime(x, "%Y-%m-%d").weekday())
dataDaily["month"] = dataDaily.date.apply(lambda x: datetime.strptime(x, "%Y-%m-%d").month)

  处理后的结果:

 

  可以看见,所有的时间数据都被统一成一种形式了。

  在原始数据集中,我们可以发现,\’season\’,\’weather\’,\’holiday\’,\’workingday\’,\’weekday\’,\’month\’,\’year\’特征是int型数据,但是我们希望他们能成为category(分类类型数据),方便我们后续分析。

  我们可以利用astype()函数,将他们转换为分类类型数据。

  

categoricalFeatureNames=[\'season\',\'weather\',\'holiday\',\'workingday\',\'weekday\',\'month\',\'year\']
for var in categoricalFeatureNames:
        dataDaily[var]=dataDaily[var].astype(\'category\')

 

  对离散型数据season、weather进行One-Hot编码:

  season季节 1:春天, 2:夏天, 3:秋天, 4:冬天

  weather天气情况 1:无云,少量云,部分多云 2:雾+多云,雾+云散开,雾+少云,雾 3:小雪,小雨+雷暴+散云,小雨+散云 4:暴雨+冰雹+雷暴+雾,雪+雾

  

dataDaily[[\'season_orig\',\'weather_orig\']]=dataDaily[[\'season\',\'weather\']]
dataDaily=pd.get_dummies(dataDaily,columns=[\'season\',\'weather\'],drop_first=True)
dataDaily.head()

 

  接下来,绘制count(结果)与其他因素的回归图,对数据进行分析:

  

#绘制count vs temp ,humidity windspeed,hour的回归图
sn.jointplot(x=\'temp\',y=\'count\',data=dataDaily,kind=\'reg\')
sn.jointplot(x=\'humidity\',y=\'count\',data=dataDaily,kind=\'reg\')
sn.jointplot(x=\'windspeed\',y=\'count\',data=dataDaily,kind=\'reg\')
sn.jointplot(x=\'hour\',y=\'count\',data=dataDaily,kind=\'reg\')

 

  

 

  虽然看上去这些自变量与因变量之间不存在线性关系,但是系统还是为我们画出了一条线性回归直线,但是这样数据的精确性就降低了,所以我们尝试利用log函数构造新的特征进行分析,我们对这几个特征的值都取对数。

dataDaily[\'log_temp\']=np.log1p(dataDaily.temp)
dataDaily[\'log_windspeed\']=np.log1p(dataDaily.windspeed)
dataDaily[\'log_humidity\']=np.log1p(dataDaily.humidity)
dataDaily[\'log_hour\']=np.log1p(dataDaily.hour)

  接着我们来检测某些特征的异常值,进行处理。

  

fig,axes=plt.subplots(2,2)
fig.set_size_inches(24,12)
sn.boxplot(data=dataDaily,y=\'count\',ax=axes[0][0])
sn.boxplot(data=dataDaily,y=\'count\',x=\'season_orig\',ax=axes[0][1])
sn.boxplot(data=dataDaily,y=\'count\',x=\'hour\',ax=axes[1][0])
sn.boxplot(data=dataDaily,y=\'count\',x=\'workingday\',ax=axes[1][1])

  

  count变量包含许多异常值数据点,这些数据点的分布右偏(因为超出外部四分位数限制的数据点更多)。可以从给出的下面的箱图做出以下推断:

  • 1.春季用车数量相对较少,这点从箱形图中位数较低可以看出来。
  • 2.Hour Of The Day的箱线图中。中位数的值在早上7点-早上8点和下午5点 – 下午6点相对较高。它可以归因于这些时间段的上学的人和上班族。
  • 3.从图中可以清楚地看出,大多数离群值主要来自Working Day工作日而不是Non Working Day非工作日。

   删除计数列count中的异常值(保留count中与平均值偏差绝对值在3倍标准差以内的标准)对数据集处理,去掉相关项与无用项。

  

dropFeatures=[\'casual\',\'atemp\',\'datetime\',\'date\',\'registered\',\'count\',\'season_orig\',\'weather_orig\']
X = dataDaily.drop(dropFeatures, axis =1).copy()
yLabels = dataDaily["count"]

#固定随机种子,分割数据
train_x,test_x,train_y,test_y=train_test_split(X,yLabels,test_size=0.3,random_state=42)

#得到训练数据
data=pd.concat([train_x,train_y],axis=1)

#去除训练数据中的异常值
print(data.shape)
mean=train_y.mean()
std=train_y.std()
data=data[np.abs(train_y-mean)<=(3*std)]
print(data.shape)

 

  

   下面对数值型特征进行MIn-Max标准化处理,使得模型能对其中的数据进行更好的训练拟合。

   

#数值特征标准化
numerialFeatureNames=[\'temp\',\'humidity\',\'windspeed\',\'hour\']

#MinMax标准化
from sklearn.preprocessing import MinMaxScaler

scaler=MinMaxScaler()
scaler.fit(data[numerialFeatureNames])
data[numerialFeatureNames]=scaler.transform(data[numerialFeatureNames])
#标准化后数值型特征的描述性统计量

data.describe()

  

 

 

 

   可以看到,我们对 \’temp\’,\’humidity\’,\’windspeed\’,\’hour\’ 四个特征进行数字特征标准化后,min(最小值):0;max(最大值):1;以及四分位值都已更新。

  现在重新建模,看看数据经过预处理后的模型预测效果。

#构造验证集
dataTest=pd.concat([train_x,train_y],axis=1)

#目标与数据分离,删除不必要的特征
train_x = data.copy().drop(["count"], axis=1)
train_y = data["count"]
test_x = dataTest.copy().drop(["count"], axis=1)
test_y = dataTest["count"]

#重新建模预测需求的自行车数量
#重新训练模型
lModel=LinearRegression()
lModel.fit(X=train_x,y=np.log1p(train_y))
preds=lModel.predict(X=test_x)

#在验证集上验证
#回归效果RMSLE评估
print(\'NEW   RMSLE: \',round(rmsle(test_y,np.expm1(preds)),4))
#查看预测效果
plt.plot(np.expm1(preds))

 

 

 

 

 

  

  

  

  

  

 

 

 

 

  

  

 

 

 

  

  

版权声明:本文为colaplus-v原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/colaplus-v/p/14458776.html