这是我学习hands on ml with sklearn and tf 这本书做的笔记,这是第二章
该笔记是‘一个完整的机器学习项目’,具体的是预测房价的中位数,包括:获取数据、发现并可视化数据,发现规律、为机器学习算法准备数据、选择模型,进行训练、微调模型、给出解决方案和部署、监控、维护系统。接下来是具体的代码。
1、下载数据
#俗话说,巧妇难为无米之炊,机器学习就是从大量数据中学习规律,所以项目第一步是下载数据,以下是具体代码
import os
import tarfile
from six.moves import urllib
import pandas as pd
DOWNLOAD_ROOT = "https://raw.githubusercontent.com/ageron/handson-ml/master/"
HOUSING_PATH = "datasets/housing"
HOUSING_URL = DOWNLOAD_ROOT + HOUSING_PATH + "/housing.tgz"
def fetch_housing_data(housing_url=HOUSING_URL, housing_path=HOUSING_PATH):
if not os.path.isdir(housing_path):
os.makedirs(housing_path)
tgz_path = os.path.join(housing_path, "housing.tgz")
urllib.request.urlretrieve(housing_url, tgz_path)
housing_tgz = tarfile.open(tgz_path)
housing_tgz.extractall(path=housing_path)
housing_tgz.close()
fetch_housing_data() # 下载数据
现在,运行完上述代码 ,就会在工作空间创建一个 datasets/housing 目录,下载 housing.tgz 文件,解压出 housing.csv 。
2、查看数据信息
下载到本地的数据还不能直接用需要使用Pandas加载数据。这里还是用一个小函数来加载数据:
import pandas as pd
def load_housing_data(housing_path=HOUSING_PATH):
csv_path = os.path.join(housing_path, "housing.csv")
return pd.read_csv(csv_path)
上述函数会返回一个包含所有数据的 Pandas DataFrame 对象。
快速查看数据结构,使用 DataFrame 的 head() 方法查看该数据集的前5行:
housing = load_housing_data()
print(housing.head())
运行上述代码,得到如下结果:
每一行都表示一个街区。共有 10 个属性(截图中可以看到 5 个):经度、维度、房屋年龄中位数、总房间数、总卧室数、人口数、家庭数、收入中位数、房屋价值中位数、离大海距离。
此外,还可以使用info() 方法快速查看数据的描述,特别是总行数、每个属性的类型和非空值的数量。
print(housing.info())
输出结果如下:
<class 'pandas.core.frame.DataFrame'>
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)
memory usage: 1.6+ MB
None
数据集中共有 20640 个实例。我们注意到总房间数只有 20433 个非空值,这意味着有 207 个街区缺少这个值。后面将对它进行处理。
容易发现,所有的属性都是数值的,除了离大海距离这项。它的类型是对象,因此可以包含任意 Python对象,但是因为该项是从 CSV 文件加载的,所以必然是文本类型。在刚才查看数据前五项时,你可能注意到那一列的值是重复的,意味着它可能是一项表示类别的属性。可以使用 value_counts() 方法查看该项中都有哪些类别,每个类别中都包含有多少个街区:
print(housing['ocean_proximity'].value_counts())
得到如下结果;
<1H OCEAN 9136
INLAND 6551
NEAR OCEAN 2658
NEAR BAY 2290
ISLAND 5
Name: ocean_proximity, dtype: int64
此外,再来看其它字段。 describe() 方法展示了数值属性的概括。
print(housing.describe())
得到如下结果:
截图中显示四个特征的信息,count 、 mean 、 min 和 max 几行的意思很明显了。注意,空值被忽略了(所以,卧室总数是 20433 而不是 20640)。 std 是标准差(揭示数值的分散度)。25%、50%、75% 展示了对应的分位数:每个分位数指明小于这个值,且指定分组的百分比。例如,25% 的街区的房屋年龄中位数小于 18,而 50% 的小于 29,75% 的小于 37。这些值通常称为第 25 个百分位数(或第一个四分位数),中位数,第 75 个百分位数(第三个四分位数)。
另一种快速了解数据类型的方法是画出每个数值属性的柱状图。柱状图(的纵轴)展示了特定范围的实例的个数。还可以一次给一个属性画图,或对完整数据集调用 hist() 方法,后者会画出每个数值属性的柱状图。例如,你可以看到略微超过 800 个街区的 median_house_value 值差不多等于 500000 美元。
import matplotlib.pyplot as plt
housing.hist(bins=50, figsize=(20,15))
plt.show()
得到如下结果;
注意柱状图中的一些点:
- 首先,收入中位数貌似不是美元(USD)。与数据采集团队交流之后,你被告知数据是
经过缩放调整的,过高收入中位数的会变为 15(实际为 15.0001),过低的会变为
5(实际为 0.4999)。在机器学习中对数据进行预处理很正常,这不一定是个问题,但你
要明白数据是如何计算出来的。 - 房屋年龄中位数和房屋价值中位数也被设了上限。后者可能是个严重的问题,因为它是
你的目标属性(你的标签)。你的机器学习算法可能学习到价格不会超出这个界限。你
需要与下游团队核实,这是否会成为问题。如果他们告诉你他们需要明确的预测值,即
使超过 500000 美元,你则有两个选项:
i. 对于设了上限的标签,重新收