Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >XGboost数据比赛实战之调参篇(完整流程)

XGboost数据比赛实战之调参篇(完整流程)

原创
作者头像
大黄大黄大黄
修改于 2018-04-03 10:12:20
修改于 2018-04-03 10:12:20
12.7K9
举报

这一篇博客的内容是在上一篇博客Scikit中的特征选择,XGboost进行回归预测,模型优化的实战的基础上进行调参优化的,所以在阅读本篇博客之前,请先移步看一下上一篇文章。

我前面所做的工作基本都是关于特征选择的,这里我想写的是关于XGBoost参数调整的一些小经验。之前我在网站上也看到很多相关的内容,基本是翻译自一篇英文的博客,更坑的是很多文章步骤讲的不完整,新人看了很容易一头雾水。由于本人也是一个新手,在这过程中也踩了很多大坑,希望这篇博客能够帮助到大家!下面,就进入正题吧。


首先,很幸运的是,Scikit-learn中提供了一个函数可以帮助我们更好地进行调参:

sklearn.model_selection.GridSearchCV

常用参数解读:

  1. estimator:所使用的分类器,如果比赛中使用的是XGBoost的话,就是生成的model。比如: model = xgb.XGBRegressor(**other_params)
  2. param_grid:值为字典或者列表,即需要最优化的参数的取值。比如:cv_params = {'n_estimators': 550, 575, 600, 650, 675}
  3. scoring :准确度评价标准,默认None,这时需要使用score函数;或者如scoring='roc_auc',根据所选模型不同,评价准则不同。字符串(函数名),或是可调用对象,需要其函数签名形如:scorer(estimator, X, y);如果是None,则使用estimator的误差估计函数。scoring参数选择如下:

具体参考地址:http://scikit-learn.org/stable/modules/model_evaluation.html

这次实战我使用的是r2这个得分函数,当然大家也可以根据自己的实际需要来选择。

调参刚开始的时候,一般要先初始化一些值:

learning_rate: 0.1 n_estimators: 500 max_depth: 5 min_child_weight: 1 subsample: 0.8 colsample_bytree:0.8 gamma: 0 reg_alpha: 0 reg_lambda: 1

链接:XGBoost常用参数一览表

你可以按照自己的实际情况来设置初始值,上面的也只是一些经验之谈吧。

调参的时候一般按照以下顺序来进行:

1、最佳迭代次数:n_estimators

代码语言:txt
AI代码解释
复制
if __name__ == '__main__':
    trainFilePath = 'dataset/soccer/train.csv'
    testFilePath = 'dataset/soccer/test.csv'
    data = pd.read_csv(trainFilePath)
    X_train, y_train = featureSet(data)
    X_test = loadTestData(testFilePath)

    cv_params = {'n_estimators': [400, 500, 600, 700, 800]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 500, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}

    model = xgb.XGBRegressor(**other_params)
    optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5, verbose=1, n_jobs=4)
    optimized_GBM.fit(X_train, y_train)
    evalute_result = optimized_GBM.grid_scores_
    print('每轮迭代运行结果:{0}'.format(evalute_result))
    print('参数的最佳取值:{0}'.format(optimized_GBM.best_params_))
    print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))

写到这里,需要提醒大家,在代码中有一处很关键:model = xgb.XGBRegressor(**other_params)两个*号千万不能省略!可能很多人不注意,再加上网上很多教程估计是从别人那里直接拷贝,没有运行结果,所以直接就用了model = xgb.XGBRegressor(other_params)。<font color=red size=4>悲剧的是,如果直接这样运行的话,会报如下错误:</font>

代码语言:txt
AI代码解释
复制
xgboost.core.XGBoostError: b"Invalid Parameter format for max_depth expect int but value...

不信,请看链接:xgboost issue

以上是血的教训啊,自己不运行一遍代码,永远不知道会出现什么Bug!

运行后的结果为:

代码语言:txt
AI代码解释
复制
[Parallel(n_jobs=4)]: Done  25 out of  25 | elapsed:  1.5min finished
每轮迭代运行结果:[mean: 0.94051, std: 0.01244, params: {'n_estimators': 400}, mean: 0.94057, std: 0.01244, params: {'n_estimators': 500}, mean: 0.94061, std: 0.01230, params: {'n_estimators': 600}, mean: 0.94060, std: 0.01223, params: {'n_estimators': 700}, mean: 0.94058, std: 0.01231, params: {'n_estimators': 800}]
参数的最佳取值:{'n_estimators': 600}
最佳模型得分:0.9406056804545407

由输出结果可知最佳迭代次数为600次。但是,我们还不能认为这是最终的结果,由于设置的间隔太大,所以,我又测试了一组参数,这次粒度小一些:

代码语言:txt
AI代码解释
复制
 cv_params = {'n_estimators': [550, 575, 600, 650, 675]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 600, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}

运行后的结果为:

代码语言:txt
AI代码解释
复制
[Parallel(n_jobs=4)]: Done  25 out of  25 | elapsed:  1.5min finished
每轮迭代运行结果:[mean: 0.94065, std: 0.01237, params: {'n_estimators': 550}, mean: 0.94064, std: 0.01234, params: {'n_estimators': 575}, mean: 0.94061, std: 0.01230, params: {'n_estimators': 600}, mean: 0.94060, std: 0.01226, params: {'n_estimators': 650}, mean: 0.94060, std: 0.01224, params: {'n_estimators': 675}]
参数的最佳取值:{'n_estimators': 550}
最佳模型得分:0.9406545392685364

果不其然,最佳迭代次数变成了550。有人可能会问,那还要不要继续缩小粒度测试下去呢?这个我觉得可以看个人情况,如果你想要更高的精度,当然是粒度越小,结果越准确,大家可以自己慢慢去调试,我在这里就不一一去做了。

2、接下来要调试的参数是min_child_weight以及max_depth

<font color=red size=4>注意:每次调完一个参数,要把 other_params对应的参数更新为最优值。</font>

代码语言:txt
AI代码解释
复制
 cv_params = {'max_depth': [3, 4, 5, 6, 7, 8, 9, 10], 'min_child_weight': [1, 2, 3, 4, 5, 6]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 550, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}

运行后的结果为:

代码语言:txt
AI代码解释
复制
[Parallel(n_jobs=4)]: Done  42 tasks      | elapsed:  1.7min
[Parallel(n_jobs=4)]: Done 192 tasks      | elapsed: 12.3min
[Parallel(n_jobs=4)]: Done 240 out of 240 | elapsed: 17.2min finished
每轮迭代运行结果:[mean: 0.93967, std: 0.01334, params: {'min_child_weight': 1, 'max_depth': 3}, mean: 0.93826, std: 0.01202, params: {'min_child_weight': 2, 'max_depth': 3}, mean: 0.93739, std: 0.01265, params: {'min_child_weight': 3, 'max_depth': 3}, mean: 0.93827, std: 0.01285, params: {'min_child_weight': 4, 'max_depth': 3}, mean: 0.93680, std: 0.01219, params: {'min_child_weight': 5, 'max_depth': 3}, mean: 0.93640, std: 0.01231, params: {'min_child_weight': 6, 'max_depth': 3}, mean: 0.94277, std: 0.01395, params: {'min_child_weight': 1, 'max_depth': 4}, mean: 0.94261, std: 0.01173, params: {'min_child_weight': 2, 'max_depth': 4}, mean: 0.94276, std: 0.01329...]
参数的最佳取值:{'min_child_weight': 5, 'max_depth': 4}
最佳模型得分:0.94369522247392

由输出结果可知参数的最佳取值:{'min_child_weight': 5, 'max_depth': 4}。(代码输出结果被我省略了一部分,因为结果太长了,以下也是如此)

3、接着我们就开始调试参数:gamma:

代码语言:txt
AI代码解释
复制
cv_params = {'gamma': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 550, 'max_depth': 4, 'min_child_weight': 5, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}

运行后的结果为:

代码语言:txt
AI代码解释
复制
[Parallel(n_jobs=4)]: Done  30 out of  30 | elapsed:  1.5min finished
每轮迭代运行结果:[mean: 0.94370, std: 0.01010, params: {'gamma': 0.1}, mean: 0.94370, std: 0.01010, params: {'gamma': 0.2}, mean: 0.94370, std: 0.01010, params: {'gamma': 0.3}, mean: 0.94370, std: 0.01010, params: {'gamma': 0.4}, mean: 0.94370, std: 0.01010, params: {'gamma': 0.5}, mean: 0.94370, std: 0.01010, params: {'gamma': 0.6}]
参数的最佳取值:{'gamma': 0.1}
最佳模型得分:0.94369522247392

由输出结果可知参数的最佳取值:{'gamma': 0.1}

4、接着是subsample以及colsample_bytree:

代码语言:txt
AI代码解释
复制
cv_params = {'subsample': [0.6, 0.7, 0.8, 0.9], 'colsample_bytree': [0.6, 0.7, 0.8, 0.9]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 550, 'max_depth': 4, 'min_child_weight': 5, 'seed': 0,
                    'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0.1, 'reg_alpha': 0, 'reg_lambda': 1}

运行后的结果显示参数的最佳取值:{'subsample': 0.7,'colsample_bytree': 0.7}

5、紧接着就是:reg_alpha以及reg_lambda:

代码语言:txt
AI代码解释
复制
 cv_params = {'reg_alpha': [0.05, 0.1, 1, 2, 3], 'reg_lambda': [0.05, 0.1, 1, 2, 3]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 550, 'max_depth': 4, 'min_child_weight': 5, 'seed': 0,
                    'subsample': 0.7, 'colsample_bytree': 0.7, 'gamma': 0.1, 'reg_alpha': 0, 'reg_lambda': 1}

运行后的结果为:

代码语言:txt
AI代码解释
复制
[Parallel(n_jobs=4)]: Done  42 tasks      | elapsed:  2.0min
[Parallel(n_jobs=4)]: Done 125 out of 125 | elapsed:  5.6min finished
每轮迭代运行结果:[mean: 0.94169, std: 0.00997, params: {'reg_alpha': 0.01, 'reg_lambda': 0.01}, mean: 0.94112, std: 0.01086, params: {'reg_alpha': 0.01, 'reg_lambda': 0.05}, mean: 0.94153, std: 0.01093, params: {'reg_alpha': 0.01, 'reg_lambda': 0.1}, mean: 0.94400, std: 0.01090, params: {'reg_alpha': 0.01, 'reg_lambda': 1}, mean: 0.93820, std: 0.01177, params: {'reg_alpha': 0.01, 'reg_lambda': 100}, mean: 0.94194, std: 0.00936, params: {'reg_alpha': 0.05, 'reg_lambda': 0.01}, mean: 0.94136, std: 0.01122, params: {'reg_alpha': 0.05, 'reg_lambda': 0.05}, mean: 0.94164, std: 0.01120...]
参数的最佳取值:{'reg_alpha': 1, 'reg_lambda': 1}
最佳模型得分:0.9441561344357595

由输出结果可知参数的最佳取值:{'reg_alpha': 1, 'reg_lambda': 1}

6、最后就是learning_rate,一般这时候要调小学习率来测试:

代码语言:txt
AI代码解释
复制
cv_params = {'learning_rate': [0.01, 0.05, 0.07, 0.1, 0.2]}
    other_params = {'learning_rate': 0.1, 'n_estimators': 550, 'max_depth': 4, 'min_child_weight': 5, 'seed': 0,
                    'subsample': 0.7, 'colsample_bytree': 0.7, 'gamma': 0.1, 'reg_alpha': 1, 'reg_lambda': 1}

运行后的结果为:

代码语言:txt
AI代码解释
复制
[Parallel(n_jobs=4)]: Done  25 out of  25 | elapsed:  1.1min finished
每轮迭代运行结果:[mean: 0.93675, std: 0.01080, params: {'learning_rate': 0.01}, mean: 0.94229, std: 0.01138, params: {'learning_rate': 0.05}, mean: 0.94110, std: 0.01066, params: {'learning_rate': 0.07}, mean: 0.94416, std: 0.01037, params: {'learning_rate': 0.1}, mean: 0.93985, std: 0.01109, params: {'learning_rate': 0.2}]
参数的最佳取值:{'learning_rate': 0.1}
最佳模型得分:0.9441561344357595

由输出结果可知参数的最佳取值:{'learning_rate': 0.1}

我们可以很清楚地看到,随着参数的调优,最佳模型得分是不断提高的,这也从另一方面验证了调优确实是起到了一定的作用。不过,我们也可以注意到,其实最佳分数并没有提升太多。提醒一点,这个分数是根据前面设置的得分函数算出来的,即:

代码语言:txt
AI代码解释
复制
optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5, verbose=1, n_jobs=4)

中的scoring='r2'。在实际情境中,我们可能需要利用各种不同的得分函数来评判模型的好坏。

最后,我们把得到的最佳参数组合扔到模型里训练,就可以得到预测的结果了:

代码语言:txt
AI代码解释
复制
def trainandTest(X_train, y_train, X_test):
    # XGBoost训练过程,下面的参数就是刚才调试出来的最佳参数组合
    model = xgb.XGBRegressor(learning_rate=0.1, n_estimators=550, max_depth=4, min_child_weight=5, seed=0,
                             subsample=0.7, colsample_bytree=0.7, gamma=0.1, reg_alpha=1, reg_lambda=1)
    model.fit(X_train, y_train)

    # 对测试集进行预测
    ans = model.predict(X_test)

    ans_len = len(ans)
    id_list = np.arange(10441, 17441)
    data_arr = []
    for row in range(0, ans_len):
        data_arr.append([int(id_list[row]), ans[row]])
    np_data = np.array(data_arr)

    # 写入文件
    pd_data = pd.DataFrame(np_data, columns=['id', 'y'])
    # print(pd_data)
    pd_data.to_csv('submit.csv', index=None)

    # 显示重要特征
    # plot_importance(model)
    # plt.show()

好了,调参的过程到这里就基本结束了。正如我在上面提到的一样,其实调参对于模型准确率的提高有一定的帮助,但这是有限的。最重要的还是要通过数据清洗,特征选择,特征融合,模型融合等手段来进行改进!

完整代码可到我的GitHub上进行下载。(声明一点,我的代码质量不是很好,大家参考一下思路就行。


更多干货,欢迎去听我的GitChat:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
9 条评论
热度
最新
请问这里各参数调节的顺序是怎么决定的呢?
请问这里各参数调节的顺序是怎么决定的呢?
回复回复点赞举报
机器学习的过程感觉很艰辛,但是也很有趣!
机器学习的过程感觉很艰辛,但是也很有趣!
回复回复点赞举报
非常详细,易错点都有,厉害可、了
非常详细,易错点都有,厉害可、了
回复回复点赞举报
很强很强,学习到了
很强很强,学习到了
11点赞举报
感谢
感谢
回复回复点赞举报
非常感谢博主!一直在研究机器学习的理论部分,真正遇到实战我感到很难下手,这篇文章对我的用处非常大!再次感谢
非常感谢博主!一直在研究机器学习的理论部分,真正遇到实战我感到很难下手,这篇文章对我的用处非常大!再次感谢
11点赞举报
很高兴能帮到你。
很高兴能帮到你。
回复回复点赞举报
很详细的文章,连重点和易错点都标出来了
很详细的文章,连重点和易错点都标出来了
11点赞举报
谢谢
谢谢
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
机器学习算法之XGBoost及其自动调参(算法+数据+代码)
本文将利用一个excel数据对常见机器学习算法(XGBoost、Random Forest随机森林、ET极度随机树、Naïve Bayes高斯朴素贝叶斯、KNN K近邻、Logistic Regression逻辑回归、Decision Tree 决策树)的使用过程进行简单的介绍,并对XGBoost算法的自动调参方法进行详解,机器学习算法的详细讲解在机器学习专辑里都有介绍。
Minerva
2020/07/06
47.5K1
工程能力UP!| LightGBM的调参与并行
【这里必须说一下,lightbg的参数的同义词实在太多了,很多不同的参数表示的是同一个意思,不过本文中使用“/”分开】
机器学习炼丹术
2020/07/23
2.4K0
XGBoost实战
The accuracy of prediction is: 0.9666666666666667 Feature importances: [0.002148238569679191, 0.0046703830672789074, 0.33366676380518245, 0.6595146145578594]
西西嘛呦
2021/02/25
6850
XGBoost实战
分位数回归(quantile regression)简介和代码实现
普通最小二乘法如何处理异常值?它对待一切事物都是一样的——它将它们平方!但是对于异常值,平方会显著增加它们对平均值等统计数据的巨大影响。
deephub
2021/11/08
6.5K0
分位数回归(quantile regression)简介和代码实现
机器学习笔记之机器学习算法XGBoost
在上一篇Boosting方法的介绍中,对XGBoost有过简单的介绍。为了更还的掌握XGBoost这个工具。我们再来对它进行更加深入细致的学习。
Jetpropelledsnake21
2021/03/04
2.5K0
机器学习笔记之机器学习算法XGBoost
极度梯度提升之玩转借贷俱乐部
在《决策树之玩转借贷俱乐部》和《集成树之玩转借贷俱乐部》两贴中,斯蒂文用决策树,随机森林和提升树预测了借贷俱乐部里面的贷款的良恶性。老板最近听说了极度梯度提升 (XGBoost),而且知道几乎每个参加 Kaggle 比赛的人都会用它。老板想让斯蒂文精通它,并且用来预测借贷俱乐部 (Lending Club) 的贷款的良恶性。
用户5753894
2019/07/05
1.3K0
极度梯度提升之玩转借贷俱乐部
XGBoost类库使用小结
    在XGBoost算法原理小结中,我们讨论了XGBoost的算法原理,这一片我们讨论如何使用XGBoost的Python类库,以及一些重要参数的意义和调参思路。
刘建平Pinard
2019/07/03
1.6K2
机器学习实战 | AutoML自动化机器学习建模
教程地址:http://www.showmeai.tech/tutorials/41
ShowMeAI
2022/03/22
1.4K0
机器学习实战 | AutoML自动化机器学习建模
我的XGBoost学习经历及动手实践
知乎地址:http://www.zhihu.com/people/meng-di-76-92
Datawhale
2020/06/23
1.7K0
【机器学习】随机森林、GBDT、XGBoost、LightGBM等集成学习代码练习
对比了六大模型,可以看出,逻辑回归速度最快,但准确率最低。而LightGBM,速度快,而且准确率最高,所以,现在处理结构化数据的时候,大部分都是用LightGBM算法。
黄博的机器学习圈子
2023/01/10
1.1K0
【机器学习】集成学习代码练习
课程完整代码:https://github.com/fengdu78/WZU-machine-learning-course
黄博的机器学习圈子
2022/05/25
4530
【机器学习基础】XGBoost、LightGBM与CatBoost算法对比与调参
虽然现在深度学习大行其道,但以XGBoost、LightGBM和CatBoost为代表的Boosting算法仍有其广阔的用武之地。抛开深度学习适用的图像、文本、语音和视频等非结构化的数据应用,Boosting算法对于训练样本较少的结构化数据领域仍然是第一选择。本文先对前述章节的三大Boosting的联系与区别进行简单阐述,并一个实际数据案例来对三大算法进行对比。然后对常用的Boosting算法超参数调优方法进行介绍,包括随机调参法、网格搜索法和贝叶斯调参法,并给出相应的代码示例。
黄博的机器学习圈子
2021/04/16
7.6K0
【机器学习基础】XGBoost、LightGBM与CatBoost算法对比与调参
史上最详细的XGBoost实战(下)
作者:章华燕 编辑:田 旭 四 XGBoost 参数详解 在运行XGboost之前,必须设置三种类型成熟:general parameters,booster parameters和task parameters: General parameters 该参数参数控制在提升(boosting)过程中使用哪种booster,常用的booster有树模型(tree)和线性模型(linear model) Booster parameters 这取决于使用哪种booster Task parameters
机器学习算法工程师
2018/03/06
3.4K0
史上最详细的XGBoost实战(下)
XGBoost参数调优完全指南(附Python代码)
作者 | Aarshay Jain 简介 如果你的预测模型表现得有些不尽如人意,那就用XGBoost吧。XGBoost算法现在已经成为很多数据工程师的重要武器。它是一种十分精致的算法,可以处理各种不规则的数据。 构造一个使用XGBoost的模型十分简单。但是,提高这个模型的表现就有些困难(至少我觉得十分纠结)。这个算法使用了好几个参数。所以为了提高模型的表现,参数的调整十分必要。在解决实际问题的时候,有些问题是很难回答的——你需要调整哪些参数?这些参数要调到什么值,才能达到理想的输出? 这篇文章
AI科技大本营
2018/04/27
8.6K1
XGBoost参数调优完全指南(附Python代码)
XGBoost超参数调优指南
本文将详细解释XGBoost中十个最常用超参数的介绍,功能和值范围,及如何使用Optuna进行超参数调优。
deephub
2023/08/30
9800
XGBoost超参数调优指南
数据挖掘机器学习[六]---项目实战金融风控之贷款违约预测
因为文档是去年弄的,很多资料都有点找不到了,我尽可能写的详细。后面以2021年研究生数学建模B题为例【空气质量预报二次建模】再进行一个教学。
汀丶人工智能
2022/12/21
1.7K0
数据挖掘机器学习[六]---项目实战金融风控之贷款违约预测
数据挖掘实践(金融风控):金融风控之贷款违约预测挑战赛(下篇)xgboots/lightgbm/Catboost等模型--模型融合:stacking、blend
通过组合多个学习器来完成学习任务,通过集成方法,可以将多个弱学习器组合成一个强分类器,因此集成学习的泛化能力一般比单一分类器要好。
汀丶人工智能
2023/05/17
4.1K0
数据挖掘实践(金融风控):金融风控之贷款违约预测挑战赛(下篇)xgboots/lightgbm/Catboost等模型--模型融合:stacking、blend
SVM检测影像的云
首先利用arcgis对landsat影像打点云样本和非云样本点图层,转为csv,用作机器学习检测样本
一个有趣的灵魂W
2020/09/15
4690
SVM检测影像的云
【机器学习】--xgboost初始之代码实现分类
默认可以通过pip安装,若是安装不上可以通过https://www.lfd.uci.edu/~gohlke/pythonlibs/网站下载相关安装包,将安装包拷贝到Anacoda3的安装目录的Scrripts目录下, 然后pip install 安装包安装。
LhWorld哥陪你聊算法
2018/09/13
1.4K0
【机器学习】--xgboost初始之代码实现分类
XGBoost简单实践
XGBoost 模型对比随机决策森林以及XGBoost模型对泰坦尼克号上的乘客是否生还的预测能力
用户3577892
2020/06/11
5210
推荐阅读
相关推荐
机器学习算法之XGBoost及其自动调参(算法+数据+代码)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档