人工智能小白挖坑记之7 ML学习篇之3线性回归合成特征和离群值

人工智能小白挖坑记之7 ML学习篇之3线性回归合成特征和离群值

前言

这几天考科三没过?,心情不是很美丽。收拾心情,继续起航。上一篇线性回归实战中了解到,机器学习的生产过程,以及如何降低误差,全部是针对单一特征的。

这篇将了解合成特征和离群值。是5-3 synthetic_features_and_outliers中的练习
在这里插入图片描述

课程内容

通篇代码,跟上一篇最后的代码一毛一样啊,跳过跳过。在这个代码基础上进行改造。

任务1: 尝试合成特征

total_rooms 和 population 特征都会统计指定街区的相关总计数据。

但是,如果一个街区比另一个街区的人口更密集,会怎么样?我们可以创建一个合成特征(即 total_rooms 与 population 的比例)来探索街区人口密度与房屋价值中位数之间的关系。

在以下单元格中,创建一个名为 rooms_per_person 的特征,并将其用作 train_model() 的 input_feature。

通过调整学习速率,您使用这一特征可以获得的最佳效果是什么?(效果越好,回归线与数据的拟合度就越高,最终 RMSE 也会越低。)

分析:这里说的合成特征,我第一反应是,变成y=a1x1+a2x2+b。后来发现不太对,它是“探索街区人口密度与房屋价值中位数之间的关系”。街区人口密度,而且叫rooms_per_person人均房数,也就是街区房子数量total_rooms/人口population。那就简单很多了,把原来的特征用rooms_per_person顶替就好了,还是y=a*x+b

还记得上节中最后调用方法是什么吗?
def train_model(learning_rate, steps, batch_size, input_feature=“total_rooms”):

这里input_feature默认值是"total_rooms",只要我们调用的时候传入rooms_per_person就可以了。但是这个属性在源数据california_housing_dataframe中并没有,这样的话必须先计算粗来,而且一定要塞到california_housing_dataframe中,因为这里参数只传入了一个名称,内部是这样调用的my_feature_data = california_housing_dataframe[[my_feature]]。



#所以,第一步往california_housing_dataframe中塞入rooms_per_person:
california_housing_dataframe['rooms_per_person'] = california_housing_dataframe['total_rooms'] / california_housing_dataframe['population'] 

#然后直接调用就行了
calibration_data = train_model(
    learning_rate=0.00004,
    steps=300,
    batch_size=10,
    input_feature='rooms_per_person')

在这里插入图片描述
吐血,效果不太好啊,调节一下超参数。

calibration_data = train_model(
    learning_rate=0.09,
    steps=300,
    batch_size=10,
    input_feature='rooms_per_person')

在这里插入图片描述
最后一段RMSE貌似过了,看看
在这里插入图片描述
到了06周期,误差又开始变大,说明学习步伐过大,继续降低学习效率就行了,后面继续微调,不列了。

任务 2:识别离群值

我们可以通过创建预测值与目标值的散点图来可视化模型效果。理想情况下,这些值将位于一条完全相关的对角线上。

使用您在任务 1 中训练过的人均房间数模型,并使用 Pyplot 的 scatter() 创建预测值与目标值的散点图。

您是否看到任何异常情况?通过查看 rooms_per_person 中值的分布情况,将这些异常情况追溯到源数据。

分析:这里任务也很清晰,就是要把预测值和目标值的散点图画出来,为了区分将这两个散点图的颜色区分一下。

先看看原来的散点图绘制代码,找scatter

#随机取样300个
 sample = california_housing_dataframe.sample(n=300)
 #绘制散点
  plt.scatter(sample[my_feature], sample[my_label])
  #第3句没啥关系,但是我们需要用到颜色,就用的上了
  colors = [cm.coolwarm(x) for x in np.linspace(-1, 1, periods)]

知识扩展
1)np.linspace(-1, 1, periods) 返回periods个介于(-1,1)的线性样本,如果你不知道什么意思,用上节的方式,打印大法好啊
首先,在jupyter左上角点+,创建一个独立的代码块
在这里插入图片描述
在这里插入图片描述
在这里单独编辑代码,为了不干扰其他代码,变量名要取的小心.
在这里插入图片描述
2)cm.coolwarm 查了一下没查到什么信息,打印一下
在这里插入图片描述
别问我为啥这么写,原代码里for循环就是这个意思,把np.linspace中的变量迭代,依次代入cm.coolwarm中,我这里随便取了一个,打印出来一个(a,b,c,d)格式的数据。

那我们大胆假设一下, 既然这是一个color,又是4个数,是不是代表着(A,R,G,B) , A是alpha代表透明度,RGB构成red,green,blue三原色。这样按照业界规定是说的通的。我们待会试试就知道了。当然看他数据最后一位是1,也有可能是(R,G,B,A)

3)尝试改变原来的散点颜色,matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, *, data=None, **kwargs),这个api太长了,我们简单看看。x,y代表2D坐标,c代表颜色,够了,后面不用看了。
先记住原来的颜色,默认的蓝色
在这里插入图片描述

修改代码

#随机取样300个
 sample = california_housing_dataframe.sample(n=300)
 #绘制散点
  plt.scatter(sample[my_feature], sample[my_label],c=(0.2298057, 0.298717966, 0.753683153, 1.0))
  #第3句没啥关系,但是我们需要用到颜色,就用的上了
  colors = [cm.coolwarm(x) for x in np.linspace(-1, 1, periods)]

在这里插入图片描述
啦啦啦,变成紫色了,我们试一下(R,G,B,A)将最后一位1变成0.1,应该就会变成蛋蛋的紫色。
在这里插入图片描述
对了,每次改完,要重新运行该段代码,让它生效,覆盖旧代码,然后运行。成功的标志是代码块左上角在这里插入图片描述
这个In里面的数字变成最大的,代表这是插入的第20个代码块。

在这里插入图片描述
当当当,跟猜测一样啊,cm.coolwarm打印出来的格式是(R,G,B,A)。

4)会改色了之后,我们来完成任务了,一个是目标值,已经绘制了。也许有人会奇怪,这些点怎么老是变,那是因为这个sample是随机取样的,每次运行,就会随机一次。接着,我们来绘制预测值,所谓预测值,就是根据特征x,使用模型y=ax+b,来计算一个目标y出来。

看了一下代码里关于预测的地方,难道整个训练结束后整个算一遍?
在这里插入图片描述
代码里是分段算的,这个有点不太对啊。

我偷偷看了一下答案:。。。我去,我去,我去。这题0分啊,完全偏题。尴尬,上面就当我自娱自乐吧。

5)重新读题啊,“并使用 Pyplot 的 scatter() 创建预测值与目标值的散点图”。这个意思是要创建一个预测值为横坐标,目标值为纵坐标的散点图。所以应该是

plt.scatter(calibration_data["predictions"], calibration_data["targets"])

在这里插入图片描述
这跟题目中的“理想情况下,这些值将位于一条完全相关的对角线上”完全不一样啊。

6) 还好后面还有介绍:校准数据显示,大多数散点与一条线对齐。这条线几乎是垂直的,我们稍后再讲解。现在,我们重点关注偏离这条线的点。我们注意到这些点的数量相对较少。

如果我们绘制 rooms_per_person直方图,则会发现我们的输入数据中有少量离群值:

_ = california_housing_dataframe["rooms_per_person"].hist()

在这里插入图片描述
应该指的是这一小撮吧。
ps:任务2结束了,我在想后面要改名叫《小白挖坑记》了- -

任务 3:截取离群值

看看您能否通过将 rooms_per_person 的离群值设置为相对合理的最小值或最大值来进一步改进模型拟合情况。

以下是一个如何将函数应用于 Pandas Series 的简单示例,供您参考:

clipped_feature = my_dataframe[“my_feature_name”].apply(lambda x: max(x, 0))
上述 clipped_feature 没有小于 0 的值。

分析:看样子要把,校准数据中的大于500的值全部剔除掉,因为,实际值中没有这么大的,这把肯定是这样,因为剔除掉,两边500,绘制出来肯定在对角上,符合刚才说的理想情况。不过要剔除的是rooms_per_person的离群值,所以看的是直方图,把那一小撮的剔除掉,达到预测值都在500内。稳!那一小撮大概是>5的位置,我们取<=5的部分就行了。

编码:

#截取
california_housing_dataframe["rooms_per_person"] = 
    california_housing_dataframe["rooms_per_person"]).apply(lambda x: min(x, 5)
#再绘制直方图
_ = california_housing_dataframe["rooms_per_person"].hist()

在这里插入图片描述
2)重新训练

#大概调了一下,这个位置差不多最佳参数
calibration_data = train_model(
    learning_rate=0.06,
    steps=300,
    batch_size=10,
    input_feature="rooms_per_person")

在这里插入图片描述
wow,这把RMSE显著下降,从原来的130左右降到了109.85
在这里插入图片描述
3)最后看看我们的预测值与实际值的散点图

_ = plt.scatter(calibration_data["predictions"], calibration_data["targets"])

在这里插入图片描述
果然是这样,哇咔咔,终于蒙对了一把。

19.1.28日补充:没想到啊没想到,以为蒙对的时候又挖坑了?。这里有个坑,被小标题误导了,截取离群值。其实不是截取啊,而是限制最值。
在这里插入图片描述
这行代码,应该解释为,if x>5: x=5。如果超出5了就用5代替,所以那串尾巴并不是截取了,而是被归并到了5的位置。
在这里插入图片描述

小结

这此挖了一手好坑,以后每次挖坑我就把小白日记,更名为小白挖坑记,?。总归,学习了什么是合成特征,以及如何剔除离群值,来对训练做优化。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值