第一章 引言
pd.scatter_matrix(pd.DataFrame(X_train),c=y_train_name,figsize=(15,15),marker='o',hist_kwds={'bins':20},s=60,alpha=.8,cmap=mglearn.cm3)#绘制散点图矩阵(pair plot),两两查看所有的特征
第二章 监督学习
2.1分类与回归
2.2泛化、过拟合与欠拟合
2.3监督学习算法
2.3.1一些样本数据集
from sklearn.datasets import load_breast_cancer #威斯康辛州乳腺癌数据集
cancer = load_breast_cancer ()
from sklearn.datasets import load_boston #波士顿房价数据集
boston= load_boston()
X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=0,test_size=.5)
2.3.2 k近邻
X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,stratify=cancer.target,random_state = 66)
stratify函数 使得train和test中各类数据的比例与原数据集一样 通常在这种类分布不平衡的情况下会用到stratify
from sklearn.neighbors import KNeighborsClassifier #分类,可调节n_neighbors参数
from sklearn.neighbors import KNeighborsRegressor
优缺点、参数:2个重要参数,邻居个数和距离度量方法; 优点是容易理解,缺点是需要对数据进行预处理,预测速度慢,对于特征多的数据集和稀疏数据集效果不好;一个不错的经验规则是: 如果有N 个样本, 应考虑sqrt(N )个邻居个数
2.3.3 线性模型
from sklearn.linear_model import LinearRegression#线性回归、普通最小二乘法(OLS),无正则化的
print(lr.coef_) #斜率w(权重)
print(lr.intercept_) #偏移b
from sklearn.linear_model import Ridge #岭回归 使用L2正则化 正则化参数alpha默认为1,增加会增加泛化性能
from sklearn.linear_model import Lasso #lasso回归 使用L1正则化 正则化参数alpha默认为1,增加会增加泛化性能,参数max_iter代表运行迭代的最大次数
Elastic Net ( 弹性网 ) 使用L1和使用L2正则化
一般首选岭回归 ,但如果特征很多,并且只有其中几个是重要的,那么选择Lasso可能更好,Lasso更容易理解
from sklearn.linear_model import LogisticRegression #logistics回归,参数C为正则化参数,与alpha不同,越大对应的正则化越弱
from sklearn.svm import LinearSVC #线性支持向量机,参数C为正则化参数,与alpha不同,越大,对应的正则化越弱
优缺点、参数:主要参数是正则化参数C和alpha,通常在对数尺度上对C和alpha进行搜索; 优点是训练速度快,预测速度快,常用于非常大的数据集,但很难对系数作出解释,在低维数据上泛化性能差。
2.3.4 朴素贝叶斯分类器
优缺点、参数:都只有参数alpha,用于控制模型复杂度,alpha越大,平滑化越强,模型复杂度越低; 优点是训练速度更快,对高维稀疏数据的效果好,但泛化能力稍差
2.3.5 决策树
from sklearn.tree import DecisionTreeClassifier
tree.feature_importances_#树的特征重要性
优缺点、参数:参数主要为预剪枝参数,设置max_depth/max_lead_nodes/min_samples_leaf防止过拟合; 优点相比而言有:1、得到的模型任意可视化,任意理解;2、算法不受数据缩放的影响,不需要对数据归一化或者标准化。主要缺点在于易于过拟合,泛化性能差
2.3.6 决策树集成
都可以用于回归和分类
1、随机森林
from sklearn.ensemble import RandomForestClassifier
优缺点、参数: 优点是通过不需要反复调节参数就可以给出很好的结果,也不需要对数据进行缩放,但对于维度非常高的稀疏数据集(如文本数据),随机森林的表现往往不是很好,训练和预测速度较慢。
设置n_jobs=-1使用计算机所有的内核,需要调节的重要参数有n_estimators和max_features(每次划分考虑的特征数),可能还包括预剪枝选项(如max_depth)。n_estimators总是越大越好,不过收益递减,内存剧增;max_features决定每棵树的随机大小,越小,可以降低过拟合,一般使用默认值:对于分类,max_features=sqrt(n_features);对于回归,max_features = n_features
2、梯度提升树
默认情况下,梯度提升树没有随机化,而是用到了强预剪枝;通常使用深度很小(1-5)的树,与随机森林相比,通常对参数设置更加敏感,但精度更高,另一个重要参数是learning_rate,用于控制每棵树纠正前一棵树的错误的强度;默认使用100棵树,最大深度3,学习率为0.1
from sklearn.ensemble import GradientBoostingClassifier#当出现过拟合时,可以限制最大深度来加强预剪枝,也可以降低学习率;
优缺点、参数:主要缺点是需要仔细调参,训练时间比较长;优点是不需要缩放,不适用于高维稀疏数据
主要参数包括树的数量n_estimators和学习率learning_rate;与随机森林相比,n_estimators不是越大越好,太大会导致过拟合;通常的做法是根据时间和内存的预算选择合适的n_estimators,然后对不同的learning_rate进行遍历;另外一个重要参数是max_depth,用于降低每棵树的复杂度。
sklearn下速度比较慢
2.3.7 核支持向量机
from sklearn.svm import SVC
优缺点、参数:在低维数据和高维数据上的表现都很好,但对样本个数的缩放表现不好,另外,需要预处理数据,调参都需要非常小心,SVM适用于所有特征的测量单位相似(如都是像素密度)且范围也差不多时。 重要参数是正则化参数C、核的选择以及与核相关的参数;RBF核只有一个参数gamma,是高斯核宽度的倒数,越大,模型越复杂
2.3.8 神经网络(深度学习)
from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(solver='lbfgs',max_iter=1000,activation='tanh',hidden_layer_sizes=[10,10],alpha=1)
优缺点、参数:主要优点是能够获取大量数据包含的信息,构建复杂的模型;但需要仔细的预处理数据
默认情况下,MLP使用100个隐结点,默认非线性relu,可以修改隐层的个数、每个隐层的单元数与正则化(alpha),solver默认为“adam",但对数据的缩放相当敏感,另一个选项是”lbfgs“,鲁棒性相当好,但在大型数据或模型上时间会比较长,还有:”sgd“选项;
神经网络调参的常用方法是,首先创建一个足以过拟合的网络,确保可以对任务进行学习,再增强泛化性能;
2.4 分类器的不确定度估计
decision_function和predict_proba 获取分类器对预测的置信程度
第三章 无监督学习与预处理
数据集变换:降维(可视化)、找到“构成”数据的各个组成部分
聚类
3.3 预处理与缩放
StandardScaler :确保每个特征的平均值为0,方差为1,但不能保证特征任何特定的最大值和最小值
RobustScaler:使用中位数和四分位数,能够忽略异常值
MinMaxScaler:移动数据,使特征刚好位于0与1之间
Normalizer:对每个特征进行不同的缩放,使用特征向量的欧式长度为1;即,投射到半径为1的圆上,这意味着每个数据点的缩放比例都不相同;如果只有数据的方向(角度)是重要的,通常会使用这种归一化
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train) #fit_trainsform
X_test_scaled = scaler.transform(X_test)
MinMaxScaler(以及其他缩放器)总是对训练集和测试集应用完全相同的变换
3.4 降维、特征提取与流形学习
第四章 数据表示与特征处理
4.1 分类变量
one-hot编码,又是虚拟变量
pd.get_dummies(data) #同时包含训练集和测试集的数据上调用
from sklearn.preprocessing import OneHotEncoder #只能将数值为整数的分类转换为虚拟变量
4.2 分箱、离散化、线性模型与树
对特征进行分箱,线性模型变得更加灵活,但对于基于树的模型通常不会有更好的效果
4.3 交互特征与多项式特征
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=10,include_bias=False)#多项式次数为10
X_train_poly = poly.fit_transform(X)
X_test_poly = poly.transform(X)
print(poly.get_feature_names())#得到每个特征的指数(特征语义)
使用Ridge时,交互特征和特征多项式对性能有很大的提升,但对复杂模型,如随机森林和svm作用不大
4.4 单变量非线性变换
使用np.log1p对特征值进行处理,对于线性模型至关重要
4.5 自动化特征选择
4.5.1 单变量统计 方差分析(ANONA)
from sklearn.feature_selection import SelectPercentile,selectKBest
select = SelectPercentile(percentile=50)
select.fit(X_train,y_train)
X_train_selected = select.transform(X_train)
select.get_support() #查看哪些特征被选中
4.5.2 基于模型的特征选择
用于特征选择的监督模型不需要与用于最终监督建模的模型相同
from sklearn.feature_selection import SelectFromModel
select = SelectFromModel(RandomForestClassifier(n_estimators=100,random_state=42),threshold="median") #使用中位数作为阈值
select.fit(X_train,y_train)
X_train_l1 = select.transform(X_train)
X_test_l1 = select.transform(X_test)
4.5.3 迭代特征选择
迭代特征消除(RFE)
from sklearn.feature_selection import RFE
select = RFE(RandomForestClassifier(n_estimators=100,random_state=43),n_features_to_select=20)
select.fit(X_train,y_train)
print(select.get_support()) #查看哪些特征被选中
4.6 利用专家知识
将任务属性的先验知识编码到特征中:
citibike示例
NOTE: 树以及随机森林无法外推到训练集之外的特征范围
第五章 模型评估与改进
5.1 交叉验证
from sklearn.model_selection import cross_val_score
scores = cross_val_score(logreg,iris.data,iris.target,cv = 5)#默认执行3折交叉验证
print(scores)
print('Average score:',scores.mean()) #得出交叉验证平均值
优缺点:模型对数据集中所有样本的泛化能力都很好,还可以提供对训练集选择的敏感性信息(应用于新数据时最坏和最好情况的可能表现);
对数据的使用更加高效; 主要缺点是增加了计算成本
Note:交叉验证的目的只是评估算法的泛化性能,不会返回一个模型;
对于回归问题,sklearn默认使用标准k折交叉验证,对于分类问题,默认使用分层k折交叉验证
可以使用交叉验证分离器作为cv参数,对数据划分进行更为精细的控制
from sklearn.model_selection import KFold
Kfold = KFold(n_splits=5,shuffle=True,random_state=0)#对于分类问题,将数据打乱会得到更好的结果
print(cross_val_score(logreg,iris.data,iris.target,cv=Kfold))
留一法交叉验证(比较耗时,但在小数据集上估计结果更好)
from sklearn.model_selection import LeaveOneOut
loo = LeaveOneOut()
scores = cross_val_score(logreg,iris.data,iris.target,cv=loo)
print(scores.mead())
打乱划分交叉验证
from sklearn.model_selection import ShuffleSplit
shufflesplit = ShuffleSplit(test_size=.5,train_size=.5,n_splits=10,random_state=43)
scores = cross_val_score(logreg,iris.data,iris.target,cv=shufflesplit)
print(scores)
分组交叉验证
from sklearn.model_selection import GroupKFold
X,y = make_blobs(n_samples=12,random_state=0)
groups = [0,0,0,1,1,1,1,2,2,3,3,3]#假设前三个样本属于同一组,接下来的4个属于同一组,以此类推
groupkflod = GroupKFold(n_splits=3)
scores = cross_val_score(logreg,X,y,groups,cv=groupkflod)
print(scores)
5.2 网格搜索
Note:需要保留一个单独的测试集,用于最终评估
GridSearchCV 带交叉验证的网格搜索
param_grid = {'C':[0.001,0.01,0.1,1,10,100],'gamma':[0.001,0.01,0.1,1,10,100]}
'''
在非网格的空间中搜索
param_grid = [{'kernel':['rbf'],'C':[0.001,0.01,0.1,1,10,100],'gamma':[0.001,0.01,0.1,1,10,100]},
{'kernel':['linear'],'C':[0.001,0.01,0.1,1,10,100]}]
'''
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
grid_search = GridSearchCV(SVC(),param_grid,cv=5)
X_train,X_test,y_train,y_test = train_test_split(iris.data,iris.target,random_state=0)#需要划分训练集和测试集,避免过拟合
grid_search.fit(X_train,y_train)
print(grid_search.score(X_test,y_test))
print(grid_search.best_score_)
print(grid_search.best_params_)
print(grid_search.best_estimator_)
分析交叉验证的结果
import pandas as pd
results = pd.DataFrame(grid_search.cv_results_)
results.head()
使用热图可视化
import mglearn
import matplotlib.pyplot as plt
%matplotlib inline
scores = np.array(results.mean_test_score).reshape(6,6)
mglearn.tools.heatmap(scores,xlabel='gamma',xticklabels=param_grid['gamma'],ylabel='C',yticklabels=param_grid['C'],cmap='viridis')
GridSearchCV对分类问题默认使用分层k折交叉验证,对回归问题默认使用k折交叉验证;也可以使用交叉验证分离器
嵌套交叉验证 使用交叉验证多次划分 用于评估给定模型在特定数据集上的效果
使用不同的交叉验证策略进行网格搜索
scores = cross_val_score(GridSearchCV(SVC(),param_grid,cv=5),iris.data,iris.target,cv=5)
print(scores)
print("Mean cross-validation score:",scores.mean())
5.3 评估指标与评分
使用混淆矩阵
from sklearn.metrics import confusion_matrix
confusion = confusion_matrix(y_test,pred_logreg)
print(confusion)
使用f1score
from sklearn.metrics import f1_score/classification_report
print(f1.score(y_test,pred_most_frequent))
print(classification_report(y_test,pred_most_frequent,target_names=['not none','nine']))
第六章 算法链与管道
6.1 用预处理进行参数选择
在交叉验证的过程中,应该在进行任何预处理之前完成数据集的划分。任何从数据集中提取信息的处理过程都应该仅用于数据集的训练部分,因此,任何交叉验证都应该位于与处理过程的“最外层循环”。Pipeline类最常见的用例是将预处理步骤(比如数据缩放)与一个监督模型(比如分类器)链接在一起。
6.2 构建管道
from sklearn.pipeline import Pipeline
pipe = Pipeline([('scaler',MinMaxScaler()),('svm',SVC())])
pipe.fit(X_train,y_train)
6.3 在网格搜索中使用管道
param_grid = {'svm__C':[0.001,0.01,0.1,1,10,100],'svm__gamma':[0.001,0.01,0.1,1,10,100]}
grid = GridSearchCV(pipe,param_grid = param_grid,cv=5)
grid.fit(X_train,y_train)
6.4 通用的管道接口
from sklearn.pipeline import make_pipeline
pipe_long = Pipeline([('scaler',MinMaxScaler()),('svm',SVC(C=100))])#标准写法
pipe_short = make_pipeline(MinMaxScaler(),SVC(C=100))#缩写写法
print(pipe_short.steps)#缩写写法自动命名,可通过steps查看每个步骤的名称
6.5 网格搜索预处理步骤与模型参数
from sklearn.datasets import load_boston
from sklearn.linear_model import Ridge
boston = load_boston()
X_train,X_test,y_train,y_test = train_test_split(boston.data,boston.target,random_state=0)
from sklearn.preprocessing import PolynomialFeatures
pipe = make_pipeline(StandardScaler(),PolynomialFeatures(),Ridge())
param_grid = {'polynomialfeatures__degree':[1,2,3],'ridge__alpha':[0.001,0.01,0.1,1,10,100]}
grid = GridSearchCV(pipe,param_grid,cv=5,n_jobs=-1)
grid.fit(X_train,y_train)
做热图可视化
import matplotlib.pyplot as plt
%matplotlib inline
plt.matshow(grid.cv_results_['mean_test_score'].reshape(3,-1),vmin=0,cmap='viridis')
plt.xlabel('ridge__alpha')
plt.ylabel('polynomialfearures__degree')
plt.xticks(range(len(param_grid['ridge__alpha'])),param_grid['ridge__alpha'])
plt.yticks(range(len(param_grid['polynomialfeatures__degree'])),param_grid['polynomialfeatures__degree'])
plt.colorbar()
6.6 网格搜索选择使用哪个模型
pipe = Pipeline([('preprocessing',StandardScaler()),('classifier',SVC())])
from sklearn.ensemble import RandomForestClassifier
param_grid = [{'classifier':[SVC()],'preprocessing':[StandardScaler(),None],'classifier__gamma':[0.001,0.01,0.1,1,10,100],'classifier__C':[0.001,0.01,0.1,1,10,100]},
{'classifier':[RandomForestClassifier(n_estimators=100)],'preprocessing':[None],'classifier__max_features':[1,2,3]}]
X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,random_state=0)
grid = GridSearchCV(pipe,param_grid,cv=5)
grid.fit(X_train,y_train)
print(grid.best_params_)
print(grid.best_score_)
print(grid.score(X_test,y_test))