机器学习实战(基于Scikit-Learn和TensorFlow)(1)

一、下载数据

import os
import tarfile
from six.moves import urllib
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()

现在,每当你调用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()方法查看前五行:

housing = load_housing_data()
housing.head()

每一行代表一个区,总共有10个属性:longitude,latitude,housing_median_age,total_rooms,total_bed_rooms,population,households,meidan_income,

median_house_value以及ocean_prroximity

通过info()方法可以快速捕获数据集的简单描述,特别是总行数,每个属性的类型和非空值的数量。

housing.info()

使用value_counts()方法查看有多少种分类存在,每种类别下分别有多少区域:

housing["ocean_proximity"].value_counts()

housing.describe()

另一种快速了解数据类型的方法是绘制每个数值属性的直方图。直方图用来显示给定值的范围(横轴)的实例数量(纵轴)。你可以一次绘制一个属性,也可以在整个数据集上调用hist()方法,绘制每个属性的直方图。

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

三、创建测试集

理论上,创建测试集非常简单:只要随机选择一些实例,通常是数据集的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_indices[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")

但这样子并不完美:如果在运行一遍,它会产生一个不同的数据集!

解决方案有两个:1.在第一次运行程序之后即保存测试集,随后的运行只是加载它而已

                               2.在调用np.random.permutation()之前设置一个随机数生成器的种子(例如,np.random.seed(42)),从而让他始终生成相同的碎机索引。

但是这两种方法在获得下一次更新的数据时都会中断。

解决办法:每个实例都使用一个标识符(identifier)来决定是否进入测试集(假定每个实例都有一个唯一且不变的标识符)。

举例来说:可以计算每个实例标识符的hash值,只取hash的最后一个字节如果该值小于等于51(约256的20%),则将实例放入测试集中。

import hashlib
def test_set_check(identifier, test_ratio, hash):
    return hash(np.int64(identifer)).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]
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")

如果使用行索引作为唯一标识符,你需要确保在数据集的末尾添加新数据,并且不会删除任何行。如果不能保证这点,可以尝试使用某个最稳定的特征来创建唯一的标识符。例如一个地区的经纬度:

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提供了一些函数,可以通过多种方式将数据集分成多个子集。

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(限制收入类别的数量),然后使用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的Stratified Shuffle Split类:

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]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九妹123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值