研究生学习生涯之机器学习篇

第二章 端到端的机器学习项目

创建测试集

方法一:随机抽样

 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]#把0-test_set_size个数据给测试集
    train_indices = shuffled_indices[test_set_size:]#把test_set_size-len个数据给训练集
    return data.iloc[train_indices], data.iloc[test_indices]#返回训练集索引及值和测试集索引及值

第一种解决方案:在首次运行时储存此测试集以便在后续运行时加载

第二种解决方案:在调用np.random.permutation()之前设置随机数生成器的种子,保证每次运行时的随机数相同

前两种方案的缺点:当数据集进行更新(增加或减少)时,都会改变测试集

第三种解决方案:使用每个样本的标识符来决定它是否应该加入测试集(假设样本的标识符具有唯一性和不变性),具体做法:计算每个样本标识符的哈希值,若哈希值小于或等于最大哈希值的20%,则将此样本放入到测试集中。

from zlib import crc32

def test_set_check(identifier, test_ratio):
    return crc32(np.int64(identifier)) & 0xffffffff < test_ratio * 2**32
    #crc32(data[, value]):计算data的CRC(循环冗余校验)值,计算的结果是一个32位的整数。参数value是校验时的起始值,其默认值为0。借助参数value可为分段的输入计算校验值。此算法没有加密强度,不应用于身份验证和数字签名。此算法的目的仅为验证数据的正确性,不适合作为通用散列算法在所有的Python版本和平台上获得相同的值

def split_train_test_by_id(data, test_ratio, id_column):
    ids = data[id_column]
    in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio))#测试在不在测试集里
    return data.loc[~in_test_set], data.loc[in_test_set]#返回不在和在测试集里的索引值

但是housing数据集没有标识符列,解决办法:为每一个样本添加行索引

housing_with_id = housing.reset_index()   # adds an `index` column将索引值传输到数据框的列中并设置一个简单的整数索引
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "index")

新的问题:
若使用行索引作为唯一标识符,则前提是如果有新数据进入,则必须被追加到数据集的末尾且期间不会删除任何行。如果做不到的话,就使用最稳定的特性来构建一个唯一的标识符。举个例子,一个地区的纬度和经度可以保证在几百万年内保持稳定,因此可以将它们合成为一个ID,如下所示:

housing_with_id["id"] = housing["longitude"] * 1000 + housing["latitude"]
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "id")

方法四:Scikit-Learn包中的train_test_split函数,功能同上述split_train_test函数相同,但增加了几个特性参数:random_state设置随机数种子,其次可以在相同的索引上分割行数相同的多个数据集,例如:

from sklearn.model_selection import train_test_split

train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)

上述抽样方法的使用前提是在数据集足够大的情况下,当数据集不够大时使用分层抽样方法

方法二:分层抽样


假设收入中位数是预测房价中位数的一个关键因素,则需要创建一个属性为收入类别,我们可以看到收入直方图中数据主要集中在1.5到6之间,但有少数人的收入已经远远超过6,在创建收入类别时尤其要注意这一点:保证每个层的样本数量足够大且层数尽可能的少。举个例子,将收入分为5个类别:0到1.5,1.5到3,… ,以此类推,如下所示:

#对每一个数据增加income_cat属性,即1-5中的对应数字标签
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])

分层结果
从sklearn里导入StratifiedShuffleSplit(分层抽样)函数:

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]

对比


可以看到分层抽样更接近整体的比例

英文

It's highly prone to do sth.容易做某事
stumble upon 意外发现
generalization error 泛化误差
data snooping bias 数据透视偏差,指基于先前得到的实证经验后对历史数据进行分析后所得到的偏差

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值