CatBoost 和 Light GBM 和 XGBoost 使用GPU训练对比

19 篇文章 2 订阅
17 篇文章 8 订阅

学习目标:

对比学习:CatBoost 和 Light GBM 和 XGBoost

  • Light GBM 最快,目前暂时对GPU CUDA支持不好,报错
  • CatBoost 有较多离散特征时效果好,对GPU支持好,所以用GPU训练快
  • XGBoost最慢,需要自己编码,效果较稳定

学习内容:

Kaggle比赛使用各种增强算法,能进入前10名。尽管神经网络最近重新出现并流行起来,但传统提升算法,在训练数据有限,训练时间少,参数调优专业知识少的情况下,仍然更有用。

CatBoost 和 Light GBM 和 XGBoost发展时间表。
在这里插入图片描述

由于XGBoost(通常称为GBM Killer)已经在机器学习领域工作了更长的时间,并且有很多文章专门介绍它,因此本文将更多地关注CatBoost和LGBM。以下是我们将涵盖的主题:

  • 结构差异
  • 每种算法处理类别变量的方式
  • 了解调优参数
  • 在数据集上具体实现
  • 每种算法的性能对比

LightGBM和XGBoost的结构差异

LightGBM使用基于梯度的单侧采样(GOSS)技术来过滤掉用于查找拆分值的数据,而XGBoost使用预排序算法和基于直方图的算法来计算最佳拆分。

首先,让我们了解一下XGBoost预排序拆分的工作原理:

1、对于每个特征,枚举所有取值
2、对于每个特征,按值对数据进行排序
3、使用线性扫描确定以该特征的信息增益的最佳分割
4、在所有特征上采取最佳的分割方案
lightGBM基于直方图拆分的工作原理:
简单来说,基于直方图的算法将特征的所有取值进行分箱,数据被拆分为离散柱,并使用这些条柱来查找直方图的分割值。因此大大减小了最佳分割点的可能取值,也就是说不用把特征的每个取值都来计算信息增益,只用在离散后的分割点处计算信息增益即可,这也是分箱的精髓。
每个虽然在训练速度上,基于直方图拆分比预排序算法更有效,它枚举了预先排序的特征值上所有可能的分割点,但在速度方面仍然落后于GOSS。

那么,是什么让这种GOSS方法变得高效呢?
在AdaBoost中,样品重量是样品重要性的良好指标。然而,在梯度提升决策树(GBDT)中,没有原生样本权重,因此不能直接应用AdaBoost的采样方法。只能基于梯度的采样。

梯度表示损失函数正切的斜率,因此从逻辑上讲,如果数据点的梯度在某种意义上很大,则这些点对于找到最佳分割点非常重要,因为它们具有更高的误差。更能帮助损失函数到达最优点。

GOSS 保留所有梯度较大的实例数据,并对梯度较小的实例执行随机抽样。例如,假设我有 500K 行数据,其中 10k 行具有较高的梯度。所以我的算法会选择(10k行的较高梯度+ 剩余490k行的x%随机选择)。假设 x 为 10%,则选择的总行数为 500K 中的 59k,如果找到拆分值,则基于该值。注意,这里随机选取的10%的数据的权重会人为增大9倍,这样才能保证原始数据中,数据的分布一致,不然这样采样会改变原始的数据分布。这点需要理解。

这里采取的基本假设是,具有小梯度的训练实例的样本具有较小的训练误差,并且已经训练有素。
为了保持相同的数据分布,在计算信息增益时,GOSS为梯度较小的数据实例引入了常数乘数。因此,GOSS在减少数据实例数量和保持学习决策树的准确性之间实现了良好的平衡。

具有较高梯度/误差的叶子用于在LGBM中进一步生长,LGBM是leaf-wise的形式增长树。
在这里插入图片描述

每个模型如何处理分类变量?

CatBoost

CatBoost 最大的优势是:对于离散特征特别多的数据,效果比较好,可以灵活地提供分类列(cat_features)的索引,以便可以使用one_hot_max_size将其编码为单热编码(对具有不同值数小于或等于给定参数值的所有要素使用独热编码)。
如果您没有cat_features参数中传递任何内容,CatBoost 会将所有列视为数值变量。此时效果可能不是很好。

注: 如果cat_features中未提供具有字符串值的列,CatBoost 将引发错误。此外,默认情况下,具有默认int类型的列将被视为数字,必须在cat_features中指定它以使算法将其视为分类。
在这里插入图片描述
这里cat_features=[0,1,2]表示输入的特征数据中,第1,2,3列数据是离散特征数据,而没有指定的4,5,6列数据就是数值型特征。
对于类别的唯一数量大于 one_hot_max_size 的其余分类列(也就是离散特征取值大于one_hot_max_size ,用onehot编码则维度增加特别高,比如‘’民族‘’特征有56个,onehot编码后,就有56维,计算量一下暴增。),CatBoost 使用一种有效的编码方法,该方法类似于平均编码,但可减少过度拟合。这个过程是这样的:

  • 1、以随机顺序排列输入观测值集。也就是对数据进行重排序。生成多个随机排列

这里理解一下为什么要对数据进行随机重排序?因为catboost采用的编码方式和数据的先后顺序有关,所以把数据打乱后,会得到多份编码不同的数据,这个有点“数据增强”的意思。比如图片我们旋转后会得到不同的数据,catboost随机打乱数据,就有点异曲同工。
比如从一个高斯分布中采样得到3个点a=0.1,b=-0.2,c=0.3。如果不区分数据顺序,那么这就是一次采样,而如果采用catboost,随机排列,会出现[a,b,c],[b.a,c],[b,c,a],[a,c,b]等等3!=6份数据,相当于做了6次不同的采样,所以比起不考虑顺序的1次采样,catboost进行了数据增强,相当于同一个分布,采样了6次,这样catboost的精度以及过拟合都会有所提高。
这个技巧比较巧妙。

  • 2、将标签值从浮点或类别转换为整数
  • 3、使用以下公式将所有分类要素值转换为数值:
    在这里插入图片描述其中,CountInClass 是具有和当前待编码的数据的特征值相同的数据,并且标签值等于“1”的次数, Prior 是分子的初步值,它由起始参数确定。TotalCount 是具有与当前特征值一样的数据的总数(截至当前对象。)

这里用一个示例解释一下,我们设 Prior =0.5.我们对第6行数据进行编码。
在这里插入图片描述
TotalCount就是性别为男的数据,并且在待编码行(第六行)之前的数据,一共3条,分别是记录(2、4、5)。CountInClass 是之前特征为男性,并且标签为1的数据,就只有一行,就是第5行、所以TotalCount=3,CountInClass =1。
带入avg_target=(1+0.5)/(3+1)=0.375,因此,第六行的男这个值,会被替换为0.375。
在数学上,这可以用下面的等式来表示:

在这里插入图片描述

LightGBM

与CatBoost类似,LightGBM也可以通过输入特征名称来处理分类特征。它不会转换为独热编码,并且比独热编码快得多。LGBM使用特殊算法来查找分类特征的分割值
在这里插入图片描述

注: 在为 LGBM 构造数据集之前,应将分类要素转换为 int 类型。它不接受字符串值,即使您通过categorical_feature参数传递字符串值也是如此。

XGBoost

与CatBoost或LGBM不同,XGBoost本身无法处理分类特征,它只接受类似于随机森林的数值。因此,在向 XGBoost 提供分类数据之前,必须执行各种编码,如标签编码、平均编码或单热编码。


超参数中的相似性

所有这些模型都有很多参数需要调整,但我们只介绍重要的参数。以下是这些参数根据其功能和不同型号的对应参数的列表。

在这里插入图片描述

数据集上的实现

我使用2015年航班延误的Kaggle数据集,因为它具有分类和数值特征。该数据集大约有 500 万行,将有利于判断每种类型增压的调优模型的速度和准确性的性能。我将采样使用此数据的10%子集〜500k行。不然训练太慢。
以下是用于建模的特征:

  • 月、日、DAY_OF_WEEK:数据类型 int
  • 航空公司和FLIGHT_NUMBER:数据类型 int
  • ORIGIN_AIRPORT和DESTINATION_AIRPORT:数据类型字符串
  • DEPARTURE_TIME:数据类型浮点型
  • ARRIVAL_DELAY:这将是目标,并转换为布尔变量,指示延迟超过 10 分钟
  • 距离和AIR_TIME:数据类型浮点型

数据预处理

import pandas as pd, numpy as np, time
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn import metrics

data = pd.read_csv('flights.csv')
data = data.sample(frac=0.1, random_state=10)
print(data.columns)

data = data[["MONTH", "DAY", "DAY_OF_WEEK", "AIRLINE", "FLIGHT_NUMBER", "DESTINATION_AIRPORT",
             "ORIGIN_AIRPORT", "AIR_TIME", "DEPARTURE_TIME", "DISTANCE", "ARRIVAL_DELAY"]]

print(data.head(5))

data.dropna(inplace=True)
print(data.head(5))

data["ARRIVAL_DELAY"] = (data["ARRIVAL_DELAY"] > 10) * 1

cols = ["AIRLINE", "FLIGHT_NUMBER", "DESTINATION_AIRPORT", "ORIGIN_AIRPORT"]
for item in cols:
    data[item] = data[item].astype("category").cat.codes +1

train, test, y_train, y_test = train_test_split(data.drop(["ARRIVAL_DELAY"], axis=1), data["ARRIVAL_DELAY"],
                                                random_state=10, test_size=0.25)

XGBoost

import xgboost as xgb

def auc(m, train, test):
    return (metrics.roc_auc_score(y_train,m.predict_proba(train)[:,1]),
                            metrics.roc_auc_score(y_test,m.predict_proba(test)[:,1]))


# Parameter Tuning
model = xgb.XGBClassifier(tree_method='gpu_hist', gpu_id=0)
param_dist = {"max_depth": [10,20,30],
              "min_child_weight" : [1,3],
              "n_estimators": [200],
              "learning_rate": [0.05, 0.1,0.5],}
grid_search = GridSearchCV(model, param_grid=param_dist, cv = 3,
                                   verbose=10, n_jobs=-1)
grid_search.fit(train, y_train)

print(grid_search.best_estimator_)

model = xgb.XGBClassifier(max_depth=20, min_child_weight=3,  n_estimators=200,\
                          n_jobs=-1 , verbose=1,learning_rate=0.1
                          ,tree_method='gpu_hist', gpu_id=0)
model.fit(train,y_train,verbose=10)

print('xgboost model score')
print(auc(model, train, test))
#xgboost model score (0.9999815408046491, 0.7848942647211888)

xgboost model score (0.9999815408046491, 0.7848942647211888)

LGBM

import lightgbm as lgb
from sklearn import metrics


def auc2(m, train, test):
    return (metrics.roc_auc_score(y_train, m.predict(train)),
            metrics.roc_auc_score(y_test, m.predict(test)))


lg = lgb.LGBMClassifier(verbose=1
                        ,device_type ='gpu')
param_dist = {"max_depth": [25,50, 75],
              "learning_rate" : [0.01,0.05,0.1],
              "num_leaves": [300,900,1200],
              "num_iterations": [200]
             }
grid_search = GridSearchCV(lg, n_jobs=-1, param_grid=param_dist, cv = 3, scoring="roc_auc", verbose=5)
grid_search.fit(train,y_train)
print('LGBMClassifier best_estimator:',grid_search.best_estimator_)

d_train = lgb.Dataset(train, label=y_train, free_raw_data=False)
# END learning_rate=0.05, max_depth=25, num_iterations=200, num_leaves=1200;, score=0.772 total time=10.6min
params = {"max_depth": 25, "learning_rate": 0.05, "num_leaves": 1200, "num_iterations": 200,
          # 'device': "gpu",'gpu_device_id': 1,
          #   'gpu_platform_id': 1,
          #   'gpu_use_dp': 'false',
          #   'max_bin': 252,
          #   'num_gpu':1
          }

# Without Categorical Features
model2 = lgb.train(params, d_train)
print('lightGBM Without Categorical Features:', auc2(model2, train, test))
# lightGBM Without Categorical Features: (0.9820454074519167, 0.7842988189129978)

# With Catgeorical Features
cate_features_name = ["MONTH", "DAY", "DAY_OF_WEEK", "AIRLINE", "DESTINATION_AIRPORT",
                      "ORIGIN_AIRPORT"]
model2 = lgb.train(params, d_train, categorical_feature=cate_features_name)
print('lightGBM With Categorical Features:', auc2(model2, train, test))
# lightGBM With Categorical Features: (0.9849578833000501, 0.7765037053711114)

lightGBM Without Categorical Features: (0.9820454074519167, 0.7842988189129978)

catboost

在调整 CatBoost 的参数时,很难传递分类特征的索引。因此,我在不传递分类特征的情况下调整了参数,并评估了两个模型 :一个具有分类特征,另一个区分没有类别特征。我单独调整了one_hot_max_size,因为它不会影响其他参数。

import catboost

cat_features_index = [0, 1, 2, 3, 4, 5, 6]


def auc(m, train, test):
    return (metrics.roc_auc_score(y_train, m.predict_proba(train)[:, 1]),
            metrics.roc_auc_score(y_test, m.predict_proba(test)[:, 1]))


params = {'depth': [7, 10,13],
          'learning_rate': [0.03, 0.15, 0.2],
          'l2_leaf_reg': [1, 4, 7],
          'iterations': [300,500]}
cb = catboost.CatBoostClassifier(task_type="GPU",
                           devices='0')
cb_model = GridSearchCV(cb, params, scoring="roc_auc", cv=3)
cb_model.fit(train, y_train)
print('CatBoostClassifier best_estimator:',cb_model.best_estimator_)
print('CatBoostClassifier best_params_:',cb_model.best_params_)

# With Categorical features
clf = catboost.CatBoostClassifier(eval_metric="AUC", depth=10, iterations=500, l2_leaf_reg=9, learning_rate=0.15
                            , task_type="GPU", devices='0')
clf.fit(train, y_train,plot=True)
print('CatBoostClassifier Without Categorical Features:', auc(clf, train, test))
# CatBoostClassifier Without Categorical Features: (0.8411768106404672, 0.7571423657177548)

# With Categorical features
clf = catboost.CatBoostClassifier(eval_metric="AUC", one_hot_max_size=31, \
                            depth=10, iterations=300, l2_leaf_reg=4, learning_rate=0.15
                            , task_type="GPU", devices='0')
clf.fit(train, y_train, cat_features=cat_features_index,plot=True)
print('CatBoostClassifier With Categorical Features:', auc(clf, train, test))
# CatBoostClassifier With Categorical Features: (0.881573635663068, 0.8129717796545255)

结果

在这里插入图片描述

总结

为了评估模型,我们应该从速度和精度的角度来研究模型的性能。

牢记这一点,CatBoost在测试集上以最大的精度(0.816),最小的过拟合(训练和测试精度都接近),以及最小的预测时间和调整时间成为赢家。但这仅仅是因为我们考虑了分类变量并调整了one_hot_max_size。如果我们不利用CatBoost的这些功能,它的表现最差,准确度仅为0.752。因此,我们了解到,只有当数据中有分类变量并正确调整它们时,CatBoost才会表现良好。

我们的下一个表演者是XGBoost,通常效果很好。它的准确性非常接近CatBoost,即使忽略了我们在数据中有分类变量的事实,我们已经将其转换为数值以供其使用。但是,XGBoost的唯一问题是它太慢了。特别是调整其参数真的很令人沮丧(我花了6个小时来运行GridSearchCV - 非常糟糕的主意!更好的方法是单独调整参数,而不是使用GridSearchCV。
提示:使用GPU可能会所有加快,默认算法使用cpu,因此本论文在原作者上改进使用GPU,会快不少。但目前lgbm不支持cuda,无法使用英伟达的显卡加速。

最后,最后一个地方是Light GBM。这里需要注意的一件重要事情是,当使用cat_features时,它在速度和准确性方面表现不佳。我相信它表现不佳的原因是因为它对分类数据使用了某种修改的均值编码,导致过度拟合(训练精度相当高 - 与测试精度相比为0.999)。然而,如果我们像XGBoost一样正常使用它,它可以达到与XGBoost(LGBM - 0.785,XGBoost- 0.789)更快的速度相似的精度。

最后,我不得不说,这些观察结果对于这个特定的数据集是正确的,对于其他数据集可能有效,也可能不有效。但是,有一件事是正确的,那就是:XGBoost比其他两种算法慢。

那么你最喜欢哪一个呢?请评论原因。
任何反馈或改进建议将不胜感激!

参考文献

原始论文
lightGBM 参数
数据集
xgboost参数

全部代码

import matplotlib.pyplot as plt
import pandas as pd, numpy as np, time
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn import metrics

data = pd.read_csv('flights.csv')
print('data.shape:',data.shape)
data = data.sample(frac=0.1, random_state=10)
print('after sample data.shape:',data.shape)
print(data.columns)

data = data[["MONTH", "DAY", "DAY_OF_WEEK", "AIRLINE", "FLIGHT_NUMBER", "DESTINATION_AIRPORT",
             "ORIGIN_AIRPORT", "AIR_TIME", "DEPARTURE_TIME", "DISTANCE", "ARRIVAL_DELAY"]]

print(data.head(5))

data.dropna(inplace=True)
print(data.head(5))

data["ARRIVAL_DELAY"] = (data["ARRIVAL_DELAY"] > 10) * 1

cols = ["AIRLINE", "FLIGHT_NUMBER", "DESTINATION_AIRPORT", "ORIGIN_AIRPORT"]
for item in cols:
    data[item] = data[item].astype("category").cat.codes + 1

train, test, y_train, y_test = train_test_split(data.drop(["ARRIVAL_DELAY"], axis=1), data["ARRIVAL_DELAY"],
                                                random_state=10, test_size=0.25)

import xgboost as xgb
### https://xgboost.readthedocs.io/en/stable/parameter.html

def auc(m, train, test):
    return (metrics.roc_auc_score(y_train, m.predict_proba(train)[:, 1]),
            metrics.roc_auc_score(y_test, m.predict_proba(test)[:, 1]))


# # Parameter Tuning
# model = xgb.XGBClassifier(tree_method='gpu_hist', gpu_id=0)
# param_dist = {"max_depth": [10,20,30],
#               "min_child_weight" : [1,3],
#               # "n_estimators": [200,500],
#               "subsample":[0.8,0.9,1],
#               "lambda":[3,6,9],
#               "alpha":[3,6],
#               # "learning_rate": [0.05, 0.1,0.5],
#                "learning_rate": [0.1],
#               }
# grid_search = GridSearchCV(model, param_grid=param_dist, cv = 3,
#                                    verbose=10, n_jobs=-1)
# grid_search.fit(train, y_train)
# print('XGBClassifier best_params_:', grid_search.best_params_)
# # alpha=3, lambda=3, learning_rate=0.1, max_depth=20, min_child_weight=1,
# # subsample=0.8;, score=0.810 total time=38.6min



model = xgb.XGBClassifier(max_depth=20, min_child_weight=3,  n_estimators=1000,learning_rate=0.05,
                          reg_lambda=1, alpha=1,
                           # subsample=0.8,
                          n_jobs=-1, verbose=10,
                          tree_method='gpu_hist', gpu_id=0)
model.fit(train,y_train,verbose=10)

print('xgboost model score:',auc(model, train, test))
#xgboost model score (0.9999999975811984, 0.7899954118937722)
#20% xgboost model score: (0.9999985093055754, 0.8220708882482494)


import lightgbm as lgb
## https://lightgbm.readthedocs.io/en/latest/Parameters-Tuning.html
def auc2(m, train, test):
    return (metrics.roc_auc_score(y_train, m.predict(train)),
            metrics.roc_auc_score(y_test, m.predict(test)))


# lg = lgb.LGBMClassifier(verbose=0,
#                         learning_rate=0.5,
#                         device_type='gpu',gpu_device_id= 0,gpu_platform_id=0,gpu_use_dp='false')
# param_dist = {
#     "max_depth": [25, 50, 75],
#     #           "learning_rate": [0.01, 0.05, 0.1],
#               "num_leaves": [100,300, 900],
#     #           "num_iterations": [200,500],
#     #           "feature_fraction": [0.7,0.8, 0.9, 1.0],
#     #           "bagging_fraction": [0,7,0.8, 0.9, 1.0],
#     # LGBMClassifier best_params_: {'bagging_fraction': 0.8, 'feature_fraction': 1.0}
#             'bagging_fraction': [0.8], 'feature_fraction': [1.0],
#
#               # "lambda_l1": [0, 3, 6, 9],
#               # "lambda_l2": [0, 3, 6],
#     # LGBMClassifier best_params_: {'lambda_l1': 6, 'lambda_l2': 3, 'num_iterations': 500}
#             'lambda_l1': [6], 'lambda_l2': [3], 'num_iterations': [500],
#     # LGBMClassifier best_params_: {'bagging_fraction': 0.8, 'feature_fraction': 1.0,
#     # 'lambda_l1': 6, 'lambda_l2': 3, 'max_depth': 75, 'num_iterations': 500, 'num_leaves': 300}
#               }
# grid_search = GridSearchCV(lg, n_jobs=-1, param_grid=param_dist, cv=3, scoring="roc_auc", verbose=1)
# grid_search.fit(train, y_train)
# print('LGBMClassifier best_estimator:', grid_search.best_estimator_)
# print('LGBMClassifier best_params_:', grid_search.best_params_)
# # learning_rate=0.05, max_depth=50, num_iterations=200, num_leaves=300;, score=0.763 total time= 3.1min

d_train = lgb.Dataset(train, label=y_train, free_raw_data=False)
# END learning_rate=0.05, max_depth=25, num_iterations=200, num_leaves=1200;, score=0.772 total time=10.6min
params = {"max_depth": 75, "learning_rate": 0.1, "num_leaves": 300,
          'lambda_l1': 6, 'lambda_l2': 3, 'num_iterations': 2000,
          'bagging_fraction': 0.8, 'feature_fraction': 1.0,
          # 'device': "gpu", 'gpu_device_id': 1,
          # 'gpu_platform_id': 1,
          # 'gpu_use_dp': 'false',
          # 'max_bin': 252,
          # 'num_gpu': 2
          }

# Without Categorical Features
model2 = lgb.train(params, d_train)
print('lightGBM Without Categorical Features:', auc2(model2, train, test))
# lightGBM Without Categorical Features: (0.9832532745589256, 0.7892403986379332)
#
# With Catgeorical Features
cate_features_name = ["MONTH", "DAY", "DAY_OF_WEEK", "AIRLINE", "DESTINATION_AIRPORT",
                      "ORIGIN_AIRPORT"]
model2 = lgb.train(params, d_train, categorical_feature=cate_features_name)
print('lightGBM With Categorical Features:', auc2(model2, train, test))
# lightGBM With Categorical Features: (0.9849578833000501, 0.7765037053711114)

import catboost

cat_features_index = [0, 1, 2, 3, 4, 5, 6]


def auc(m, train, test):
    return (metrics.roc_auc_score(y_train, m.predict_proba(train)[:, 1]),
            metrics.roc_auc_score(y_test, m.predict_proba(test)[:, 1]))

#
# # params = {'depth': [7, 10,13],
# #           'learning_rate': [0.03, 0.15, 0.2],
# #           'l2_leaf_reg': [1, 4, 7],
# #           'iterations': [300,500]}
# # cb = catboost.CatBoostClassifier(task_type="GPU",
# #                            devices='0')
# # cb_model = GridSearchCV(cb, params, scoring="roc_auc", cv=3)
# # cb_model.fit(train, y_train)
# # print('CatBoostClassifier best_estimator:',cb_model.best_estimator_)
# # print('CatBoostClassifier best_params_:',cb_model.best_params_)
#
# With Categorical features
clf = catboost.CatBoostClassifier(eval_metric="AUC", depth=10, iterations=500, l2_leaf_reg=4, learning_rate=0.15
                            , task_type="GPU", devices='0')
clf.fit(train, y_train,plot=True)
print('CatBoostClassifier Without Categorical Features:', auc(clf, train, test))
# CatBoostClassifier Without Categorical Features: (0.8411768106404672, 0.7571423657177548)
# 20% CatBoostClassifier Without Categorical Features: (0.8125473336833896, 0.767777462764133)

# With Categorical features
clf = catboost.CatBoostClassifier(eval_metric="AUC", one_hot_max_size=31, \
                            depth=10, iterations=500, l2_leaf_reg=4, learning_rate=0.15
                            , task_type="GPU", devices='0')
clf.fit(train, y_train, cat_features=cat_features_index,plot=True)
print('CatBoostClassifier With Categorical Features:', auc(clf, train, test))
plt.show()
# CatBoostClassifier With Categorical Features: (0.881573635663068, 0.8129717796545255)
# CatBoostClassifier With Categorical Features: (0.8969051893380249, 0.8243120308981184)
# 20% CatBoostClassifier With Categorical Features: (0.8942350930660874, 0.8478804417411229)

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值