从决策树到xgboost(二)

文章目录

  • 3 集成学习
  • 4 Adaboost
    • 4.1 Adaboost算法
      • 4.1.1 初始化训练数据的起始权值分布
      • 4.1.2 对m个弱分类器m=1,2,3...M
      • 4.1.3 构建弱分类器的线性组合
      • 4.1.4 得到最终的分类器
  • 5 Boosting
    • 5.1 加法模型
    • 5.2 前向分布算法
  • 6 提升决策树BDT
    • 6.1 BDT算法
    • 6.2 回归问题提升树
  • 7 梯度提升决策树GBDT
  • 8 极限梯度提升XGboost
    • 8.1 GBDT的问题
    • 8.2 重新定义树模型
    • 8.3 提升决策树

3 集成学习

所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果。通俗比喻就是“三个臭皮匠赛过诸葛亮”,或一个公司董事会上的各董事投票决策,它要求每个弱分类器具备一定的“准确性”,分类器之间具备“差异性”。

集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:

Boosting流派,各分类器之间有依赖关系,必须串行,比如Adaboost、GBDT(Gradient Boosting Decision Tree)、Xgboost。是一个迭代学习的过程,用于自适应地改变训练样本的分布,使得基分类器聚焦在那些很难分的样本上。对错误的样本重点学习,准确率会更高。

Bagging流派,各分类器之间没有依赖关系,可各自并行,比如随机森林(Random Forest)。是一个自助聚集过程,是一种根据均匀概率分布从数据中重复抽样的技术。选择训练集之后,单独训练每个分类器。最后的结果由投票决定。对每个样本的学习是均等的,所以有更低的方差,也就是更好的稳定性。

而著名的Adaboost作为boosting流派中最具代表性的一种方法。

4 Adaboost

AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。

Adaboost的两个问题:
1 每一轮如何改变训练数据的权值:提高那些被前一轮弱分类器错误分类样本的权值,降低那些被正确分类样本的权值。
2 如何将弱分类器组合成一个强分类器:加权多数表决,加大分类误差率小的弱分类器的权值,使其在表决中起较大的作用,减小分类误差率大的弱分类器的权值,使其在表决中起较小的作用。

4.1 Adaboost算法

输入:二分类的数据训练集T={(x1,y1),(x2,y2)...(xN,yN)}T=\{(x_1,y_1),(x_2,y_2)...(x_N,y_N)\}T={(x1,y1),(x2,y2)...(xN,yN)}
yi∈y={−1,+1}y_i \in y=\{-1,+1\}yiy={1,+1}

输出:最终分类器G(X)

4.1.1 初始化训练数据的起始权值分布

D1=(w11,w12,...w1N)D_1=(w_{11},w_{12},...w_{1N})D1=(w11,w12,...w1N),w1i=1Nw_{1i}=\dfrac{1}{N}w1i=N1
这个代表第一轮的权值分布。

4.1.2 对m个弱分类器m=1,2,3…M

  1. 在权值DmD_mDm下训练数据集,得到弱分类器
    Gm(X)−>{+1,−1}G_m(X)->\{+1,-1\}Gm(X)>{+1,1}
    这里并没有指定若分类器的具体模型。也就是说哪种模型都可以。
  2. 计算GmG_mGm的训练误差
    em=P(Gm(xi)≠yi)=∑i=1nwmiI(Gm(xi)≠yi)e_m=P(G_m(x_i)\ne y_i)=\sum_{i=1}^nw_{mi}I(G_m(x_i)\ne y_i)em=P(Gm(xi)=yi)=i=1nwmiI(Gm(xi)=yi)

对于分类错误的数据,按照权重计算其损失。也可以称为分类错误率。是当前分类器分类性能的一个指标。

  1. 计算GmG_mGm的系数
    αm=12log1−emem\alpha_m=\dfrac{1}{2}log\dfrac{1-e_m}{e_m}αm=21logem1em

em<=12e_m<=\dfrac{1}{2}em<=21的时候,αm>=0\alpha_m>=0αm>=0。也就是说如果当前分类器,比随机猜测的概率要好。
em>12e_m>\dfrac{1}{2}em>21的时候,αm<0\alpha_m<0αm<0。当前分类器被丢弃。

  1. 更新训练数据集的权值分布
    Dm+1=(wm+1,1,wm+1,2...wm+1,N)D_{m+1}=(w_{m+1,1},w_{m+1,2}...w_{m+1,N})Dm+1=(wm+1,1,wm+1,2...wm+1,N)
    wm+1,i=wmiZmexp(−αmyiGm(xi))=wmiexp(−αmyiGm(xi))Zmw_{m+1,i}=\dfrac{w_{mi}}{Z_m}exp(-\alpha_my_iG_m(x_i))=w_{mi}\dfrac{exp(-\alpha_my_iG_m(x_i))}{Z_m}wm+1,i=Zmwmiexp(αmyiGm(xi))=wmiZmexp(αmyiGm(xi))

如果分对了,那么yiGm(xi)y_iG_m(x_i)yiGm(xi)是一个正数,那么−αmyiGm(xi)-\alpha_my_iG_m(x_i)αmyiGm(xi)就是一个负数。如果分错了,那么−αmyiGm(xi)-\alpha_my_iG_m(x_i)αmyiGm(xi)就是一个正数。
因为exp(正数)>exp(负数)exp(正数)>exp(负数)exp()>exp(),最后除以一个归一化因子,所以相对而言,在分错的情况下,wmiw_{mi}wmi就会占一个比较大的权重。

ZmZ_mZm是归一化因子,Zm=∑i=1Nwmiexp(−αmyiGm(xi))Z_m=\sum_{i=1}^Nw_{mi}exp(-\alpha_my_iG_m(x_i))Zm=i=1Nwmiexp(αmyiGm(xi))

4.1.3 构建弱分类器的线性组合

f(x)=∑m=1MαmGm(x)f(x)=\sum_{m=1}^M\alpha_mG_m(x)f(x)=m=1MαmGm(x)

分类器强,权重就高。

4.1.4 得到最终的分类器

G(x)=sign(f(x))=sign(∑m=1MαmGm(x))G(x)=sign(f(x))=sign(\sum_{m=1}^M\alpha_mG_m(x))G(x)=sign(f(x))=sign(m=1MαmGm(x))

看这里αm\alpha_mαm的作用。
αm\alpha_mαm会随着eme_mem的增加而减少。这是因为如果一个分类器误差率高,那它起得作用就小。
在训练数据权重分配方面,当分类不正确的时候wm+1,i=wm,iZmeαmw_{m+1,i}=\dfrac{w_{m,i}}{Z_m}e^{\alpha_m}wm+1,i=Zmwm,ieαm,当分类正确的时候wm+1,i=wm,iZme−αmw_{m+1,i}=\dfrac{w_{m,i}}{Z_m}e^{-\alpha_m}wm+1,i=Zmwm,ieαm,数值比分配不正确的时候要小。通过正负号,增加错误样本的学习权重。

5 Boosting

5.1 加法模型

f(x)=∑m=1Mβmb(x;rm)f(x)=\sum_{m=1}^M\beta_mb(x;r_m)f(x)=m=1Mβmb(x;rm)
β\betaβ是基函数的系数
bbb是基函数

这个形式和Adaboost一样:f(x)=∑m=1MαmGm(x)f(x)=\sum_{m=1}^M\alpha_mG_m(x)f(x)=m=1MαmGm(x),不同的是学习过程不同。Adaboost是不断调整训练数据集数据的权重学习的。

给定训练数据和损失函数L(y,f(x)),学习加法模型f(x),使用损失函数极小化:minβm,γm∑i=1NL(yi,∑m=1Mβmb(x;rm))min_{\beta_m,\gamma_m} \sum_{i=1}^NL(y_i, \sum_{m=1}^M\beta_mb(x;r_m))minβm,γmi=1NL(yi,m=1Mβmb(x;rm))

寻找使得损失函数最小的βm,γm\beta_m,\gamma_mβm,γm。但是这是一个复杂的优化问题。使用前向分布算法解决。

5.2 前向分布算法

解决思路:根据学习的是加法模型,如果能够从前向后,每一步只学习一个基函数及其系数,逐步逼近优化目标函数。最后累加起来就是学习目标。

每一步的优化的损失函数是:minβ,γ∑i=1NL(yi,βb(xi;γ))min_{\beta,\gamma} \sum_{i=1}^NL(y_i,\beta b(x_i;\gamma))minβ,γi=1NL(yi,βb(xi;γ))
学习M步之后,得到minβm,γm∑i=1NL(yi,∑m=1Mβmb(x;rm))min_{\beta_m,\gamma_m} \sum_{i=1}^NL(y_i, \sum_{m=1}^M\beta_mb(x;r_m))minβm,γmi=1NL(yi,m=1Mβmb(x;rm))

前向分布算法
输入:训练数据集 T={(x1,y1),(x2,y2)....(xN,yN)}T=\{(x_1,y_1),(x_2,y_2)....(x_N,y_N)\}T={(x1,y1),(x2,y2)....(xN,yN)},损失函数L(y,f(x))L(y,f(x))L(y,f(x)),基函数集{b(x;γ)}\{b(x;\gamma)\}{b(x;γ)}
输出:加法模型f(x)

1 初始化f0(x)=0f_0(x)=0f0(x)=0

f0(f)=0f_0(f)=0f0(f)=0是一个函数,是一个效果很差的函数,一个函数就是一个映射。

2 对m=1,2…M
极小化损失函数:(βm,γm)=argminβ,γ∑i=1NL(yi,fm−1(xi)+βb(xi;γ))(\beta_m,\gamma_m)=argmin_{\beta,\gamma}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+\beta b(x_i;\gamma))(βm,γm)=argminβ,γi=1NL(yi,fm1(xi)+βb(xi;γ))得到参数βm,γm\beta_m,\gamma_mβm,γm

这里是一个加法模型,加法模型可以累加。fm−1f_{m-1}fm1是上一轮学习得到的函数。本轮学习的函数是在上一轮函数的基础上加上当前要学习的基函数βb(xi;γ)\beta b(x_i;\gamma)βb(xi;γ)

更新fm(x)=fm−1(x)+βmb(xi;γm)f_m(x)=f_{m-1}(x)+\beta_m b(x_i;\gamma_m)fm(x)=fm1(x)+βmb(xi;γm)

3 得到加法模型
f(x)=∑m=1Mβmb(xi;γm)f(x)=\sum_{m=1}^M\beta_m b(x_i;\gamma_m)f(x)=m=1Mβmb(xi;γm)

可以通过证明:Adaboost是boosting方法的一种特例,是基函数为分类器,损失函数是指数函数的boosting。
那也就是基函数如果为回归函数的话,应该也有一种称呼?

6 提升决策树BDT

如果boosting的基函数是决策树,并且所有基函数的系数都为1,那么成为提升决策树BDT。

BDT被认为是统计学习中性能最好的方法之一。

树可以相加?
什么是一棵树:是对特征空间的划分以及每个划分的输出。树相加就是对重叠区域的进一步划分。
对分类问题,决策树是二叉分类树。
对回归问题,决策树是二叉回归树。

定义:fM(x)=∑m=1MT(x;θm)f_M(x)=\sum_{m=1}^MT(x;\theta_m)fM(x)=m=1MT(x;θm)

6.1 BDT算法

1 确定初始提升树f0(x)=0f_0(x)=0f0(x)=0
2 第m步的模型:fm(x)=fm−1(x)+T(x;θm)f_m(x)=f_{m-1}(x)+T(x;\theta_m)fm(x)=fm1(x)+T(x;θm)
fm−1(x)f_{m-1(x)}fm1(x)是当前模型,通过经验风险极小化确定下一颗决策树的参数θm\theta_mθmθm^=argminθm∑i=1NL(yi,fm−1(xi)+T(xi;θm))\hat{\theta_m}=arg min_{\theta_m}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+T(x_i;\theta_m))θm^=argminθmi=1NL(yi,fm1(xi)+T(xi;θm))

决策树模型。将X划分为J个互不相交的区域R1,R2…RJ。并且在每个空间上确定输出常量cjc_jcj。那么树可以表示为T(x;θ)=∑j=1JcjI(x∈Rj)T(x;\theta)=\sum_{j=1}^Jc_jI(x\in R_j)T(x;θ)=j=1JcjI(xRj)

针对不同问题的提升树,使用的函数不同。回归问题使用平方误差损失;分类问题使用指数损失函数。

当使用平方误差损失函数的时候,
L(y,f(x))=(y−f(x))2=[y−fm−1(x)−T(x;θ)]2=[r−T(x;θ)]2L(y,f(x))=(y-f(x))^2\\ =[y-f_{m-1}(x)-T(x;\theta)]^2\\ =[r-T(x;\theta)]^2L(y,f(x))=(yf(x))2=[yfm1(x)T(x;θ)]2=[rT(x;θ)]2
其中r=y−fm−1(x)r=y-f_{m-1}(x)r=yfm1(x),这可以理解为是在之前模型的残差上学习当前树模型。可以认为当前模型学习的不是y,而是y减去上一次模型已经学好部分,也就是说学习的是上一次模型的残差。每一次学习,学得是之前的模型没有学习好的部分。

6.2 回归问题提升树

输入:训练数据集T={(x1,y1),(x2,y2)...(xN,yN)}T=\{(x_1,y_1),(x_2,y_2)...(x_N,y_N)\}T={(x1,y1),(x2,y2)...(xN,yN)}yi∈yy_i \in yyiy是一个R
输出:提升树fM(x)f_M(x)fM(x)

1 初始化f0(x)=0f_0(x)=0f0(x)=0
2 对m=1,2…M
fm(x)=fm−1(x)+T(x;θm)f_m(x)=f_{m-1}(x)+T(x;\theta_m)fm(x)=fm1(x)+T(x;θm),m=1,2,3…M
计算残差L(y,f(x))=(y−f(x))2=[y−fm−1(x)−T(x;θ)]2=[r−T(x;θ)]2L(y,f(x))=(y-f(x))^2=[y-f_{m-1}(x)-T(x;\theta)]^2=[r-T(x;\theta)]^2L(y,f(x))=(yf(x))2=[yfm1(x)T(x;θ)]2=[rT(x;θ)]2
其中r=y−fm−1(x)r=y-f_{m-1}(x)r=yfm1(x)。这是因为对于第m轮,fm−1(x)f_{m-1}(x)fm1(x)是一个已知的值。

拟合残差学习一个回归树,得到T(x;θ)T(x;\theta)T(x;θ)。拟合残差的过程就是求得:
θm^=argminθm∑i=1NL(yi,fm−1(xi)+T(xi;θm))=argminθm[r−T(x;θ)]2\hat{\theta_m}=arg min_{\theta_m}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+T(x_i;\theta_m))=arg min_{\theta_m}[r-T(x;\theta)]^2θm^=argminθmi=1NL(yi,fm1(xi)+T(xi;θm))=argminθm[rT(x;θ)]2
使得损失函数最小的参数θ\thetaθ

更新fm(x)=fm−1(x)+T(x;θ)f_m(x)=f_{m-1}(x)+T(x;\theta)fm(x)=fm1(x)+T(x;θ)

3 得到回归问题提升树:fM(x)=∑m−1MT(x;θ)f_M(x)=\sum_{m-1}^MT(x;\theta)fM(x)=m1MT(x;θ)

7 梯度提升决策树GBDT

BDT使用一阶梯度学习得到最优参数,称为GBDT。

BDT每次学习的是残差。GBDT是使用f(x)的一阶梯度来学习参数。

利用损失函数的负梯度更新模型:直接对f(x)求偏导,而不是对f(x)的参数θ\thetaθ求偏导。在这里插入图片描述

为什么使用梯度学习参数?
1 函数f(x),是一个从X空间到Y空间的一个映射。这个f(x)可能有很多个。所有的f(x)构成一个假设空间,我们需要从假设空间中查找一个最优的f(x)作为最终的映射。寻找方法可以是平方误差损失最小,或者指数损失函数最小。
2 一般我们在查找最优的f(x)的时候,是通过f(x)的参数空间去寻找,找到最优的参数,就找到了最优的f(x)。例如假设f(x)=wx+b,那么就是寻找使得损失函数最小的w和b。
这是一般情况。
w∗=argminwL(w)w^*=argmin_wL(w)w=argminwL(w)
∂L(w)∂x=0=>w∗=w−α∂L(w)∂x\dfrac{{\partial L(w)}}{{\partial x}}=0=>w*=w-\alpha\dfrac{{\partial L(w)}}{{\partial x}}xL(w)=0=>w=wαxL(w)

找到w∗w^*w,找到最优的f(x)。
那是不是可以直接在假设空间学习f(x)?也是就是∂L(y,f(x))∂f(x)\dfrac{\partial L(y,f(x))}{\partial f(x)}f(x)L(y,f(x))
计算过程就是假设,∂L(y,f(x))∂f(x)=0\dfrac{\partial L(y,f(x))}{\partial f(x)}=0f(x)L(y,f(x))=0
f∗=f−α∂L(y,f(x))∂f(x)f^*=f-\alpha \dfrac{\partial L(y,f(x))}{\partial f(x)}f=fαf(x)L(y,f(x))
假设学习率α=1\alpha=1α=1,那么就是f∗=f−∂L(y,f(x))∂f(x)f^*=f-\dfrac{\partial L(y,f(x))}{\partial f(x)}f=ff(x)L(y,f(x)),也就是函数f(x)-函数的梯度。
最终就变成了使用f(x)梯度的负值,来拟合学习f(x)。

下一个问题:不是所有函数都有参数。看我们的决策树:T(x;θ)=∑j=1JcjI(x∈Rj)T(x;\theta)=\sum_{j=1}^Jc_jI(x\in R_j)T(x;θ)=j=1JcjI(xRj)

梯度提升算法:
在这里插入图片描述

8 极限梯度提升XGboost

XGBoost=eXtreme+GBDT=eXtreme+(Gradient+BDT)=eXtreme+Gradient+(Boosting+DecisionTree)XGBoost = eXtreme + GBDT\\ =eXtreme+(Gradient + BDT)\\ =eXtreme+ Gradient + (Boosting + DecisionTree)XGBoost=eXtreme+GBDT=eXtreme+Gradient+BDT=eXtreme+Gradient+(Boosting+DecisionTree)

8.1 GBDT的问题

GBDT的问题是:1 使用一阶梯度,我们知道如果可以使用二阶梯度那结果会更加准确。2 训练方式是使得经验风险最小化,这就可能会出现过拟合。需要加入正则化项。

8.2 重新定义树模型

训练数据集D={(Xi,yi)}D=\{(X_i,y_i)\}D={(Xi,yi)},其中Xi∈RmX_i \in R^mXiRmyi∈Ry_i \in RyiR,|D|=n
决策树模型:f(X)=wq(X)f(X)=w_{q(X)}f(X)=wq(X)
其中q:RmR^mRm->{1,2,3…T},也就是X到决策树叶子节点编号的映射。w∈RTw \in R^TwRT,是叶子节点向量。T为决策树叶子节点数量。w⃗=(w(1),w(2)...w(T))T\vec{w}=(w^{(1)},w^{(2)}...w^{(T)})^Tw=(w(1),w(2)...w(T))T,每一个元素是叶子节点的预测输出。

这个模型的含义就是:首先有输入XiX_iXi,通过q(X)能够得到叶子节点的编号t。其次,通过访问w[t]能够得到这个叶子节点的预测输出。从而完成从XiX_iXi到输出。

而之前的决策树模型定义为T(X)=∑j=1JcjI(X∈Rj)T(X)=\sum_{j=1}^Jc_jI(X \in R^j)T(X)=j=1JcjI(XRj)
为什么要重新定义决策树?是为了后面做二阶梯度降低难度。这是xgboost第一个精彩的地方。

8.3 提升决策树

提升决策树模型:yi^=ϕ(Xi)=∑k=1Kfk(Xi)\hat{y_i}=\phi(X_i)=\sum_{k=1}^Kf_k(X_i)yi^=ϕ(Xi)=k=1Kfk(Xi),其中fk(x)f_k(x)fk(x)为第k颗决策树。
正则化目标函数:L(ϕ)=∑il(yi,yi^)+∑kΩ(fk)L(\phi)=\sum_{i}l(y_i,\hat{y_i})+\sum_k\Omega(f_k)L(ϕ)=il(yi,yi^)+kΩ(fk)
其中Ω(fk)=γT+12λ∣∣w∣∣2=γT+12∑j=1Twj2\Omega(f_k)=\gamma T+\dfrac{1}{2}\lambda ||w||^2=\gamma T+\dfrac{1}{2}\sum_{j=1}^Tw_j^2Ω(fk)=γT+21λw2=γT+21j=1Twj2

也就是加入正则化项。对树的规模T,以及树的输出wjw_jwj都做了限制。无论模型多么复杂,我们都可以通过约束其系数,降低模型复杂度。

第t轮目标函数,也就是ftf_tft这颗树的正则化目标函数:
L(t)=∑i=1nl(yi,yi^(t−1)+ft(Xi))+Ω(ft)L^{(t)}=\sum_{i=1}^nl(y_i,\hat{y_i}^{(t-1)}+f_t(X_i))+\Omega(f_t)L(t)=i=1nl(yi,yi^(t1)+ft(Xi))+Ω(ft)
根据泰勒公式展示二阶:
在这里插入图片描述
移除常数项之后:
在这里插入图片描述

这个式子中的第一部分是对数据集的遍历,第s三分是对叶子节点的遍历。这种方式不利于计算。
我们考虑对于数据集的遍历,对于每一条数据最终肯定分到某个叶子节点了。所以可以把对数据集的遍历转为对叶子节点的遍历:
定义叶子节点j上的样本的下标集合Ij={i∣q(Xj)=j}I_j=\{i|q(X_j)=j\}Ij={iq(Xj)=j},那么
在这里插入图片描述

举个例子。例如我们班有50名同学。班级有5个小组,每个同学属于一个小组。那如果想点名,叫到每个同学一次。我们可以按照花名册,从1到50点名。我们也可以按照小组,从第1组点到第5组,这样也可以完成对所有同学的点名。

这相当于xgboos第二个精彩的地方。

由于 wj∗=argminwjL~(t)w^*_j=arg min_{w_j} \widetilde{L}^{(t)}wj=argminwjL(t)
∂L~(t)∂wj=0\dfrac{\partial \widetilde{L}^{(t)}}{\partial w_j}=0wjL(t)=0
得到每个叶子节点最优的输出值:wj∗=−∑i∈Ijgi∑i∈Ijhi+λw_j^*=-\dfrac{\sum_{i\in I_j}g_i}{\sum_{i\in I_j}h_i+\lambda}wj=iIjhi+λiIjgi
gig_igihih_ihi是关于t-1轮的函数,所以是可以计算得到的。
带回到上面的式子得到损失函数:
在这里插入图片描述

那怎么确定T呢?在这里以损失函数作为树分裂的依据。假设依据某个特征以及值分裂后得到ILI_LILIRI_RIR左右两个实例集。令I=IL+IRI=I_L+I_RI=IL+IR,则分裂之后的损失减少量:在这里插入图片描述
这个可以作为依据评估待分裂节点。

具体分裂查找的精确贪婪算法:
在这里插入图片描述
特征维度有d个。
第一层先遍历特征维度k从1到d。
根据第k个特征的值,把所有数据集排序。
按照排序后到的数据集遍历,遍历到第j个数据,按照xjkx_jkxjk将数据集分为两部分。
分别计算两部分的损失值。
score保存最大的损失值差。
最终以score最大时候的特征k以及数值xjkx_jkxjk作为树分裂的依据。

因为这里是贪婪算法,所以得到的是局部最优解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423918.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[伤了昨天的心 裂成碎片和沙一起飞]五香里脊

今晨3点挂的电话&#xff0c;6点睁开的眼。困到头痛&#xff0c;但还是烧了道肉菜。…**…**…**…**…**…**…**…*分隔 五香里脊*…**…**…**…**…**…**…**…五香里脊 材料&#xff1a;1&#xff0e;里脊肉、油、麻油。2&#xff0e;蒜末、辣椒末、水、生抽、老醋、糖、…

MOTOMAN-SV3X运动学建模验证图

以下是正解&#xff0c;逆解 结果 转载于:https://www.cnblogs.com/wqj1212/archive/2008/01/01/1022177.html

小程序·云开发实战 - 迷你微博

0. 前言 本文将手把手教你如何写出迷你版微博的一行行代码&#xff0c;迷你版微博包含以下功能&#xff1a; Feed 流&#xff1a;关注动态、所有动态发送图文动态搜索用户关注系统点赞动态个人主页使用到的云开发能力&#xff1a; 云数据库云存储云函数云调用没错&#xff0c;几…

spring mvc学习(60):ssm项目整合

SSM整合 建立springmvc项目&#xff0c;先跑起来&#xff0c;再整合spring和mybatis 一.SpringMVC建立 1.新建maven工程&#xff0c;安装tomcat 2.导入pom <!-- springmvc --><dependency><groupId>org.springframework</groupId><artifactId>…

回溯算法归纳

回溯算法解题思路回溯的两种思路题目描述按照思路1解决按思路2解决回溯的两种思路 看不同的解题方法&#xff0c;形成不同的思维。 先说结论。回溯解题思路1&#xff1a;是对可选择每个元素&#xff0c;采取不选择、选择两种策略&#xff0c;不断递归下去。最近看花花酱的视频…

mybatis学习(1):【持久化框架】Mybatis简介与原理

从这篇博文开始我们学习一下Mybatis&#xff0c;希望大家提出宝贵的建议。 什么是Mybatis MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code&#xff0c;并且改名为MyBatis 。iBATIS一词来源于“internet”和“abati…

UML类图解义

小菜&#xff1a;“对了&#xff0c;我时常在一些技术书中看到这些类图表示&#xff0c;简单的还看得懂&#xff0c;有些标记我很容易混淆。要不你给我讲讲吧。” 大鸟&#xff1a;“这个其实多看多用就熟悉了。我给你举一个例子&#xff0c;来看这样一幅图&#xff0c;其中就包…

mybatis学习(2):基本设置和核心配置

1创建一个简单的java项目 2导入jar包 建立一个lib包 链接&#xff1a;https://pan.baidu.com/s/1eJ7xXF2qvUbgde2T--Sphg 提取码&#xff1a;3bgy 加入junit的包 右键项目---build path---add library 4导入配置文件 log4j.properties ### ### log4j.rootLogger ERROR,s…

mybatis学习(3):映射文件的配置和接口创建

配置文件 db.properties jdbc.drivercom.oracle.jdbc.OracleDriver jdbc.urljdbc:oracle:thin:127.0.0.1:1521:wiicare jdbc.usernamewiicare jdbc.passwordMdsd123 log4j.properties ### ### log4j.rootLogger ERROR,stdout### ¡ ### log4j.appender.stdout org.ap…

mybatis学习(4):工具类和实体类的创建

配置文件 db.properties jdbc.drivercom.oracle.jdbc.OracleDriver jdbc.urljdbc:oracle:thin:127.0.0.1:1521:wiicare jdbc.usernamewiicare jdbc.passwordMdsd123 log4j.properties ### ### log4j.rootLogger ERROR,stdout### ¡ ### log4j.appender.stdout org.ap…

windows下解决pip安装出错问题

今天使用pip install xxx突然报错&#xff0c;找了好久全是在linux上的解决方案&#xff0c;好不容易找到一个windows下的解决方案&#xff0c;所以将他记录下来。 解决方案&#xff1a; cmd中敲命令&#xff1a;python -m ensurepip 得到pip的setuptools 然后就可以用&#xf…

检测ID卡的输入或者是其它卡的输入。

由于ID卡或者是其它的一些不同类型的卡&#xff0c;它们只是负责模拟键盘的录入&#xff0c;但是&#xff0c;它们在录入的时候没有一个很好的标识位可以让我们知道当前输入的是客户手工录入的字符串还是ID卡读入的字符串&#xff0c;我相信&#xff0c;很多人在做这样的开发时…

mybatis学习(6):IntelliJ IDEA 如何创建一个普通的 Java 项目,及创建 Java 文件并运行

一、创建 Java 项目&#xff1a; 1、打开 IDEA 软件&#xff0c;点击界面上的 Create New Project 2、出现以下界面&#xff0c;选中 Java&#xff0c;然后选择 JDK&#xff0c;最后点击 Next&#xff0c;进行下一步&#xff08;我的是 jdk1.8&#xff09; 3、这里是选择生成项…

第一百五十期:Java程序员必备:异常的十个关键知识点

总结了Java异常十个关键知识点&#xff0c;面试或者工作中都有用哦&#xff0c;加油。异常是指阻止当前方法或作用域继续执行的问题。比如你读取的文件不存在&#xff0c;数组越界&#xff0c;进行除法时&#xff0c;除数为0等都会导致异常。 前言 总结了Java异常十个关键知识点…

学用 TStringGrid [1] - ColCount、RowCount、Cells

本例功能:1、获取 StringGrid 的行数、列数;2、给单元赋值.运行效果图://示例代码: unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ExtCtrls, Grids;typeTForm1 class(TForm)StringGrid1: TStringG…

第一百五十一期:最新计算机技能需求排名出炉:Python仅排第三,第一你猜得到吗?

除了编程语言之外&#xff0c;要想找一份计算机相关的工作&#xff0c;还需要很多其他方面的技能。最近&#xff0c;来自美国求职公司 Indeed 的一份报告显示&#xff1a;在全美工作技能需求中&#xff0c;数据库语言 SQL、编程语言 Java 分列前两位。 除了编程语言之外&#x…

歌谣致学习编程的你们

目录 致学习编程的你们&#xff0c;希望对大家有所帮助&#xff0c;纯属个人学习经验 前言 学习路线 个人网课学习平台 个人推荐两款软件 个人对于参加培训的看法 个人博客写作 同事同学资源 总结 前言 我是歌谣&#xff0c;一个致力于成为一名优秀的技术革新人员。高…

开发者福音!面向Web场景的云开发服务正式开放!

导 语 继支持小程序开发之后&#xff0c;云开发也支持Web使用啦&#xff01;开发者们可以使用云开发提供的云端能力&#xff0c;直接开发网站应用&#xff0c;如PC端网页、公众号中的网页等。由此开发者可以在网站应用中借助云函数实现业务逻辑&#xff0c;通过与云数据库、对象…

PetShop4.0--转载

以下文章转载于http://www.cnblogs.com/dragonlhf/archive/2006/07/30/463110.html petshop是微软推出的企业级程序架构随着asp.net 2.0推出了petshop4.0&#xff0c;正好这几天没有事&#xff0c;研究一下&#xff0c;学习一下2.0的新特性&#xff0c; 它包括…

mybatis学习(7):Windows下安装MySQL详细教程

1、安装包下载。 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 点击下载之后&#xff0c;可以选择注册Oracle账号&#xff0c;也可以跳过直接下载。 下载完成后&#xff0c;选择一个磁盘内放置并解压。 2 安装教程 &#xff08;1&#xff09;配置环境变量 变量…