做邮轮的网站,提高网站转化率,四川省安监站网址,网站迁移建设方案使用真实数据
当你在研习机器学习时#xff0c;最好是使用真实世界中的数据#xff0c;而不是采用人工数据。巧的是#xff0c;数以千计的数据集可供选择#xff0c;涵盖了各种领域。
流行的开放数据存储库#xff1a; OpenML.orgKaggle.compaperswithcode.com UC Irvin…使用真实数据
当你在研习机器学习时最好是使用真实世界中的数据而不是采用人工数据。巧的是数以千计的数据集可供选择涵盖了各种领域。
流行的开放数据存储库 OpenML.orgKaggle.compaperswithcode.com UC Irvine Machine Learning RepositoryAmazon’s AWS datasets TensorFlow datasets 元门户数据库 DataPortals.org OpenDataMonitor.eu 其他流行的开房数据集 Wikipedia’s list of machine learning datasets Quora.com The datasets subreddit
本文数据来自于 StatLib 仓库的加州房价数据见下图它是基于 1990 年加利福尼亚州人口普查的数据而不是最近的数据不必过于纠结我们的重心在于研习机器学习并非是在讨论房价的问题。 看图说话
机器学习的首要任务是利用加州人口普查数据建立一个该州房价的模型。你的模型应该从这些数据中学习并能够在给定所有其他指标的情况下预测任何地区的房屋中位数价格。
框架问题
建立一个模型可能并不是最终目标公司期望使用该模式如何从中获益故而了解目标是至关重要的因为它将决定该如何去构建问题、将选择哪些算法、将使用哪些性能度量来评估您的模型以及您将花费多少精力来调整它。
你的模型的输出(一个地区的房价中位数的预测)将被馈送到另一个机器学习系统(见下图)以及许多其他的这个下游系统将决定它是否值得在一个给定的领域投资。做好这一点至关重要因为它直接影响收入。
目前的解决方案是什么样的(如果有的话)。目前的情况往往会给你一个性能的参考以及如何解决问题 的见解。该地区的房价目前是由专家手动估算的一个团队收集有关该地区的最新信息当他们无法得到房价中位数时他们使用复杂的规则来估算。 这既费钱又费时而且他们的估计也不准确在他们设法找出实际中位房价的情况下他们常常意识到自己的估计误差超过30%。这就是为什么该公司认为考虑到有关该地区的其他数据建立一个预测该地区房价中值的模型将是有用的。人口普查数据看起来是一个很好的数据集因为它包 括数千个地区的房屋价格中位数以及其他数据。 管道 数据处理组件的序列称为数据管道。管道在机器学习系统中非常常见因为有很多数据要操作很多数据转换要应用。 组件通常异步运行。每个组件都拉入大量数据对其进行处理并将结果吐出到另一个数据存储中。然后过了一段时间管道中的下一个组件拉入该数据并输出它自己的输出。每个组件都是相当独立的:组件之间的接口仅仅是数据存储。这使得系统易于掌握(借助数据流 图)不同的团队可以专注于不同的组件。此外如果一个组件坏了下游组件通常可以继续正常运行(至少一段时间)只需要使用坏掉的组件的最后一个输出。这使得体系结构相当健壮。 另一方面如果没有实现适当的监视一个损坏的组件可能在一段时间内不会被注意到。数据变得陈旧整个系统的性能下降。 虽然有了这些信息可以开始设计你的系统但请回答它是监督、无监督、半监督、自我监督、或强化学习任务它是一个分类任务、回归任务抑或是其它别的什么你应该使用批量学习还是在线学习技术呢
你能回答出来了吗这显然是一个典型的监督学习任务因为模型可以用带标签的示例进行训练(每个示例都带有预期输出即该地区的房价中值)。这是一个典型的回归任务因为模型将被要求预测一个值。更具体地说这是一个多元回归问题因为系统将使用多个特征进行预测(地区的人口、中位数收入等)。这也是一个单变量回归问题因为我们只是试图预测每个地区的一个单一值。如果我们试图预测每个地区的多个值这将是一个多元回归问题。最后没有连续的数据流进入系统没有特别的需要来适应快速变化的数据数据足够小可以放入内存中所以普通的批处理学习应该做得很好。
选择性能度量
回归问题的一个典型性能度量是均方根误差(RMSE)。它给出了系统在其预测中通常会产生多大误差的概念较大误差的权重较高。公式给出了计算RMSE的数学公式。 注意 这个方程介绍了我将在本书中使用的几个非常常见的机器学习符号 m 是您测量RMSE 的数据集中的实例数。 例如如果您在 2,000 个地区的验证集上评估 RMSE则 m 2,000。 x(i) 是数据集中第i 个实例的所有特征值不包括标签的向量y(i) 是其标签该实例的所需输出值。 例如如果数据集中的第一个区位于经度 –118.29°纬度 33.91°有 1,416 名居民收入中位数为 38,372 美元房屋价值中位数为 156,400 美元暂时忽略其他特征 然后 和 X是一个矩阵包含数据集中所有实例的所有特征值不包括标签。 每个实例一行第 i 行等于 x(i) 的转置记为 (x(i))⊺.3 — 例如如果第一区如上所述则矩阵 X 如下所示 h 是系统的预测函数也称为假设。 当给定系统一个实例的特征向量 x(i) 时它会输出该实例的预测值 ŷ(i) h(x(i))ŷ 发音为“y-hat”。 — 例如如果您的系统预测第一区的房价中位数为 158,400 美元则 ŷ(1) h(x(1)) 158,400。 该地区的预测误差为 ŷ(1) – y(1) 2,000。 MSE(X,h) 是使用假设 h 在一组示例上测量的成本函数。 我们使用小写斜体表示标量值例如 m 或 y(i)和函数名称例如 h使用小写粗体表示向量例如 x(i)使用大写粗体表示矩阵例如 X。 尽管RMSE通常是回归任务的首选性能度量但在某些上下文中您可能更喜欢使用其他函数。例如如果有许多离群的地区。在这种情况下你可以考虑使用平均绝对误差(MAE也称为平均绝对偏差)如下公式所示 RMSE和MAE都是度量两个向量之间距离的方法:预测向量和目标值向量。各种距离测量或规范是可能的:
计算平方和的根 (RMSE) 对应于欧几里得范数这是我们都熟悉的距离概念。 它也称为 ℓ2 范数记作 ∥ · ∥2或简称 ∥ · ∥。计算绝对值之和 (MAE) 对应于 ℓ1 范数记为 ∥ · ∥1。 这有时被称为曼哈顿范数因为如果您只能沿着正交的城市街区行驶它会测量城市中两点之间的距离。更一般地包含 n 个元素的向量 v 的 ℓk 范数定义为 ∥v∥k (|v1|k |v2|k … |vn|k)1/k。 ℓ0 给出向量中非零元素的数量ℓ∞ 给出向量中的最大绝对值。
范数指数越高越注重大值而忽视小值。 这就是 RMSE 比 MAE 对异常值更敏感的原因。 但是当异常值呈指数级稀有时例如在钟形曲线中RMSE 表现非常好并且通常是首选。
检查假设
最后列出并验证到目前为止(您或其他人)所做的假设是一个很好的实践这可以帮助您尽早发现严重的问题。例如您的系统输出的地区价格将被输入到下游机器学习系统并且您假设这些价格将被如此使用。但是如果下游系统将价格转换成类别(例如“便宜”、“中等”或“昂贵”)然后使用这些类别而不是价格本身呢?在这种情况下获得完全正确的价格一点也不重要;您的系统只需要获得正确的类别。如果是这样的话那么这个问题应该被定义为一个分类任务而不是一个回归任务。你不想在做了几个月的回归系统之后发现这个问题。
幸运的是在与负责下游系统的团队交谈后您确信他们确实需要实际价格而不仅仅是类别。太好了!一切就绪绿灯亮了现在就可以开始编码了!
下载数据
在典型环境中您的数据可在关系数据库或其他一些常见数据存储中使用。
要访问它您首先需要获取凭据和访问授权并熟悉数据架构。 然而在这个项目中事情要简单得多您只需下载一个压缩文件 housing.tgz其中包含一个名为 housing.csv 的逗号分隔值 (CSV) 文件以及所有数据。
通常最好编写一个函数来为您执行此操作而不是手动下载和解压缩数据。 如果数据定期更改这尤其有用您可以编写一个小脚本使用该函数来获取最新数据或者您可以设置一个计划作业以定期自动执行此操作。 如果您需要在多台计算机上安装数据集自动化获取数据的过程也很有用。
from pathlib import Path
import pandas as pd
import tarfile
import urllib.requestdef load_housing_data():tarball_path Path(datasets/housing.tgz)if not tarball_path.is_file():Path(datasets).mkdir(parentsTrue, exist_okTrue)url https://github.com/ageron/data/raw/main/housing.tgzurllib.request.urlretrieve(url, tarball_path)with tarfile.open(tarball_path) as housing_tarball:housing_tarball.extractall(pathdatasets)return pd.read_csv(Path(datasets/housing/housing.csv))housing load_housing_data()
当调用 load_housing_data() 时它会查找 datasets/housing.tgz 文件。 如果没有找到它会在当前目录中创建 datasets 目录从 Ageron/data GitHub 存储库下载 housing.tgz 文件并将其内容提取到 datasets 目录中 ; 这将创建 datasets/housing 目录其中包含 housing.csv 文件。 最后该函数将此 CSV 文件加载到包含所有数据的 Pandas DataFrame 对象中并返回它。
创建测试集
在这个阶段自愿搁置部分数据可能看起来很奇怪。 毕竟您只是快速浏览了一下数据在决定使用哪些算法之前您当然应该了解更多相关信息对吗 这是事实但你的大脑是一个令人惊奇的模式检测系统这也意味着它很容易过度拟合如果你查看测试集你可能会在测试数据中偶然发现一些看似有趣的模式从而引导你选择 一种特殊的机器学习模型。 当您使用测试集估计泛化误差时您的估计将过于乐观并且您将启动一个性能不如预期的系统。 这称为数据窥探偏差。 import numpy as npdef shuffle_and_split_data(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_indices[test_set_size:]return data.iloc[train_indices], data.iloc[test_indices]
好了这个工作但它并不完美:如果你再次运行这个程序它将生成一个不同的测试集!随着时间的推移你(或你的机器学习算法)将看到整个数据集这是你要避免的
一种解决方案是在第一次运行时保存测试集然后在后续运行中加载。另一个选项是在调用np.random.permutation()之前设置随机数生成器的seed(例如使用np.random.seed(42))。以便它总是生成相同的打乱索引。
但是这两种解决方案在下次获取更新的数据集时都会中断。即使在更新数据集之后也要进行稳定的训练/测试分割常见的解决方案是使用每个实例的标识符来决定是否应该在测试集中运行(假设实例具有唯一和不可变的标识符)。例如如果哈希值低于或等于最大哈希值的20%则可以计算每个实例的标识符的散列并将该实例放入测试集中。这可以确保测试集在多个运行期间保持一致即使刷新数据集也是如此。新的测试集将包含20%的新实例但它不会包含以前在训练集中的任何实例。 from zlib import crc32def is_id_in_test_set(identifier, test_ratio):return crc32(np.int64(identifier)) test_ratio * 2**32def split_data_with_id_hash(data, test_ratio, id_column):ids data[id_column]in_test_set ids.apply(lambda id_: is_id_in_test_set(id_, test_ratio))return data.loc[~in_test_set], data.loc[in_test_set]
不幸的是住房数据集没有标识符列。最简单的解决方案是使用行索引作为ID:
housing_with_id housing.reset_index() # adds an index column
train_set, test_set split_data_with_id_hash(housing_with_id, 0.2, index)如果使用行索引作为唯一标识符则需要确保将新数据追加到数据集的末尾并且不会删除任何行。果这是不可能的那么你可以尝试使用最稳定的功能来建立一个唯一的标识符。例如一个地区的纬度和经度保证在几百万年内是稳定的因此您可以将它们组合成一个ID如下所示: housing_with_id[id] housing[longitude] * 1000 housing[latitude]
train_set, test_set split_data_with_id_hash(housing_with_id, 0.2, id)
Scikit-Learn提供了一些函数以各种方式将数据集拆分为多个子集。最简单的函数train_test_split()它的功能与我们前面定义的shuffle_and_split_data ()函数非常相似只是增加了几个特性。首先有一个random_state参数它允许您设置随机生成器种子。其次您可以向它传递具有相同行数的多个数据集它将按照相同的索引将它们拆分(这是非常有用的例如如果你有一个单独的DataFrame标签): from sklearn.model_selection import train_test_splittrain_set, test_set train_test_split(housing, test_size0.2, random_state42)
到目前为止我们已经考虑了纯随机抽样方法。 如果您的数据集足够大尤其是相对于属性数量而言这通常没问题但如果不是您就会面临引入显着抽样偏差的风险。 当一家调查公司的员工决定给 1,000 个人打电话询问一些问题时他们不会只是在电话簿中随机挑选 1,000 个人。 他们试图确保这 1000 人能够代表全体民众了解他们想问的问题。 例如美国人口中女性占 51.1%男性占 48.9%因此在美国进行的一项精心调查将尽力维持样本中的这一比例511 名女性和 489 名男性至少如果答案可能是这样的话 因性别而异。 这称为分层抽样将总体分为称为层的同质子组并从每个层中抽取正确数量的实例以保证测试集能够代表总体。 如果进行调查的人使用纯粹随机抽样则有大约 10.7% 的机会对女性参与者少于 48.5% 或超过 53.5% 的倾斜测试集进行抽样。 不管怎样调查结果可能会有很大偏差。
假设你和一些专家聊天他们告诉你收入中位数是预测房价中位数的一个非常重要的属性。你可能想确保测试集代表了整个数据集中的各种收入类别。由于中位数收入是一个连续的数字属性您首先需要创建一个收入类别属性。让我们更仔细地看看收入中位数的柱状图(回到图2-8):大多数收入中位数都聚集在1.5至6(即15,000至60,000美元)但一些中等收入远远超过6。在数据集中为每个层提供足够数量的实例是很重要的否则对层的重要性的估计可能会有偏差。这意味着你不应该有太多的阶层每个阶层都应该足够大。下面的代码使用pd.cut()函数创建一个包含五个类别(标记为1到5)的income category属性;category 1的范围是0到1.5(即低于$15,000),category 2的范围是1.5到3依此类推:
housing[income_cat] pd.cut(housing[median_income],bins[0., 1.5, 3.0, 4.5, 6., np.inf],labels[1, 2, 3, 4, 5])housing[income_cat].value_counts().sort_index().plot.bar(rot0, gridTrue)
plt.xlabel(Income category)
plt.ylabel(Number of districts)
save_fig(housing_income_cat_bar_plot) # extra code
plt.show() 现在您已准备好根据收入类别进行分层抽样。 Scikit-Learn 在 sklearn.model_selection 包中提供了许多拆分器类这些类实现了各种策略来将数据集拆分为训练集和测试集。 每个拆分器都有一个 split() 方法该方法返回同一数据的不同训练/测试拆分的迭代器。
准确地说split()方法生成的是训练和测试指标而不是数据本身。如果你想更好地估计你的模型的性能有多个拆分是很有用的当我们在本章后面讨论交叉验证的时候你会看到。例如下面的代码生成同一数据集的10个不同的分层拆分: from sklearn.model_selection import StratifiedShuffleSplitsplitter StratifiedShuffleSplit(n_splits10, test_size0.2, random_state42)
strat_splits []
for train_index, test_index in splitter.split(housing, housing[income_cat]):strat_train_set_n housing.iloc[train_index]strat_test_set_n housing.iloc[test_index]strat_splits.append([strat_train_set_n, strat_test_set_n])
现在就可以拆分了
strat_train_set, strat_test_set strat_splits[0]或者因为分层抽样很常见所以有一个更简单的方法使用带stratify参数的train_test_split ()函数来获得单个拆分: strat_train_set, strat_test_set train_test_split(housing, test_size0.2, stratifyhousing[income_cat], random_state42)
让我们看看这是否像预期的那样工作。你可以从测试集中的收入类别比例开始: 使用类似的代码您可以测量整个数据集中的收入类别比例。下图比较了总体数据集、分层抽样生成的测试集和纯粹随机抽样生成的测试集中的收入类别比例。如您所见使用分层抽样生成的测试集的收入类别比例几乎与完整数据集中的收入类别比例相同而使用纯粹随机抽样生成的测试集是倾斜的。 您不会再次使用income_cat列所以您不妨删除它将数据恢复到原始状态: for set_ in (strat_train_set, strat_test_set):set_.drop(income_cat, axis1, inplaceTrue)
我们在测试集生成上花了相当多的时间这是有充分理由的:这是一个机器学习项目中经常被忽视但非常关键的部分。此外当我们讨论交叉验证时这些想法中的许多将是有用的。现在是时候进入下一个阶段了:探索数据。