机器学习实战之路 —— 4 Boosting算法

  • 1. Boosting算法概述
  • 2. 主要算法实现
    • 2.1 AdaBoost
    • 2.2 GBDT
    • 2.3 XGBoost
  • 3. 实战 - 鸢尾花数据集分类
    • 3.1 AdaBoost
    • 3.2 GBDT & XGBoost
  • 4.参考学习的书目及论文

1. Boosting算法概述

一般集成学习的结构可如下图所示:通过样本训练集产生一组个体学习器,每个个体学习器完成训练后对于每个测试样本都会产生各自的预测结果。经由一种组合策略,从个体学习器的预测结果中选择一个结果或者给出一个平均值作为最终的输出。对于分类任务而言,个体学习器通常由现有的分类算法从训练数据中产生。但是每种分类器都会有各自的优点或者缺点,不可能适用所有的分类场景。因此,在具体的分类任务中,需要采用适用的分类算法作为集成学习的个体学习器。 一般而言,个体学习器存在一定差异的集成学习算法拥有更好的分类性能。

根据个体学习器的不同生成方式,目前集成学习算法按照学习的分类方式可以大致分为两类:并行序列化生成和串行生成。并行化生成个体学习器的算法有 Bagging和Random Forest<请参考博主前面写的随机森林算法章节博客>,它们通过采样方法,训练出多样性的基学习器,降低方差,之后 Random Forest 又引入了随机属性,使得多样性进一步提高,于是获得了更好的效果。
串行化生成个体学习器的代表算法则是Boosting (也称作提升法),通过对错判训练样本重新赋权来重复训练,通过提高基学习器准确性来降低偏差。

上图即展示了一个Boosting的实现过程,算法主要关注分错样本的数据处理。如果在当前建模的分类器中,存在分类错误的样本数据,则将会在下一次建模的分类器中,给上次分错的样本增大权重,如图2(m=2)之后的红点和蓝点被标识放大。随着训练次数增加,被分错的样本权重不断增大,被错分的样本将不断被重视及加大权重,直至模型所有样本基本实现分类正确。
Boosting的主要算法有Ada Boost、GBDT、XGboost,以下将对这三种算法分别展开论述。

2. 主要算法实现

2.1 AdaBoost

AdaBoost(Adaptive Boosting)是最著名的 Boosting 算法,属于提升类的自适应算法。其基本工作过程是:第一轮训练数据的权重都相同,训练得出第一个基分类器,之后,下一轮的基分类器的权重根据上一轮的基分类器的错分样本进行调整,即错分样本具有更高的权重值;之后,每一轮中具有不同权重值的样本对本轮基分类器进行训练,即在考虑样本不同权重的情况下得到本轮错误率最低的基分类器。重复以上步骤直到完成设定的轮数,每一轮训练得到一个基分类器,最后根据采取合适的结合策略得到次级分类器的预测结果。AdaBoost算法流程如下图所示。

其中,加权误差率 e 的定义为:
e=P(Gm(xi)≠yi)=∑i=1NωmiI(Gm(xi)≠yi)e=P(G_m(x_i)≠y_i)=\sum_{i=1}^Nω_{mi}I(G_m(x_i)≠y_i) e=P(Gm​(xi​)​=yi​)=i=1∑N​ωmi​I(Gm​(xi​)​=yi​)
其中Gm(xi)G_m(x_i)Gm​(xi​)为基本分类器。其系数为:
αm=12ln1−emem\alpha_m=\frac{1}{2}ln\frac{1-e_m}{e_m} αm​=21​lnem​1−em​​
样本的权值分布为:
ωm+1,i=ωmiZme(−αmyiGm(xi))ω_{m+1,i}=\frac{ω_{mi}}{Z_m}e^{(-\alpha_my_iG_m(x_i))} ωm+1,i​=Zm​ωmi​​e(−αm​yi​Gm​(xi​))
其中yiy_iyi​为样本标记值,对于二分类,yi∈{−1,1}y_i∈\{-1,1\}yi​∈{−1,1};ZmZ_mZm​为规范化因子,使得ωm+1,iω_{m+1,i}ωm+1,i​相加为1。
Zm=∑i=1Nωmie(−αmyiGm(xi))Z_m=\sum_{i=1}^Nω_{mi}e^{(-\alpha_my_iG_m(x_i))} Zm​=i=1∑N​ωmi​e(−αm​yi​Gm​(xi​))
最终分类器为:
G(x)=sign(f(x))=sign(∑m=1MαmGm(x))G(x)=sign(f(x))=sign\left({\sum_{m=1}^M\alpha_mG_m(x)}\right) G(x)=sign(f(x))=sign(m=1∑M​αm​Gm​(x))
由ωm+1,iω_{m+1,i}ωm+1,i​可知被基本分类器Gm(x)G_m(x)Gm​(x)误分类样本的权值得以扩大,而被正确分类样本的权值得以缩小。因此,误分类样本将在下一轮学中起更大的作用。训练数据没有改变,而不断改变训练数据权值的分布,使得训练数据在基本分类器的学习中起不同的作用。

由αm\alpha_mαm​可知其随着eme_mem​的减小而增大,所以分类误差率越小的基本分类器在最终分类器中的作用越大。

实现代码如下:

"""
单层决策树分类
Args:dataMatrix - 数据矩阵dimen - 特征列threshVal - 阈值threshIneq - 标志位
Returns: retArray - 分类结果
"""
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):retArray = np.ones((np.shape(dataMatrix)[0],1))         # 初始化retArray为1if threshIneq == 'lt':retArray[dataMatrix[:,dimen] <= threshVal] = -1.0   # 若小于等于阈值,赋值为-1else:retArray[dataMatrix[:,dimen] > threshVal] = -1.0    # 若大于阈值,赋值为-1return retArray"""
基于权重向量生成单层决策树
Args:dataArr - 数据矩阵classLabels - 类别标签D - 权重向量
Returns:bestStump - 最佳单层决策树信息minError - 最小误差bestClassEst - 最优分类结果
"""
def buildStump(dataArr, classLabels, D):dataMatrix = np.mat(dataArr); labelMat = np.mat(classLabels).T  # 转换数据及数据标签为numpy矩阵m, n = np.shape(dataMatrix)                                     # 数据集的行数和列数numSteps = 10.0                                                 # 遍历的步数bestStump = {}                                                  # 最佳单层决策树信息bestClassEst = np.mat(np.zeros((m, 1)))                         # 初始化最佳预测值minError = np.inf                                               # 初始化最小误差为正无穷大for i in range(n):                                              # 遍历特征rangeMin = dataMatrix[:, i].min()                           # 特征中的最小值rangeMax = dataMatrix[:, i].max()                           # 特征中的最大值stepSize = (rangeMax - rangeMin) / numSteps                 # 计算步长for j in range(-1, int(numSteps) + 1):                      # 遍历步长for inequal in ['lt', 'gt']:                            # 遍历大于、小于threshVal = (rangeMin + float(j) * stepSize)        # 计算阈值predictedVals = stumpClassify(dataMatrix, i, threshVal, inequal)  # 计算分类结果errArr = np.mat(np.ones((m, 1)))                    # 初始化误差矩阵errArr[predictedVals == labelMat] = 0               # 分类正确的赋值为0weightedError = D.T * errArr                        # 计算加权错误率if weightedError < minError:                        # 找到误差最小的分类方式,并赋值minError = weightedErrorbestClassEst = predictedVals.copy()bestStump['dim'] = ibestStump['thresh'] = threshValbestStump['ineq'] = inequalreturn bestStump, minError, bestClassEst"""
基于单层决策树的AdaBoost训练
Args:dataArr - 数据矩阵classLabels - 类别标签numIt - 迭代次数
Returns:weakClassArr - 分类器数组aggClassEst - 类别估计累计值
"""
def adaBoostTrainDS(dataArr,classLabels,numIt=40):weakClassArr = []                                                   # 分类器数组m = np.shape(dataArr)[0]                                            # 数据集的特征值个数D = np.mat(np.ones((m,1))/m)                                        # 初始化权重向量aggClassEst = np.mat(np.zeros((m,1)))                               # 初始化类别估计累计值for i in range(numIt):                                              # 根据迭代次数遍历bestStump,error,classEst = buildStump(dataArr,classLabels,D)    # 基于权重向量生成单层决策树alpha = float(0.5 * np.log((1.0 - error) / max(error, 1e-16)))  # 计算权重alpha,防止发生除零溢出bestStump['alpha'] = alpha                                      # 记录权重值weakClassArr.append(bestStump)                                  # 存储最好的单层决策树expon = np.multiply(-1 * alpha * np.mat(classLabels).T, classEst) # 计算e的指数项D = np.multiply(D, np.exp(expon))                               # 计算新的权重向量D = D / D.sum()                                                 # 权重向量归一化aggClassEst += alpha * classEst                                 # 计算类别估计累计值aggErrors = np.multiply(np.sign(aggClassEst) != np.mat(classLabels).T, np.ones((m, 1))) # 计算误差errorRate = aggErrors.sum() / mprint("total error: ", errorRate)if errorRate == 0.0: break                                      # 误差为0则退出循环return weakClassArr, aggClassEst"""
AdaBoost分类函数
Args:datToClass - 待分类样例classifierArr - 训练好的弱分类器
Returns: 分类结果
"""
def adaClassify(datToClass,classifierArr):dataMatrix = np.mat(datToClass)             # 转换待分类样例为numpy矩阵m = np.shape(dataMatrix)[0]                 # 待分类样例个数aggClassEst = np.mat(np.zeros((m,1)))       # 初始化类别估计累计值for i in range(len(classifierArr)):         # 遍历所有弱分类器classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],classifierArr[i]['thresh'],classifierArr[i]['ineq'])  # 计算类别估计值aggClassEst += classifierArr[i]['alpha']*classEst   # 根据权重累加得到类别估计累计值print(aggClassEst)return np.sign(aggClassEst)if __name__ == '__main__':dataArr,classLabels = loadSimpData()weakClassArr, aggClassEst = adaBoostTrainDS(dataArr, classLabels)print(adaClassify([[0,0],[5,5]], weakClassArr))

使用sklearn.ensemble 实现 AdaBoost 代码如下:

from sklearn.ensemble import AdaBoostClassifier# 决策树
base_estimator = DecisionTreeClassifier(criterion='gini', max_depth=3, min_samples_split=4)
# AdaBoost学习器,10棵树,学习率为0.1
model = AdaBoostClassifier(base_estimator=base_estimator, n_estimators=10, learning_rate=0.1)
# 训练AdaBoost学习器
model.fit(x_train, y_train)
# AdaBoost学习器预测训练集
y_train_pred = model.predict(x_train)

2.2 GBDT

Gradient Boosting与之前的Boosting的不同点在于,在每一次进行训练的目的是为了减少上一次的残差,为了不断的降低残差,我们需要在减少残差的梯度方向训练一个新的模型,所以可以理解,Gradient Boosting算法训练每一个新的模型都是为让之前的模型的残差在梯度方向上降低。将Gradient Boosting用于决策树模型上之后,就是GBDT(Gradient Boosting Decision Tree,梯度提升树),其损失函数的负梯度在当前模型的值:
−[∂L(y,f(xi)))∂f(xi)]f(x)=fm−1(x)-\bigg[\frac{\partial L(y, f(x_i)))}{\partial f(x_i)}\bigg]_{f(x) = f_{m-1} (x)} −[∂f(xi​)∂L(y,f(xi​)))​]f(x)=fm−1​(x)​
作为回归问题提升树算法中的残差的近似值,拟合一个回归树。

实现代码如下:
使用sklearn.ensemble 实现 GBDT 代码如下:

from sklearn.ensemble import GradientBoostingClassifier# GBDT,100棵树,学习率0.1,最大深度2
gb = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1, max_depth=2)
# GBDT训练
gb.fit(x_train, y_train.ravel())
# GBDT预测训练集
y_train_pred = gb.predict(x_train)

2.3 XGBoost

GBDT在优化时仅用一阶导数信息,XGBoost则对损失函数进行了二阶泰勒展开,同时用到了一阶导数和二阶导数,加入该正则化项对模型的复杂程度施加惩罚,以提高模型的泛化能力,防止过拟合,也具备较高的计算效率。

实现代码如下:

import xgboost as xgb# 设置参数
# max_depth - 树的深度为3
# eta - 学习率,为1时是原始模型,过小的学习率会造成计算次数增多,可防止过拟合,通过减少每一步的权重,可以提高模型的鲁棒性。典型值0.01-0.2
# silent-是否输出中间结果
# objective-定义需要被最小化的损失函数(分类问题的逻辑回归)
param = {'max_depth': 3, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic'}
watchlist = [(data_test, 'eval'), (data_train, 'train')]    # 输出过程中的错误率
n_round = 7 # 7颗决策树
# 训练XGBoost
bst = xgb.train(param, data_train, num_boost_round=n_round, evals=watchlist)
# XGBoost预测数据集
y_hat = bst.predict(data_test)

3. 实战 - 鸢尾花数据集分类

本小节所用实战数据同样为前面章节博客用过的经典莺尾花数据集,具体的数据描述可参见前面博客。以下分别给出AdaBoost和GBDT & XGBoost的算法实现。

3.1 AdaBoost

与前面的随机森林章节一样,对鸢尾花数据选取两特征组合进行分类,使用Adaboost算法实现代码如下:

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_splitif __name__ == "__main__":mpl.rcParams['font.sans-serif'] = ['SimHei']mpl.rcParams['axes.unicode_minus'] = False# 读取数据path = 'iris.data'  # 数据文件路径data = pd.read_csv(path, header=None)# 特征定义iris_feature = '花萼长度', '花萼宽度', '花瓣长度', '花瓣宽度'# 数据处理:如果是字符型特征,则转换成数值型x_prime = data[list(range(4))]              # 数值型数据,无需额外转换操作y = pd.Categorical(data[4]).codes           # 字符型数据,需转换成数值型# 拆分数据为训练集(70%)和测试集(30%)x_prime_train, x_prime_test, y_train, y_test = train_test_split(x_prime, y, train_size=0.7, random_state=0)# 特征组合feature_pairs = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]plt.figure(figsize=(11, 8), facecolor='#FFFFFF')for i, pair in enumerate(feature_pairs):# 准备数据x_train = x_prime_train[pair]x_test = x_prime_test[pair]# 决策树base_estimator = DecisionTreeClassifier(criterion='gini', max_depth=3, min_samples_split=4)# AdaBoost学习器,10棵树,学习率为0.1model = AdaBoostClassifier(base_estimator=base_estimator, n_estimators=10, learning_rate=0.1)model.fit(x_train, y_train)# 画图N, M = 500, 500  # 横纵各采样多少个值x1_min, x2_min = x_train.min()x1_max, x2_max = x_train.max()t1 = np.linspace(x1_min, x1_max, N)t2 = np.linspace(x2_min, x2_max, M)x1, x2 = np.meshgrid(t1, t2)  # 生成网格采样点x_show = np.stack((x1.flat, x2.flat), axis=1)  # 测试点# 训练集上的预测结果y_train_pred = model.predict(x_train)acc_train = accuracy_score(y_train, y_train_pred)y_test_pred = model.predict(x_test)acc_test = accuracy_score(y_test, y_test_pred)print('特征:', iris_feature[pair[0]], ' + ', iris_feature[pair[1]])print('\t训练集准确率: %.4f%%' % (100*acc_train))print('\t测试集准确率: %.4f%%\n' % (100*acc_test))cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])y_hat = model.predict(x_show)y_hat = y_hat.reshape(x1.shape)plt.subplot(2, 3, i+1)plt.contour(x1, x2, y_hat, colors='k', levels=[0, 1], antialiased=True, linestyles='--', linewidths=1.5)plt.pcolormesh(x1, x2, y_hat, cmap=cm_light)  # 预测值plt.scatter(x_train[pair[0]], x_train[pair[1]], c=y_train, s=20, edgecolors='k', cmap=cm_dark)plt.scatter(x_test[pair[0]], x_test[pair[1]], c=y_test, s=100, marker='*', edgecolors='k', cmap=cm_dark)plt.xlabel(iris_feature[pair[0]], fontsize=14)plt.ylabel(iris_feature[pair[1]], fontsize=14)plt.xlim(x1_min, x1_max)plt.ylim(x2_min, x2_max)plt.grid(b=True)plt.suptitle('Adaboost对鸢尾花数据两特征组合的分类结果', fontsize=18)plt.tight_layout(1, rect=(0, 0, 1, 0.95))    # (left, bottom, right, top)plt.show()

输出结果如下:

特征: 花萼长度  +  花萼宽度训练集准确率: 87.6190%测试集准确率: 75.5556%特征: 花萼长度  +  花瓣长度训练集准确率: 99.0476%测试集准确率: 88.8889%特征: 花萼长度  +  花瓣宽度训练集准确率: 98.0952%测试集准确率: 88.8889%特征: 花萼宽度  +  花瓣长度训练集准确率: 100.0000%测试集准确率: 95.5556%特征: 花萼宽度  +  花瓣宽度训练集准确率: 98.0952%测试集准确率: 93.3333%特征: 花瓣长度  +  花瓣宽度训练集准确率: 99.0476%测试集准确率: 97.7778%

输出的分类结果图像如下:

3.2 GBDT & XGBoost

分别使用XGBoost、GBDT、随机森林、逻辑回归对鸢尾花数据进行分类,实现代码如下:

import numpy as np
import pandas as pd
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegressionCV
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.metrics import accuracy_scoreif __name__ == "__main__":# 读取数据path = 'iris.data'                    data = pd.read_csv(path, header=None)   # 数据处理:如果是字符型特征,则转换成数值型x = data[list(range(4))]              # 数值型数据,无需额外转换操作y = pd.Categorical(data[4]).codes           # 字符型数据,需转换成数值型# 拆分数据为训练集(50%)和测试集(50%)x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1, test_size=50)# 转换为xgboost中的矩阵格式data_train = xgb.DMatrix(x_train, label=y_train)data_test = xgb.DMatrix(x_test, label=y_test)watch_list = [(data_test, 'eval'), (data_train, 'train')]   # 输出过程中的错误率# 3分类的softmax训练模型param = {'max_depth': 8, 'eta': 0.8, 'silent': 1, 'objective': 'multi:softmax', 'num_class': 3}# 训练XGBoostbst = xgb.train(param, data_train, num_boost_round=6, evals=watch_list)# XGBoost预测数据集y_hat = bst.predict(data_test)result = y_test == y_hatprint('测试集正确率:\t', float(np.sum(result)) / len(y_hat))print('END.....\n')# 分别用GBDT、随机森林和逻辑回归训练models = [# GBDT 30棵决策树,学习率为0.1,树的最大深度为5('GBDT', GradientBoostingClassifier(n_estimators=30, learning_rate=0.1, max_depth=5)),# 随机森林 30棵决策树,特征选择用gini系数,树的最大深度为5('RandomForest', RandomForestClassifier(n_estimators=30, criterion='gini', max_depth=5)),('LogisticRegression', LogisticRegressionCV(Cs=np.logspace(1, 100, 100), cv=3))]for name, model in models:model.fit(x_train, y_train)print(name, '训练集正确率:', accuracy_score(y_train, model.predict(x_train)))print(name, '测试集正确率:', accuracy_score(y_test, model.predict(x_test)))

输出结果如下:

[0]  eval-merror:0.02    train-merror:0.02
[1] eval-merror:0.02    train-merror:0.02
[2] eval-merror:0.02    train-merror:0.02
[3] eval-merror:0.04    train-merror:0.01
[4] eval-merror:0.04    train-merror:0.01
[5] eval-merror:0.04    train-merror:0.01
测试集正确率:  0.96
END.....GBDT 训练集正确率: 1.0
GBDT 测试集正确率: 0.96
RandomForest 训练集正确率: 1.0
RandomForest 测试集正确率: 0.96
LogisticRegression 训练集正确率: 0.97
LogisticRegression 测试集正确率: 0.92

4.参考学习的书目及论文

  1. 机器学习算法视频 - 邹博
  2. 《机器学习实战》第7章 利用AdaBoost元算法提高分类性能
  3. 《机器学习之路》第2章 2.6 模型融合
  4. 《机器学习 - 周志华》第8章 集成学习
  5. 《统计学习方法》第8章 提升方法
  6. 《基于Boosting的集成树算法研究与分析》 连克强 2019 硕士论文 第3章 Boosting 集成方法
  7. 《基于AdaBoost算法的车载CAN总线报文异常检测》王成龙 2019 硕士论文 第4章 基于AdaBoost算法的CAN总线报文异常检测

=文档信息=
本学习笔记由博主整理编辑,仅供非商用学习交流使用
由于水平有限,错误和纰漏之处在所难免,欢迎大家交流指正
如本文涉及侵权,请随时留言博主,必妥善处置
版权声明:非商用自由转载-保持署名-注明出处
署名(BY) :zhudj
文章出处:https://zhudj.blog.csdn.net/

机器学习实战之路 —— 4 Boosting算法相关推荐

  1. 机器学习实战之路 —— 5 SVM支持向量机

    机器学习实战之路 -- 5 SVM支持向量机 1. 支持向量机概述 1.1 线性分类 1.2 非线性分类 2. 支持向量机分类中的问题 2.1 核函数的选择 2.2 多类分类 2.3 不平衡数据的处理 ...

  2. 机器学习实战2.3. k-近邻算法例子-识别手写数字

    机器学习实战2.3. k-近邻算法例子-识别手写数字 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多机器学习干货 csdn:https://blog.csdn.net/ ...

  3. 机器学习实战-57: 人工神经网络分类算法(Artificial Neural Network)

    机器学习实战-57: 人工神经网络分类算法 深度学习原理与实践(开源图书)-总目录,建议收藏,告别碎片阅读! 人工神经网络(Artificial Neural Network)分类算法属于监督学习算法 ...

  4. 《机器学习实战》chapter02 K-近邻算法(KNN)

    2.2 示例:使用K-近邻算法改进约会网站的配结果 收集数据:提供文本文件 准备数据:使用Python解析文本文件(文本转numpy矩阵.归一化数据等) 分析数据:使用Matplotlib画二维扩散图 ...

  5. 机器学习实战第15章pegasos算法原理剖析以及伪代码和算法的对应关系

    Pegasos原文是: http://ttic.uchicago.edu/~nati/Publications/PegasosMPB.pdf 还是挺长的,论文结构是: 第1~6页:主要原理 第7~15 ...

  6. 阿旭机器学习实战【2】KNN算法进行人体动作识别

    本系列文章为机器学习实战内容,旨在通过实战的方式学习各种机器学习算法的知识,更易于掌握和学习,更过干货内容持续更新- 目录 人类动作识别问题描述 导入相关数据并查看数据信息 构建KNN算法模型并查看准 ...

  7. 机器学习之集成学习(Boosting算法、Bagging算法、Stacking算法)总结

    1.集成学习概述 机器学习分为有监督学习算法和无监督学习算法.在有监督学习中,我们的目标是学习一个稳定的且各方面都表现较好的模型.但是,实际情况往往不理想,有时我们只能得到多个在某些方面表现比较好的& ...

  8. 机器学习实战(二)LR算法:实现简单的分类模型

    说明:主要参考 机器学习实战之Logistic,里面有更详尽的Logistic Regression原理分析和案例实现流程详解,是一个关于机器学习实战的不错的学习资料,推荐一波.出于编程实践和机器学习 ...

  9. 机器学习之Bagging算法和Boosting算法

    2.1 Bagging和Boosting区别 Bagging算法和Boosting都属于集成算法,最重要的假设是:当弱模型被正确组合时,我们可以得到更精确和/或更鲁棒的模型. bagging算法通常考 ...

最新文章

  1. 使用TensorRT集成推理inference
  2. IIS 6.0曝远程代码执行漏洞 安全狗可拦截
  3. LightOJ1171 Knights in Chessboard (II)(二分图最大点独立集)
  4. 一条SQL完成跨数据库实例Join查询
  5. 万物互联的根底就是嵌入式,小到智能手表,大到智能汽车,能落地的支撑之一就是嵌入式。
  6. 拓端tecdat|用R语言实现神经网络预测股票实例
  7. windows驱动开发技术详解 VC6与DDK搭配使用的设置
  8. 基于java实现学科竞赛管理系统「Springboot+mybatis+lyaui」
  9. pandas_计算前复权收盘价和后复权收盘价
  10. excel内容少却文件很大_Excel文件内容很少,但文件很大,打开很慢、很卡怎么办?...
  11. JAVA基础——对象与引用概念(转载)
  12. 电脑插上耳机后声音依然外放,简单解决两步走!
  13. OpenCV源码剖析之ImageDecoder
  14. 升级Android Q之路遇到的坑-abc_screen_simple
  15. 我们跟8个程序员聊了一晚上,攒齐了来自BAT的吐槽
  16. C# 导出Excel文件 打开Excel文件格式与扩展名指定格式不一致。
  17. 秋招在即,你准备好了吗?BAT算法工程师面试经验分享。
  18. 【总结】大学生寒假社会实践总结-社区志愿关爱模板
  19. 论文版「ChatGPT」来了!看论文问问题可同时进行,网友:看文献更省时了|开源...
  20. 要怎么在计算机里清除桌面内存,电脑内存过大?教你如何清理电脑内存

热门文章

  1. 对常见的三个免费数据库软件的一些个人看法
  2. 将数据集分为训练集和测试集(python脚本)
  3. LayaAir拖拽移动对象并吸附(附源码)
  4. 赛马网基本算法之--上台阶
  5. 【gl-transitions配置】原项目dockerfile修改,为视频添加转场效果
  6. 《软件需求规格说明书》几点重要内容
  7. 2021-11-15 求100以内偶数与奇数之和
  8. 中国才储--才储MBTI之概念主义者
  9. x86架构ubuntu18下运行GBA模拟器mgba
  10. 帆软独立部署tomcat服务器