文章目录

  • 一、什么是随机森林?
    • 1.1 定义
    • 1.2 目的
    • 1.3 随机森林 VS bagging
  • 二、集成学习
    • 2.1 定义
    • 2.2 决策树的问题
    • 2.3 袋装法概念与理论
    • 2.4 装袋法的优缺点
    • 2.5 提升法概念与理论
    • 2.6 bagging vs boosting
    • 2.7 AdaBoosting
    • 2.8 Gradient Boosting(GBM)
  • 三、案例实现(bagging)
    • 3.1 数据集描述
    • 3.2 数据处理
    • 3.3 决策树
    • 3.4 bagging方法
    • 3.5 随机森林
  • 四、案例实现(boosting)
    • 4.1 数据集介绍
    • 4.2 数据处理
    • 4.3 AdaBoost介绍
    • 4.4 AdaBoost 实现
    • 4.5 XGBoost介绍
    • 4.6 XGBoost 实现
  • 五、结论

一、什么是随机森林?

1.1 定义

随机森林回归是一种使用集成学习方法进行回归的监督学习算法。集成学习方法是一种将多种机器学习算法的预测结合起来进行比单个模型更准确的预测的技术。随机森林属于集成学习中的袋装法。

1.2 目的

随机森林是Bagging的改进版本,它在Bagging的基础上做出了一个小调整,使得各个树之间的相关性降低了(decorrelate trees)。

1.3 随机森林 VS bagging

每个分支点上,Bagging能够考虑所有m=p个特征,而Random Forest只能考虑m=sqrt§个特征。如果random forest的m取成p,那么它与Bagging是相同的。(注:对于分类,一个好的默认值是:m = sqrt(p))。其中:m是在分割点可搜索的特征的数量,这些特征是随机选取的;p是输入变量的总数量。例如,如果一个分类问题的数据集有25个变量,那么:m = sqrt(25)=5。

二、集成学习

2.1 定义

集成方法是一种将来自多个机器学习算法的预测组合在一起以做出比任何单个模型更准确的预测的技术。由许多模型组成的模型称为集成模型。

2.2 决策树的问题

  1. 决策树对训练它们的特定数据很敏感。如果训练数据发生变化,最终的决策树可能会完全不同,反过来,预测也会不同。
  2. 决策树的缺点在于High Variance(高方差),也就是说,我们将样本一分为二,用两个子样本分别拟合模型,得到的结果很可能不一样。而Bagging,又称Bootstrap Aggregation,就是为了降低分类器的Variance。这就是说,应用了Bagging后,不同样本子集产出的分类器结果将会更相似。
  3. 决策树的训练计算成本也很高,存在过度拟合的巨大风险,并且往往会找到局部最优值。
  4. 为了解决这些弱点,我们转向随机森林,它说明了将许多决策树组合成一个模型的力量,能更完美。

2.3 袋装法概念与理论

Bagging (袋装法)是一种通用过程,可用于降低那些具有高方差的算法的方差,通常是决策树。Bagging 使每个模型独立运行,然后在最后聚合输出优先于任何模型。Bagging的基本理念是:求平均值会降低Variance。
聚合是 Bagging 的最后一个阶段。将基础模型做出的多个预测组合起来产生一个最终模型。最终模型将具有低方差和高准确度分数。

想要降低模型的Variance(方差),并提高准确率的方法就是,从样本总体中抽取很多个训练集(Training Set),对每个训练集分别拟合模型。将每个模型的结果求平均(Average)。

实现步骤如下:

  1. 通过Bootstrap的方法,从一个Training Set中反复提取出多个样本集,假设样本集数量为B。
  2. 用这B个样本分别拟合出B个预测性模型
  3. 将B个模型的结果取平均值,得到Bagging的预测结果。

其公式表达为:

回归和分类:

  1. 对于回归树而言,Bagging的结果就是B个没有经过Prune(剪枝)树的结果平均值。
  2. 对于分类树而言,我们通过Majority Vote,多数投票制,计算大多数模型认为结果应当属于哪一类,Bagging认为多数的结果是最终的分类结果。

因此我们只需要处理分类做袋装即可。

2.4 装袋法的优缺点

优点:

  • Bagging 算法提高了模型的准确度得分。
  • Bagging 算法可以处理过度拟合。
  • Bagging 算法减少了偏差和方差错误。
  • Bagging 可以很容易地实现并生成更健壮的模型。

但是,由于模型在最后用了平均值,因此Bagging结果的可解释性降低了。

2.5 提升法概念与理论

Boosting同样是Bagging的改进版本。它与Bagging的不同在于:树的推导是有序的,每个树的生成都借鉴了之前树的经验。Boosting方法不采用Boostrap的取样方法,每个树用的都是修正后的原始数据集(Original Dataset)。

在Boosting中,有如下参数需要考虑:

  1. B:树的数量。要生成多少棵树。
  2. d:每个树中的分支(split)数。它掌握每棵树的复杂度,若d=1,则树只有一个节点。
  3. λ:Shrinkage parameter,压缩参数。一个非常小的正数。它掌握着Boosting学习的速率。代表着每个树的作用大小。一般可以设定为0.01或0.001.一个非常小的λ代表每个树的作用很小,所以需要非常大的B,非常多的树去得到优秀的结果。

Boosting方法通过以上的步骤,以很慢的学习方式拟合模型。Boosting将残差引入拟合模型的过程中,它在模型表现的不太好的地方慢慢的去优化它。也就是说,Boosting先拟合出一个原始的模型,之后的模型希望能够一点点的优化原始模型中的Residual(残差)。在拟合过程中,每个树的权重,即发挥效用的大小就是shrinkage parameter(收缩参数)。

Boosting的学习方法是有时间循序(Sequential)的,在T时刻生成的树的Residual,会在T+1时刻生成的树中被改善优化。因此,Boosting是与原始模型息息相关的。同时,这种学习方法一般训练成本较高,学习结果比较慢。

2.6 bagging vs boosting

2.7 AdaBoosting

在AdaBoost初始化时,对每个训练的样本给出相等的权重。之后对每个样本进行模型的拟合。每一次训练后,对之前失败的训练样本集给予较大的权重。所以,之后的训练会更加侧重之前失败的样本集。最后,得到的模型按照预测效果给出权重,最终回归或者分类的结果会按照加权平均,或者加权投票结果给出判别。

2.8 Gradient Boosting(GBM)

Gradient Boosting是Boosting的一种实现方法,在Boosting中,GBM定义了损失函数(Loss Function)的概念。GMB主要的理念在于,后建立的模型是在之前建立模型的梯度下降方向的。损失函数就是模型的误差程度,损失函数越大,模型越容易出错。如果我们的模型能够让损失函数持续的下降,则说明我们的模型在不停的改进,而最好的方式就是让损失函数在其梯度(Gradient)的方向下降。

三、案例实现(bagging)

3.1 数据集描述

我们将使用糖尿病数据集来预测一个人是否患有糖尿病。收集的数据集具有Age和blood pressure等特征,Outcome列标记为 0(非糖尿病)或 1(糖尿病)。可帮助模型确定此人是否患有糖尿病。

数据集如下:

3.2 数据处理

第一步:读取数据集

import pandas as pddf = pd.read_csv("tang.csv")
df

如下:

第二步:检查下缺失值(当然,数据用的完好的,实际情况下有可能会有缺失值)。

df.isnull().sum()

如下:

第三步:提取自变量和因变量

X = df.drop("Outcome",axis="columns")
y = df.Outcome

第四步:数据缩放。

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X) # 对x缩放,y不需要缩放。

第五步:分割训练集和测试集。

from sklearn.model_selection import train_test_split
#85%的数据是训练集,25%是测试集。
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size = 0.25, random_state=10)

3.3 决策树

第六步:建立模型并评估模型。

# 使用 k 折交叉验证来构建我们的决策树分类器
# K-fold 交叉验证允许我们将数据集拆分为不同的子集或部分。然后使用每个子集训练模型,并在每次迭代后获得准确度分数。
#最后,计算平均准确度得分。K 是指我们拆分数据集的子集/部分的数量。
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeClassifier # 导入模型
scores = cross_val_score(DecisionTreeClassifier(), X, y, cv=5)
scores
#我们将数据集分成五份。它在每次迭代后生成模型准确度分数,如下面的输出所示,不断变大了

如下:

array([0.69480519, 0.66233766, 0.7012987 , 0.77124183, 0.71895425])

获取平均分:

# 平均分
scores.mean()

如下:

0.7097275273745862

使用交叉验证分数,我们得到准确度分数为0.7097275273745862。我们可以使用 bagging 算法构建相同的模型来比较准确度得分。

3.4 bagging方法

第一步:构建学习器

# 添加学习器
from sklearn.ensemble import BaggingClassifier
#  base_estimator - 这表示用作基础/弱学习器的算法。我们使用DecisionTreeClassifier算法作为我们的弱/基础学习器。
# n_estimators - 这表示使用的弱学习器的数量。我们将使用 100 个决策树来构建 bagging 模型。
# max_samples - 从训练集中采样的最大数据数。我们使用 80% 的训练数据集进行重采样。
#bootstrap - 允许在不替换的情况下对训练数据集进行重新采样。
# oob_score - 用于在训练后计算模型的准确度得分。
# random_state - 允许我们重现相同的数据集样本。此外,它确保在生成多个子集时使用相同的比率。bag_model = BaggingClassifier(base_estimator=DecisionTreeClassifier(), n_estimators=100, max_samples=0.8, bootstrap=True,oob_score=True,random_state=0
)

第二步:训练模型。

# 拟合模型
bag_model.fit(X_train, y_train)

第三步:评估模型。

# 模型准确率。结果确实比决策树高。准确度得分从 提高0.7097275273745862到0.7604166666666666
bag_model.oob_score_

第四步: 检测是否过拟合。

# 我们还可以使用测试数据集检查准确度分数,以确定我们的模型是否过拟合。
# 准确度得分表明我们的模型没有过度拟合。当我们在使用测试数据集时获得较低的准确性时,就会发生过度拟合。
bag_model.score(X_test, y_test)

如下说明没有过拟合:

0.7760416666666666

3.5 随机森林

随机森林不仅对数据行进行采样,而且对列进行采样。它还遵循装袋步骤来生成聚合的最终模型。

第一步:创建模型。

from sklearn.ensemble import RandomForestClassifiermodel=RandomForestClassifier(n_estimators=50)

第二步:训练并获取评分。

scores = cross_val_score(model, X, y, cv=5)
scores

如下:

array([0.74675325, 0.73376623, 0.80519481, 0.81699346, 0.78431373])

第三步: 获取平均分。

scores.mean() # 平均分

如下:

0.7774042950513538

准确度得分很高,表明装袋算法提高了模型准确度得分,它还可以防止模型过度拟合,所以不用去检查过拟合了。评分从0.7760416666666666增加到0.7774042950513538,说明bagging和随机森林差不多。

四、案例实现(boosting)

第一个提升算法被称为 AdaBoost(自适应提升),由 Freund 和 Schapire 设计发明。

集成方法是使用多个模型并将它们组合成一个以增强结果的技术。术语“模型”可以指任何模型 - 回归、支持向量机和 kNN,需要改进性能的模型称为基础模型。尽管“提升”技术使用决策树来提高模型的准确性,但它可以应用于任何基础模型。然而,据观察,提升基于决策树的模型比提升其他模型提供更好的结果。一种可能的解释是基础模型(决策树)和提升算法的结构相似性。

文章分为两部分,便于读者理解和留存信息。这深入解释了两种提升算法——自适应提升(AdaBoost)和极限梯度提升(XGBoost)。与该算法类似的还有Light Gradient Boosting Method (LightGBM) 和 Category Boosting (CatBoost),读者自行去了解。

4.1 数据集介绍

对于数据集中的一组特征,任务是识别蘑菇的类型是有毒的还是可食用的。数据集如下:

4.2 数据处理

第一步:读取数据

import pandas as pd
df = pd.read_csv("mushrooms.csv")
df

如下:

第二步:由于特征数太多,查看以下每一个特征类别数量。如果一个特征只有一个唯一值,我们可以删除它,因为它在构建模型时没有意义。

for col in df.columns:print(col,'特征个数',  'is', len(df[col].unique()))

如下:

class 特征个数 is 2
cap-shape 特征个数 is 6
cap-surface 特征个数 is 4
cap-color 特征个数 is 10
bruises 特征个数 is 2
odor 特征个数 is 9
gill-attachment 特征个数 is 2
gill-spacing 特征个数 is 2
gill-size 特征个数 is 2
gill-color 特征个数 is 12
stalk-shape 特征个数 is 2
stalk-root 特征个数 is 5
stalk-surface-above-ring 特征个数 is 4
stalk-surface-below-ring 特征个数 is 4
stalk-color-above-ring 特征个数 is 9
stalk-color-below-ring 特征个数 is 9
veil-type 特征个数 is 1
veil-color 特征个数 is 4
ring-number 特征个数 is 3
ring-type 特征个数 is 5
spore-print-color 特征个数 is 9
population 特征个数 is 6
habitat 特征个数 is 7

第三步:删除特征的类别数量只有一个的,因为它对分类没有意义了。

df = df.drop("veil-type", axis=1)
df.head(5)

如下:

第四步: 数据编码。由于机器学习模型更喜欢数字数据,它识别不了字符,让我们通过编码将数据集转换为数字。LabelEncoder()是 Scikit-Learn 包中将标签转换为数字的方法。

from sklearn.preprocessing import LabelEncoder
# 对每一列分别编码再合并回去
label_encoder = LabelEncoder()
for column in df.columns:df[column] = label_encoder.fit_transform(df[column])
df

如下:

第五步:提取目标矩阵Y和特征矩阵X(也就是自变量与因变量)。

X = df.drop('class',axis=1)
Y = df['class']

第六步:拆分数据集。数据集必须分成两部分——训练数据和测试数据。70% 用于训练,30% 用于测试和标准化值。

from sklearn.model_selection import train_test_split # 拆分模块
from sklearn.preprocessing import StandardScaler # 标准化模块X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.3, random_state = 100)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

4.3 AdaBoost介绍

AdaBoost是 Adaptive Boosting 的缩写, 专注于提高基础学习器失败区域的性能。基础学习器是模型的第一次迭代。

从一个决策树开始,错误分类的示例通过增加它们的权重(权重被提升)来惩罚。另一个决策树是根据新的和修改的训练数据构建的,其中包含加权样本。新的弱学习器被依次添加到模型中,以学习和识别更复杂的模式。

每次迭代后的数据永远不会相同,并且指出可能的错误分类以供算法识别和学习。错误分类的权重会增加,以便下一次迭代可以拾取它们。该过程重复指定为参数的迭代次数。该算法根据弱学习者的多数票以及它们各自的准确性进行预测。

随着迭代次数的增加,AdaBoost 可以抵抗过度拟合,并且在处理二元分类问题时最有效。AdaBoost 包括一个额外的条件,即模型需要有小于 50% 的误差才能维持它,否则,重复迭代直到生成更好的学习器。


AdaBoost 在模型构建中包含随机化,因此每次运行一段代码时,都会生成一个略有不同的模型。每次运行代码时,随机学习算法都会产生不同的结果,因此,通过多次运行代码并对获得的结果取平均值来评估此类算法的性能是一种很好的做法。

4.4 AdaBoost 实现

Python 中的sklearn库有一种AdaBoostClassifier方法,用于将特征分类为有毒或可食用。

它的参数如下:

  • base_estimator: boosted ensemble 是根据这个参数构建的。如果None,则值为DecisionTreeClassifier(max_depth=1)。
  • n_estimators:估计器的上限,默认值为 50 终止提升。如果完美拟合,则提前停止学习。
  • learning_rate:学习率通过这个值减少了分类器的贡献。它的默认值为 1。
  • algorithm:“SAAME”的默认值。此参数的另一个选项 SAMME.R 算法比 SAMME 算法收敛得更快,同时采用更少的提升迭代并产生更低的测试错误。
  • random_state:随机数生成器使用的种子。

第七步: 接着处理后的数据,创建模型、训练模型、评估模型。

from sklearn.ensemble import AdaBoostClassifier
model = AdaBoostClassifier(n_estimators = 50, learning_rate = 0.2) # 创建模型
adaboost=model.fit(X_train, Y_train)  # 训练
score = adaboost.score(X_test, Y_test) # 评估
score

如下:

0.9848236259228876

4.5 XGBoost介绍

为什么 XGBoost 如此受欢迎?

  1. 速度和性能:最初是用 C++ 编写的,它比其他集成分类器要快。
  2. 核心算法是可并行化的:因为核心 XGBoost 算法是可并行化的,它可以利用多核计算机的力量。它还可以在 GPU 上和跨计算机网络上并行化,从而也可以在非常大的数据集上进行训练。
  3. 始终优于其他算法方法:它在各种机器学习基准数据集上表现出更好的性能。
  4. 多种调优参数:XGBoost 内部具有交叉验证、正则化、用户定义的目标函数、缺失值、树参数、scikit-learn 兼容 API 等参数。

XGBoost(Extreme Gradient Boosting)属于提升算法家族,其核心使用梯度提升(GBM)框架。它是一个优化的分布式梯度提升库。

什么是梯度提升?

  1. 在组合模型的梯度提升中,使用梯度下降将损失函数最小化。从技术上讲,损失函数可以说是误差,即预测值与实际值之间的差异。当然,误差越小,机器学习模型就越好。
  2. 梯度提升是一种创建新模型的方法,该模型预测先前模型的残差或误差,然后将它们加在一起以进行最终预测。
  • XGBoost 带有一个额外的随机化参数,可以降低树之间的相关性。分类器树之间的较少相关性转化为分类器集合的更好性能。
  • XGBoost 通过正则化校正复杂模型来解决过拟合问题。正则化梯度提升也是一种选择,同时考虑了 L1 正则化和 L2 正则化。
  • 在增强处理性能时,该算法在 CPU 中使用多个内核。该算法利用 CPU 中的所有内核并行生成多个决策树。
  • 该系统被设计为块状结构,这使得数据的布局可以在后续迭代中重复使用,而不是重新计算。

4.6 XGBoost 实现

与 AdaBoost 不同的是,XGBoost 有一个独立的库,自己pip安装。在导入库和创建 的实例XGBClassifier之前,让我们看一下调用该XGBClassifier方法所需的一些参数。

  1. max_depth:基础学习者的树的最大深度。
  2. learning_rate:XGBooster 的学习率。
  3. verbosity: 详细程度。有效值介于 0(静默)和 3(调试)之间。
  4. objective:要使用的学习目标。
  5. booster:要在和gbtree中选择的助推器。gblineardart
  6. tree_method:要使用的树方法。最保守的选项设置为默认值。
  7. n_jobs:并行线程数。
  8. gamma:在树的叶节点上进行另一次分裂所需的最小损失减少。
  9. reg_alpha: XGBoost 权重的 L1 正则化项。
  10. reg_lambda: XGBoost 权重的 L2 正则化项。
  11. base_score:初始预测(也称为全局偏差)。
  12. random_state:随机数种子。
  13. importance_type:要关注的功能;gain, weight,或. _
    cover_total_gaintotal_cover

第八步:继续接着上面小结的模型进行实现:搭建模型、训练模型、评估模型。

#  pip install XGBoost
from xgboost import XGBClassifier
model= XGBClassifier(n_estimators = 1000, learning_rate = 0.05) # 创建模型
xgboost=model.fit(X_train, Y_train, early_stopping_rounds = 5, eval_set = [(X_test, Y_test)],verbose = False) # 训练模型
score_xgb = xgboost.score(X_test,Y_test) # 评估
score_xgb

如下:

1.0

五、结论

本文简要介绍了两种流行的集成方法 - bagging 和 boosting,并解释了它们的区别。从技术角度讨论了 AdaBoost 和 XGBoost 算法,对方法进行了简要讨论并进行了编码。

鼓励读者运行代码位,并鼓励调整参数以获得更高的准确性。最后,希望读者不要将他们关于提升算法的知识限制在本文中,并鼓励读者阅读其他资源以扩大他们对该主题的视野。

机器学习(九):集成学习(bagging和boosting),随机森林、XGBoost、AdaBoost相关推荐

  1. [白话解析] 通俗解析集成学习之bagging,boosting 随机森林

    [白话解析] 通俗解析集成学习之bagging,boosting & 随机森林 0x00 摘要 本文将尽量使用通俗易懂的方式,尽可能不涉及数学公式,而是从整体的思路上来看,运用感性直觉的思考来 ...

  2. 树模型系列之集成学习(Bagging、Boosting、Stacking)

    文章目录 树模型系列之集成学习(Bagging.Boosting.Stacking) bagging Boosting Stacking 偏差与方差 集成学习的偏差与方差 Bagging 的偏差与方差 ...

  3. 集成学习——Bagging、Boosting、Stacking

    目录 偏差与方差 投票法 集成学习 Bagging Bootstraps Bagging Boosting 基本概念 Adaboost 前向分步算法 梯度提升树(GBDT) XGBoost Light ...

  4. 集成学习-Bagging和Boosting算法

    文章目录 集成学习 Bagging 随机森林 Bosting Adaboost GBDT XGBoost 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到网 ...

  5. 机器学习入门(五):集成学习Bagging,Boosting,RandomForest和GridSearchCV参数调优

    0)集成学习 集成学习(ensemble methods)的目的是结合不同的分类器,生成一个meta-classifier, 从而使其拥有比单个classifier有更好的泛化能力(The goal ...

  6. 集成学习Bagging和Boosting算法总结

    一.集成学习综述 1.集成方法或元算法是对其他算法进行组合的一种方式,下面的博客中主要关注的是AdaBoost元算法.将不同的分类器组合起来,而这种组合结果被称为集成方法/元算法.使用集成算法时会有很 ...

  7. 【IM】关于集成学习Bagging和Boosting的理解

    集成学习在各大比赛中非常流程,如XGboost.LGBM等,对其基学习器决策树及其剪枝等,可参考: https://blog.csdn.net/fjssharpsword/article/detail ...

  8. 集成学习(一)——随机森林以及GBDT

    文章目录 一.bagging 随机森林 二.boosting 1.Adaboost sklearn实现AdaBoost 2.GBDT (1)Regression Decision Tree:回归树 ( ...

  9. 机器学习基础 集成学习基础(Boosting+Adaboost+GBDT)

    文章目录 一.Boosting 1. 什么是boosting 2. 实现过程: 3. bagging集成与boosting集成的区别: 4. AdaBoost介绍 4.1 构造过程细节 4.2 关键点 ...

  10. 【机器学习】集成学习--Bagging

    1. 概述 Bagging也叫做bootstrap aggregating,是在原始数据集选择S次后得到S个新数据集的一种技术.是一种有放回抽样.如图: 2. 示例 3. 算法流程        Ba ...

最新文章

  1. html登录界面cookie,HTML中使用cookie保存登录账户
  2. Repeater鼠标经过变色
  3. Eval()特殊绑定
  4. Ubuntu 19.10 发布 | 云原生生态周报 Vol. 24
  5. PCB线宽与电流的关系
  6. linux中UDP程序流程、客户端、服务端
  7. 枚举类型 c# 1201
  8. 7-137 凯撒密码 (20 分)
  9. raspberry pi_使用Kubernetes在Raspberry Pi上进行集群计算
  10. C# interface 理解 数据库统一接口
  11. 我从吴恩达课堂演讲中学到的一些建议
  12. BZOJ3437 小P的牧场
  13. [转]linux命令技巧
  14. jQuery EasyUI API 中文文档 - 数值微调器(NumberSpinner)
  15. suse linux11安装 dhcp,Suse Linux DHCP的设定过程
  16. matlab导入arcgis中国边界图,【干货】ArcGIS提取影像边界的几种方法
  17. 安卓计算机切换用户,电脑模拟器小米游戏怎么切换账号
  18. [Linux]正则表达式和grep使用
  19. 建筑装饰毕业论文题目
  20. stm32幂指数运算时的错误显示与解决方案

热门文章

  1. unity学习笔记-特效篇
  2. 怎么免费把PDF转成Word?PDF转Word的软件有哪些?
  3. 软件测试常用工具总结(测试管理、单元测试、接口测试、自动化测试、性能测试、负载测试...)
  4. Java学习DAY8~类和对象(一)~2021.01.17
  5. 进攻即是最好的防御!19 个练习黑客技术的在线网站
  6. 明日书院:毛笔字临帖注意六大章法关系 以尺牍为例
  7. 无锡换社保卡的流程(旧社保卡在手上)
  8. 微信小程序中Vant Weapp的引用与使用
  9. window的pip命令
  10. Android项目实战记录