Datawhale房租预测实战(特征工程)
个人认为特征工程就是首先:根据一些业务常识或数据常识,从几十个特征中删掉一部分没有用的特征,如此例中的“ID”(只是每个样本的标识符),“city”(所有样本的city值都是上海),“tradeTime”(因为数据中的tradeTime全部是2018年,将月和日分割成单独的新特征后,原来的tradeTime就没有用了),所以我认为删除特征的数据常识就是找一些在所有样本中值都差不多一样或对Label没什么用的特征。这里分享一个可能比参考答案写得略简洁的划分年月日的代码:
data['tradeMonth'] = pd.to_datetime(data['tradeTime'], format="%Y/%m/%d").dt.month
data['tradeDay'] = pd.to_datetime(data['tradeTime'], format="%Y/%m/%d").dt.day
data = data.dropna().drop(['ID', 'city', 'tradeTime'], axis=1)
关于特征选择,这篇文章总结得比较全面:几种常用的特征选择方法
对于类别特征的编码问题,参考分析中使用的是LabelEncoder,而我认为用OneHotEncoder可能更合适一点,查了一下LabelEncoder的官方文档,给出的例子是(我平时比较喜欢先直接看官方文档中的例子,这样可能比较直观,毕竟全是英文的那些详细说明一时半会儿不想看哈哈):
>>> from sklearn import preprocessing
>>> le = preprocessing.LabelEncoder()
>>> le.fit([1, 2, 2, 6])
LabelEncoder()
>>> le.classes_
array([1, 2, 6])
>>> le.transform([1, 1, 2, 6])
array([0, 0, 1, 2]...)
-------------------------------------------------------
>>> le = preprocessing.LabelEncoder()
>>> le.fit(["paris", "paris", "tokyo", "amsterdam"])
>>> list(le.classes_)
['amsterdam', 'paris', 'tokyo']
>>> le.transform(["tokyo", "tokyo", "paris"])
array([2, 2, 1]...)
这个例子给我的感受是LabelEncoder完每一个类别之间还是会有数值上的差异(如果类别较多的话,这一问题会更加明显),所以我认为在这里不如用OneHotEncoder比较好,或者可以具体问题具体分析,对每个类别特征进行value_counts()
,对类别少的特征使用LabelEncoder,对类别多的特征使用OneHotEncoder,但我还是觉得这种作法有点脱裤子放屁的感觉。。为什么不直接全部OneHot掉呢- -,只是个人看法,欢迎大佬来喷。
from sklearn.preprocessing import OneHotEncoder
import numpy as np
columns = ['rentType', 'houseType', 'houseFloor', 'totalFloor', 'houseToward', 'houseDecoration', 'communityName', 'region', 'plate',
'buildYear', 'tradeMonth', 'tradeDay']
for encode in columns:
onehotcoder = OneHotEncoder(handle_unknown='ignore')
data[encode] = onehotcoder.fit(np.array(data[encode]).reshape(-1, 1))
这段代码是我想把所有类别特征列全部用OneHotEncoder替换掉,其实我本意是想让每一列都类似这样去表示:
rentType
[0. 0. 1.]
[0. 0. 1.]
[0. 0. 1.]
...
[1. 0. 0.]
[1. 0. 0.]
[0. 0. 1.]
但是用上述代码encoder完以后查询每一列,都只是给出一个onehotencoder的标记,这部分onehotencoder代码还需再改一下。。不知道如果就算不显示成我想要的效果,功能还一样不一样。
先写这么多吧。。先去google改代码了- -
修改后的onehot代码:
# onehot encode
from sklearn.preprocessing import OneHotEncoder
import numpy as np
# def encode
def encoder(columns):
for encode in columns:
onehotcoder = OneHotEncoder(handle_unknown='ignore', sparse=False)
temporary_df = pd.DataFrame(onehotcoder.fit_transform(np.array(data[encode]).reshape(-1, 1)))
temporary_df['onehot'] = ''
for num in range(temporary_df.shape[1]-1):
temporary_df['onehot'] += temporary_df[num].map(str)
data[encode] = temporary_df['onehot']
---------------------------------------------------------------------
columns = ['rentType', 'houseType', 'houseFloor', 'totalFloor', 'houseToward', 'houseDecoration', 'communityName', 'region', 'plate',
'buildYear', 'tradeMonth', 'tradeDay']
encoder(columns)
感觉是用了两个for循环的缘故,目前跑了几分钟还没有跑完。。菜鸡十分蛋疼
也有可能是因为我list(columns)里选的一些特征量,类别太多了,所以onehot起来十分慢,这也告诉我们在认识数据的时候最好用value_counts()
挑出来类别少一点的特征去onehot,别像我一样仅凭自己的业务认知筛选。