第三章数据建模及模型评估
数据建模
基本术语
- 数据集的监督学习和无监督学习
- 监督学习:监督学习的样本集是既有特征也有结果的数据,即已知输入与输出值。监督学习的任务时根据这些已知特征和结果的数据,训练模型,使得模型能够根据输入的特征值,预测结果。
- 无监督学习:无监督学习是指数据样本是只有特征值而没有结果值得一组数据。例如:Google的聚合新闻就是典型的无监督学习应用,其基本功能是将网络上各种新闻按照不同的主题聚合到一起进行分主题呈现。
- 标签是我们要预测的事物,即简单线性回归中的
y
变量。标签可以是小麦未来的价格、图片中显示的动物品种的含义或任何事物。 - 特征是输入变量,即简单线性回归中的
x
变量。简单的机器学习项目可能会使用单个特征,而比较复杂的机器学习项目可能会使用数百万个特征。 - 样本是指数据的特定实例:x。(我们采用粗体 x 表示它是一个矢量。)我们将样本分为以下两类:
- 有标签样本:同时包含特征和标签
- 无标签样本:同时包含特征和标签
选择模型
- 模型的选择和任务、数据样本量以及特征的稀疏性来决定,常用库-sklearn来完成模型搭建
- 数据拟合(曲线拟合)
- 根据已知数据得到一个和数据吻合的曲线
- 得到曲线后,可以推算出曲线公式,可以根据公式预测出其他未知数据的结果
- 过拟合:过于复杂,每一个点都在曲线上,曲线不够光滑
- 欠拟合:使用模型过于简单,导致预测不准确
- 异常值和数据集噪音会导致数据拟合发生变化(是否拟合由数据和任务决定)
切割数据集(训练集和测试集)
- 训练集用来找出曲线
- 测试集用来评估模型的性能和泛化能力
- 划分方法:流出法、交叉验证法、自动法
- 流出法
- 将数据集分为自变量和因变量
- 按比例切割训练集和测试集(一般测试集的比例有30%、25%、20%、15%和10%),数据量越大,测试集占比越小
#sklearn中切割数据集的方法:train_test_split
from sklearn.model_selection import train_test_split #导入包
X_train,X_test, y_train, y_test =cross_validation.train_test_split(X,y,test_size, random_state)
- 使用分层抽样
- 设置随机种子以便结果能复现
模型创建
基于线性模型的分类模型(逻辑回归)
- 逻辑回归所在模块为
sklearn.linear_model
from sklearn.linear_model import LogisticRegression
lr=LogisticRegression().fit(x,y) #x,y是特征和标签
- allfirst_rank_ecpm_v1~rank_v31_ecpm-1-78499801-null-null.142
- 参数:
penalty:
一个字符串,制定了正则化策略。
如果为'l2',则优化目标函数为:为极大似然函数。
如果为'l1',则优化目标函数为:为极大似然函数。
dual:
一个布尔值。如果为True,则求解对偶形式(只是在penalty='l2' 且solver='liblinear' 有对偶形式);如果为False,则求解原始形式。
C:
默认为1.0,是正则化系数的倒数,一个浮点数,它指定了惩罚系数的倒数。如果它的值越小,正则化越大,越能限制模型的复杂度,模型越简单,。
fit_intercept:
一个布尔值,默认为True,制定是否需要b 值。如果为False,则不会计算b值(模型会假设你的数据已经中心化)。
intercept_scaling:
一个浮点数,只有当 solver='liblinear' 才有意义。当采用 fit_intercept 时,相当于人造一个特征出来,该特征恒为 1,其权重为b 。在计算正则化项的时候,该人造特征也被考虑了。因此为了降低人造特征的影响,需要提供 intercept_scaling。
class_weight:
一个字典或者字符串'balanced'。
如果为字典:则字典给出了每个分类的权重,如{class_label:weight}。
如果为字符串 'balanced':则每个分类的权重与该分类在样品中出现的频率成反比,即样本多的权重就低,样本少的权重就高。
如果未指定,则每个分类的权重都为 1。
random_state:
一个整数或者一个RandomState实例,或者None。
如果为整数,则它指定了随机数生成器的种子。
如果为RandomState实例,则指定了随机数生成器。
如果为None,则使用默认的随机数生成器。
tol:
一个浮点数,指定判断迭代收敛与否的一个阈值,默认为0.0001,小于等于这个数时停止迭代
- 方法:
lr.score(X,y[,sample_weight]):#返回(X,y)上的预测准确率(accuracy)
lr.predict(x) #预测标签
lr.predict_proba(x) #输出标签的概率
ex:
print('测试集得分:{:.3f}'.format(lr.score(x_test,y_test))) # :.3f 表示输出时保留三位小数
基于树的分类模型(决策树、随机森林)
- 树模型所在模块为sklearn.ensemble
from sklearn.ensemble import RandomForestClassifier
rf=RandomForestClassifier().fit(x,y) #x,y是特征和标签
- 随机森林:每次随机抽取特征,由多颗决策树组成,且每个决策树之间没有联系,每个决策树都会对子样本进行测试,提高噪声处理的稳定性
- …%2522%257D&request_id=165348357116782390585361&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-4-120037954-null-null.142
- 参数说明
n_estimators :
决策树的数量,默认是100,这个参数的大小决定了最后的准确性,越大准,但是也会让你的运行速度变的很慢,所以需要不断的测试去决定。
max_features:
随机森林允许单个决策树使用特征的最大数量。
Auto/log2/sqrt :
简单地选取所有特征,每颗树都可以利用他们。这种情况下,每颗树都没有任何的限制。
默认是auto,和sqrt一样,都表示最大特征数都是特征数n的平方根
log2:所有特征数的log2值
int:是整数
float:百分比选取
criterion :
分裂节点所用的标准,可选“gini”, “entropy”,默认“gini”。
max_depth:
决策树的最大深度。如果为None,则将节点展开,直到所有叶子都是纯净的(只有一个类),或者直到所有叶子都包含少于min_samples_split个样本。默认是None,如果数据过多或者数据特征多,需要限制一下最大深度。
bootstrap:
是否对数据集放回抽样来构建决策树,默认为True即放回
oob_score:
是否使用袋外样本(即在某一次决策树训练中,没有被bootstrap选中的数据)来评估模型,默认为False,使用条件:bootstrap=True
min_samples_split:
拆分内部节点所需的最少样本数:默认是2,如果为int,则将min_samples_split视为最小值。如果为float,则min_samples_split是一个分数,而ceil(min_samples_split * n_samples)是每个拆分的最小样本数。
min_samples_leaf:
在叶节点处需要的最小样本数。仅在任何深度的分割点在左分支和右分支中的每个分支上至少留下min_samples_leaf个训练样本时,才考虑。这可能具有平滑模型的效果,尤其是在回归中。如果为int,则将min_samples_leaf视为最小值。如果为float,则min_samples_leaf是分数,而ceil(min_samples_leaf * n_samples)是每个节点的最小样本数。默认是1。
模型评估
- 数据集被切割为测试集和训练集,为了避免数据的偶然性(偶然性:测试集里面的数据更适合用来训练),选择交叉验证法
- 交叉验证:
- allsobaiduweb~default-0-119762665.nonecase&spm=1018.2226.3001.4187
- 数据被多次划分,并且需要训练多个模型
- 最常用的交叉验证法是k折交叉验证,其中k是用户指定的数字,通常取5或10(k越大模型越稳定)
- 参数说明
from sklearn.model_selection import cross_val_score #导入包
参数:
estimator: 需要使用交叉验证的模型
X: 输入样本数据
y: 样本标签,默认不填(监督学习除外)
scoring: 交叉验证最重要的就是他的验证方式,选择不同的评价方法,会产生不同的评价结果。可去官方查看详细评价方法解释。
cv: 交叉验证折数或可迭代的次数。默认为none,即五折交叉验证。
若cv参数是整数或者不填,且模型是分类器,用来二分类或者多分类,则使用StratifiedKFold(分层抽样)(cv等价于StratifiedKFold,即cv=5 <=> cv=StratifiedKFold(n_splits=5))
ex:
from sklearn.model_selection import cross_val_score
lr=LogisticRegression()
score=cross_val_score(lr,x_train,y_train,cv=10) #得到十次验证的结果
- 混淆矩阵
- llsobaiduweb~default-7-108140455.142
- 用分类模型去预测,得到预测结果后,将预测结果填入矩阵,与正确结果相比较来评估预测结果准确性
- 行表示实际类别,列表示预测类别
- F1分数:又称F平衡分数,他被定义为精确率和召回率的调和平均数(当进去了和召回率发生冲突时),不能单凭召回率和精确率去判定模型的好坏
示例:(以下为二分类的混淆矩阵,多元分类的混淆矩阵转换为二分类,即 是 和 不是)
- 参数说明
- 混淆矩阵
from sklearn.metrics import confusion_matrix #导入包
confusion_matrix(y_train,y_pred,labels=[...])
参数:
y_true:实际标签
y_pred:预测标签
lables:可以调整标签次序,或者选择子集,默认顺序:数字为从小到大,字母按A-Z排
sample_weight:样本权重
normalize:标准化
ex:
from sklearn.metrics import confusion_matrix #导入包
lr=LogisticRegression().fit(x_train,y_train) #逻辑回归模型预测标签
y_pred=lr.predict(x_train) #预测
confusion_matrix(y_train,y_pred,labels=[0,1]) #将预测结果和正确结果导入
- 计算精确率、召回率、F1函数(可以不使用混淆矩阵,直接得出精确率,召回率,f1分数)
from sklearn.metrics import classification_report #导入包
参数:
y_true:实际标签
y_pred:预测标签
target_names:可以输出你想要的标签的替代名字
from sklearn.metrics import classification_report #导入包
classification_report(y_train,y_pred)
- ROC曲线 (receiver operating characterisitic 接收者操作特征曲线)
- 纵轴为召回率(即猜正确的比例),横轴相反为未召回比例(即猜错误的比例,计算公式如下:FPR=FP/(FP+TN))
- 将多个混淆矩阵化成图,就有了ROC曲线,,线上的每一点都是一个分类器的预测结果
- 参数说明
- roc_curve
from sklearn.metrics import plot_roc_curve
参数:
y_true:实际标签,默认标签为{-1,1}或者{0,1},如果不是这些,需要用pos_label去定义
pos_label:用来指定正类标签
y_score:每个样本的预测分类,可调用逻辑回归里面的descision_function方法,返回三个值,即fpr(非召回率),tpr(召回率),thresholds(判断正负类的边界值)
ex:
lr=LogisticRegression().fit(x_train,y_train)
fpr,tpr,thresholds=roc_curve(y_test,lr.decision_function(x_test)) #此时返回的fpr,tpr,thresholds都是数据,不是图
plt.plot(fpr,tpr) # 用fpr和tpr作图,并命名
plt.xlabel('False Postive Rate ')
plt.ylabel('True Postive Rate ')
close_zero=np.argmin(np.abs(thresholds)) #找出预测最准确的点,即thresholds越接近0的点
plt.plot(fpr[close_zero],tpr[close_zero],'o') #在图中用o标记这个点
- plot_roc_curve
from sklearn.metrics import roc_curve
lr=LogisticRegression().fit(x_train,y_train)
lr_display=plot_roc_curve(lr,x_test,y_test,name='LR',response_method='decision_function')
参数:
estimator:分类器名字
x:测试标签
y:实际标签
response_method:决定是用predict_proba方法还是decision_function方法来得到每个样本的预测分数,默认为auto,即先尝试使用predict_proba,该分类器若没有这个方法,才调用的decision_function
name:给每一根曲线取名,多根曲线用到ax来叠加
ex:
#3个不同参数的逻辑回归模型
lr=LogisticRegression().fit(x_train,y_train)
lr1=LogisticRegression(C=1000).fit(x_train,y_train)
lr2=LogisticRegression(class_weight='balanced').fit(x_train,y_train)
lr_display=plot_roc_curve(lr,x_test,y_test,name='LR',response_method='decision_function') #直接使用plot_roc_curve分别画图,不需要计算等
plot_roc_curve(lr1,x_test,y_test,name='LR1',response_method='decision_function',ax=lr_display.ax_)
plot_roc_curve(lr2,x_test,y_test,name='LR2',response_method='decision_function',ax=lr_display.ax_)
#AUC表示曲线与x轴面积,面积越大表示该参数下预测越准确