Fork me on GitHub

《Hands on sklearn & TensorFlow》读书笔记--end to end machine learning project

[toc]

end to end machine learning project

这一章主要介绍了整个机器学习的过程,从获取数据处理数据开始,然后到应用到模型,调整模型。本章数据为加州某个时期房价的数据,所以主要的任务是一个回归任务,下面具体总结一下作者在这一章主要传授的观点和自己的一些收获。

Look at the big picture

也就是说,在可是意向任务之前,需要思考一下,你需要解决一个什么样的问题?期望得到的结果是什么?为了得到这样的结果需要做哪些工作?手头有哪些数据?需不需要获取额外的data?可以把这个问题抽象成一个什么样的问题?supervised or unsupervised or semi-supervised, 是回归还是分类,有没有现成的解决方案?这些解决方案够不够解决我需要的问题,不够,我需要如何改进这些方案?综合各种成本,我需要投入多少时间和精力?

Take quick look at the data structure

  1. 常用函数
    • data.head()
    • data.info() 可以快速看到数据框每列的大小、类型、以及是否有缺失值
    • data[‘’].value_counts()
    • data.describe()
  2. 画出所有数值类型的条形图,可以直观的看书数值类型的分布情况。
    1
    2
    3
    4
    %matplotlib inline
    import matplotlib.pyplot as plt
    data.hist(bins=50,figsize=(20,15))
    plt.show()

划分训练集和测试集

书中的观点是提起把测试集划分出来,并不参与训练集的数据预处理部分,只是在后面重新把数据预处理重新应用在测试集上面,我的观点是是否可以放在一起作数据预处理,后面训练模型的时候再划分开数据集

数据集可视化

学到一条厉害的命令

1
2
3
4
5
6
7
8
9
housing.plot(kind='scatter',x='longitude',y='latitude')
# 这条命令也是直接在数据框上面操作的,用之前也需要导入上面提到的包等,这个图最终画出的是一条散点图。
# 由于样本点还是挺多的,所以画散点图的时候,有些店会有重叠,故可以添加一个alpha参数,透明
housing.plot(kind='scatter',x='longitude',y='latitude',alpha = 0.3)
# 为了完善图像,还需要添加一些图例等东西
housing.plot(kind='scatter',x='longitude',y='latitude',alpha = 0.3,s = housing['population']/100,label='population',c='media_house_value', cmap=plt.get_cmap('jet'),colorbar=True,)
plt.legend()
# 上面的参数,s: 散点的大小, c: 颜色, cmap暂时还没搞清楚
# 这个图的最终的结果可以看出4个维度的东西,1,2:点的位置,3: 根据点的大小能看出population的大小,4: 根据点的颜色可以看出media_house_value的大小,厉害!!

探索特征之间的相关性

housing.corr(): 返回特征与特征之间的相关系数,取值为【-1,1】,但是要注意的是,这个数值描述的只是变量之间的线性相关性,不能体现出他们之间的非线性关系,如corr(a,b)=0, 不能说a与b是完全独立的,有可能它们之间存在非线性的关系

可视化

1
2
3
4
from pandas.tools.plotting import scatter_matrix
attributes = ['v1','v2',...,'v_m']
scatter_matrix(housing[attributes],figsize=(12,8))
# 这个函数会画出m*m个散点图,对角线上是频率直方图

属性之间的连接关系

也就是说属性与属性之间可以作乘除等一些变换,具体需要根据实际的业务场景,单个特征也可以做一些非线性的变换,比如log

为算法模型准备标准化的数据

这一个步骤主要集中在对数据的预处理方面,比如说,数据清洗、缺失值处理,离散数据或者非数值型数据的编码、数据的缩放、标准化等

data cleaning

sklearn 提供了一个处理缺失值的类Imputer,其实在实际应用中,这一个步骤还是需要灵活应用,具体根据实际情况来处理

1
2
3
4
5
6
7
from sklearn.preprocessing import Imputer
imputer = Imputer(strategy = 'median') # 根据中位数填充
# 让数框只包含数值类型
housing_num = housing.drop('ocean_proximity',axis=1)
imputer.fit_transform(housing_num)
# 后续处理的时候,只需要
# imputer.transform(housing_new)

文本、字符型、category特征的处理

对待这类特征,首先大部分的模型只能处理数值型的向量,所以需要量化这些特征,但量化后就会存在一个问题,有了数字,那么在计算机的眼里,这些category就有了大小,同时就会产生不同的度量,比如颜色红、黄、蓝,不能说谁比谁大,但是数值编码红黄蓝分别为1,2,3,那你就默认了黄与红之间差1,红与蓝差2,这样在实际中是不存在这种关系的,一种好的解决办法就是hotonecode—热编码。

sklearn提供的编码机制

1
2
3
4
5
6
7
8
9
10
11
12
13
# 普通的数值化编码
form sklearn.preprocesing import LabelEncoder
encoder = LabelEncoder()
housing_cat_encoded = encoder.fit_transform(housing_cat)
# 热编码
form sklearn.preprocesing import OneHotEncoder
encoder = OneHotEncoder()
# 这地方将上面数值化编码后的变量再次使用热编码,但是需要注意的地方是,此处传入的参数需要是一个二维数组,返回的是一个稀疏矩阵
housing_cat_1hot = encoder.fit_transform(housing_cat_encoded.reshape(-1,1))
# 直接热编码
form sklearn.preprocesing import LabelBinarizer
encoder = LabelBinarizer()
housing_cat_1hot = encoder.fit_transform(housing_cat)

特征缩放

这里是将数值型(到了这一步,应该都已经是数字型)的变量统一映射到一个范围,这样做对基于度量的一些模型是很有必要的。主要有两种方法

  • MinMaxScaler 统一映射到一个范围,但是对outlier比较敏感
  • StandardScaler 每个特征都标准化成均值为0,方差为1的数值,但是特征之间的映射范围可能不会一致,对outlier不敏感

    Pipline

    学会使用pipline,序列化地数据处理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    from sklearn.pipeline import Pipeline
    from sklearn.preprocessing import StandarScaler

    num_attribes = list['数值型特征']
    num_pipeline = Pipeline([
    ('selector',DataFrameSelectot(num_attribes)),
    ('Imputer',Imputer(strategy='median')),
    ('std_scaler',StandarScaler()),
    ])
    # 传入数据之后,按照顺序依次处理,上一个执行的输出是下一个执行的输入
    housing_num_tr = num_pipeline.fit_transform(housing_num)

    # 还可以并行执行
    from sklearn.pipeline import FeatureUnion

    cat_attribes = list['ocean_proximity']
    cat_pipeline = Pipeline([
    ('selector',DataFrameSelectot(cat_attribs)),
    ('label_binarizer',cat_pipeline),
    ])
    full_pipeline = FeatureUnion(transform_list = [
    ('num_pipeline',num_pipeline),
    ('cat_pipeline',cat_pipeline),
    ])
    housing_prepared = full_pipeline.fit_transform(housing)

模型选择

这一步,开始可以多尝试几个模型,选择一两个效果较好的重点调整。调整模型的参数以及观察模型的效果主要靠交叉验证。

  1. 方式一直接做交叉验证,得出结果

    1
    2
    3
    4
    5
    from sklearn.model_selection import cross_val_score
    cross_val_score(clf,housing_prepared,housing_labels,
    scoring='neg_mean_squared_error',cv=10)
    # clf : 分类器、学习器
    # 直接输出10次交叉验证的结果
  2. 方式二 方便调整模型的参数

    1
    2
    3
    4
    5
    from sklearn.model_selection import GridSearchCV
    # 设置调整的参数
    param_grid = [{'opt1':value1,'opt2':value2}{'opt3':value3,'opt4':value4}]
    grid_search = GridSearchCV(clf,param_grid,cv=5,scoring='')
    grid_search.fit(housing_prepared,housing_labels)
  3. 方式三

    1
    2
    3
    4
    5
    6
    from sklearn.model_selection import StratifiedKFold

    cv = StratifiedKFold(n_splits=k)
    for train_index,test_index in cv :
    clf.fit()
    proba = clf.predict_proba()

保存最终的模型

1
2
3
4
5
from sklearn.externals import joblib
# saving
joblib.dump(my_model,'my_model.pkl')
# loading
my_model = joblib.load('my_model.pkl')