数据探索和可视化、发现规律

目前为止,你只是快速查看了数据,对要处理的数据有了整体了解。现在的目标是更深的探索数据。

首先,保证你将测试集放在了一旁,只是研究训练集。另外,如果训练集非常大,你可能需要再采样一个探索集,保证操作方便快速。在我们的案例中,数据集很小,所以可以在全集上直接工作。创建一个副本,以免损伤训练集:

  1. housing = strat_train_set.copy()

地理数据可视化

因为存在地理信息(纬度和经度),创建一个所有街区的散点图来数据可视化是一个不错的主意(图 2-11):

  1. housing.plot(kind="scatter", x="longitude", y="latitude")

数据探索和可视化、发现规律 - 图1

图 2-11 数据的地理信息散点图

这张图看起来很像加州,但是看不出什么特别的规律。将alpha设为 0.1,可以更容易看出数据点的密度(图 2-12):

  1. housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.1)

数据探索和可视化、发现规律 - 图2

图 2-12 显示高密度区域的散点图

现在看起来好多了:可以非常清楚地看到高密度区域,湾区、洛杉矶和圣迭戈,以及中央谷,特别是从萨克拉门托和弗雷斯诺。

通常来讲,人类的大脑非常善于发现图片中的规律,但是需要调整可视化参数使规律显现出来。

现在来看房价(图 2-13)。每个圈的半径表示街区的人口(选项s),颜色代表价格(选项c)。我们用预先定义的名为jet的颜色图(选项cmap),它的范围是从蓝色(低价)到红色(高价):

  1. housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.4,
  2. s=housing["population"]/100, label="population",
  3. c="median_house_value", cmap=plt.get_cmap("jet"), colorbar=True,
  4. )
  5. plt.legend()

数据探索和可视化、发现规律 - 图3

图 2-13 加州房价

这张图说明房价和位置(比如,靠海)和人口密度联系密切,这点你可能早就知道。可以使用聚类算法来检测主要的聚集,用一个新的特征值测量聚集中心的距离。尽管北加州海岸区域的房价不是非常高,但离大海距离属性也可能很有用,所以这不是用一个简单的规则就可以定义的问题。

查找关联

因为数据集并不是非常大,你可以很容易地使用corr()方法计算出每对属性间的标准相关系数(standard correlation coefficient,也称作皮尔逊相关系数):

  1. corr_matrix = housing.corr()

现在来看下每个属性和房价中位数的关联度:

  1. >>> corr_matrix["median_house_value"].sort_values(ascending=False)
  2. median_house_value 1.000000
  3. median_income 0.687170
  4. total_rooms 0.135231
  5. housing_median_age 0.114220
  6. households 0.064702
  7. total_bedrooms 0.047865
  8. population -0.026699
  9. longitude -0.047279
  10. latitude -0.142826
  11. Name: median_house_value, dtype: float64

相关系数的范围是 -1 到 1。当接近 1 时,意味强正相关;例如,当收入中位数增加时,房价中位数也会增加。当相关系数接近 -1 时,意味强负相关;你可以看到,纬度和房价中位数有轻微的负相关性(即,越往北,房价越可能降低)。最后,相关系数接近 0,意味没有线性相关性。图 2-14 展示了相关系数在横轴和纵轴之间的不同图形。

数据探索和可视化、发现规律 - 图4

图 2-14 不同数据集的标准相关系数(来源:Wikipedia;公共领域图片)

警告:相关系数只测量线性关系(如果x上升,y则上升或下降)。相关系数可能会完全忽略非线性关系(例如,如果x接近 0,则y值会变高)。在上面图片的最后一行中,他们的相关系数都接近于 0,尽管它们的轴并不独立:这些就是非线性关系的例子。另外,第二行的相关系数等于 1 或 -1;这和斜率没有任何关系。例如,你的身高(单位是英寸)与身高(单位是英尺或纳米)的相关系数就是 1。

另一种检测属性间相关系数的方法是使用 Pandas 的scatter_matrix函数,它能画出每个数值属性对每个其它数值属性的图。因为现在共有 11 个数值属性,你可以得到11 ** 2 = 121张图,在一页上画不下,所以只关注几个和房价中位数最有可能相关的属性(图 2-15):

  1. from pandas.tools.plotting import scatter_matrix
  2. attributes = ["median_house_value", "median_income", "total_rooms",
  3. "housing_median_age"]
  4. scatter_matrix(housing[attributes], figsize=(12, 8))

数据探索和可视化、发现规律 - 图5

图 2-15 散点矩阵

如果 pandas 将每个变量对自己作图,主对角线(左上到右下)都会是直线图。所以 Pandas 展示的是每个属性的柱状图(也可以是其它的,请参考 Pandas 文档)。

最有希望用来预测房价中位数的属性是收入中位数,因此将这张图放大(图 2-16):

  1. housing.plot(kind="scatter", x="median_income",y="median_house_value",
  2. alpha=0.1)

数据探索和可视化、发现规律 - 图6

图 2-16 收入中位数 vs 房价中位数

这张图说明了几点。首先,相关性非常高;可以清晰地看到向上的趋势,并且数据点不是非常分散。第二,我们之前看到的最高价,清晰地呈现为一条位于 500000 美元的水平线。这张图也呈现了一些不是那么明显的直线:一条位于 450000 美元的直线,一条位于 350000 美元的直线,一条在 280000 美元的线,和一些更靠下的线。你可能希望去除对应的街区,以防止算法重复这些巧合。

属性组合试验

希望前面的一节能教给你一些探索数据、发现规律的方法。你发现了一些数据的巧合,需要在给算法提供数据之前,将其去除。你还发现了一些属性间有趣的关联,特别是目标属性。你还注意到一些属性具有长尾分布,因此你可能要将其进行转换(例如,计算其log对数)。当然,不同项目的处理方法各不相同,但大体思路是相似的。

给算法准备数据之前,你需要做的最后一件事是尝试多种属性组合。例如,如果你不知道某个街区有多少户,该街区的总房间数就没什么用。你真正需要的是每户有几个房间。相似的,总卧室数也不重要:你可能需要将其与房间数进行比较。每户的人口数也是一个有趣的属性组合。让我们来创建这些新的属性:

  1. housing["rooms_per_household"] = housing["total_rooms"]/housing["households"]
  2. housing["bedrooms_per_room"] = housing["total_bedrooms"]/housing["total_rooms"]
  3. housing["population_per_household"]=housing["population"]/housing["households"]

现在,再来看相关矩阵:

  1. >>> corr_matrix = housing.corr()
  2. >>> corr_matrix["median_house_value"].sort_values(ascending=False)
  3. median_house_value 1.000000
  4. median_income 0.687170
  5. rooms_per_household 0.199343
  6. total_rooms 0.135231
  7. housing_median_age 0.114220
  8. households 0.064702
  9. total_bedrooms 0.047865
  10. population_per_household -0.021984
  11. population -0.026699
  12. longitude -0.047279
  13. latitude -0.142826
  14. bedrooms_per_room -0.260070
  15. Name: median_house_value, dtype: float64

看起来不错!与总房间数或卧室数相比,新的bedrooms_per_room属性与房价中位数的关联更强。显然,卧室数/总房间数的比例越低,房价就越高。每户的房间数也比街区的总房间数的更有信息,很明显,房屋越大,房价就越高。

这一步的数据探索不必非常完备,此处的目的是有一个正确的开始,快速发现规律,以得到一个合理的原型。但是这是一个交互过程:一旦你得到了一个原型,并运行起来,你就可以分析它的输出,进而发现更多的规律,然后再回到数据探索这步。