1. 集成学习的思想

对于训练集数据,我们通过训练若干个个体学习器,通过一定的结合策略,就可以最终形成一个强学习器,以达到博采众长的目的。
集成学习(Ensemble learning)可以用于分类问题集成,回归问题集成,特征选取集成,异常点检测集成等等。
Q1:如何获得若干个个体学习器
Q2:采用什么样的结合策略

2. 集成学习-个体学习器

不稳定的学习器更适合作为基学习器,因为不稳定的学习器容易受到样本分布的影响(方差大),很好的引入了随机性,这有助于在集成学习中提升模型的泛化能力

2.1 同质学习器(常用)

比如都是决策树个体学习器,或者都是神经网络个体学习器。

  • 强依赖同质学习器
    个体学习器之间存在强依赖关系,一系列个体学习器基本都需要串行生成,代表算法是boosting系列算法,Boosting主要关注降低偏差,因此Boosting能基于泛化性能相当弱的学习器构建出很强的集成;

  • 无依赖同质学习器
    个体学习器之间不存在强依赖关系,一系列个体学习器可以并行生成,代表算法是bagging随机森林系列算法,Bagging主要关注降低方差,因此它在不剪枝的决策树、神经网络等学习器上效用更为明显。

2.2 异质学习器

对训练集采用支持向量机个体学习器,逻辑回归个体学习器和朴素贝叶斯个体学习器来学习,再通过某种结合策略(如stacking)来确定最终的分类强学习器。

3. 集成学习-结合策略

  • 平均法
    对于若干个弱学习器的输出进行平均得到最终的预测输出。
  • 投票法
    相对多数投票法、绝对多数投票法、加权多数投票法
  • 学习法
    代表方法是stacking(常用于异质集成),当使用stacking的结合策略时, 我们不是对弱学习器的结果做简单的逻辑处理,而是再加上一层学习器,也就是说,我们将训练集弱学习器的学习结果作为输入,将训练集的输出作为输出,重新训练一个学习器来得到最终结果。在这种情况下,我们将弱学习器称为初级学习器,将用于结合的学习器称为次级学习器

4. 集成学习算法

4.1 boosting

Boosting系列算法里最著名算法主要有AdaBoost算法和提升树(boosting tree)系列算法。提升树系列算法里面应用最广泛的是梯度提升树(Gradient Boosting Tree)。

4.1.1 boosting原理

  • 先从初始训练集训练出一个基学习器
  • 再根据基学习器的表现对训练样本分布进行调整(数据加权),使得先前基学习器做错的训练样本在后续受到更多关注;
  • 基于调整后的样本分布来训练下一个基学习器;
  • 重复进行上述步骤,直至基学习器数目达到事先指定的值T,最终将这T个基学习器进行加权结合

Q1:如何计算第k个弱分类器在训练集上的学习误差率eke_kek​
Q2:如何由学习误差率eke_kek​更新第k个弱分类器的权重系数αk\alpha_kαk​
Q3:如何更新训练集上的样本权重D
Q4:使用何种结合策略

4.1.2 boosting基分类器

对于Boosting来说,每一步我们都会在上一轮的基础上更加拟合原数据,所以可以保证偏差小,所以对于每个基分类器来说,问题就在于如何选择方差更小的分类器(即更简单的分类器),所以我们选择了深度很浅的决策树。

为什么使用决策树作为基学习器/ 基学习器有什么特点

(1). 决策树的表达能力和泛化能力,可以通过剪枝快速调整;
(2). 决策树可以方便地将样本的权重整合到训练过程中;
(3). 决策树是一种不稳定的学习器;

为什么不稳定的学习器更适合作为基学习器?
  • 所谓不稳定,指的是数据样本的扰动会对学习器的结果产生较大的影响;
  • 不稳定的学习器容易受到样本分布的影响(方差大),很好的引入了随机性;这有助于在集成学习(特别是采用 Bagging 策略)中提升模型的泛化能力
  • 为了更好的引入随机性,有时会随机选择一个属性子集中的最优分裂属性,而不是全局最优(随机森林
还有哪些模型也适合作为基学习器?

神经网络也属于不稳定的学习器,通过调整神经元的数量、网络层数,连接方式初始权重也能很好的引入随机性和改变模型的表达能力和泛化能力。

4.1.3 boosting系列算法之AdaBoost算法

Adaboost算法的特点是通过迭代每次学习一个基分类器,在每次迭代中,提高那些被前一轮分类器错误分类的样本权值,降低那些被正确分类的样本权值。最后,将这些基分类器的线性组合作为强分类器,其中给分类误差率小的基分类器以大的权值,给分类误差率大的基分类器以小的权值。简单点说:Adaboost 是让“错分的样本权重越来越大,使它们更被重视”。

一般来说,使用最广泛的Adaboost弱学习器是决策树和神经网络。对于决策树,Adaboost分类用了CART分类树,而Adaboost回归用了CART回归树。


Adaboost是模型为加法模型,学习算法为前向分步学习算法,损失函数为指数函数的分类问题。上述公式均可由其损失函数推导得出,详情见参考教程。

Adaboost的优点

1)Adaboost作为分类器时,分类精度很高

2)在Adaboost的框架下,可以使用各种回归分类模型来构建弱学习器,非常灵活。

3)作为简单的二元分类器时,构造简单,结果可理解。

4)不容易发生过拟合

Adaboost的缺点

对异常样本敏感,异常样本在迭代中可能会获得较高的权重,影响最终的强学习器的预测准确性。

4.1.4 boosting系列算法之提升树

提升树是以决策树(分类树或回归树)为基分类器,采用加法模型与前向分布算法的提升方法。由于树的线性组合可以很好地拟合训练数据,即使数据中的输入与输出之间的关系很复杂也是如此,所以提升树是一个高功能的学习算法。

提升树模型可以表示为决策树的加法模型:fm(x)=∑m=1MT(x;θm)f_m(x)=\sum_{m=1}^MT(x;\theta_m)fm​(x)=m=1∑M​T(x;θm​)其中,T(x;θm)T(x;\theta_m)T(x;θm​)表示决策树;θm\theta_mθm​为决策树的参数;M为树的个数。

回归问题提升树使用以下前向分步算法:
f0(x)=0f_0(x)=0f0​(x)=0fm(x)=fm−1(x)+T(x;θm)m=1,...Mf_m(x)=f_{m-1}(x)+T(x;\theta_m)\quad m=1,...Mfm​(x)=fm−1​(x)+T(x;θm​)m=1,...MfM(x)=∑m=1MT(x;θm)f_M(x)=\sum_{m=1}^MT(x;\theta_m)fM​(x)=m=1∑M​T(x;θm​)在前向分步算法的第m步,给定当前模型fm−1(x)f_{m-1}(x)fm−1​(x),需求解θ^m=argminθm∑i=1NL(yi,fm−1(xi)+T(xi;θm))\hat\theta_m=argmin_{\theta_m}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+T(x_i;\theta_m))θ^m​=argminθm​​i=1∑N​L(yi​,fm−1​(xi​)+T(xi​;θm​))得到θ^m\hat\theta_mθ^m​,即第m棵树的参数。

常用损失函数
  • 分类问题

    • 指数损失L(y,f(x))=exp(−yf(x))L(y,f(x))=exp(-yf(x))L(y,f(x))=exp(−yf(x))
    • 对数损失L(y,f(x)=−∑k=1Kyklogpk(x)L(y,f(x)=-\sum_{k=1}^Ky_klogp_k(x)L(y,f(x)=−k=1∑K​yk​logpk​(x)K是类别数
  • 回归问题
    • 均方损失L(y,f(x))=(y−f(x))2L(y,f(x))=(y-f(x))^2L(y,f(x))=(y−f(x))2
    • 绝对损失L(y,f(x))=∣y−f(x)∣L(y,f(x))=|y-f(x)|L(y,f(x))=∣y−f(x)∣

以均方损失为例,L(yi,fm−1(xi)+T(xi;θm))=[y−fm−1(x)−T(x;θm)]2=[r−T(x;θm)]2L(y_i,f_{m-1}(x_i)+T(x_i;\theta_m))=[y-f_{m-1}(x)-T(x;\theta_m)]^2=[r-T(x;\theta_m)]^2L(yi​,fm−1​(xi​)+T(xi​;θm​))=[y−fm−1​(x)−T(x;θm​)]2=[r−T(x;θm​)]2其中,rm=y−fm−1(x)r_m=y-f_{m-1}(x)rm​=y−fm−1​(x)表示当前模型拟合数据的残差,通过拟合残差rmi(i=1,2,...,N)r_{mi}(i=1,2,...,N)rmi​(i=1,2,...,N)学习一个回归树,得到T(x;θm)T(x;\theta_m)T(x;θm​),从而可以更新fm(x)f_m(x)fm​(x)

4.1.4.1 梯度提升GBDT(Gradient Boosting Decison Tree)

当损失函数是平方损失和指数损失函数时,每一步优化是很简单的。但对于一般损失函数而言,每一步的优化并不容易。
于是就有了梯度提升算法,这是利用最速下降法的近似方法,关键在于利用损失函数的负梯度在当前模型的值作为残差的近似值,拟合一个回归树。−[∂L(y,f(xi))∂f(xi)]f(x)=fm−1(x)-[\frac{\partial L(y,f(x_i))}{\partial f(x_i)}]_{f(x)=f_{m-1}(x)}−[∂f(xi​)∂L(y,f(xi​))​]f(x)=fm−1​(x)​

GBDT每一次的计算是为了减少上一次的残差,而为了消除残差,我们可以在残差减少的梯度方向上建立一个新的模型。所以说,在GBDT中,每个新模型的建立是为了使得之前模型的残差往梯度方向减少。

GBDT的优点
  • 非线性变换比较多,表达能力强
  • 不需要做复杂的特征工程和特征变换
GBDT的缺点
  • Boost是一个串行过程,不好并行化,计算复杂度高
  • 不太适合高维稀疏特征。

GBDT和基于树的adaboost的区别
1、相同点:
加性模型+前向分步算法
每一步训练一个弱学习器以弥补前面模型的不足
2、不同点:
Adaboost的迭代是重点拟合那些之前分错的样本,让“错分的样本权重越来越大,使它们更被重视”。
GBDT则是直接用梯度拟合残差,没有样本权重的概念。

4.1.4.2 XGB:GBDT的C++实现

xgboost(XGB) 是GBDT的一个c++实现,能自动利用cpu的多线程,而且适当改进了GBDT,加了剪枝,控制了模型的复杂程度。因而在计算速度和准确率上,较GBDT有明显的提升。

xgboost的优点
  • 自动利用cpu的多线程进行并行:这是XGBoost最大的特点!
  • 支持线性分类器: 传统GBDT只能以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)
  • 对代价函数作二阶展开:传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数,精度更高。
  • 支持自定义代价函数:只要函数可一阶和二阶求导。
  • 加入正则项:主要是对树模型的复杂度(树的叶子数和叶子分数)做惩罚,确保了树模型的简单性,防止过拟合。
  • 节点分裂算法:利用局部近似算法对分裂节点的贪心算法优化,取适当的eps时,可以保持算法的性能且提高算法的运算速度。
  • 支持列抽样:借鉴了随机森林的做法,不仅能降低过拟合,还能减少计算。
  • 缺失值处理:对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。
  • 样本预排序:样本数据事先排好序并以block的形式存储,利于并行计算
xgboost的缺点
  • 样本预排序需要消耗很多的内存空间(2 * #data * # features)
  • 数据分割点上,由于XGB对不同的数据特征使用pre-sorted算法而不同特征其排序顺序是不同的,所以分裂时需要对每个特征单独做依次分割,遍历次数为#data * #features来将数据分裂到左右子节点上。
  • 尽管使用了局部近似计算,但是处理粒度还是太细
  • 由于pre-sorted处理数据,在寻找特征分裂点时(level-wise),会产生大量的cache随机访问

参考:
『我爱机器学习』集成学习(三)XGBoost - 细语呢喃

4.1.4.3 LightGBM

LightGBM 是一个梯度 boosting 框架, 使用基于学习算法的决策树. 它是分布式的, 高效的, 装逼的。相比较XGB,LightGBM 速度更快,内存消耗更低。

LightGBM的主要特性
  • 速度和内存使用的优化
    许多提升工具对于决策树的学习使用基于 pre-sorted 的算法(例如,在xgboost中默认的算法) ,这是一个简单的解决方案,但是不易于优化。LightGBM 利用基于 histogram 的算法,通过将连续特征(属性)值分段为 discrete bins 来加快训练的速度并减少内存的使用。
  • 稀疏优化
    对于稀疏的特征仅仅需要 O(2 * #non_zero_data) 来建立直方图
  • 准确率的优化
    • Leaf-wise (Best-first) 的决策树生长策略:选取具有最大 delta loss 的叶节点来生长

      • 当生长相同的 #leaf,leaf-wise 算法可以比 level-wise 算法减少更多的损失。
      • 当 #data 较小的时候,leaf-wise 可能会造成过拟合。 所以,LightGBM 可以利用额外的参数 max_depth 来限制树的深度并避免过拟合。
    • 类别特征值的最优分割:根据训练目标的相关性对类别进行重排序
      • 我们通常将类别特征转化为 one-hot coding。 然而,对于学习树来说这不是个好的解决方案。 原因是,对于一个基数较大的类别特征,学习树会生长的非常不平衡,并且需要非常深的深度才能来达到较好的准确率。
      • LightGBM则是根据训练目标的相关性对类别进行重排序。 更具体的说,根据累加值(sum_gradient / sum_hessian)重新对(类别特征的)直方图进行排序,然后在排好序的直方图中寻找最好的分割点。
  • 网络通信的优化
    LightGBM 实现了 state-of-art 算法, 这些聚合通信算法可以提供比点对点通信更好的性能。
  • 并行学习的优化
    • 特征并行
    • 数据并行
    • 投票并行
  • GPU 支持可处理大规模数据

参考:LightGBM 中文文档
http://lightgbm.apachecn.org/#/

4.1.4.4 ThunderGBM:快成一道闪电的梯度提升决策树

尽管 XGBoost 等库已经支持 GPU 了,但毕竟不是一开始就为 GPU 而设计的,因此在优化和加速上会有一些瑕疵。而 ThunderGBM 旨在帮助用户轻松高效地应用 GBDT 和随机森林来解决问题,它可以利用 GPU 完成高效训练。

ThunderGBM的主要特性
  • 速度通常是其它库的 10 倍。
  • 支持 Python(scikit-learn)接口。
  • 支持操作系统 Linux。
  • 支持分类、回归和排序。

4.2 bagging

Bagging是引导聚合的意思。 通过对 n 个独立不相关的模型预测结果取平均,来减少估计方差(方差是原来的1/n)

对于Bagging需要注意的是,每次训练集可以取全部的特征进行训练,也可以随机选取部分特征训练,例如随机森林就是每次随机选取部分特征。

bagging的个体弱学习器的训练集是通过随机采样得到的。通过T次的随机采样,我们就可以得到T个采样集,对于这T个采样集,我们可以分别独立的训练出T个弱学习器,再对这T个弱学习器通过集合策略来得到最终的强学习器。通常分类任务使用投票的方式集成,而回归任务通过平均的方式集成。

随机采样:
一般采用的是自助采样法(bootstrap),即对于m个样本的原始训练集,我们每次先随机采集一个样本放入采样集,接着把该样本放回,也就是说下次采样时该样本仍有可能被采集到,这样采集m次,最终可以得到m个样本的采样集,由于是随机采样,这样每次的采样集是和原始训练集不同的,和其他采样集也是不同的,这样得到多个不同的弱学习器。m次采样都没有被采集中的概率:(1−1m)m→1e=36.8%(1-\frac{1}{m})^m\to\frac{1}{e}=36.8\%(1−m1​)m→e1​=36.8%这36.8%的数据称为袋外数据,它们没有参与训练集模型的拟合,因此可以用来检测模型的泛化能力。

4.3 随机森林

随机森林就是通过集成学习的思想将多棵决策树集成的一种算法,是bagging的一个特化进阶版,所谓的特化是因为随机森林的弱学习器都是决策树。所谓的进阶是随机森林在bagging的样本随机采样基础上,又加上了特征的随机选择,其基本思想没有脱离bagging的范畴。

RF的算法思路
  1. 样本的随机:从样本集中用自助采样法随机选取n个样本

  2. 特征的随机:从所有属性中随机选取K个属性,选择最佳分割属性作为节点建立CART决策树(泛化的理解,这里面也可以是其他类型的分类器,比如SVM、Logistics)

  3. 重复以上两步m次,即建立了m棵CART决策树

  4. 这m个CART形成随机森林,通过投票表决结果,决定数据属于哪一类(投票机制有一票否决制、少数服从多数、加权多数)

在随机森林中,每个树模型都是随机采样训练的。另外,特征也是随机选择的,最后对于训练好的树也是随机选择的。这种处理的结果是随机森林的偏差增加的很少,而由于弱相关树模型的平均,方差也得以降低,最终得到一个方差小,偏差也小的模型。

RF的主要优点

1) 训练可以高度并行化,对于大数据时代的大样本训练速度有优势。个人觉得这是的最主要的优点。

2) 由于可以随机选择决策树节点划分特征,这样在样本特征维度很高的时候,仍然能高效的训练模型。

3) 在训练后,可以给出各个特征对于输出的重要性

4) 由于采用了随机采样,训练出的模型的方差小,泛化能力强。

5) 相对于Boosting系列的Adaboost和GBDT, RF实现比较简单

6) 对部分特征缺失不敏感。

RF的主要缺点

1)在某些噪音比较大的样本集上,RF模型容易陷入过拟合

2) 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。

4.4 stacking


Stacking是指训练一个模型用于组合(combine)其他各个模型,即首先我们先训练多个不同的基础模型(基础模型利用整个训练集做训练),然后再以之前训练的各个基础模型的输出为输入来训练一个元模型(元模型将基础模型的特征作为特征进行训练),以得到一个最终的输出。在实际应用中,我们通常使用单层logistic回归作为组合模型。通过一个元分类器或者元回归器来整合多个分类模型或回归模型的集成学习技术。由于基础模型通常包含不同的学习算法,因此stacking通常是异质集成。

Stacking被Kaggle竞赛获奖者广泛使用。例如,Otto Group Product分类挑战赛的第一名通过对30个模型做stacking赢得了冠军。他将30个模型的输出作为特征,继续在三个模型中训练,这三个模型XGBoost,Neural Network和Adaboost,最后再加权平均。详见文章。

参考教程

  • 集成学习原理小结 - 刘建平Pinard - 博客园
    https://www.cnblogs.com/pinard/p/6131423.html
  • 集成学习之Adaboost算法原理小结 - 刘建平Pinard - 博客园
    https://www.cnblogs.com/pinard/p/6133937.html
  • 梯度提升树(GBDT)原理小结 - 刘建平Pinard - 博客园
    https://www.cnblogs.com/pinard/p/6140514.html
  • [机器学习] Boosting算法 — AdaBoost、GBDT与XGBoost - 努力奋斗的小墨鱼专栏 - CSDN博客
    https://blog.csdn.net/zwqjoy/article/details/80424783
  • 机器学习研究会订阅号
    https://mp.weixin.qq.com/s?__biz=MzU1NTUxNTM0Mg==&mid=2247490516&idx=2&sn=df2b11c4ed994264d6e33b8f56cb1a36&chksm=fbd27775cca5fe6398b7a0dbc29edcd063e8e95ec6f815037fe34ecc91d5f8fc07e7e6c84916&mpshare=1&scene=1&srcid=#rd

【ML小结10】集成学习相关推荐

  1. 秦州:西瓜书 + 南瓜书 吃瓜系列 10. 集成学习(下)

    Datawhale南瓜书是经典机器学习教材<机器学习>(西瓜书)的公式推导解析指南,旨在让在学习西瓜书的过程中,再也没有难推的公式,学好机器学习. 航路开辟者:谢文睿.秦州 开源内容:ht ...

  2. 机器学习集成学习算法

    目录 1 集成学习算法简介 1.1 什么是集成学习 1.2 机器学习的两个核心任务 1.3 集成学习中boosting和Bagging 1.4 小结 2 Bagging和随机森林 2.1 Baggin ...

  3. ML之回归预测:利用Lasso、ElasticNet、GBDT等算法构建集成学习算法AvgModelsR对国内某平台上海2020年6月份房价数据集【12+1】进行回归预测(模型评估、模型推理)

    ML之回归预测:利用Lasso.ElasticNet.GBDT等算法构建集成学习算法AvgModelsR对国内某平台上海2020年6月份房价数据集[12+1]进行回归预测(模型评估.模型推理) 目录 ...

  4. 集成学习框架-学习小结20161121

    1 参数可分为两种,一种是影响模型在训练集上的准确度或是影响防止过拟合能力的参数:另外一种是不影响这两者的其他参数.模型在样本总体上的准确度(后简称准确度)由其在训练集上的准确度及其防止过拟合的能力所 ...

  5. 集成学习原理小结(转载)

    集成学习(ensemble learning)可以说是现在非常火爆的机器学习方法了.它本身不是一个单独的机器学习算法,而是通过构建并结合多个机器学习器来完成学习任务.也就是我们常说的"博采众 ...

  6. [Hands On ML] 7. 集成学习和随机森林

    文章目录 1. 投票分类 2. Bagging.Pasting 3. Out of Bag 评价 4. 随机贴片与随机子空间 5. 随机森林 6. 极端随机树 Extra-Trees 7. 特征重要程 ...

  7. 周志华教授力作,豆瓣10分好评,集成学习如何破解AI实践难题 | 赠书

    本文内容节选自<集成学习:基础与算法>一书.由南京大学人工智能学院院长周志华教授编著,中文版由其学生李楠博士翻译. 回顾机器学习最近30 年的发展历程,各种学习方法推陈出新.不断演进.但是 ...

  8. ML之mlxtend:基于iris鸢尾花数据集利用逻辑回归LoR/随机森林RF/支持向量机SVM/集成学习算法结合mlxtend库实现模型可解释性(决策边界可视化)

    ML之mlxtend:基于iris鸢尾花数据集利用逻辑回归LoR/随机森林RF/支持向量机SVM/集成学习算法结合mlxtend库实现模型可解释性(决策边界可视化) 目录 相关文章 ML之mlxten ...

  9. ML《集成学习(二)Boosting之Adaboosting》

    一:集成学习 集成学习通过构建并结合多个学习器来完成学习任务,有时也被称为多分类器系统.基于委员会的学习等.集成学习通过将多个学习器进行结合,常可获得比单一学习器显著优越的泛化性能,也就是平常所说的& ...

  10. ML《集成学习(一)Bagging 和 Random Forest》

    今天一起来学习集成学习,其中的Bagging和随机森林(Random Forest). 一:bootstrap 二:Bagging 三:随机森林(Random Forest)

最新文章

  1. 零代价修复海量服务器的内核缺陷——UCloud内核热补丁技术揭秘
  2. 计算机c语言试题文档,c语言计算机考试试题
  3. python每天1道面试题(3)--字符串组合
  4. python基础教程(十一)
  5. Access denied for user 'root'@'localhost' (using password: YES) 问题解决小记
  6. 现在有一个map集合如下: Map<Integer,String> map = new HashMap<Integer, String>(); map.put(1, “
  7. Java编程实现静态多态,java基础--多态-域与静态方法1(java编程思想)
  8. 大唐波斯将军 机器人_跑到大唐的萨珊波斯遗民
  9. Android 应用开发(38)TableLayout(表格布局)
  10. python学习笔记(十一)-python程序目录工程化
  11. visual studio 图标_知识内容创作者必会:如何一键获取苹果软件图标?
  12. ubuntu mongodb安装
  13. js获取ip地址、浏览器信息
  14. DellR740制作Raid0
  15. QQ.COM二级域名大全 腾讯旗下产品大全
  16. Python刷题系列(8)_Pandas_Dataframe
  17. java线程池newfi_Java进阶——线程与多线程
  18. 对Slim 框架进行总结
  19. 支付--支付宝手机网站支付(WAP)
  20. 数据结构课程设计-(五)行车路线(图的应用)

热门文章

  1. 华为三层交换机-路由-硬件防火墙的配置
  2. [C++]面向对象部分——类
  3. String的replaceAll方法中的正则表达式用法
  4. 温故知新----css盒模型
  5. linux ftdi 虚拟,linux – 由FTDI USB串行转换器创建的监控(嗅探)/ dev / ttyUSB0
  6. javascript高级程序设计pdf_Java、C语言、Python、PHP、JavaScript五大编程语言,要学哪个?...
  7. C程序设计--结构体+单向链表
  8. python内置对象的实现_Python面向对象——内置对象的功能扩展
  9. php 图像居中裁剪函数,php中自定义图像居中裁剪函数实现的代码案例
  10. Neo4j之下载安装:windows