关于支持向量机,其原理讲解不是本次博文记录的主题,后面会用一篇文章专门记录SVM的相关问题。这里主要是对于天气预测的问题,要怎样处理数据,选取什么核函数或模型,以及模型的调优和评估展开。这里先贴一个 Notebook的笔记链接,在看完文章后可复制链接在浏览器中查看 python的详细代码,文中对就不赘述了。
Jupyter Notebook nbviewer 链接 |
---|
https://nbviewer.jupyter.org/github/lda188/my-data/blob/master/%E5%A4%A9%E6%B0%94%E9%A2%84%E6%B5%8B%EF%BC%9A2019.09.19.ipynb |
数据来源&业务需求
数据来源于Kaggle,是未经过预处理的澳大利亚天气数据集,目标是在这个数据集上来预测明天是否会下雨。
数据初步探索
导入数据Kaggle后,并进行初步探索,我们发现该数据有142193行22列。个字段含义如下:
特征/标签 | 含义 |
---|---|
Date | 观察日期 |
Location | 获取该信息的气象站的名称 |
MinTemp | 以摄氏度为单位的最低温度 |
MaxTemp | 以摄氏度为单位的最高温度 |
Rainfall | 当天记录的降雨量,单位为mm |
Evaporation | 到早上9点之前的24小时的A级蒸发量(mm) |
Sunshine | 白日受到日照的完整小时 |
WindGustDir | 在到午夜12点前的24小时中的最强风的风向 |
WindGustSpeed | 在到午夜12点前的24小时中的最强风速(km / h) |
WindDir9am | 上午9点时的风向 |
WindDir3pm | 下午3点时的风向 |
WindSpeed9am | 上午9点之前每个十分钟的风速的平均值(km / h) |
WindSpeed3pm | 下午3点之前每个十分钟的风速的平均值(km / h) |
Humidity9am | 上午9点的湿度(百分比) |
Humidity3am | 下午3点的湿度(百分比) |
Pressure9am | 上午9点平均海平面上的大气压(hpa) |
Pressure3pm | 下午3点平均海平面上的大气压(hpa) |
Cloud9am | 上午9点的天空被云层遮蔽的程度,这是以“oktas”来衡量的,这个单位记录 了云层遮挡天空的程度。0表示完全晴朗的天空,而8表示它完全是阴天。 |
Cloud3pm | 下午3点的天空被云层遮蔽的程度 |
Temp9am | 上午9点的摄氏度温度 |
Temp3pm | 下午3点的摄氏度温度 |
RainTomorrow | 目标变量,我们的标签:明天下雨了吗? |
根据字段含义及数据原型,可以知道该数据是由一部分分类型数据、一部分连续型数据构成。那么便可以根据不同的数据类型采用不同的数据处理技术。其中云层遮蔽程度“Cloud9am”&“Cloud3pm”虽然 是以数字表示,但其本质是分类变量。且大部分特征是采集的自然数据,如蒸发量,日照时间,等等,另外少部分特征是人为构成。还有一些单纯表示样本信息的变量,如采集信息的地点、采集的时间。当然,还得检查一下样本的不均衡问题。
知道数据的大致结构后,必须先分训练集和测试集,再进行数据预处理。因为测试集在现实中往往是(或者被假设为是)不可获得的。追求实用的我们不希望建模的任何过程受到测试集数据的影响,否则的话,就相当于提前告诉了模型一部分预测的答案。所以 采取了现实中所使用的这种方式:先分训练集和测试集,再逐步进行预处理。这样导致的结果是,我们对训练集执行的所有操作,都必须对测试集执行一次,工作量是翻倍的(不过是值得的)。
数据探索&预处理
数据预处理需要逐步展开,本次大致有一下几步(同时在训练集测试集操作):
第一步
先对数据进行分离,包括分离特征矩阵和标签矩阵,训练集与测试集的拆分,(拆分后的数据集要重置索引)拆分结果如下:
符号 | 含义 |
---|---|
X | 特征数据 |
Y | 标签数据 |
X_train | 训练特征数据 |
Y_train | 训练标签数据 |
X_test | 测试特征数据 |
Y_test | 测试标签数据 |
第二步
样本均衡性检查。对标签数据(测试训练同步)进行编码处理。
编码前 | 编码后 |
---|---|
NO | 0 |
Yes | 1 |
第三步
数据的异常值检查与处理,通常超过变量3倍标准差的数据被认为是异常值。异常值比例<10%的时候,通常做删除处理。删除异常值后要重置个数据集的索引。
第四步
对于日期和当日下雨量两个变量对明天是否下雨的影响是不定的,可以将其处理后保留:
处理前变量名 | 处理后变量名 | 处理后值 |
---|---|---|
Date | Mounth | 1,2,……12. |
Rainfall | Raintody | Yes|No |
第五步
对于缺失值,分类变量的缺失值处理一般用众数填充,连续型变量一般用均值填充。这里要注意一定要将分类数据和连续型数据区分开。
第六步
前面解决了数据缺失值问题和异常值问题后,数据基本上是完整的,这里再次进行数据缺失的检验。之后,需要将分类变量进行编码处理。然后对连续型数据做标准化处理。
第七步
数据预处理完成后,一定记得将整理好的干净数据导出。
模型探索
建模选择自然是我们的支持向量机SVM,先用核函数的学习曲线来选择核函数 。我们希望同时观察精确性,recall以及AUC分数 。因为SVM是计算量很大的模型,所以我们需要时刻监控我们的模型运行时间。
SVM有四个核函数:“linear”,“poly”,“rbf”,“sigmoid”。那么,核函数的选择可能成为模型优化的一个方向。下面截图是四个函数的建模耗时:
我们注意到,模型的准确度和auc面积还是勉勉强强,但是每个核函数下的recall都不太高。相比之 下,其实线性模型的效果是最好的。那现在我们可以开始考虑了,在这种状况下,我们要向着什么方向 进行调参呢?我们最想要的是什么?
我们可以有不同的目标:
一,我希望不计一切代价判断出少数类,得到最高的recall。 二,我们希望追求最高的预测准确率,一切目的都是为了让accuracy更高,我们不在意recall或者 AUC。
三,我们希望达到recall,ROC和accuracy之间的平衡,不追求任何一个也不牺牲任何一个。
如果我们希望模型的recall指标高一些。那么,SVM的class_weight参数可能成为模型优化的一个方向。下面截图是class_weight = "balanced"的建模耗时:
随着recall地无节制上升,我们的精确度下降得十分厉害,不过看起来AUC面积却还好,稳定保持在 0.86左右。如果此时我们的目的就是追求一个比较高的AUC分数和比较好的recall,那我们的模型此时 就算是很不错了。虽然现在,我们的精确度很低,但是我们的确精准地捕捉出了每一个雨天。
我们来调节线性核函数的C值,试试能否有效果:
首先,我们注意到,随着C值逐渐增大,模型的运行速度变得越来越慢。对于SVM这个本来运行就不 快的模型来说,巨大的C值会是一个比较危险的消耗。所以正常来说,我们应该设定一个较小的C值范围 来进行调整。
其次,C很小的时候,模型的各项指标都很低,但当C到1以上之后,模型的表现开始逐渐稳定,在C 逐渐变大之后,模型的效果并没有显著地提高。可以认为我们设定的C值范围太大了,然而再继续增大 或者缩小C值的范围,AUC面积也只能够在0.86上下进行变化了,调节C值不能够让模型的任何指标实现 质变。
如果我们追求平衡,也就是模型的各项指标都过得去,那SVM本身的结果就已经非常接近最 优结果了。调节阈值,调节参数C和调节class_weight都不一定有效果。但整体来看,我们的模型不是 一个糟糕的模型,但这个结果如果提交到kaggle参加比赛是绝对不足够的。
显然,还可以更加深入地探索模型,或者换别的方法来处理特征,以达到AUC面积0.9以上,或是准确度或recall都提升 到90%以上。至于支持向量机对天气预测的准确率高低要看人为主观的容忍度,也可能会有其他模型的调参使得该模型对天气的预测优于支持向量机。