《Sklearn与TensorFlow机器学习实用指南》学习笔记 第2章 一个完整的机器学习项目

本文是《Sklearn与TensorFlow机器学习实用指南》第二章的学习笔记,详细介绍了如何完成一个完整的机器学习项目,包括获取数据、数据探索、特征工程、模型选择与训练、模型微调等步骤。通过案例展示了如何处理加州房价预测问题,使用了Scikit-Learn的工具进行数据预处理、模型选择(如线性回归、决策树、随机森林)和模型评估,强调了特征缩放、交叉验证和集成学习在模型优化中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《Sklearn与TensorFlow机器学习实用指南》学习笔记

第2章 一个完整的机器学习项目

案例项目主要步骤:1、项目概述 2、获取数据 3、发现并可视化数据,发现规律 4、为机器学习算法准备数据 5、选择模型,进行训练 6、微调模型 7、给出解决方案 8、部署、监控、维护系统

使用真实数据

一些可以查找数据的地方:

项目概览

利用加州普查数据,建立一个加州房价模型。这个数据包含每个分区组的人口、收入中位数、房价中位数等指标。

划定问题

管道:一系列的数据处理组件被称为数据管道。管道在机器学习系统中很常见,因为有许多数据要处理和转换。
组件通常是异步运行的。每个组件吸纳进大量数据,进行处理,然后将数据传输到另一个数据容器中,而后管道中的另一个组件收入这个数据,然后输出,这个过程依次进行下去。每个组件都是独立的:组件间的接口只是数据容器。若一个组件失效了,下游的组件使用失效组件最后生产的数据,通常可以正常运行(一段时间)。这样就使整个架构相当健壮。

选择性能指标

回归问题的典型指标是均方根误差(RMSE)。均方根误差测量的是系统预测误差的标准差。

获取数据

下载数据

一般情况下,数据是存储于关系型数据库(或其它常见数据库)中的多个表、文档、文件。要访问数据,首先要有密码和登录权限,并要了解数据结构。
这个项目相对简单:只需下载一个压缩文件,housing.tgz,它包含一个CSV文件housing.csv,含有所有数据。
下面是获取数据的函数:

import os
import tarfile
from six.moves import urllib

DOWNLOAD_ROOT = "http://raw.githubusercontent.com/ageron/handson/"
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。
然后使用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()
housing.head()

info()方法可以快速查看数据的描述,包括总行数、每个属性的类型和非空值的数量。
housing.info()
所有属性都是数值的,除了大海距离这项。它的类型是对象,因此可以包含任意Python对象,但是因为是从CSV文件加载的,所以必然是文本。当查看顶部的5行时,可能注意到那一列的值是重复的,意味着它可能是一个分类属性。可以使用value_counts()方法查看都有什么类型,每个类都有多少分区:

housing["ocean_proximity"].value_counts()

describe()方法展示了数值属性的概括。

housing.describe()

另一种快速了解数据类型的方法是画出每个数值属性的柱状图。柱状图(的纵轴)展示了特定范围的实例的个数。还可以一次给一个属性画图,或对完整数据集调用hist()方法,后者会画出每个数值属性的柱状图。例如,可以看到略微超过800个街区的median_house_value值差不多等于500000美元。

%matplotlib inline
import matplotlib.pyplot as plt
housing.hist(bins=50, figsize=(20,15))
plt.show()

e3594eef6427de4f2d057bfc8a9b5662.png
注:hist()方法依赖于Matplotlib,后者依赖于用户指定的图形后端以打印到屏幕上。因此在画图之前,需要指定Matplotlib要使用的后端。最简单的方法是使用Jupyter的魔术命令%matplotlib inline。它会告诉Jupyter设定好Matplotlib,以使用Jupyter自己的后端。绘图就会在notebook中渲染了。注意在Jupyter中调用show()不是必要的,因为代码框执行后Jupyter会自动展示图像。

创建测试集

理论上,创建测试集很简单:只要随机挑选一些实例,一般是数据集的20%,放到一边:

import numpy as np

def split_train_test(data, test_ratio):
    shuffled_indices = np.random.permutation(len(data))
    test_set_size = int(len(data) * test_ratio)
    test_indices = shuffled_indices[:test_set_size]
    train_indices = shuffled_indeices[test_set_size:]
    return data.iloc[train_indices], data.iloc[test_indices]

然后可以像下面使用这个函数:

train_set, test_set = split_train_test(housing, 0.2)
print(len(train_set), "train +", len(test_set), "test")

16512 train + 4128 test
这个方法可行,但是并不完美:若再次运行程序,就会产生一个不同的测试集。多次运行之后,机器学习算法就会得到整个数据集,这是需要避免的。
解决的办法之一是保存第一次运行得到的测试集,并在随后的过程加载。另一个方法是在调用np.random.permutation()之前,设置随机数生成器的种子(比如np.random.seed(42)),以产生总是相同的混合指数(shuffled indices)。
但若获取更新后的数据集,这两个方法都会失败。一个通常的解决方法是使用每个实例的识别码,以判断这个实例是否应该放入测试集(假设实例有单一且不变的识别码)。例如,你可以计算出每个实例ID的哈希值,只保留其最后一个字节,如果该值小于等于 51(约为 256 的 20%),就将其放入测试集。这样可以保证在多次运行中,测试集保持不变,即使更新了数据集。新的测试集会包含新实例中的 20%,但不会有之前位于训练集的实例。下面是一种可用的方法:

import hashlib

def test_set_check(identifier, test_ratio, hash):
    return hash(np.int64(identifier)).digest()[-1] < 256 * test_ratio

def split_train_test_by_id(data, test_ratio, id_column, hash=hashlib.md5):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio, hash))
    return data.loc[~in_test_set], data.loc[in_test_set]

不过,房产数据集没有识别码这一列。最简单的方法是使用行索引作为ID:

housing_with_id = housing.reset_index()
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "index")

Scikit-Learn提供了一些函数,可以用多种方式将数据集分割成多个子集。最简单的函数是train_test_split,它的作用和之前的函数split_train_test很像,并带有其它一些功能。首先,它有一个random_state参数,可以设定随机生成器种子;第二,可以将种子传递到多个行数相同的数据集,可以在相同的索引上分割数据集。
大多数的收入中位数的值聚集在2-5(万美元),一些收入中位数会超过6。数据集中的每个分层都要有足够的实例位于数据中。代码将收入中位数除以1.5(以限制收入分类的数量),创建了一个收入分类属性,用ceil对值舍入(以产生离散的分类),然后将所有大于5的分类归于到分类5:

housing["income_cat"] = np.ceil(housing["median_income"] / 1.5)
housing["income_cat"].where(housing["income_cat"] < 5, 5.0, inplace=True)

可以根据收入分类,进行分层采样,使用Scikit-Learn的StratifiedShuffleSplit类:

from sklearn.model_selection import StratifiedShuffleSplit

split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值