Skip to main content

用于 Python 的端到端机器学习工具包 (MLToolkit/mltk)

项目描述

MLToolKit 项目

DOI 文件状态 派皮
www.mltoolkit.org

当前版本:PyMLToolkit [v0.1.11]

MLToolKit (mltk) 是一个 Python 包,提供了一组用户友好的功能,以帮助在数据科学研究、教学或生产重点项目中构建端到端机器学习模型。

介绍

MLToolKit 支持机器学习应用程序开发过程的所有阶段。

安装

pip install pymltoolkit

如果安装因依赖问题而失败,请使用 --no-dependencies 执行上述命令

pip install pymltoolkit --no-dependencies

功能

  • 数据提取(SQL、平面文件、二进制文件、图像等)
  • 探索性数据分析(统计汇总、单变量分析、可视化分布等)
  • 特征工程(支持数字、文本、日期/时间。图像数据支持将集成在 v0.1 的后续版本中)
  • 模型构建(目前仅支持二元分类和回归)
  • 超参数调整 [v0.2 开发中]
  • 交叉验证(将在 v0.1 的后续版本中集成)
  • 模型性能分析、解释预测(LIME 和 SHAP)以及模型之间的性能比较。
  • 用于执行模型构建和评分任务的 JSON 输入脚本。
  • 模型构建 UI [为 v0.2 开发中]
  • ML 模型构建项目 [正在为 v0.2 开发]
  • Auto ML(自动机器学习)[为 v0.2 开发]
  • 模型 Deploymet 和 Serving [包括在内,将针对 v0.2 进行改进]

支持的机器学习算法/包

  • 随机森林分类器:scikit-learn
  • 逻辑回归:statsmodels
  • 深度前馈神经网络 (DFF):张量流
  • 卷积神经网络 (CNN):张量流
  • 梯度提升:catboost、xgboost、lightgbm
  • 线性回归:statsmodels
  • RandomForestRegressor:scikit-learn
  • ...更多模型将在未来的版本中添加...

用法

import mltk

警告:Python 变量、函数或类名称

Python 解释器有许多内置函数。编码时可以覆盖他们的定义,而不会从 Python 解释器发出任何警告。( https://docs.python.org/3/library/functions.html ) 因此,避免将这些名称作为变量、函数或类名。

腹肌全部任何ASCII垃圾桶布尔字节数组字节
可调用的chr类方法编译复杂的德拉特听写目录
divmod枚举评估执行筛选漂浮格式冻结集
获取属性全局变量有属性哈希帮助十六进制ID输入
整数实例是子类迭代器列表当地人地图
最大限度记忆视图分钟下一个目的十月打开秩序
战俘打印财产范围代表反转圆形的
设置排序的静态方法字符串极好的元组
类型变量压缩__进口__

如果您偶然覆盖了任何内置函数(例如列表),请执行以下操作以引入内置定义。

del(list)

同样,避免在 DataFrame 的列名中使用特殊字符和空格。执行以下操作以从列名中删除特殊字符。

Data = mltk.clean_column_names(Data, replace='')

MLToolkit 示例

数据加载和探索

import numpy as np
import pandas as pd
import mltk as mltk

Data = mltk.read_data_csv(file=r'C:\Projects\Data\incomedata.csv')
Data = mltk.clean_column_names(Data, replace='')
Data = mltk.add_identity_column(Data, id_label='ID', start=1, increment=1)
DataStats = mltk.data_description(Data)

数据预处理和特征工程

# Analyze Response Target
print(mltk.variable_frequency(DataFrame=Data, variable='income'))

# Set Target Variables
targetVariable = 'HighIncome'
targetCondition = "income=='>50K'" #For Binary Classification

Data=mltk.set_binary_target(Data, target_condition=targetCondition, target_variable=targetVariable)
print(mltk.variable_frequency(DataFrame=Data, variable=targetVariable))
        Counts  CountsFraction%
income                         
<=50K    24720         75.91904
>50K      7841         24.08096
TOTAL    32561        100.00000
# Flag Records to Exclude
excludeCondition="age < 18"
action = 'flag' # 'drop' #
excludeLabel = 'EXCLUDE'
Data=mltk.exclude_records(Data, exclude_ondition=excludeCondition, action=action, exclude_label=excludeLabel) # )#

# Get list of uniques values in categorical variables
categoryVariables = set({'sex', 'nativecountry', 'race', 'occupation', 'workclass', 'maritalstatus', 'relationship'})
print(mltk.category_lists(Data, list(categoryVariables)))

# Merge unique categorical values
category_merges = [{'variable':'maritalstatus', 'category_variable':'maritalstatus', 'group_value':'Married', 'values':["Married-civ-spouse", "Married-spouse-absent", "Married-AF-spouse"]}]
Data = mltk.merge_categories(Data, category_merges)

# Show Frequency distribution of categorical variable
sourceVariable='maritalstatus'
table = mltk.variable_frequency(Data, variable=sourceVariable, show_plot=False)
table.style.background_gradient(cmap='Greens').set_precision(3)

# Response Rate For Categorical Variables
mltk.variable_responses(Data, variables=categoryVariables, target_variable=targetVariable, show_output=False, show_plot=True)

获取数字单位列表

mltk.get_number_units()

变量操作

# General form
{
	'type':'category'
	'out_type':'cat',
	'include':True,
	'operation':'bucket',
	'variables': {
		'source':'age',
		'destination': None  # None for mult-variable operations, variable1 (for pair operations), variable1a (for pair sequence operation)
	},
        'parameters': {
        'labels_str': ['0', '20', '30', '40', '50', '60', 'INF'],
        'right_inclusive':True,
        "default":'OTHER',
        "null": 'NA'
    }
}
List of Avaiable Transformation
 |- Date/Numeric Transformations (transform)
 | |- normalize
 | |- datepart
 | |- dateadd
 | |- log
 | |- exponent
 | |- segment (piecewise functions)
 |- String Transformation (str_transform)
 | |- normalize
 | |- strcount
 | |- extract
 |- Multi-variable Operations (operation_mult)
 | |- expression
 |- Sequence Order Check (seq_order)
 | |- seqorder
 |- Numeric/Date Comparison* (comparison)
 | |- numdiff
 | |- ratio
 | |- datediff
 | |- rowmin (pair)
 | |- rowmax (pair)
 |- String Comparison* (str_comparison)
 | |- levenshtein
 | |- jaccard
 | |- ..more to add ..
 |- Pair comparison

List of Avaiable Discrete Feature Transforms
 |- Binary Variable (condition)
 |- Numeric to Catergory (buckets)
 |- Entity Grouping (dictionary)
 |- Pair Equality/Existance (pair_equality)
 |- Category Merge(category_merge)
# Transform numeric variable
rule_set = {
    "operation":"normalize", 
    'variables': {
        'source':'age', 
        'destination':'normalizedage'
    },
    "parameters":{"method":"zscore"}
}
Data, transformed_variable = mltk.create_transformed_variable_task(Data, rule_set, return_variable=True)

# Create Categorical Variables from continious variables
sourceVariable='age'
table = mltk.histogram(Data, sourceVariable, n_bins=10, orientation='vertical', density=True, show_plot=True)
print(table)

# Divide to categories
rule_set = {   
    'operation':'bucket',
    'variables': {
        'source':'age', 
        'destination':None
    },
    'parameters': {
        'labels_str': ['0', '20', '30', '40', '50', '60', 'INF'],
        'right_inclusive':True,
        "default":'OTHER',
        "null": 'NA'
    }
}
Data, categoryVariable = mltk.create_categorical_variable_task(Data, rule_set, return_variable=True)
mltk.variable_response(DataFrame=Data, variable=categoryVariable, target_variable=targetVariable, show_plot=True)
            Counts  HighIncome  CountsFraction%  ResponseFraction%  ResponseRate%
ageGRP                                                                           
1_(0,20]      2410           2          7.40149            0.02551        0.08299
2_(20,30]     8162         680         25.06680            8.67236        8.33129
3_(30,40]     8546        2406         26.24612           30.68486       28.15352
4_(40,50]     6983        2655         21.44590           33.86048       38.02091
5_(50,60]     4128        1547         12.67774           19.72963       37.47578
6_(60,INF)    2332         551          7.16194            7.02716       23.62779
TOTAL        32561        7841        100.00000          100.00000        0.24081
# Create One Hot Encoded Variables
Data, featureVariables, targetVariable = mltk.to_one_hot_encode(Data, category_variables=categoryVariables, binary_variables=binaryVariables, target_variable=targetVariable)
Data[identifierColumns+featureVariables+[targetVariable]].sample(5).transpose()

相关性

correlation=mltk.correlation_matrix(Data, featureVariables+[targetVariable], target_variable=targetVariable, method='pearson', return_type='list', show_plot=False)

拆分训练,验证测试数据集

TrainDataset, ValidateDataset, TestDataset = mltk.train_validate_test_split(Data, ratios=(0.6,0.2,0.2))

建筑模型

identifierColumns = ['ID']
modelDataStats = mltk.data_description(TrainDataset)

sample_attributes = {
                    'SampleDescription':'Adult Census Income Dataset',
                    'NumClasses':2,
                    'ClassLabelsMap':{'<=50K':0, '>50K':1},
                    'DataFormat':'table',
                    'RecordIdentifiers':identifierColumns,
                    'ModelDataStats':modelDataStats
                }                 

score_parameters = {
                    'Edges':[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
                    'Percentiles':[0, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1.0],
                    'Threshold':0.5,
                    'Quantiles':10,
                    'TargetClass': '>50K',
                    'ScoreVariable':'Probability',
                    'ScoreLabel':'Score',
                    'QuantileLabel':'Quantile',
                    'PredictedLabel':'Predicted'
                }

分类模型

模型属性

model_attributes = {
                    'ModelID': None,
                    'ModelType':'classification',# 'regression'
                    'EnumerationType': 'binary', # 'multi' 'mono' None
                    'ModelName': 'IncomeLevel',
                    'Version':'0.1',
                    'TrainingMethod': 'supervised'                   
                }

逻辑回归

model_parameters = {
                    'MLAlgorithm':'LGR', # 'RF', #  'NN', # 'CATBST', (# 'CNN',  # 'XGBST')
                    'MaxIterations':50
                }  

随机森林

model_parameters = {
                    'MLAlgorithm':'RF', # 'LGR', #  'NN', # 'CATBST', (# 'CNN',  # 'XGBST')
                    'NTrees':500,
                    'MaxDepth':100,
                    'MinSamplesToSplit':10,
                    'Processors':2,
                    'Verbose':True
                } 

神经网络

# Setup Architecture
# Binary classification
SimpleDFF_architecture = {'layers': [
        {'name': 'Dense1', 'class_name': 'Dense', 'position':'input', 'config':{'units': 512, 'activation':'relu', 'input_shape':(48,)}},
        {'name': 'Dense2', 'class_name': 'Dense', 'position':'hidden', 'config':{'units': 512, 'activation':'relu', 'kernel_regularizer':{'l1':0.01}}},
        {'name': 'Dropout1', 'class_name': 'Dropout', 'position':'hidden', 'config':{'rate':0.5, 'noise_shape':None, 'seed':None}},
        {'name': 'Dense3', 'class_name': 'Dense', 'position':'output',  'config':{'units': 2, 'activation':'softmax'}}
       ]}

# Binary classification 
LogisticRegressionNN_architecture = {'layers': [
        {'name': 'Dense1', 'class_name': 'Dense', 'position':'input',  'config':{'units': 2, 'activation':'softmax', 'input_shape':(32,)}}
       ]}

# Multi Class classification 
n_classes = 8
SimpleImageClassifier_architecture = {'layers': [
        {'name':'Conv2D1', 'type':'Conv2D', 'position':'input', 'config':{'filters':32, 'kernel_size':(3,3), 'strides':None, 'padding':'same', 'activation':'relu', 'input_shape':(128, 128, 1), 'data_format':'channels_last'}},
        {'name':'MaxPooling2D1', 'type':'MaxPooling2D', 'position':'hidden', 'config':{'pool_size':(2,2), 'strides':None, 'padding':'same', 'data_format':'channels_last'}},      
        {'name':'Conv2D2', 'type':'Conv2D', 'position':'hidden', 'config':{'filters': 64, 'kernel_size': (3,3), 'strides':None, 'padding':'same', 'activation':'relu', 'data_format':'channels_last'}},
        {'name':'MaxPooling2D2', 'type':'MaxPooling2D', 'position':'hidden', 'config':{'pool_size':(2,2), 'strides':None, 'padding':'same', 'data_format':'channels_last'}},       
        {'name':'Dropout1', 'type':'Dropout', 'position':'hidden', 'config':{'rate':0.5, 'noise_shape':None, 'seed':None}},
        {'name':'Flatten1', 'type':'Flatten', 'position':'hidden', 'config':{'data_format':'channels_last'}},
        {'name': 'Dense1', 'type':'Dense', 'position':'output',  'config':{'units': 256, 'activation':'relu', 'kernel_regularizer':None}}, 
        {'name':'Dropout2', 'type':'Dropout', 'position':'hidden', 'config':{'rate':0.5, 'noise_shape':None, 'seed':None}},
        {'name': 'Dense2', 'type':'Dense', 'position':'output',  'config':{'units':n_classes, 'activation':'softmax'}}
    ]}

model_parameters = {
                    'MLAlgorithm':'NN',
                    'BatchSize':512,
                    'InputShape':InputShape,
                    'num_classes':2, #change accordingly
                    'Epochs':10,
                    'metrics':['accuracy'],
                    'architecture':SimpleDFF_architecture,
                    'Verbose':True
                } 

CatBoost

model_parameters = {
                    'MLAlgorithm':'CBST',
                    'NTrees': 500,
                    'MaxDepth':10,
                    'LearningRate':0.7,
                    'LossFunction':'Logloss',#crossEntropy
                    'EvalMatrics':'Accuracy',
                    'Imbalanced':False,
                    'TaskType':'GPU',
                    'Processors':2,
                    'UseBestModel':True,
                    'Verbose':True
                }

XGBoost

model_parameters = {
                    'MLAlgorithm':'XGBST',
                    'NTrees': 500,
                    'MaxDepth':10,
                    'LearningRate':0.7,
                    'LossFunction':'binary:logistic',
                    'EvalMatrics':['auc', 'error'],
                    'Regularization': {'L1':0.0, 'L2' 1.0},
                    'SamplesRatioPerTree':0.8,
                    'FeaturesRatioPerTree':1.0,
                    'Processors':2,
                    'EarlyStopAttempts':5,
                    'Verbose':True
                }

光GBM

model_parameters = {
                    'MLAlgorithm':'XGBST',
                    'NTrees': 500,
                    'MaxDepth':10,
                    'LearningRate':0.7,
                    'LossFunction':'binary:logistic',
                    'EvalMatrics':['auc', 'error'],
                    'Regularization': {'L1':0.0, 'L2' 1.0},
                    'SamplesRatioPerTree':0.8,
                    'FeaturesRatioPerTree':1.0,
                    'Processors':2,
                    'EarlyStopAttempts':5,
                    'Verbose':True
                }

构建模型

XModel = mltk.build_ml_model(TrainDataset, ValidateDataset, TestDataset, 
                                  model_variables=modelVariables,
                                  variable_setup = None,
                                  target_variable=targetVariable,
                                  model_attributes=model_attributes, 
                                  sample_attributes=sample_attributes, 
                                  model_parameters=model_parameters, 
                                  score_parameters=score_parameters, 
                                  return_model_object=True, 
                                  show_results=False, 
                                  show_plot=True
                                  )

print(XModel.model_attributes['ModelID'])
print(XModel.model_interpretation['ModelSummary'])
print('ROC AUC: ', XModel.get_auc(curve='roc'))
print('PRC AUC: ', XModel.get_auc(curve='prc'))
print(XModel.model_evaluation['RobustnessTable'])

XModel.plot_eval_matrics(comparison=False)
          minProbability  maxProbability  meanProbability  BucketCount  ResponseCount  BucketFraction  ResponseFraction  BucketPrecision  CumulativeBucketFraction  CumulativeResponseFraction  CumulativePrecision
Quantile                                                                                                                                                                                                           
1                0.00000         0.00008      3.85729e-06          652            3         0.10011           0.00192          0.00460                   1.00000                     1.00000              0.23967
2                0.00008         0.00432      1.52655e-03          651            9         0.09995           0.00577          0.01382                   0.89989                     0.99808              0.26582
3                0.00435         0.02042      1.10941e-02          652           14         0.10011           0.00897          0.02147                   0.79994                     0.99231              0.29731
4                0.02049         0.05702      3.58648e-02          650           20         0.09980           0.01281          0.03077                   0.69983                     0.98334              0.33677
5                0.05711         0.12075      8.51409e-02          652           65         0.10011           0.04164          0.09969                   0.60003                     0.97053              0.38767
6                0.12086         0.20457      1.63366e-01          651          109         0.09995           0.06983          0.16743                   0.49992                     0.92889              0.44533
7                0.20469         0.31870