Scikit-Learn线性回归从API到实战:参数调优与踩坑全解析
周末收到一封读者来信问的是用Scikit-Learn做线性回归API到底怎么调才不算白用。乍一看这问题似乎简单到有点基础但真正聊下去就会发现十个用sklearn的人里至少有五个只用了默认参数遇到多重共线性、量纲不一致或数据泄露时完全没有招架之力。因为机器学习线性回归Scikit-Learn API虽然看起来只有几行代码但它背后牵扯的是模型假设、正则化策略、求解器选择以及特征工程的前置配合随便一个环节没搞对模型结果就会失真。这篇内容就来聊聊线性回归在sklearn里从调用到落地的完整实操路径既有API层面的参数图解也有踩坑之后的复盘记录。文章面向正准备上手或已经用过LinearRegression但想更进一步的朋友目标是让读者从能跑通升级到会调、会判、会修。1. 线性回归到底在解决什么问题1.1 从业务需求到数学模型先不急着写代码。任何一个机器学习任务第一步都不是找API而是搞清楚手里的数据更适合回答什么问题。线性回归解决的问题本质上是连续值预测也就是回归问题。比如预测房价、预测销量、预测温度、预测设备的剩余使用寿命这些都是典型的回归场景。为什么线性模型从几十年前一直被用到现在因为它有一个其他复杂模型不具备的优点可解释性极强。逻辑回归还能输出概率排序树模型还能看特征重要性但线性模型直接给你每个特征的权重系数这个系数代表的是在其他条件不变的情况下该特征每变化一个单位目标变量平均变化多少。对于需要向非技术方解释结论的工程师来说这一条足够企业愿意为它开会讨论。数学表达上线性回归就是拟合这样一条线在高维空间中是一个超平面y w0 w1*x1 w2*x2 ... wn*xn其中w0是截距interceptw1到wn是各个特征的系数coefficients。机器学习的训练过程本质上就是在求解一组w使得模型预测值y_hat和真实值y之间的误差最小。sklearn中LinearRegression默认使用的误差度量方式是残差平方和这也是最小二乘法名称的由来。1.2 为什么选择sklearn作为实现工具你当然可以用NumPy手写一个梯度下降来求解线性回归这在学习推导公式时非常值得做。真到了实际项目里手写的方式有几个绕不开的麻烦特征矩阵的秩不足怎么处理不同量纲要不要标准化正则化系数怎么设这些问题虽然都有数学解法但每一块都需要自己造轮子。而Scikit-Learn的线性回归API将这些可靠、经过大规模社区验证的实现封装好直接暴露出来的是方便实验的参数选择。这也是我在实际项目里一直把sklearn当作第一选择的原因。它不只是一个算法库更是一套统一的API规范fit、predict、transform、score这套流程一旦学会就能沿用到随机森林、支持向量机、K-Means等几乎所有sklearn模型上。学习成本被大幅押后这对快速验证想法来说是实实在在的效率收益。从工程架构的视角看sklearn还解决了回归模型落地过程中的一个关键痛点它的估计器接口与Pipeline机制是天然配套的。你可以把特征标准化、降维、模型训练串成一条流水线避免在每一次实验时手工重复那些琐碎的预处理步骤。这套体系的合理性和便捷性在模型进入生产环境时会体现得更加明显。好清楚了线性回归的任务边界和工具定位下面就该进入正题到底该用哪一个类参数怎么调才能发挥出这条经典模型最大的潜力。2. API选型与核心参数解析2.1 四大回归类模型的适用边界Scikit-Learn中与线性回归直接相关的类不止一个常见的有LinearRegression、Ridge、Lasso和ElasticNet。很多人一上来就默认选LinearRegression但这并不总是最优解。这四个类解决的问题有细微差异理解它们之间的区别就理解了整个线性模型家族的设计思路。LinearRegression是最纯粹的普通最小二乘OLS模型。它没有正则化项目标是最小化残差平方和。当特征数量远少于样本数量、特征之间不存在严重的多重共线性、量纲差异也没大到离谱的时候它的效果和可解释性都是最好的。但如果你手里的特征数量接近样本数量或者特征之间存在高度相关性OLS的解会变得极其不稳定轻微的噪声扰动就可能让系数产生巨大波动。Ridge在OLS的基础上加入了L2范数惩罚也就是把系数的平方和也纳入损失函数。它的作用是让系数不断向零收缩但不会精确等于零这样可以缓解多重共线性问题。所有特征都会在模型里保留但相关性高的特征会被分摊权重整体预测的稳定性优于普通线性回归。Lasso则使用L1范数惩罚它的特性是会让一部分系数直接变成零。这意味着它本身在做一个隐式的特征选择特别适合特征非常多但实际有效的只有少数几个的高维场景。Lasso和Ridge在实际使用时没有绝对的优劣之分更多要看业务对稀疏性是否有要求。ElasticNet是Ridge和Lasso的加权组合同时包含L1和L2惩罚项由参数l1_ratio控制二者的比例。当你面对的特征之间存在分组相关性比如一组one-hot编码出来的特征Lasso可能从一组相关特征中随机挑一个而ElasticNet会选择整组保留或整组剔除结果更加稳。模型类正则化方式系数是否收缩到零主要场景LinearRegression无否特征独立、低维、无共线性问题RidgeL2否但会变小多重共线性明显、特征多但都有效LassoL1是高维稀疏场景需要特征选择ElasticNetL1 L2是特征分组相关兼顾稳定和稀疏2.2 LinearRegression核心参数的黑盒拆解LinearRegression的构造参数在sklearn中一直很简洁直到近两个版本才持续增加但往往被忽视的参数正是决定模型质量的关键。第一个是fit_intercept默认是True。它决定模型是否计算截距项。大多数真实场景中数据不会精确穿过原点所以保留截距几乎是必然选择。但有一个例外如果你在特征工程里已经对目标变量做了中心化处理让目标均值为零此时可以把fit_intercept设为False来强制模型过原点。需要注意一旦设置False模型的表达能力会受限没有十足的理论依据不要轻易关掉它。第二个是normalize这个参数在新版本中已经标记为deprecated但在旧版本中它控制是否在拟合前对X做L2范数归一化。官方给出的建议是不建议通过该参数处理应该在预处理阶段用StandardScaler或Normalizer显式完成。原因是这个参数只对特征做简单的归一化无法保存具体的转换器供后续预测时复用。把归一化放到Pipeline中才能在训练集和测试集上使用完全一致的处理逻辑。实际动手时请直接忽略normalize在Pipeline里设置好StandardScaler效果更好。第三个容易被遗漏的是positive参数它在1.5版本中作为实验性参数出现但在后续版本中并未完全稳定。设置为True时会约束所有系数必须为非负值这在一些物理或业务场景中非常重要比如在蛋白质含量预测模型中每个特征对目标的影响方向应当可解释且非负。第四个是copy_X默认True决定是否在拟合时复制特征矩阵。设置为False可以省下一部分内存但代价是fit过程中可能会覆盖原始数据。除非数据结构简单且清晰否则默认保持True更安全。还有一个在近几个版本中陆续开放的高阶参数是tol它配合求解器使用决定迭代优化的停止阈值。当使用默认的精确求解方式时tol可能没啥感知但切换为迭代求解器时需要调小tol才能换来更精细的收敛结果。2.3 从属性解读模型的体检报告模型训练完毕后通过几个核心属性可以快速判断它的健康状况。coef_各个特征的权重系数数组。形状为(n_features,)或(n_targets, n_features)多输出回归时会给出每一列目标对应的独立系数集。这是解释模型含义的首要入口。intercept_截距值。一个标量多输出时为一维数组。它可以用来计算特征全为零时的基准预测值。n_features_in_在fit阶段观测到的特征数量。这个属性对于排查特征列数不匹配的问题非常有用。有一次我在做特征筛选时训练测试集都是同样的特征维度但部署到线上时配置文件少选了一列结果接口直接抛错。当时要是早一点检查n_features_in_和feature_names_in_就能立刻定位问题。feature_names_in_记录fit时的特征名前提是传入的DataFrame列名均为字符串且无重复。这个属性在做特征重要性分析和模型复现时非常重要。如果一个模型用了不同的列名顺序重新加载预测结果很可能完全对不上。在做模型持久化后读取模型并用feature_names_in_做输入校验几乎是我每条生产环境的必经步骤。2.4 Ridge、Lasso的参数差异Ridge的alpha参数控制惩罚力度默认1.0。这个值越大系数向零收缩得越多模型复杂度越低。但alpha的选择对结果影响极其敏感我的建议是务必配合交叉验证类RidgeCV来自动搜索。窄范围日志化网格比凭经验拍脑袋要稳得多。Lasso的alpha同样控制惩罚强度但因为它会直接把系数压成零alpha过大时所有特征都可能被剔除。曾经我做过一个特征数超过200的稀疏回归lasso给出的结果几乎与只保留3个特征的全新模型一致这在业务上大大简化了部署依赖。另一个值得关注的参数是max_iterLasso在默认条件下如果数据集较大容易提示最大迭代次数的警告把它调大到20000甚至50000不是坏习惯。3. 实操过程与核心环节实现3.1 完整案例分步骤搭建一个回归预测模型选一份模拟房价数据来展示完整流程包含800个样本特征有面积、卧室数量、楼龄、距离市中心的公里数以及一个表示朝向的类别特征。先加载数据、划分训练测试集然后进入特征工程。import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression from sklearn.pipeline import Pipeline from sklearn.metrics import mean_squared_error, r2_score第一步划分训练集和测试集。在这里划分比例选择7:3设置random_state42保证实验可复现。测试集在整个流程中必须放在最后才能使用这点是数据泄露的底线。X df.drop(price, axis1) y df[price] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42 )第二步设计Pipeline。先说数据预处理的好处把标准化和模型绑定在一起可以避免反复手写transform更关键的是保证预测时对上线数据使用完全相同的处理逻辑。这里先实例化一个Pipeline对象加入StandardScaler用于特征标准化再放入LinearRegression作为最终的估计器。pipe Pipeline([ (scaler, StandardScaler()), (reg, LinearRegression()) ]) pipe.fit(X_train, y_train) train_pred pipe.predict(X_train) test_pred pipe.predict(X_test) print(Train R2:, r2_score(y_train, train_pred)) print(Test R2:, r2_score(y_test, test_pred)) print(RMSE Train:, mean_squared_error(y_train, train_pred, squaredFalse)) print(RMSE Test:, mean_squared_error(y_test, test_pred, squaredFalse))训练脚本也就不过几行但这个过程中有几个容易被忽略的地方我挨个拆开讲。3.2 精度对比为什么做特征标准化对同一份数据集分别用先标准化再拟合和直接拟合两种方式训练注意查看系数和测试精度差异。你会发现如果不做标准化面积这个特征动辄几百万的数值会让coef_变得非常小而卧室数量这种小数值特征的系数变得很大单看系数根本无法比较特征影响力。标准化后所有特征均值归零、方差归1系数才能被直接视为相对影响力的度量。另外一个不容易注意的点在于标准化会影响正则化模型的惩罚力度这也是为什么做岭回归或Lasso之前必须把特征统一到相近量纲否则不同量纲的特征会得到不对称的惩罚正则化形同虚设。3.3 在不平衡条件下如何调整模型假如这份数据里存在极少数超高价格的小面积房产它们对最小二乘的损失函数影响巨大模型会被这些分布边缘的样本强行拉动。一个非常直接的应对策略是改用HuberRegressor它对离群点的敏感性低于普通最小二乘。更稳妥的做法是先对目标变量做log变换让长尾分布更加对称再使用LinearRegression、RidgeCV配合这些处理做方案对比。我一般会在拆解方案时同时跑两套版本一套为原始目标 默认模型用于基准参考另一套为log目标 正则化 标准化作为候选方案。最终用测试集R2和RMSE对比选择更稳的方案。注意如果对目标做了log变换所有预测结果必须用np.expm1()进行逆变换后再计算模型误差指标否则比较没有意义。3.4 多种特征与交互项的引入在线性模型中加入特征的多项式组合是突破线性假设的有效方法。sklearn的PolynomialFeatures可以将原始特征升维生成包含交互项和高次项的扩展特征。以两个特征a和b为例degree2时会生成1、a、b、a^2、ab、b^2六列。配合前面讲到的Pipeline这一过程可以安全地纳入训练流程。from sklearn.preprocessing import PolynomialFeatures poly PolynomialFeatures(degree2, include_biasFalse) pipe_poly Pipeline([ (poly, PolynomialFeatures(degree2, include_biasFalse)), (scaler, StandardScaler()), (reg, Ridge(alpha1.0)) ]) pipe_poly.fit(X_train, y_train)这里我特意选用了Ridge而不是LinearRegression因为多项式和交互特征会显著增加特征维度几乎必然引入共线性问题普通的OLS过拟合风险非常大。多项式特征的系数在业务解释上更为困难所以这类方案更适合用来提升预测精度如果项目强依赖可解释性务必权衡复杂度与收益。4. 常见问题与排查技巧实录4.1 高频报错的背后逻辑ValueError: Input contains NaN, infinity or a value too large for dtype(float64)这是线性回归模型里最见惯不惊的报错之一。遇到这种问题不要盲目删行正确做法是先用df.info()检查列的非空数量再用df.isna().sum()找到具体列最后判断缺失值是否是随机缺失。回归任务缺失值默认用中位数或均值填充并不总是安全的如果想保持数据的分布特性用sklearn的IterativeImputer进行多变量插值往往效果更好。ConvergenceWarning在Lasso和ElasticNet中较常见本质是迭代没有在默认的max_iter内收敛。老实说这个警告在中小型数据中极少出现一旦出现基本说明特征量已经相当大或者存在非常强的共线性。处理方式不是简单把max_iter调大而是先看看数据量是不是足够支撑这么多特征。特征太多而样本太少时再多的迭代也只是在拟合噪声。LinAlgError: Singular matrix则发生在特征矩阵秩不足时常见于样本数少于特征数或者特征之间存在精确的线性关系比如one-hot编码后忘记丢弃某一列。解决思路有两个一是去掉冗余列二是直接用带L2惩罚的Ridge模型从源头上规避矩阵奇异问题。4.2 预测效果不佳的排查顺序表模型跑通了但R2很低的时候很多人第一反应是换模型。我的建议是先从输入侧排查。现象首要排查思路常见解法训练R2高、测试R2低过拟合添加正则化、减少特征数、增加样本量训练R2和测试R2都低特征质量不够增加特征、做多项式交互、换非线性模型训练R2低、测试R2更低数据泄露反向影响检查是否有时间穿越特征或预处理阶段的泄漏R2为负模型比均值预测还差检查目标变量是否被错误排序、数据是否有异常脏值这里特别提醒一件事R2为负并不代表报错它说的是模型预测效果比永远预测均值还要差一定是哪里出了系统性偏差。我遇到过一次发现特征里混入了一列与目标高度相关但属于未来信息的变量拆分数据时不小心把同一时期的数据同时放进了训练和测试导致测试集R2出现了奇怪的边界值。4.3 多重共线性与回归系数的稳定性多重共线性是线性回归最容易踩的暗坑。它的危害不在于让预测变差而在于让模型系数变得极其不稳定。两个高度相关的特征会在OLS求解时出现系数一个很大正数一个很大负数互相抵消肉眼很难察觉。识别方式最直观的是看相关系数矩阵如果两个特征的相关系数绝对值超过0.7就值得警惕。更严谨的做法是计算VIF方差膨胀因子VIF超过10则基本判定为该特征与其他特征存在严重共线性。处理方法优先级排序为优先保留业务上更可解释的特征其次使用Ridge或ElasticNet处理最后再考虑对相关特征做PCA降维。4.4 数据泄露的经典场景时间序列与分组划分这个问题在回归项目中非常常见。如果数据本质上是时间序列例如商品销量、设备温度那么训练集和测试集的划分就应该严格按照时间边界而不是用train_test_split做随机打散。随机打散等于让模型偷看未来的分布模式测试集评估就会虚高上线后立刻失效。处理方式很简单用TimeSeriesSplit或者手动按时间索引切片。另外如果数据存在明显的分组结构比如来自不同供应商的样本交叉验证时要使用GroupKFold保证同一组的样本不跨训练集和测试集否则会产生严重的预测偏差。5. 从单模型到竞赛实务线性回归的边界与进化5.1 何时应该升级到更复杂的模型线性回归最大的限制是它对特征与目标之间关系的假设过于线性。当真实关系呈现明显的非线性、特征间交互作用复杂时线性模型再努力也只是在刻画一条平均线。但这就引出另一个关键问题模型不是越复杂越好。在特征量很大但数据量不够的项目里线性模型配合正则化反而比树模型和神经网络鲁棒得多。业界有个不成文的经验先把线性模型做扎实跑出能接受的基准分数再去尝试复杂模型如果复杂模型在测试集上提升小于1%而训练时间却多了几个数量级就要慎重考虑是否值得。在实际比赛中线性模型也往往是第一版必交的基准线它能帮你检查特征工程的正确性。如果一个随机森林模型比线性模型好很多说明数据中的非线性关系显著后续排查和迭代都可以集中到这个方向。5.2 特征工程配合线性模型的进阶思路线性回归有一个特性它对特征的数值范围敏感但对特征的分布形态并不敏感。所以做特征工程时可以围绕让特征与目标之间的关系更线性来展开。最常用的手段是目标变换。如果目标值分布极端偏态可以用log1p将长尾压缩模型收敛更快误差指标也往往更漂亮。注意log1p对应的逆变换是expm1这两个函数在sklearn的TransformedTargetRegressor中可以直接包装。另一个手段是分箱与woe编码结合。对于连续特征先做等频分箱转变为类别特征再对每个分箱计算目标均值用目标编码后的取值代替原始数值。这种做法在线性模型中能显著提高上限因为它允许特征与目标呈分段线性关系。不过分箱数目的选择、保活策略都需要用交叉验证来兜底。5.3 插入一个完整版回归方案对比借用前面那批模拟数据做一个小的实验对比。from sklearn.linear_model import RidgeCV, LassoCV, ElasticNetCV from sklearn.model_selection import KFold kf KFold(n_splits5, shuffleTrue, random_state42) ridge RidgeCV(alphasnp.logspace(-3, 3, 50)) lasso LassoCV(alphasnp.logspace(-3, 3, 50), cvkf) enet ElasticNetCV(alphasnp.logspace(-3, 3, 50), l1_ratio[0.1, 0.3, 0.5, 0.7, 0.9], cvkf)四个模型依次放入同一份标准化后的数据中训练最终的测试集R2排序通常是ElasticNetCV RidgeCV LinearRegression LassoCV。但这个结论并不绝对alpha的搜索空间不同、特征稀疏程度不同都会改变排名。Lasso在稀疏特征场景中优势会很突出ElasticNet在特征相关性强的场景中更稳。以后先做特征相关性分析再选模型比盲目套一个交叉验证模型要靠谱得多。6. 值得收藏的生产级小技巧6.1 API之外必须掌握的计算细节使用Stochastic Average GradientSAG求解器时注意LinearRegression并没有直接暴露求解器为SAG的选项但Ridge拟合时可以指定solversag数据量大时这种选择能显著提升效率。SAG对特征缩放非常敏感使用前必须确保标准化完成否则容易出现数值不稳定。另一个可以直接提升生产环境效率的技巧是利用n_jobs参数。虽然线性回归本身运算量不大但在配合交叉验证且特征数量很大的情况下并行拟合能明显缩短工程量。6.2 模型持久化与特征一致性校验训练好的模型用一个joblib.dump保存部署时用joblib.load加载。但回归模型落地时真正的功夫不在序列化而在特征一致性。sklearn 1.3之后的版本中feature_names_in_的存在让这个问题变得可查。部署接口收到请求后先把字段顺序按模型保存时的feature_names_in_排列再做预测这是我在项目里保留下来的必备校验。特征类型同样需要检查。模型训练时如果特征是float而线上请求传过来的却是int同一列名的值不会有问题但若使用了不同的编码方式例如类别列被映射成了字符串预处理器可能在transform阶段报错甚至因为pandas的category类型自动重排而引发数据错位。处理建议是定义统一的数据类型schema把校验逻辑在入口写好而不是等模型挂了再去查日志。6.3 从回归系数推导业务决策线性模型的收官之作往往是把模型系数翻译成业务解读。以房价模型为例如果标准化后coef_最大的特征是建筑面积那么可以这样说保持其他特征不变建筑面积每增加一个标准差预测房价平均上涨约XX万元。如果要给业务方出报告建议再给出置信区间利用fit_intercept模型的残差标准差可推导预测区间虽然sklearn没有直接暴露置信区间接口但基于残差的经验近似足够业务使用。表达系数的单位变换时注意不要混淆标准化前后的系数语义。未经标准化的系数是每增加1个单位的影响标准化后的系数是每增加1个标准差的影响。两者数值完全不同一旦在报告中用混业务方很可能做出错误判断。7. 回归模型调优的完整操刀顺序调优过程中的一个常见误区是一口气把所有模型都跑一遍然后看哪个分数高就选哪个。这种方式既不高效也难以解释。我建议按照下面这个顺序走一遍每一步都有明确目标最后得到的模型既稳又可控。第一步先直接用LinearRegression跑一版裸模型记录R2和RMSE。这一步的意义不是挑选而是建立基准。如果基准R2已经很高说明问题线性度好。第二步做特征标准化并检查是否引入共线性。如果VIF超过阈值换上RidgeCV看分数变化同时观察alpha的选择值。这个alpha如果选得很大说明正则化对模型的提升非常明显数据中可能存在强共线性。第三步尝试加多项式或者交互特征配合Ridge或ElasticNet防止过拟合。此时如果分数有明显提升说明特征间交互项帮助大。第四步检查残差图。如果预测值在某个区间出现明显的规律性偏差说明有非线性关系没有捕捉到。可以尝试对目标变量做变换或者逐步引入更复杂的模型。第五步在测试集上一次完成最终评估记录所有数据划分的随机种子、预处理的参数、模型超参数的长名单。只有这样后续任何环节出了异常才能快速回溯。举个实际例子在曾经做的一个某设备故障时间预测项目中我先用Lasso拿到了RMSE12.3看似一切正常。绘制残差后才发现在目标值较大区域内模型始终系统性低估。于是切换到对目标做log变换再接LassoRMSE降到9.8残差图也均匀了很多。这个改进过程完全不是靠换一个更复杂的模型而是靠认真检查残差图修正了目标空间的假设。8. 几个容易吃大亏的盲区8.1 类别特征的正确打开方式线性回归不能直接吃字符串类别。One-Hot编码是最常见的做法但很多新手会用pd.get_dummies()直接处理却忘了设置drop_firstTrue导致产生完全共线的虚拟变量。这会触发奇异矩阵的问题虽然sklearn在底层会做内部处理但系数解释会变得混乱。在Pipeline中使用OneHotEncoder(dropfirst)是最稳的方法。还有一种更推荐的处理方式是用OrdinalEncoder给类别赋值。但注意如果类别本身没有天然的强弱排序关系直接把数值当作有序会强行引入不存在的线性关系。类别少的特征优先考虑OneHot类别非常多的特征比如城市名称很多可以试目标编码。8.2 样本量与特征数的比值关系经验法则上是样本量至少是特征数5到10倍特征太多而样本不足时线性模型的方差会非常吓人。更稳妥的方案是降维或正则化。即使使用Lasso如果样本只有100而特征有500最终的稀疏解也未必稳定不同随机种子跑出来的特征选择结果可能完全不一样。此时考虑先行降维或者用嵌入特征选择方法先做一个粗筛。8.3 验证集合划分的策略必须前置有时候模型本身训练得不错但验证方式选错了。回归问题如果存在季节周期纯随机划分完全没有意义必须使用按时间顺序或带分组的交叉验证。对于数据量很小的场景推荐使用LeaveOneOut虽然训练成本高但每个样本都能当一次验证样本能逼出更真实的泛化水平。交叉验证的评估策略应该在特征工程之前就定好否则每次变更对比指标会混乱。固定的random_state和固定的交叉验证分片是回归项目可复现的底线。做机器学习越久越会发现一件事真正有区分度的从来不是你会不会调用某个API而是你能不能理解这个API在替你做什么以及它做不了什么。Scikit-Learn把线性回归的实现打磨得极其稳定这反而要求我们付出额外的主动性去校验模型假设、监控特征一致性、审视评估流程。我个人在实际操作中最深的体会是与其花时间追求一个看起来更高端的算法不如先把线性回归在正确的前置条件下调整到极限。很多时候一个构造干净、验证严谨的线性模型在业务落地中的效果会远超一个花里花哨却没有被充分诊断的复杂模型。如果你正准备动手做第一版回归模型不妨就从这一套流程开始把每一步都走到位再回头看看模型表现收获大概率会超出预期。