机器学习之数据集基本特征可视化(二)

524 阅读4分钟
原文链接: github.com

机器学习之数据集基本特征可视化(二)

上一篇文章简单了解了获取数据,切分训练集和测试集,对数据的简单理解。 接着对数据做进行更深一步的探索与可视化。

In [31]:
#准备工作
# 基本包的导入
import numpy as np
import os

# 画图相关
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split

# 忽略警告
import warnings

# 图片存储目录
PROJECT_ROOT_DIR = '../'
CHAPTER_ID = 'end_to_end_project'
IMAGE_PATH = os.path.join(PROJECT_ROOT_DIR, "images", CHAPTER_ID)

def save_fig(fig_id, tight_layout=True, fig_extension='png', resolution=300):
    path = os.path.join(IMAGE_PATH, fig_id + "." + fig_extension)
    print("保存图片:", fig_id)
    
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)


warnings.filterwarnings(action='ignore', module='scipy', message='internal')

# 加载数据
HOUSING_PATH = os.path.join("../datasets", "housing")
def loading_housing_data(housing_path=HOUSING_PATH):
    csv_path = os.path.join(housing_path, "housing.csv")
    return pd.read_csv(csv_path)

housing = loading_housing_data()
In [32]:
housing["income_cat"] = np.ceil(housing["median_income"] / 1.5)
housing["income_cat"].where(housing["income_cat"] < 5, 5.0, inplace=True)
In [33]:
from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42) 
for train_index, test_index in split.split(housing, housing["income_cat"]):
        strat_train_set = housing.loc[train_index]
        strat_test_set = housing.loc[test_index]

for set in (strat_train_set, strat_test_set): 
    set.drop(["income_cat"], axis=1, inplace=True)

以上是准备工作,涉及获取数据,分层抽样测试集。

In [ ]:

进一步探索和可视化数据

由于数据量比较小,因此可以操作整个数据集。首先不影响训练集,进行copy。

In [34]:
housing = strat_train_set.copy()
In [35]:
# 可视化地理数据,经纬度信息
housing.plot(kind='scatter', x='longitude', y='latitude')
Out[35]:
<matplotlib.axes._subplots.AxesSubplot at 0x1a1e777cc0>

pd.plot()函数会经常用到,kind表示画图类,x,y分别表示某个属性数据。

In [36]:
# 由于上图中点的大小,透明度一致,无法精确地反映出某个地区的密集程度,因此用如下方法:
housing.plot(kind='scatter', x='longitude', y='latitude', alpha=0.1)
Out[36]:
<matplotlib.axes._subplots.AxesSubplot at 0x1a1e598438>

上图要好很多,可以清楚的看到高密度区域。更进一步, 往图上加入跟多的信息。比如控制每个点的大小,让其表示特定的意义:如下:

In [37]:
housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.4,
            s=housing["population"]/100, label="population", 
             c="median_house_value", cmap=plt.get_cmap("jet"),colorbar=True)
plt.legend()
Out[37]:
<matplotlib.legend.Legend at 0x1a1e54f1d0>

如图有更详细的信息:s 表示特性属性决定点的半径,c表示特定的颜色。plt.legend()用于显示图例。

根据图片信息,可以推断地理位置跟房价有很大的关系。

数据间的相互关系

由于数据集不是很大,因此可以用全部数据计算不同属性间的线性相关系数, 使用corr()函数。

In [38]:
corr_matirx = housing.corr()

可以针对某个属性,查看其它属性与该属性之间的线性相关,1表示正相关, 0--不相关, -1 -- 负相关。

In [39]:
corr_matirx['median_house_value'].sort_values(ascending=False)
Out[39]:
median_house_value    1.000000
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
Name: median_house_value, dtype: float64

该函数只能刻画属性之间的线性关系,不能描述非线性关系。另一个可视化方法如下:

In [41]:
from pandas.tools.plotting import scatter_matrix
attributes = ["median_house_value", "median_income", "total_rooms",
                  "housing_median_age"]
scatter_matrix(housing[attributes], figsize=(12, 8))
/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:4: FutureWarning: 'pandas.tools.plotting.scatter_matrix' is deprecated, import 'pandas.plotting.scatter_matrix' instead.
  after removing the cwd from sys.path.
Out[41]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x1a1dbc47f0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a1b1707b8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a1a01e3c8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a1dccaa90>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x1a1dc3bf28>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a1dc3b668>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a12e24f98>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a12c467f0>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x1a133ae3c8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a12e54940>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a1ea07cc0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a1e998ba8>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x1a1bcf3c88>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a17e1bd68>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a179b4198>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x1a179d76d8>]],
      dtype=object)

从上面两种方式都得知,median income跟房价的关联性比较大。着重看一下其相关性。

In [43]:
housing.plot(kind="scatter", x="median_income", y="median_house_value",
            alpha=0.1)
plt.axis([0, 16, 0, 550000])
Out[43]:
[0, 16, 0, 550000]

axis表示做标注的范围。上图表明,两属性之间的相关性比较强,可以看到明显的上升趋势,并且点也不离散。 并且房价又明显的上限,但在某几处也有明显的水平线, 可能需要移除它们,防止其干扰训练。

属性组合的探索

经过上面的分析,发现了一些干扰数据,后面需要对齐进行清洗。也有部分头尾较大的数据,需要求其对数。 另外可以对特征进行组合分析。比如total rooms , 如果不知道人口数的话,对于房价来说关联性不强。 比较想知道的是人均房间数。下面计算了平均房间数, 平均卧室数, 平均人口数。

In [46]:
housing["rooms_per_household"] = housing["total_rooms"]/housing["households"]
housing["bedrooms_per_room"] = housing["total_bedrooms"]/housing["total_rooms"]
housing["population_per_household"]=housing["population"]/housing["households"]
In [47]:
housing.head()
Out[47]:
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value ocean_proximity rooms_per_household bedrooms_per_room population_per_household
17606 -121.89 37.29 38.0 1568.0 351.0 710.0 339.0 2.7042 286600.0 <1H OCEAN 4.625369 0.223852 2.094395
18632 -121.93 37.05 14.0 679.0 108.0 306.0 113.0 6.4214 340600.0 <1H OCEAN 6.008850 0.159057 2.707965
14650 -117.20 32.77 31.0 1952.0 471.0 936.0 462.0 2.8621 196900.0 NEAR OCEAN 4.225108 0.241291 2.025974
3230 -119.61 36.31 25.0 1847.0 371.0 1460.0 353.0 1.8839 46300.0 INLAND 5.232295 0.200866 4.135977
3555 -118.59 34.23 17.0 6592.0 1525.0 4459.0 1463.0 3.0347 254500.0 <1H OCEAN 4.505810 0.231341 3.047847
In [51]:
# 看一下相关性
corr_matrix = housing.corr()
corr_matrix["median_house_value"].sort_values(ascending=False)
Out[51]:
median_house_value          1.000000
median_income               0.687160
rooms_per_household         0.146285
total_rooms                 0.135097
housing_median_age          0.114110
households                  0.064506
total_bedrooms              0.047689
population_per_household   -0.021985
population                 -0.026920
longitude                  -0.047432
latitude                   -0.142724
bedrooms_per_room          -0.259984
Name: median_house_value, dtype: float64

如上,bedrooms_per_room 与房价之间的关系有较强的负相关性,显示每栋房子中的卧室越少, 房价越贵。

总结

针对数据的探索永远都可以进行,关键要从正确的角度出发,迅速得到关键点,可以得到一个较好的原型。该训练的过程汇总,可以反复回到这一步,进行特征探索。

In [ ]: