工具
评估函数:RMSE即损失函数,范数越大,越注重预测值偏差大的样例学习
用 python 的pandas包导入样本数据,查看前五行,每一行表示一个街区,包含十项数据特征:测试
经度 | 维度 | 房龄 | 房间数 | 卧室数 | 人口数 | 家庭数 | 收入 | 房价 | 临海 |
---|---|---|---|---|---|---|---|---|---|
-122.23 | 37.88 | 41 | 880 | 129 | 322 | 126 | 8.3252 | 452600 | NEAR BAY |
-122.22 | 37.86 | 21 | 7099 | 1106 | 2401 | 1138 | 8.3014 | 358500 | NEAR BAY |
-122.24 | 37.85 | 52 | 1467 | 190 | 496 | 177 | 7.2574 | 352100 | NEAR BAY |
-122.25 | 37.85 | 52 | 1274 | 235 | 558 | 219 | 5.6431 | 341300 | NEAR BAY |
-122.25 | 37.85 | 52 | 1627 | 280 | 565 | 259 | 3.8462 | 342200 | NEAR BAY |
其中房价一列实际是这次任务的 label, 查看数据基本状况:编码
RangeIndex: 20640 entries, 0 to 20639
Data columns (total 10 columns):
longitude 20640 non-null float64
latitude 20640 non-null float64
housing_median_age 20640 non-null float64
total_rooms 20640 non-null float64
total_bedrooms 20433 non-null float64
population 20640 non-null float64
households 20640 non-null float64
median_income 20640 non-null float64
median_house_value 20640 non-null float64
ocean_proximity 20640 non-null object
dtypes: float64(9), object(1)
能够看到一共有 20640 行记录,注意到其中 total_rooms 属性有207行缺失,ocean_proximity 属性是 object 类型,查看该属性的统计状况:
<1H OCEAN 9136
INLAND 6551
NEAR OCEAN 2658
NEAR BAY 2290
ISLAND 5
对9项数值型属性画直方图,感觉下每一个属性的分布状况:
能够看到 housing_median_age、median_house_value、median_income 有明显的翘尾状况,说明这三个属性在数据收集阶段,作过被截断处理。median_house_value 做为这次任务的预测目标值,它的截断处理在实际状况中多是个问题,由于它意味着你模型的预测值可能没法超过这个上限。上图还能够看出有四项属性属于“长尾分布”的状况,通常来讲,机器学习的模型更喜欢相似正态分布的“钟型”特征。
人脑很是擅长图像视觉的信息处理。用经度纬度肯定地理位置,用圆圈大小表示人口数量,用热力图表示房价高低,再从外部导入一张经纬度吻合的地图,能够获得一张可视化的数据图:
能够看到海景房房价广泛偏高,可是北部区域是个例外,说明临海距离应该是个很好的特征。另外,人口汇集地中心区域,房价也相应偏高,是否是作聚类以后,计算到聚类中心的距离也是一个很好的特征呢?
相关性既包括特征与label的相关性,也包括特征之间的相关性。首先看特征与 label 之间的皮尔逊系数:
median_income 0.687160
total_rooms 0.135097
housing_median_age 0.114110
households 0.064506
total_bedrooms 0.047689
population -0.026920
longitude -0.047432
latitude -0.142724
观察房价与收入的二维图:
整体上,房价与收入具备很强的相关性,收入越高,该地区的房价也越高。可是也有一些收入较高,可是房价很低,或者收入较低,房价奇高的点,多是异常点,须要从训练数据中去除。
测试集从数据集中分离而来,大小通常设置为所有数据的20%。分离的办法能够随机取,有点是采样均匀,缺点是每次取出的测试集可能不同。要克服这个缺点,在随机取的时候,能够固定随机数种子。其余的方法还有根据某列属性的尾号或者 md5 来划分,优势是每次运行的测试集是固定的,肯定是要确保尾号或者 md5 数值是均匀分布的,而且与 label 不存在相关性。在工业界,上线算法ab分桶时,经常也用相似的方法,好比按照用户id尾号分流、按照用户id的md5分流等,特别要注意未登陆用户的分桶状况,由于未登陆用户与点击率是有相关性的。
随机产生测试集,可能有的一个弊端是,重要属性的部分区间可能丢失。举个极端的例子,在全部分类模型中,label是最重要的属性,假设100个样本中只有2个正样本,则有很大几率训练样本所有是负样本。这个任务中,median_income 属性是决定房价的一个重要特征,在直方图中,能够看到收入大于7.5的样本已经比较稀疏了。若是彻底按照随机采样方法产生训练样本和测试样本,有可能训练样本中彻底不包含收入大于7.5的样本,这对于模型训练是很不利的。
解决的方法很简单,将 median_income 进行分组,每组里面按照0.2的比例抽取测试样本。分组的时候,注意每组里面样本数量不能太少,能够参考以下处理方法:
group = ceil(min(median\_income,7.5) / 1.5)
将 median_income 分为5组,每组按比例采样,这样处理的结果是,测试样本在 median_income 的分布,比当作总体(一组)彻底随机采样的方法,更符合总体分布。
先用线性回归模型在训练集上训练,而后用训练好的模型再次预测训练集的label,计算RMSE为6.8w刀,MAE偏差为4.9w刀,模型明显underfitting。解决的方法有:用复杂模型、用更好的特征、用更弱的约束。
改用决策树模型进行训练,获得训练集的偏差为0.0,在测试集中偏差极大 。在回归问题里,百分百彻底预测准确基本是不可能的,说明模型存在过拟合现象。解决的方法有:用简单模型、用更大的数据量、更强的约束、ensemble方法等。为了更好评估过拟合状况,能够用 K-fold 进行交叉验证。基本过程以下:把所有数据集随机分红K份,每次挑选其中K-1份训练数据,剩下一份做为测试集计算偏差,总共重复K次。相比于只划分一份训练集和测试集,这种方法更加健壮。
随机森林模型是多个决策树模型ensemble后的结果,比单个决策树模型具备更强抗overfitting的能力。改用随机森林模型进行训练,发现结果好得多,可是测试集偏差依旧远远大于训练集偏差,说明模型还须要更强的约束。为了找到较好的约束参数,能够采用grid search方法。
模型的超参可能有多个,每一个有多种选择,由此造成了参数网格grid。前面讲过用交叉验证的方法能够评估一个模型的效果,以上两种方法结合,可让模型遍历每一个网格点,用交叉验证的方法获得该网格点的模型预测偏差,从而找到表现最好的模型。最终找的的较好超参是 max_features 为6,n_estimators 为 30, RMSE 49900。
准确率top4%的 kenerl 地址连接,真实的数据集和本文以上描述有所区别