Hands on Machine Learning with sklearn and TensorFlow —— 一个完整的机器学习项目(加州房地产)

数据集地址:https://github.com/ageron/handson-ml/tree/master/datasets

先行知识准备:NumPy,Pandas,Matplotlib的模块使用

机器学习项目流程(一般):可视化数据,发现规律

             对数据进行预处理,为算法准备数据

             选择模型,训练

             微调模型

数据集使用1990年加州普查数据,包含:每个街区的人口、收入中位数、房价中位数等指标

一、划分问题

  可以将问题划分为分类问题或者回归问题,选择不同的模型

二、选择性能指标

  选择合适的性能指标例如:均方根误差、平方绝对误差。此外,还有多种类似的测量距离的方法,例如:范数等。

三、加载数据

  将Pandas模块包,导入到程序段中:

import pandas as pd

  使用Pandas中的read_csv方法读取数据

housing_data = pd.read_csv("./housing.csv") #“”号里面的是数据集存储的路径

  查看数据集的结构(特征值有哪些)

print(housing_data.info()) #housing_data是一个DataFrame类型,使用DF的info方法查看

  查看数据集数据的主要特征 

print(housing_data.describe())

  数据的主要特征主要包括该数据集的各项统计数据

  若想使得数据可视化的话,可以使用Matplotlib.pypolt模块包

import matplotlib.pyplot as plt

housing_data.hist(bins = 50,figsize=(20,15))
plt.show()

  生成了每个属性的柱状图,可以很轻易的从图中看出数据的特性

四、生成测试集

  挑选数据集的一部分用作测试训练后的模型的性能,一般是数据集的20%。一般采用sklearn模块自带的函数对数据集进行分割。

from sklearn.model_selection import train_test_split
train_data,test_data = train_test_split(housing_data,test_size=0.2,random_state=42)

  但是,我们分割数据是不能忽视一个问题,就是如果采用纯随机采样的话,会导致采样出现偏差,最好的方法是对数据集进行分层采样。例如,对数据集的收入中位数进行分层抽样。

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_data,housing_data["income_cat"]):
    strat_train_data = housing_data.loc[train_index]
    strat_tes_data = housing_data.loc[test_index]


#删除income_cat列
housing_data.drop("income_cat",axis=1)
#复制训练集测试集到新表格
housing_train_data = strat_train_data.copy()
housing_test_data = strat_tes_data.copy()

————————————————以上为数据预处理过程—————————————————

一、数据可视化从而发现规律

  对地理位置信息进行可视化,从经纬度入手

housing_train_data.plot(kind = "scatter",x = "longitude",y = "latitude",alpha = 0.1)

 plt.show()

  然后以经纬度信息为基础,显示人口数量以及房价的

housing_train_data.plot(kind = "scatter",x = "longitude",y = "latitude",alpha = 0.4,s = housing_train_data["population"]/100,label = "population",c = "median_house_value",cmap = plt.get_cmap("jet"),colorbar = True)
plt.show()

每个散点的把你那个表示该街区人口数量,颜色代表房价的高低

二、查找关联性

  1、当数据集不大时,可以使用corr()方法计算每对属性之间的标准关系数(皮尔逊相关系数)

print(housing_train_data.corr()["median_house_value"].sort_values(ascending=False))

  2、也可以使用Pandas模块的scatter_matrix函数,画出每对属性之间的的相关图

attribute = ["median_house_value","median_income","total_rooms","housing_median_age"]
scatter_matrix(housing_train_data[attribute],figsize = (12,8))
plt.show()

 三、属性组合发现新规律

  当你拿到数据集时,可能现有的属性对目标属性并没有很高的相关性,可以尝试对现有的属性进行组合,产生新属性,可能对目标属性有更好的拟合效果。

housing_train_data["rooms_per_household"] = housing_train_data["total_rooms"]/housing_train_data["households"]
housing_train_data["bedrooms_per_room"] = housing_train_data["total_bedrooms"]/housing_train_data["total_rooms"]
housing_train_data["population_per_household"] = housing_train_data["population"]/housing_train_data["households"]

print(housing_train_data.corr()["median_house_value"].sort_values(ascending=False))

————————————————————————————————算法数据准备————————————————————————————————————————

将训练集的预测量和标签分离

housing = housing_train_data.drop("median_house_value",axis = 1)
housing_labels = housing_train_data["median_house_value"].copy()

一、数据清洗

  主要针对个别样本属性值的缺失,可以有三种处理方式:

    ①删除存在缺失属性的样本

    ②删除存在缺失的属性

    ③对缺失的属性值进行赋值(中位数、平均值等)

housing.dropna(subset = ["total_badrooms"])#去掉缺失的样本(一行)
housing .drop("total_bedrooms",axis = 1)#去掉缺失的属性值(一列)
housing["total_bedrooms"].fillna(housing["total_bedrooms"].median())#使用中位数对缺失数据进行赋值

当用中位数补充训练集的缺失值时,也应该用该值对测试集进行填充。

Sklearn提供了比较方便的处理缺失值的方法——Imputer。

  首先创建一个Imputer实例,并指定用某属性的中位数或其他值来填充该属性的所有缺失值,只有数值数值属性才能处理,所有创建一份不包含文本属性的副本,最后用fit()方法将Imputer实例拟合到训练数据集。

imputer = Imputer(strategy="median")
housing_num = housing.drop("ocean_proximity",axis = 1)
imputer.fit(housing_num)
x = imputer.transform(housing_num)
housing_tr = pd.DataFrame(x,columns = housing_num.columns)

计算出的每个属性的中位数,会将结果自动保存在statistics_中。

———————————————————————————————Sklearn————————————————————————————————————————————

Sklearn的API设计原则

  1、一致性:所有的对象接口一致且简单

    ①估计器:任何基于数据集对一些参数进行估计的对象都被称为估计器。估计通过fit()方法实现,只需要一个数据集作为参数(监督学习需要两个数据集,第二个数据集包含标签)。任何其他用来直到估计过程的参数都被当做超参数(imputer的strategy),超参数要被设置为实例变量。

    ②转换器:一些转换器也可以作为转换器,可以用来转换数据集。转换是通过transform()方法,被转换数据作为参数。返回的是经过转换的数据集(x = imputer.transform(housing_num))。转换过程依赖学习到的参数。所有的转换有一个便捷的方法是fit_transform(),等同于调用fit()后调用transfrom()

    ③预测器:一些估计器也可以根据给出的数据集做预测,这些估计器也叫作预测器。例如LinearRegression模型。预测器有一个predict()方法,可以用新实例的数据集进行相应的预测。预测器还有一个socre()方法,可以根据测试集对预测进行评估。

  2、可检验。所有的估计器超参数都可以通过public变量访问,所有的估计器学习到的参数可以通过实例变量名后加下划线访问。

  3、类不可扩散。数据集被表示成NumPy数组或Scipy稀疏矩阵。超参数知识普通的Python字符串后数字。

  4、可组合。尽可能使用现存的模块。

  5、合理的默认值。

 ———————————————————————————————————————————————————————————————————————————————

文本和类别属性的处理方法

  一、Sklearn为该任务提供了转换器LabelEncoder(注:该方法多用于转换标签,对于转换文本特征列应该使用factorize()方法)

from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
housing_cat = housing["ocean_proximity"]
housing_cat_encoder = encoder.fit_transform(housing_cat)

  二、使用Sklearn自带的OnehotEncoder方法。(略)

  三、使用sklearn的LabelBinarizer,可以直接执行这两个转换(从文本到整数分类,再从整数分类到onehot向量)(注:这个类适用于标签列的转换,正确的做法是使用Sklearn提供的CategoricalEncoder类)(略)

自定义转换器

  一些情况下需要自己写一些转换器完成自己想要的操作,例如,自定义的清理操作或者属性组合。需要让自己制作的转换器和Scikit-Learn组件衔接使用。Scikit-Learn是依赖鸭子类型不是继承,所以创建一个类并执行三个方法就可以了(fit()、transfrom()、fit_transfrom())。以TransfromerMixin作为基类得到fit_transfrom(),添加BaseEstimator作为基类可以得到两个额外方法(get_params()和set_params())。

from sklearn.base import BaseEstimator, TransformerMixin
rooms_ix, bedrooms_ix, population_ix, household_ix = 3, 4, 5, 6

class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
    def __init__(self, add_bedrooms_per_room = True): # no *args or **kargs
        self.add_bedrooms_per_room = add_bedrooms_per_room
    def fit(self, X, y=None):
        return self  # nothing else to do
    def transform(self, X, y=None):
        rooms_per_household = X[:, rooms_ix] / X[:, household_ix]
        population_per_household = X[:, population_ix] / X[:, household_ix]
        if self.add_bedrooms_per_room:
            bedrooms_per_room = X[:, bedrooms_ix] / X[:, rooms_ix]
            return np.c_[X, rooms_per_household, population_per_household,
                         bedrooms_per_room]
        else:
            return np.c_[X, rooms_per_household, population_per_household]

attr_adder = CombinedAttributesAdder(add_bedrooms_per_room=False)
housing_extra_attribs = attr_adder.transform(housing.values)

特征缩放

  当输入的数值属性度量不同时,学习算法的性能会比较差,所以需要对目标值进行缩放。

常见的缩放方法可以让所有的属性有相同的量度:线性函数归一化(Min-Max scaling)和标准化(standardization)。

  线性函数归一化,也常称为归一化。通过Scikit-Learn提供的一个转换器MinMaxScaler来实现,他有一个超参数feature_range,这个参数可以让你改变范围(如果期望范围不在0-1间)。

  标准化通过Scikit-Learn提供的转换器StandardScaler来实现标准化。

转换流水线

  许多数据的转换步骤要按照一定的顺序进行,所以,Scikit-Learn提供了Pipline类。Pipeline构造器需要一个定义步骤顺序的名字/估计器对的列表。当你调用流水线的fit()方法时,会对所有的转换器调用fit_transform()方法,对估计器执行fit()方法,每次调用的输出作为参数传递给下一个调用。 

选择并训练模型

对模型预测结果进行评估

根据评估结果重新选择合适模型或者对模型进行微调(微调主要是对超参数的调整)

猜你喜欢

转载自www.cnblogs.com/AfroNick/p/10257323.html