二手车交易价格预测——数据的特征工程

环境:Pycharm、python3.7

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import mean_absolute_error
# 导入训练集
file = open("used_car_train.csv", encoding = 'UTF-8')
x_data = pd.read_csv(file, sep = ' ')
X = x_data

# 'notRepairedDamage' 是 object 类型,在实际运算中需要强制转换为 float
# 'notRepairedDamage' 其中有 '-' 符号,这里将其替换为数值 0.5
X['notRepairedDamage'] = X['notRepairedDamage'].replace('-', '0.5')
X['notRepairedDamage'] = X['notRepairedDamage'].astype('float')

# 'bodyType' 有缺失值,根据特征值特点,用数值 8 代替其他未知
# 'bodyType' 由于数值不代表大小或先后顺序,因此进行独热编码增加维度
X['bodyType'] = X['bodyType'].fillna(value = 8)
X['bodyType'] = X['bodyType'].astype('int')
OneHotEncoder(sparse = False).fit_transform(X[['bodyType']])

# 'fuelType' 有缺失值,根据特征值特点,用数值 7 代替其他未知
# 'fuelType' 由于数值不代表大小或先后顺序,因此进行独热编码增加维度
X['fuelType'] = X['fuelType'].fillna(value = 7)
X['fuelType'] = X['fuelType'].astype('int')
OneHotEncoder(sparse = False).fit_transform(X[['fuelType']])

# 'gearbox' 有缺失值,根据特征值特点,用数值 2 代替其他未知
# 'gearbox' 由于数值不代表大小或先后顺序,因此进行独热编码增加维度
X['gearbox'] = X['gearbox'].fillna(value = 2)
X['gearbox'] = X['gearbox'].astype('int')
OneHotEncoder(sparse = False).fit_transform(X[['gearbox']])

# 'seller' 由于数值不代表大小或先后顺序,因此进行独热编码增加维度
OneHotEncoder(sparse = False).fit_transform(X[['seller']])

# 'offerType' 由于数值不代表大小或先后顺序,因此进行独热编码增加维度
OneHotEncoder(sparse = False).fit_transform(X[['offerType']])

# 'model' 在训练集中有一个未知值,在测试集中没有未知值
# 因此可以将训练集中的未知值删去,不影响整体数据
X = X.dropna(how = "any", subset = ['model'])

# 'power' 取值范围为 0 ~ 600,数据分析中可以发现有越界值
# 因此对 'power' 范围进行约束
X['power'] = X['power'].map(lambda x: 600 if x > 600 else x)

# 使用时间:data['creatDate'] - data['regDate'],反应汽车使用时间,一般来说价格与使用时间成反比
# 不过要注意,数据里有时间出错的格式,所以我们需要 errors = 'coerce'
X['used_time'] = (pd.to_datetime(X['creatDate'], format = '%Y%m%d', errors = 'coerce') - pd.to_datetime(X['regDate'], format = '%Y%m%d', errors = 'coerce')).dt.days

# 从邮编中提取城市信息,相当于加入了先验知识
X['city'] = X['regionCode'].apply(lambda x : str(x)[:-3])

# 数据分桶,以 'power' 为例
# 为什么要做数据分桶呢,原因有很多
# 1. 离散后稀疏向量内积乘法运算速度更快,计算结果也方便存储,容易扩展;
# 2. 离散后的特征对异常值更具鲁棒性,如 age > 30 为 1 否则为 0,对于年龄为 200 的也不会对模型造成很大的干扰;
# 3. LR 属于广义线性模型,表达能力有限,经过离散化后,每个变量有单独的权重,这相当于引入了非线性,能够提升模型的表达能力,加大拟合;
# 4. 离散后特征可以进行特征交叉,提升表达能力,由 M + N 个变量编程 M * N 个变量,进一步引入非线形,提升了表达能力;
# 5. 特征离散后模型更稳定,如用户年龄区间,不会因为用户年龄长了一岁就变化
# 当然还有很多原因,LightGBM 在改进 XGboost 时就增加了数据分桶,增强了模型的泛化性
bin = [i * 10 for i in range(31)]
X['power_bin'] = pd.cut(X['power'], bin, labels = False)
X[['power_bin', 'power']].head()

# 删除不需要的数据
X = X.drop(['creatDate', 'regDate', 'regionCode'], axis = 1)

# 对 'kilometer' 直接做归一化
X['kilometer'] = ((X['kilometer'] - np.min(X['kilometer'])) / 
                        (np.max(X['kilometer']) - np.min(X['kilometer'])))

# 根据数据分析的特征相关性分析,删除以下特征相关性较高的特征
X = X.drop(['v_6', 'v_4', 'v_13', 'v_2'], axis = 1)

# 将 y 划分为 label 标签值
y = X.price

# 将 X 划分为所有的特征值
X = X.drop(['price'], axis = 1)
X = X.drop_duplicates()
X = X.iloc[ : , 1 : ]

# 划分用于训练的数据和用于检测的数据
# 按 90% 训练样本、 10% 测验样本
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.1, random_state = 4)

"""
导入训练模型
………………
………………(此处省略)
………………
训练模型完成
"""

# 导入预测集
file = open("used_car_testA.csv", encoding = 'UTF-8')
y_data = pd.read_csv(file, sep = ' ')
y_test = data.iloc[ : , 1 : ]

"""
预测集的处理方法同训练集的处理方法(此处省略)
"""

数据的特征工程就到这里,接下来将进行建模与调参等一系列模型构造处理,使用机器学习算法核心。
如有错误,请多指正。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值