模型构建和优化过程 | 您所在的位置:网站首页 › 怎么构建预测模型 › 模型构建和优化过程 |
机器学习流水线 一、预处理过程 探索数据集、数据预处理、特征工程。 ——见相关笔记 二、构建模型过程 包括构建模型的预处理,选择算法与模型优化,而模型优化涉及评估验证和调参。 三、预测过程 系统设计指导原则 快速搭建你的第一个系统,然后开始迭代。而不是妄图一口吃成个胖子,一下就能搭建出复杂而完美的系统。 不断地验证,不断地调试,不要妄图一下就写出一个完美的模型,而宁愿一开始比较粗糙,比较简单,但迅速实现,然后一步一步的误差分析和优化而使它变好。 (一)构建模型的预处理过程1、提取特征集和标签 labels = data['income'] features = data.drop('income', axis = 1)2、切分训练集、验证集(开发集)、测试集 如果像一些kaggle竞赛之类的,别人已经为你切分了训练集和测试集,只给你训练集训练,那这时只需切分一次即可,将训练集再切分为训练集和验证集。但如果没有,那就可能需要切分两次。第一次切分一般就是留出法切出测试集;第二次切分则有两种方法:留出法和交叉验证法。 2.1 train、valid(dev)、test的区别 训练集用于训练模型(模型的学习),验证集用于调参(模型的优化)、测试集用于实践(模型的应用) 训练集 → 题解大全 验证集 → 模拟考试 测试集 → 高考 2.2 测试集大小的设置 一是取决于你拥有的数据量的大小,数据量越大,比例可以越小。 二是取决于对系统性能是否有要有置信度很高的评估,越靠谱的评估需要测试集越大。 小数据时代:6:2:2 百万数据,98:1:1 更多:99.5:0.25:0.25 2.3 具体切分方法 (1)留出法 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size = 0.2, random_state = 42)(2)交叉验证 ——充分利用数据集 kf = KFold(n_splits=2)将 shuffle(洗牌) 参数设置为 true。以防止可能产生的问题:一类数据大都被归入了训练集,另一类数据大都被归入了测试集,因此导致算法的准确度很低。(比如说一堆邮件分别是甲和乙写的,而我们把甲写的都划入了训练集,把乙写的都划入了测试集) (二)设置评估指标无论是选择不同的算法,还是不同的参数(调参),都需要基于一个评估指标。 选择不同评估指标,具体取决于我们要尝试解决的问题,比如分类问题和回归问题就有不同的评估指标。又比如有些数据存在样本不平衡问题, 有些问题旨在识别某一类数据,这时用简单的准确度(accuracy)指标就没有意义(天真预测器的对比)。 分类问题 true和false:真和假;代表你的判断是否正确。 positive和negative:阳、正和阴、负;代表你判断的类别。 (1)查准率(命中率):precision precision=真正例/(真正例+假正例)——多做多错、少做少错 ——我们只统计你选P并正确的题除以你选P的题,以此来判断你的分数。看你是否对某一类一击即命中。 适合:倾斜数据集。我们一般把数量较少的样本叫阳性样本(正例,positive),一般情况下我们也只关心阳性样本的预测结果。最常见的倾斜数据例子是癌症检查,得了癌症的不幸的人就是阳性样本,相对于健康的大众,他们是稀少的存在。 (2)查全率(召回率、识别率):recall recall=真正例/(真正例+假负例)——宁可错杀、不可放过 ——我们只统计你选P并正确的题除以正确答案应该是P的题,以此来判断你的分数。看你是否对把某一类全部识别出来。 适合:假阳性和假阴性这两种错误的重要性不同的场景。比如边境的安检会犯两种错误,不是恐怖分子却当作恐怖分子审讯(假阴),是恐怖分子却当作正常人放行(假阳),无疑假阳的错误更严重。再比如统计学中,第一类错误就是假阳性错误,即原假设本为真,却错误地拒绝,如前所述,这里的阳性(或正例)不是正确或错误、肯定或否定,而是我们所更关心的那个结果,拒绝原假设就是我们更关心的,因为这样才能证明备择假设正确。 (3)F分数 F分数将两个指标结合在一起变成一个指标,同时考虑精确率和召回率,叫做单一数字评估指标或单实数评估指标。 F_{\beta}=\frac{(1+\beta^{2})\times p\times r}{(\beta^{2}\times p)+r}=\frac{1+\beta^{2}}{\frac{\beta^{2}}{r}+\frac{1}{p}} ——其实就是两个指标的加权调和平均数,权重β越大表示召回率越重要,等于1时就是F1分数。 from sklearn.metrics import fbeta_score, accuracy_score results = {} results['acc'] = accuracy_score(y_true,predictions) results['f'] = fbeta_score(y_true,predictions,beta=0.5)(4)ROC 与 AUC ROC(Receiver Operating Characteristic):接收者操作特征曲线。 AUC(Area Under Curve):ROC曲线下的面积。 为什么要使用 ROC和AUC:在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。当测试集中的正负样本的分布变化的时候,其性能得分就会有很大的变动(想想如果是瞎蒙,全猜A或全猜B的情况),但ROC曲线能够保持不变。 ROC曲线的横坐标为FPR(false positive rate),纵坐标为TPR(true positive rate)。 考虑ROC曲线图中的四个点和一条线: 第一个点(0,1),即FPR=0, TPR=1,也意味着TNR=1,FNR=0,没有分类false的,所有的分类均正确。 第二个点(1,0),即FPR=1,TPR=0,同理这意味着所有分类均错误。 第三个点(0,0),即FPR=TPR=0,意味着TNR=FNR=1,该分类器预测所有的样本都为负样本(N)。 第四个点(1,1),该分类器预测所有的样本都为正样本(P)。 基于以上分析,可以说:ROC曲线越接近左上角,该分类器的性能越好。 AUC是ROC曲线下的面积,显然数值不大于1。又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围一般在0.5和1之间。 使用AUC值作为评价标准是因为很多时候ROC曲线只是一个曲线,当两条曲线比较接近时不容易比较,而AUC作为一个数值,可以更直接的比较大小。 回归问题 (1)平均绝对误差(Mean Absolute Error):MAE= \frac{1}{m}\sum_{i=1}^{m}{|y_{predict}^{(i)}-y_{true}^{(i)}|} ——有关平均绝对误差和如何在 sklearn 中使用它的更多信息,查看此处。 (2)均方误差(Mean Square Error):MSE= \frac{1}{m}\sum_{i=1}^{m}{(y_{predict}^{(i)}-y_{true}^{(i)})^{2}} ——误差平方和(Sum of Squares for Error,SSE)=MSE×m (3)均方根误差(Root Mean Square Error):RMSE=√MSE (4)均方根百分比误差(Root Mean Square Percentage Error ):RMSPE ——Kaggle比赛Rossmann Store Sales项目即用RMSPE作为评估销售预测的误差。就是在RMSE的基础上,令真实值与预测值之差再除以真实值,形成一个比例。 def metric_RMSPE(y_true, y_predict): y1 = np.array(y_predict) y2 = np.array(y_true) n = len(y_true) temp = np.square((y1 - y2)/y2).sum() score = np.sqrt(temp/n) return score(5)R2分数=SSR/SST=1-SSE/SST ——指模型里可解释内容的占比。 残差或误差平方和(预测值/估计值与真实值)SSE(Sum of Squares for Error) = RSS (residual sum of squares) 总的平方和(真实值与均值)SST(Sum of Squares for Total) = TSS(total sum of squares) 回归平方和(预测值与均值)SSR(Sum of Squares for Regression) = ESS (explained sum of squares) 鉴于R^2局限性:当给模型增加自变量时,决定系数也随之逐步增大,但这种增大是因为自变量个数的增多引起的,而不一定真的是模型的拟合度变好。 所以有调整后的R2=1-(SSE/dfE)/(SST/dfT) 区别:R^2相当于是对所有的数据都会有一个相同的比较标准。也就是说你得到一个值0.9999,那就非常好(当然对不同的应用你对好的定义可能会不一样,比如某些你觉得0.6就够了,某些你要0.8)。而MAE和MSE就是数据相关了,范围可以非常大,你单纯根据一个值完全不知道效果怎么样。 相比于 R^2 作为拟合度的评价, RMSPE 更贴近误差的概念。而相比于 MSE 和 RMSE, RMSPE 计算的是一个误差率,这样就避免了真实值之间大小的不同而对误差产生的影响。 RMSPE 的缺点是,如果预测值是真实值的两倍以上,则 RMSPE 取值可能就会非常大,失去了评估的意义。所以理论上, RMSPE的取值范围是 0 到正无穷 (三)选择算法1、kaggle调查:最常使用的算法排名 logistic回归基于经典的回归理论,最大的优点是结果可解释,速度快,操作还简单(不用调参),所以在工业界应用最为广泛(第1)。 DT的输出结果可以进行可视化,也易于理解,在特征不多时效果也很好,应用也很多。(第2) DT有稳定性差、易过拟合等问题,而各种基于树的算法不同程度解决了这些问题,成为在传统机器学习中比较强大的算法。(RF第3,集成方法第6,GBM第8) 神经网络、深度学习随着大数据的兴起,在CV/NLP等领域应用越来越广泛(NN第4,CNN第9,RNN第10)。 贝叶斯模型是与别的不同的生成式模型,有其自己的应用领域(第5)。 SVM的应用与神经网络、深度学习有所重合,在后者的冲击下有些失势(第7)。 HMM(隐马尔可夫模型)的应用与RNN有些重合(第13) 2、监督学习的算法选择思路 (1)看问题类型:是分类还是回归? (2)看准确度要求 (3)看处理速度要求 (4)看调参难度 调参容易:logistic回归(不需调参,除非要正则化) 调参困难:XGBoost、神经网络及深度学习 (5)是否有局部最优问题 局部最优问题:神经网络、DT 无局部最优问题:logistic回归、SVM、NB (6)是否易于理解、解释 简单:logistic回归、NB、DT 复杂:神经网络及深度学习(黑箱) (7)特征数量 适合多特征:NB、神经网络及深度学习 适合少特征:DT(多特征容易过拟合)、RF(也只有几十维) (8)数据规模 要大数据:神经网络、DT、集成学习 要小数据:logistic回归、SVM、NB (9)是否容易过拟合 容易过拟合:DT、神经网络 不易过拟合:logistic回归、NB、RF (10)是否需要特征缩放 需要缩放的:logistic回归、SVM、K均值聚类 不需要缩放的:决策树、NB (11)缺失值较多 抗缺失能力强:DT、NB(?) 抗缺失能力弱:SVM (12)噪声、异常值较多 抗干扰能力强:NB、神经网络 抗干扰能力弱:SVM、DT 3、其他参考: Choosing a Machine Learning Classifier :Edwin Chen所做的概述,短小易懂,可读性强。scikit-learn的“机器学习导图” :选择“正确”的估计器(estimator)。Machine Learning Done Wrong :深思熟虑的建议,避免在机器学习中掉进常见的坑,有些建议涉及算法的选择。Practical machine learning tricks from the KDD 2011 best industry paper :较上一项更高级的建议。An Empirical Comparison of Supervised Learning Algorithms :发表于2006年的研究论文。(四)模型优化(调参)模型优化实际就是一个调参的过程,在使用各种模型优化策略时,不可避免的需要设定各种超参数,通过设置一个最佳超参数达到模型的最佳性能。 1、模型优化的目标:降低偏差与方差,避免欠拟合和过拟合 我们希望最优的模型不仅可以很好地拟合训练数据,而且有较好的泛化能力,也就是说训练误差和泛化误差都小,即同时具有较小的偏差(bias)和方差(variance)。偏差过大就是欠拟合,说明模型并没有很好地学到数据的信息;方差过大就是过拟合,说明模型并没有把在训练集数据上学到的东西很好地用到测试集上。 2、如何衡量偏差和方差/如何衡量 法(1):设定一个最优误差(贝叶斯误差),将最优误差、训练集误差、验证集误差三者进行对比。 比如三者分别为1/2/7,妥妥的方差过大;比如三者为1/10/11,妥妥的偏差过大。 ——一般将人类水平作为贝叶斯误差,否则就需要自己手动设置一个基准(benchmark)。 法(2):通过学习曲线(准确率和数据规模的关系)和模型复杂度曲线(准确率和模型复杂度的关系)来看。 from sklearn.learning_curve import learning_curve # sklearn 0.17 from sklearn.model_selection import learning_curve # sklearn 0.18 learning_curve(estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes)参数说明: estimator是我们正在用来预测的模型,cv是交叉验证生成器,例如KFold(); train_sizes是依次用多少数量的训练数据来生成曲线。比如 train_sizes = np.linspace(.1,1.0,10),就是生成[ 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.]的数组。这里是一个比例。比如你的总训练集是1000,kf = KFold(n_splits=3),那么就是把总训练数据分三份,三分之一为验证集,三分之二(666)为训练集,那么就是从0.1*666到1*666为横轴的刻度。 这个参数的意义:画学习曲线时,一口一口喂数据,喂一口,得到score,画点,最后连点成线。既然这样,怎么决定这个数组的数量呢,你中意,你喜欢光滑点,大口喂,喜欢波澜点,小口喂。 scoring参数设置一个评分函数(比如accuracy和F1) 3、解决方法 (1)降低偏差减少欠拟合 更多的特征、不同的模型和参数(复杂度升高) (2)降低方差减小过拟合 更多的数据、不同的模型和参数(复杂度降低)、正则化 法1:正则化 即将前面一直说的代价函数(损失函数、风险函数)中加入一个正则化项。以线性回归为例: J(w)=\frac{1}{2m}\sum_{i=1}^{m}{L(f(x^{(i)}),y^{(i)})}+\frac{1}{2m}\lambda||w||_{2}^{2} ||w||_{2}=\sqrt{\sum_{j=1}^{d}{w_{j}^{2}}}=\sqrt{w^{T}w} 这时的代价函数又叫结构风险函数,前面的部分叫做经验风险或经验损失(机器学习的训练过程类比人类的经验式学习)。λ叫做正则化参数,||w||是范数,其下标为2代表是L2范数(欧几里得距离),所以叫L2正则化。(加平方为了消去根号,便于计算,并且增大惩罚力度) 而L1正则化用曼哈顿距离,即绝对值。用L1可能造成有些w为0的情况(造成稀疏)。 神经网络中,多了层数的概念,正则化项略有不同,对于每一层都有一个参数矩阵: ||w^{[l]}||_{F}=\sqrt{\sum_{i=1}^{n^{[l-1]}}\sum_{j=1}^{n^{[l]}}{(w_{ij}^{[l]})^{2}}} 第l层有n[l]个节点就需要n[l]个方程,每个方程都有n[l-1]个参数(对应上一层的输出)。 上式叫做弗罗贝尼乌斯范数(Frobenius norm)。 带正则化项的目标函数进行梯度下降,相当于每次迭代都比原来减少的更多,所以L2正则化叫又权重衰减。 无λ不能起到正则化作用,λ过大则会导致w过小(即压缩权重,但压缩过大会导致很多w被设置为0,可理解为删掉神经网络中的部分node,使得神经网络过于简单),倾向于欠拟合。所以找到合适的中间值,才能实现 just right。 法2:调参 手动调参:参考经验、其他人的成果。使用sklearn中网格调参,暴力搜索最佳参数组合from sklearn.model_selection import GridSearchCV from sklearn.metrics import make_scorer # 建立模型 clf = # 以字典格式创建待调参数的列表 parameters = {} # 自定义评估标准(可选) scorer = make_scorer(fbeta_score,beta=0.5) # 交叉验证(可选) cross_validator = KFold() # 创建网格搜索器 grid_obj = GridSearchCV(clf, parameters, scoring=scorer, cv=cross_validator) # 用训练数据拟合以找到最佳参数 grid_obj.fit(X_train, y_train) # 获取具有最佳参数的模型 best_reg = grid_obj.best_estimator_ # 用此模型预测结果 val_predictions = best_clf.predict(X_val)因为 sklearn 中 GridSearchCV 遍历所有给定的参数组合。所以内存占用高,运算速度慢。在实践中还有 RandomizedSearchCV 也可以使用,并且效果还不错。可以参考这篇文章和论文。 4、深度学习的优化策略 ——更多神经网络的优化策略见相关笔记 对于传统机器学习算法,常常面临方差和偏差两者的权衡(二者负相关),但对于深度神经网络算法和大数据,我们可能做到降低一方的同时不影响另一方(这可能是深度学习对传统监督学习的其中一个提升)。 这就是所谓正交化(orthogonalization)的优化策略。 ——正交意味着互成90度,比如电视机,一个按钮对应一个功能,互不影响。 但是,深度学习虽然可以很多方法来优化模型,但同时也有代价,就是很多方法都会附带着超参数,所以用的优化方法越多,需要调的超参数越多。 吴恩达推荐一个系统化的步骤,先通过增加网络的层数(深度)、增加训练时长以降低偏差,再通过增加数据、正则化等方式降低方差,然后不断循环这个过程。 比如你希望有一组独立的方法可以分别提升训练集、验证集(开发集)、测试集上的表现,而能够互不影响,这样就不会出现类似需要平衡偏差和方差的情况了。 提升训练集表现:更大的神经网络、优化算法 提升验证集表现:更大的训练集、正则化 提升测试集表现:更大的验证集 但像early stopping就会同时影响训练集和验证集,这种方法就没那么正交化了。 5、其他参考 维基百科 https://en.wikipedia.org/wiki/Bias%E2%80%93variance_tradeoff 华盛顿大学机器学习课程 https://www.coursera.org/learn/ml-regression/home/week/3 Scott Fortmann-Roe 撰写的这篇文章。 吴恩达去年在 Deep Learning School 讲了该如何应对bias variance tradeoff。(视频)。 他的新书 也讲的是这方面的内容。 ROC和AUC介绍以及如何计算AUC |
CopyRight 2018-2019 实验室设备网 版权所有 |