多分类
背景:多分类是指具有两类以上的分类任务; 例如,分类一组可能是橘子,苹果或梨的水果图像。本文旨在为大家提供一段即写即用的代码,跳过对原理的解说,直接上手跑一版baseline。当然,后续的优化任务还是需要一定的算法基础,比如模型参数以及性能参数优化。
初步结论
本数据集上, 在迭代次数量级基本一致的情况下,lightgbm表现更优:树的固有多分类特性使得不需要OVR或者OVO式的开销,而且lightgbm本身就对决策树进行了优化,因此性能和分类能力都较好。
模型 | AUC | 精确率 | 耗时(s) |
---|---|---|---|
linearSVC | 0.9169 | 0.6708 | 883 |
LR | 0.9226 | 0.6571 | 944 |
lightgbm | 0.9332 | 0.6947 | 600 |
数据定义
一个样本仅对应一个标签
数据量: 800M(32w样本量 * 929 特征)
数据格式
特征1|特征2|...|特征N|label
评测算法
- LR
- linearSVC
- lightgbm
notice: 树模型是天生的多分类模型,LR、linearSVC则是基于“One-Vs-The-Rest”,即为N类训练N个模型,为样本选择一个最佳类别。
参考:多分类和多标签算法
版本
系统 64bit centOS
sklearn 0.19.1
代码走读
import pandas as pd
import numpy as np
import time
import logging
import os, sys
import psutil
import lightgbm as lgb
from datetime import datetime
from itertools import cycle
from sklearn import svm
from sklearn.metrics import *
from sklearn.cross_validation import *
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from sklearn.externals import joblib
from scipy import interp
# 循环读取多个文件
path = "./data/d20190416/"
os.chdir(path)
files = os.listdir(path)
files_csv = list(filter(lambda x: x[:4]=='part' , files))[:200]
data_list = []
for file in files_csv:
tmp = pd.read_csv(path + file, sep = '|', header=None)
data_list.append(tmp)
data_set = pd.concat(data_list, axis = 0)
del data_list
#配置列名
sample_cnt, col_cnt = data_set.shape
cols = ["x_%d"%(i) for i in range(col_cnt - 1)]
cols.append("y")
data_set.columns = cols
# 数据预览,事先准备好one-hot特征,最后一列为label={0,1,2,3}
# >> 0|1|1|1|0|0....|2
- 模型 OneVsRestClassifier
元分类器 svm.LinearSVC
说明:OneVsRestClassifier模块, 是通过将分类问题分解为二进制分类问题来解决,因此构建样本时需要将label列转为二进制格式 e.g. 2 -> [0, 0, 1, 0] 0 ->[1, 0, 0, 0]
性能:单核883s, 迭代1000次
AUC : 0.9169
精确率:0.6708
#########################################################################################
# 模型 OneVsRestClassifier
# 元分类器 svm.LinearSVC
#########################################################################################
y = label_binarize(data_set["y"], classes=[0,1,2,3])
X = data_set.iloc[:, :-1]
# 随机化数据,并划分训练数据和测试数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,random_state=0)
#训练
model = OneVsRestClassifier(svm.LinearSVC(random_state = 0, verbose = 1))
btime = datetime.now()
model.fit(X_train, y_train)
print 'all tasks done. total time used:%s s.\n\n'%((datetime.now() - btime).total_seconds())
# 评价
y_score = model.decision_function(X_test) # 计算属于各个类别的概率,返回值的shape = [n_samples, n_classes]
# 1、调用函数计算micro类型的AUC
print '调用函数auc:', roc_auc_score(y_test, y_score, average='micro')
# 2、混淆矩阵
y_pred = model.predict(X_test) # 预测属于哪个类别
confusion_matrix(y_test.argmax(axis=1), y_pred1.argmax(axis=1)) # 需要0、1、2、3而不是OH编码格式
# 3、经典-精确率、召回率、F1分数
precision_score(y_test, y_pred,average='micro')
recall_score(y_test, y_pred,average='micro')
f1_score(y_test, y_pred,average='micro')
# 4、模型报告
classification_report(y_test, y_pred, digits=4)
''' precision recall f1-score support
0 0.78 0.85 0.81 42276
1 0.83 0.66 0.74 18960
2 0.59 0.34 0.44 13591
3 0.59 0.35 0.44 13170
4 0.00 0.00 0.00 8151
avg / total 0.67 0.60 0.62 96148
'''
# 保存模型
joblib.dump(model, './model/LinearSVC.pkl')
- 模型(分类器) LR
说明:LogisticRegression模块,设置multi_class='ovr',会训练出“类别数”个分类器,构建样本时需要原始label即可
性能:单核944s , 迭代1000次
AUC : 0.9226
精确率:0.6571
#########################################################################################
# 模型 LogisticRegression(random_state=0, solver='sag',multi_class='ovr', verbose = 1)
#########################################################################################
from sklearn.linear_model import LogisticRegression
# 准备数据
X = data_set.iloc[:, :-1]
X_train, X_test, y_train, y_test = train_test_split(X, data_set["y"], test_size=0.3,random_state=0)
# 训练
btime = datetime.now()
lr_clf = LogisticRegression(random_state=0, solver='sag',multi_class='ovr', verbose = 1)
lr_clf.fit(X_train, y_train)
print 'all tasks done. total time used:%s s.\n\n'%((datetime.now() - btime).total_seconds())
# 1、AUC
y_pred_pa = lr_clf.predict_proba(X_test)
y_test_oh = label_binarize(y_test, classes=[0,1,2,3])
print '调用函数auc:', roc_auc_score(y_test_oh, y_pred_pa, average='micro')
# 2、混淆矩阵
y_pred = lr_clf.predict(X_test)
confusion_matrix(y_test, y_pred_1)
# 3、经典-精确率、召回率、F1分数
precision_score(y_test, y_pred_1,average='micro')
recall_score(y_test, y_pred_1,average='micro')
f1_score(y_test, y_pred_1,average='micro')
# 4、模型报告
print(classification_report(y_test, y_pred , digits=4))
# 保存模型
joblib.dump(lr_clf, './model/lr_clf.pkl')
- 模型(分类器) lightgbm
说明:树的输出本身就可以是多分类,应该是操作最简单的,构建样本时需要原始label即可
性能:单核600s, 迭代200次
AUC : 0.9332
精确率:0.6947
#########################################################################################
# 模型 lightgbm
#########################################################################################
import lightgbm as lgb
# 准备数据
X = data_set.iloc[:, :-1]
X_train, X_test, y_train, y_test = train_test_split(X, data_set["y"], test_size=0.3,random_state=0)
# 训练
btime = datetime.now()
train_data=lgb.Dataset(X_train,label=y_train)
validation_data=lgb.Dataset(X_test,label=y_test)
params={
'learning_rate':0.1,
'lambda_l1':0.1,
'lambda_l2':0.2,
'max_depth':6,
'objective':'multiclass',
'num_class':4,
}
clf=lgb.train(params,train_data,valid_sets=[validation_data])
print 'all tasks done. total time used:%s s.\n\n'%((datetime.now() - btime).total_seconds())
# 1、AUC
y_pred_pa = clf.predict(X_test) # !!!注意lgm预测的是分数,类似 sklearn的predict_proba
y_test_oh = label_binarize(y_test, classes= [0,1,2,3])
print '调用函数auc:', roc_auc_score(y_test_oh, y_pred_pa, average='micro')
# 2、混淆矩阵
y_pred = y_pred_pa .argmax(axis=1)
confusion_matrix(y_test, y_pred )
# 3、经典-精确率、召回率、F1分数
precision_score(y_test, y_pred,average='micro')
recall_score(y_test, y_pred,average='micro')
f1_score(y_test, y_pred,average='micro')
# 4、模型报告
print(classification_report(y_test, y_pred))
# 保存模型
joblib.dump(clf, './model/lgb.pkl')
网友评论