1. 创建测试集
1.1 随机抽样
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_indices[test_set_size:] # 训练集的索引
return data.iloc[train_indices], data.iloc[test_indices] #data.iloc:读取行或列
train_set, test_set = split_train_test(housing, 0.2) #生成训练集和测试集
缺点:如果再运行一遍,它又会产生一个不同的数据集,这样下去,将会看到整个完整的数据集。
解决方案:每个实例都使用一个标识符来决定是否进入测试集(假定每个实例都有一个唯一且不变的标识符)
from zlib import crc32
def test_set_check(identifier, test_ratio):
return crc32(np.int64(identifier)) & 0xffffffff < test_ratio * 2**32 # 如果它低于 test_ratio * maximum 截止点,则认为它已被选中
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数据集没有标识符列,可以尝试使用某个最稳定的特征来创建唯一标识符。例如,可以将一个区域的经纬度组合成如下的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():
from sklearn.model_selection import train_test_split
train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)
如果数据集足够庞大(特别是相较于属性的数量而言),纯随机的抽样方法通常不错;如果不是,则有可能会导致明显的抽样偏差。
1.2 分层抽样
用pd.cut()来创建5个收入类别属性的(用1~5来做标签),0~1.5是类别1,1.5~3是类别2,以此类推:
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])
根据收入类别进行分层抽样了。使用Scikit-Learn的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]