Files
my_wiki/raw/量化/abuquant-src/abupy/MLBu/ABuML.py
T

1897 lines
91 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- encoding:utf-8 -*-
"""
中间层,从上层拿到xydf
拥有create estimator
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import logging
import os
import functools
from enum import Enum
import numpy as np
import pandas as pd
from sklearn.base import TransformerMixin, ClassifierMixin, RegressorMixin, clone
from sklearn import metrics
from sklearn.datasets import load_iris
from sklearn.feature_selection import RFE, VarianceThreshold
from sklearn.preprocessing import label_binarize, StandardScaler, binarize
from . import ABuMLExecute
from .ABuMLCreater import AbuMLCreater
from ..CoreBu import ABuEnv
from ..CoreBu.ABuFixes import train_test_split, cross_val_score, mean_squared_error_scorer, six
from ..UtilBu import ABuFileUtil
from ..UtilBu.ABuProgress import AbuProgress
from ..UtilBu.ABuDTUtil import warnings_filter
from ..UtilBu.ABuDTUtil import params_to_numpy
from ..CoreBu.ABuFixes import signature
__author__ = '阿布'
__weixin__ = 'abu_quant'
p_dir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.path.pardir))
ML_TEST_FILE = os.path.join(p_dir, 'RomDataBu/ml_test.csv')
class _EMLScoreType(Enum):
"""针对有监督学习的度量支持enum"""
"""有监督学习度量准确率"""
E_SCORE_ACCURACY = 'accuracy'
"""有监督学习度量mse"""
E_SCORE_MSE = mean_squared_error_scorer
"""有监督学习度量roc_auc"""
E_SCORE_ROC_AUC = 'roc_auc'
class EMLFitType(Enum):
"""支持常使用的学习器类别enum"""
"""有监督学习:自动选择,根据y的label数量,> 10使用回归否则使用分类"""
E_FIT_AUTO = 'auto'
"""有监督学习:回归"""
E_FIT_REG = 'reg'
"""有监督学习:分类"""
E_FIT_CLF = 'clf'
"""无监督学习:HMM"""
E_FIT_HMM = 'hmm'
"""无监督学习:PCA"""
E_FIT_PCA = 'pca'
"""无监督学习:KMEAN"""
E_FIT_KMEAN = 'kmean'
def entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG, EMLFitType.E_FIT_HMM,
EMLFitType.E_FIT_PCA, EMLFitType.E_FIT_KMEAN)):
"""
类装饰器函数,对关键字参数中的fiter_type进行标准化,egfiter_type参数是'clf' 转换为EMLFitType(fiter_type)
赋予self.fiter_type,检测当前使用的具体学习器不在support参数中不执行被装饰的func函数了,打个log返回
:param support: 默认 support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG, EMLFitType.E_FIT_HMM,
EMLFitType.E_FIT_PCA, EMLFitType.E_FIT_KMEAN)
即支持所有,被装饰的函数根据自身特性选择装饰参数
"""
def decorate(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
org_fiter_type = self.fiter_type
if 'fiter_type' in kwargs:
# 如果传递了fiter_type参数,pop出来
fiter_type = kwargs.pop('fiter_type')
# 如果传递的fiter_type参数是streg'clf' 转换为EMLFitType(fiter_type)
if isinstance(fiter_type, six.string_types):
fiter_type = EMLFitType(fiter_type)
self.fiter_type = fiter_type
check_support = self.fiter_type
if self.fiter_type == EMLFitType.E_FIT_AUTO:
# 把auto的归到具体的分类或者回归
check_y = self.y
if 'y' in kwargs:
check_y = kwargs['y']
check_support = EMLFitType.E_FIT_CLF if len(np.unique(check_y)) <= 10 else EMLFitType.E_FIT_REG
if check_support not in support:
# 当前使用的具体学习器不在support参数中不执行被装饰的func函数了,打个log返回
self.log_func('{} not support {}!'.format(func.__name__, check_support.value))
# 如果没能成功执行把类型再切换回来
self.fiter_type = org_fiter_type
return
return func(self, *args, **kwargs)
return wrapper
return decorate
# noinspection PyUnresolvedReferences
class AbuML(object):
"""封装有简单学习及无监督学习方法以及相关操作类"""
@classmethod
def create_test_fiter(cls):
"""
类方法:使用iris数据构造AbuML对象,测试接口,通过简单iris数据对方法以及策略进行验证
iris数据量小,如需要更多数据进行接口测试可使用create_test_more_fiter接口
eg: iris_abu = AbuML.create_test_fiter()
:return: AbuML(x, y, df)
eg: df
y x0 x1 x2 x3
0 0 5.1 3.5 1.4 0.2
1 0 4.9 3.0 1.4 0.2
2 0 4.7 3.2 1.3 0.2
3 0 4.6 3.1 1.5 0.2
4 0 5.0 3.6 1.4 0.2
.. .. ... ... ... ...
145 2 6.7 3.0 5.2 2.3
146 2 6.3 2.5 5.0 1.9
147 2 6.5 3.0 5.2 2.0
148 2 6.2 3.4 5.4 2.3
149 2 5.9 3.0 5.1 1.8
"""
iris = load_iris()
x = iris.data
"""
eg: iris.data
array([[ 5.1, 3.5, 1.4, 0.2],
[ 4.9, 3. , 1.4, 0.2],
[ 4.7, 3.2, 1.3, 0.2],
[ 4.6, 3.1, 1.5, 0.2],
[ 5. , 3.6, 1.4, 0.2],
....... ....... .......
[ 6.7, 3. , 5.2, 2.3],
[ 6.3, 2.5, 5. , 1.9],
[ 6.5, 3. , 5.2, 2. ],
[ 6.2, 3.4, 5.4, 2.3],
[ 5.9, 3. , 5.1, 1.8]])
"""
y = iris.target
"""
eg: y
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
"""
x_df = pd.DataFrame(x, columns=['x0', 'x1', 'x2', 'x3'])
y_df = pd.DataFrame(y, columns=['y'])
df = y_df.join(x_df)
return AbuML(x, y, df)
@classmethod
def load_ttn_raw_df(cls):
"""
读取泰坦尼克测试数据
:return: pd.DataFrame对象,from接口pd.read_csv(train_csv_path)
"""
train_csv_path = ML_TEST_FILE
if not ABuFileUtil.file_exist(train_csv_path):
# 泰坦尼克数据文件如果不存在RuntimeError
raise RuntimeError('{} not exist, please down a ml_test.csv!'.format(train_csv_path))
# 训练文件使用read_csv从文件读取
return pd.read_csv(train_csv_path)
@classmethod
@warnings_filter
def create_test_more_fiter(cls):
"""
类方法:使用泰坦尼克数据构造AbuML对象,测试接口,对方法以及策略进行验证 比iris数据多
eg: ttn_abu = AbuML.create_test_more_fiter()
:return: AbuML(x, y, df),构造AbuML最终的泰坦尼克数据形式如:
eg: df
Survived SibSp Parch Cabin_No Cabin_Yes Embarked_C Embarked_Q \
0 0 1 0 1 0 0 0
1 1 1 0 0 1 1 0
2 1 0 0 1 0 0 0
3 1 1 0 0 1 0 0
4 0 0 0 1 0 0 0
5 0 0 0 1 0 0 1
6 0 0 0 0 1 0 0
7 0 3 1 1 0 0 0
8 1 0 2 1 0 0 0
9 1 1 0 1 0 1 0
.. ... ... ... ... ... ... ...
Embarked_S Sex_female Sex_male Pclass_1 Pclass_2 Pclass_3 \
0 1 0 1 0 0 1
1 0 1 0 1 0 0
2 1 1 0 0 0 1
3 1 1 0 1 0 0
4 1 0 1 0 0 1
5 0 0 1 0 0 1
6 1 0 1 1 0 0
7 1 0 1 0 0 1
8 1 1 0 0 0 1
9 0 1 0 0 1 0
.. ... ... ... ... ... ...
Age_scaled Fare_scaled
0 -0.5614 -0.5024
1 0.6132 0.7868
2 -0.2677 -0.4889
3 0.3930 0.4207
4 0.3930 -0.4863
5 -0.4271 -0.4781
6 1.7877 0.3958
7 -2.0295 -0.2241
8 -0.1943 -0.4243
.. ... ...
"""
raw_df = cls.load_ttn_raw_df()
def set_missing_ages(p_df):
"""
对数据中缺失的年龄使用RandomForestRegressor进行填充
"""
from sklearn.ensemble import RandomForestRegressor
age_df = p_df[['Age', 'Fare', 'Parch', 'SibSp', 'Pclass']]
known_age = age_df[age_df.Age.notnull()].as_matrix()
unknown_age = age_df[age_df.Age.isnull()].as_matrix()
y_inner = known_age[:, 0]
x_inner = known_age[:, 1:]
rfr_inner = RandomForestRegressor(random_state=0, n_estimators=2000, n_jobs=-1)
rfr_inner.fit(x_inner, y_inner)
predicted_ages = rfr_inner.predict(unknown_age[:, 1::])
p_df.loc[(p_df.Age.isnull()), 'Age'] = predicted_ages
return p_df, rfr_inner
def set_cabin_type(p_df):
"""
对数据中缺失的Cabin处理
"""
p_df.loc[(p_df.Cabin.notnull()), 'Cabin'] = "Yes"
p_df.loc[(p_df.Cabin.isnull()), 'Cabin'] = "No"
return p_df
raw_df, rfr = set_missing_ages(raw_df)
raw_df = set_cabin_type(raw_df)
# 对多label使用get_dummies进行离散二值化处理
dummies_cabin = pd.get_dummies(raw_df['Cabin'], prefix='Cabin')
"""
eg:
data_train['Cabin']:
0 No
1 Yes
2 No
3 Yes
4 No
5 No
6 Yes
7 No
8 No
9 No
...
dummies_cabin:
Cabin_No Cabin_Yes
0 1 0
1 0 1
2 1 0
3 0 1
4 1 0
5 1 0
6 0 1
7 1 0
8 1 0
9 1 0
.. ... ...
"""
dummies__embarked = pd.get_dummies(raw_df['Embarked'], prefix='Embarked')
dummies__sex = pd.get_dummies(raw_df['Sex'], prefix='Sex')
dummies__pclass = pd.get_dummies(raw_df['Pclass'], prefix='Pclass')
# 将离散二值化处理生成的dummies和data进行拼接
df = pd.concat([raw_df, dummies_cabin, dummies__embarked, dummies__sex, dummies__pclass], axis=1)
# 删除之前非离散二值的数据
# noinspection PyUnresolvedReferences
df.drop(['Pclass', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], axis=1, inplace=True)
# 使用StandardScaler对数据进行标准化处理
scaler = StandardScaler()
# noinspection PyUnresolvedReferences
df['Age_scaled'] = scaler.fit_transform(df['Age'].values.reshape(-1, 1))
"""
eg:
df['Age']
0 22.000
1 38.000
2 26.000
3 35.000
4 35.000
5 23.829
6 54.000
7 2.000
8 27.000
9 14.000
...
df['Age_scaled']
0 -0.5614
1 0.6132
2 -0.2677
3 0.3930
4 0.3930
5 -0.4271
6 1.7877
7 -2.0295
8 -0.1943
9 -1.1486
...
"""
# noinspection PyUnresolvedReferences
df['Fare_scaled'] = scaler.fit_transform(df['Fare'].values.reshape(-1, 1))
# noinspection PyUnresolvedReferences
df = df.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Cabin_.*|Embarked_.*|Sex_.*|Pclass_.*')
train_np = df.as_matrix()
y = train_np[:, 0]
x = train_np[:, 1:]
return AbuML(x, y, df)
def __init__(self, x, y, df, fiter_type=EMLFitType.E_FIT_AUTO):
"""
AbuML属于中间层需要所有原料都配齐,x, y, df,构造方式参考
create_test_fiter方法中的实行流程
:param x: 训练集x矩阵,numpy矩阵
:param y: 训练集y序列,numpy序列
:param df: 拆分xy使用的pd.DataFrame对象
:param fiter_type: 使用的学习器类型,默认使用E_FIT_AUTO即根据y的label数量选择分类或者回归
"""
self.estimator = AbuMLCreater()
# 如果传递进来的是字符串类型,转换为EMLFitType
if isinstance(fiter_type, six.string_types):
fiter_type = EMLFitType(fiter_type)
self.x = x
self.y = y
self.df = df
# ipython notebook下使用logging.info
self.log_func = logging.info if ABuEnv.g_is_ipython else print
self.fiter_type = fiter_type
def is_supervised_learning(self):
"""
返回self.fiter_type所使用的是有监督学习还是无监督学习
:return: boolTrue: 有监督,False: 无监督
"""
return self.fiter_type == EMLFitType.E_FIT_REG or self.fiter_type == EMLFitType.E_FIT_CLF or \
self.fiter_type == EMLFitType.E_FIT_AUTO
def echo_info(self, fiter=None):
"""
显示fiter class信息,self.df信息包括,headtaildescribe
eg
fiter class is: DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
max_features=None, max_leaf_nodes=None,
min_impurity_split=1e-07, min_samples_leaf=1,
min_samples_split=2, min_weight_fraction_leaf=0.0,
presort=False, random_state=None, splitter='best')
describe:
y x0 x1 x2 x3
count 150.0000 150.0000 150.0000 150.0000 150.0000
mean 1.0000 5.8433 3.0540 3.7587 1.1987
std 0.8192 0.8281 0.4336 1.7644 0.7632
min 0.0000 4.3000 2.0000 1.0000 0.1000
25% 0.0000 5.1000 2.8000 1.6000 0.3000
50% 1.0000 5.8000 3.0000 4.3500 1.3000
75% 2.0000 6.4000 3.3000 5.1000 1.8000
max 2.0000 7.9000 4.4000 6.9000 2.5000
:param fiter:
:return:
"""
if fiter is None:
fiter = self.get_fiter()
self.log_func('fiter class is: {}'.format(fiter))
self.log_func('describe:\n{}'.format(self.df.describe()))
self.log_func('head:\n{}'.format(self.df.head()))
self.log_func('tail:\n{}'.format(self.df.tail()))
def get_fiter(self):
"""
根据self.fiter_type的类型选择从self.estimator返回学习器对象
self.fiter_type == EMLFitType.E_FIT_AUTO
自动选择有简单学习,当y的label数量 < 10个使用分类self.estimator.clf,否则回归self.estimator.reg
self.fiter_type == EMLFitType.E_FIT_REG:
使用有监督学习回归self.estimator.reg
self.fiter_type == EMLFitType.E_FIT_CLF:
使用有监督学习分类self.estimator.clf
self.fiter_type == EMLFitType.E_FIT_HMM:
使用无监督学习hmmself.estimator.hmm
self.fiter_type == EMLFitType.E_FIT_PCA:
使用无监督学习pcaself.estimator.pca
self.fiter_type == EMLFitType.E_FIT_KMEAN:
使用无监督学习kmeanself.estimator.kmean
:return: 返回学习器对象
"""
if self.fiter_type == EMLFitType.E_FIT_AUTO:
if len(np.unique(self.y)) <= 10:
# 小于等于10个class的y就认为是要用分类了
fiter = self.estimator.clf
else:
fiter = self.estimator.reg
elif self.fiter_type == EMLFitType.E_FIT_REG:
fiter = self.estimator.reg
elif self.fiter_type == EMLFitType.E_FIT_CLF:
fiter = self.estimator.clf
elif self.fiter_type == EMLFitType.E_FIT_HMM:
if self.estimator.hmm is None:
self.estimator.hmm_gaussian()
fiter = self.estimator.hmm
elif self.fiter_type == EMLFitType.E_FIT_PCA:
if self.estimator.pca is None:
self.estimator.pca_decomposition()
fiter = self.estimator.pca
elif self.fiter_type == EMLFitType.E_FIT_KMEAN:
if self.estimator.kmean is None:
self.estimator.kmean_cluster()
fiter = self.estimator.kmean
else:
raise TypeError('self.fiter_type = {}, is error type'.format(self.fiter_type))
return fiter
@entry_wrapper(support=(EMLFitType.E_FIT_CLF,))
def cross_val_accuracy_score(self, cv=10, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF,))装饰,
即只支持有监督学习分类,使用cross_val_score对数据进行accuracy度量
:param cv: 透传cross_val_score的参数,默认10
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
确定传递self._do_cross_val_score中参数xy
装饰器使用的fiter_typeegttn_abu.cross_val_accuracy_score(fiter_type=ml.EMLFitType.E_FIT_CLF)
:return: cross_val_score返回的score序列,
eg: array([ 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 0.95, 1. ])
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
return self._do_cross_val_score(x, y, cv, _EMLScoreType.E_SCORE_ACCURACY.value)
@entry_wrapper(support=(EMLFitType.E_FIT_CLF,))
def cross_val_prob_accuracy_score(self, pb_threshold, cv=10, show=True, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF,))装饰,
即只支持有监督学习分类,拆分训练集,测试集,对所有数据进行一次predict_proba
获取分类的概率(具体阅读ABuMLExecute.run_prob_cv_estimator),之后根据
pb_threshold的值对结果概率进行二值转换,pb_threshold的均衡对影响数据的度量
准确度等
eg:
in: ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.estimator.svc(probability=True)
ttn_abu.cross_val_prob_accuracy_score(pb_threshold=0.60)
out:
threshold=0.6 prob accuracy=0.83, effect cnt=870, effect rate=0.98, score=0.81
阀值0.6,准确率0.83,生效比例0.98,分数0.81
in:
ttn_abu.cross_val_prob_accuracy_score(pb_threshold=0.80)
out:
threshold=0.8 prob accuracy=0.87, effect cnt=718, effect rate=0.81, score=0.70
阀值0.8,准确率0.87 提高,生效比例0.81 降低,分数0.70 降低
in:
ttn_abu.cross_val_prob_accuracy_score(pb_threshold=0.85)
out:
threshold=0.85 prob accuracy=0.89, effect cnt=337, effect rate=0.38, score=0.34
阀值0.85,准确率0.89 再次提高,生效比例0.38 很低,分数0.34 降低
即通过训练集数据寻找合适的prob值对数据的predict_prob进行非均衡处理,必然对交易的拦截进行非均衡
处理,只对有很大概率的的交易进行拦截
:param pb_threshold: binarize(y_prob, threshold=pb_threshold)中使用的二分阀值,float0-1)
:param cv: 透传ABuMLExecute.run_prob_cv_estimator中的cv参数,默认10int
:param show: 是否显示输出结果信息,默认显示
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
确定传递self._do_cross_val_score中参数xy
装饰器使用的fiter_type
:return: accuracy, effect_cnt, effect_rate, score
"""
if pb_threshold < 0.0 or pb_threshold > 1:
self.log_func('pb_threshold must > 0 and < 1! now={}'.format(pb_threshold))
return
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
y_prob = ABuMLExecute.run_prob_cv_estimator(fiter, x, y, n_folds=cv)
"""
eg: y_prob
array([[ 0.8726, 0.1274],
[ 0.0925, 0.9075],
[ 0.2485, 0.7515],
...,
[ 0.3881, 0.6119],
[ 0.7472, 0.2528],
[ 0.8555, 0.1445]])
"""
y_prob_binarize = binarize(y_prob, threshold=pb_threshold)
"""
根据参数中pb_threshold的值对y_prob进行二值化,二值化的结果中有一行全是1,或者全是0的,
pb_threshold的值越是非均衡,结果中全是1,或者全是0的的数据越多,度量准确性的时候这些都
是期权票
eg: y_prob_binarize
array([[ 1., 0.],
[ 0., 1.],
[ 1., 1.],
...,
[ 0., 0.],
[ 1., 0.],
[ 1., 0.]])
"""
# y_unique eg: array([ 0., 1.])
y_unique = np.unique(y)
y_label_binarize_df = pd.get_dummies(y, prefix='true')
"""
eg: y_label_binarize_df
true_0.0 true_1.0
0 1 0
1 0 1
2 0 1
3 0 1
4 1 0
5 1 0
6 1 0
7 1 0
8 0 1
9 0 1
.. ... ...
881 1 0
882 1 0
883 1 0
884 1 0
885 1 0
886 1 0
887 0 1
888 1 0
889 0 1
890 1 0
"""
y_prob_df = pd.DataFrame(y_prob_binarize, columns=['prob_{}'.format(y_label) for y_label in y_unique])
"""
eg: y_prob_df
prob_0.0 prob_1.0
0 1.0 0.0
1 0.0 1.0
2 0.0 1.0
3 0.0 1.0
4 1.0 0.0
5 1.0 0.0
6 1.0 0.0
7 1.0 0.0
8 0.0 0.0
9 0.0 1.0
.. ... ...
881 1.0 0.0
882 0.0 1.0
883 1.0 0.0
884 1.0 0.0
885 1.0 0.0
886 1.0 0.0
887 0.0 1.0
888 0.0 0.0
889 1.0 0.0
890 1.0 0.0
"""
# 把两个df合并起来
true_prob_df = pd.concat([y_label_binarize_df, y_prob_df], axis=1)
"""
eg: true_prob_df
true_0.0 true_1.0 prob_0.0 prob_1.0
0 1 0 1.0 0.0
1 0 1 0.0 1.0
2 0 1 0.0 1.0
3 0 1 0.0 1.0
4 1 0 1.0 0.0
5 1 0 1.0 0.0
6 1 0 1.0 0.0
7 1 0 1.0 0.0
8 0 1 0.0 0.0
9 0 1 0.0 1.0
.. ... ... ... ...
881 1 0 1.0 0.0
882 1 0 0.0 1.0
883 1 0 1.0 0.0
884 1 0 1.0 0.0
885 1 0 1.0 0.0
886 1 0 1.0 0.0
887 0 1 0.0 1.0
888 1 0 0.0 0.0
889 0 1 1.0 0.0
890 1 0 1.0 0.0
"""
# 即筛选出非均衡阀值情况下有效的投票行index
vote_index = (y_prob_df.sum(axis=1) > 0) & (y_prob_df.sum(axis=1) < 2)
"""
需要过滤非均衡阀值情况下如pb_threshold = 0.1,都投了1
和如pb_threshold = 0.9,都不进行投票(全是0)的情况
eg: pb_threshold = 0.1
prob_0.0 prob_1.0
0 1.0 1.0
1 1.0 1.0
2 1.0 1.0
3 1.0 1.0
4 1.0 1.0
5 1.0 1.0
.. ... ...
eg: pb_threshold = 0.9
prob_0.0 prob_1.0
0 0.0 0.0
1 0.0 0.0
2 0.0 0.0
3 0.0 0.0
4 0.0 0.0
5 0.0 0.0
.. ... ...
"""
# 再次进行拆开,根据vote_index
# noinspection PyUnresolvedReferences
true_df = true_prob_df[vote_index].filter(regex='true*')
# noinspection PyUnresolvedReferences
prob_df = true_prob_df[vote_index].filter(regex='prob*')
"""
prob_df即是y_prob_df中拥有有效投票的序列,true_df对应prob_df的index
egprob_df
prob_0.0 prob_1.0
0 1.0 0.0
1 0.0 1.0
2 0.0 1.0
3 0.0 1.0
4 1.0 0.0
5 1.0 0.0
6 1.0 0.0
7 1.0 0.0
9 0.0 1.0
10 0.0 1.0
.. ... ...
880 0.0 1.0
881 1.0 0.0
882 0.0 1.0
883 1.0 0.0
884 1.0 0.0
885 1.0 0.0
886 1.0 0.0
887 0.0 1.0
889 1.0 0.0
890 1.0 0.0
"""
# 生效数量,投票不合格的不做准确率统计
effect_cnt = prob_df.shape[0]
# 生效率:effect_cnt / y.shape[0]
effect_rate = effect_cnt / y.shape[0]
# 生效的数据准确率
accuracy = 0.0
if effect_cnt > 0:
accuracy = metrics.accuracy_score(true_df, prob_df)
# 分数:生效比例 * 生效准确率(0-1)
score = effect_rate * accuracy
if show:
self.log_func(
'threshold={} prob accuracy={:.2f}, effect cnt={}, effect rate={:.2f}, score={:.2f}'.format(
pb_threshold,
accuracy,
effect_cnt,
effect_rate,
score))
return accuracy, effect_cnt, effect_rate, score
@entry_wrapper(support=(EMLFitType.E_FIT_KMEAN,))
def cross_val_silhouette_score(self, cv=10, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_KMEAN, ))装饰,即
只支持无监督学习kmean的cv验证,使用silhouette_score对聚类后的结果labels_
进行度量使用silhouette_score
:param cv: 透传run_silhouette_cv_estimator的参数,默认10
:param kwargs: 外部可以传递x 通过
x = kwargs.pop('x', self.x)
确定传递ABuMLExecute.run_silhouette_cv_estimator中参数x
装饰器使用的fiter_type
egttn_abu.cross_val_silhouette_score(fiter_type=ml.EMLFitType.E_FIT_KMEAN)
:return: run_silhouette_cv_estimator返回的score序列,
eg: array([ 0.6322, 0.6935, 0.7187, 0.6887, 0.6699, 0.703 , 0.6922,
0.7049, 0.6462, 0.6755])
"""
x = kwargs.pop('x', self.x)
fiter = self.get_fiter()
scores = ABuMLExecute.run_silhouette_cv_estimator(fiter, x, n_folds=cv)
scores = np.array(scores)
self.log_func('{} score mean: {}'.format(fiter.__class__.__name__, scores.mean()))
return scores
@entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))
def cross_val_mean_squared_score(self, cv=10, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))装饰,
即支持有监督学习回归和分类,使用cross_val_score对数据进行rmse度量
:param cv: 透传cross_val_score的参数,默认10
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
确定传递self._do_cross_val_score中参数xy
以及装饰器使用的fiter_typeegttn_abu.cross_val_roc_auc_score(fiter_type=ml.EMLFitType.E_FIT_CLF)
:return: cross_val_score返回的score序列,
eg: array([-0.1889, -0.1667, -0.2135, -0.1348, -0.1573, -0.2022, -0.1798,
-0.2022, -0.1348, -0.1705])
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
return self._do_cross_val_score(x, y, cv, _EMLScoreType.E_SCORE_MSE.value)
@entry_wrapper(support=(EMLFitType.E_FIT_CLF,))
def cross_val_roc_auc_score(self, cv=10, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF,))装饰,
即支持有监督学习分类,使用cross_val_score对数据进行roc_auc度量,如果数据的y的
label标签 > 2,通过label_binarize将label标签进行二值化处理,
依次计算二值化的列的roc_auc,结果返回score最好的数据度量
:param cv: 透传cross_val_score的参数,默认10
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
确定传递self._do_cross_val_score中参数xy
以及装饰器使用的fiter_typeegttn_abu.cross_val_roc_auc_score(fiter_type=ml.EMLFitType.E_FIT_REG)
:return: cross_val_score返回的score序列,
eg: array([ 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 0.95, 1. ])
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
return self._do_cross_val_score(x, y, cv, _EMLScoreType.E_SCORE_ROC_AUC.value)
@entry_wrapper()
def feature_selection(self, show=True, **kwargs):
"""
被装饰器entry_wrapper()装饰,默认参数即支持有监督和无监督学习
监督学习通过sklern中的RFE包装拟合器进行fit(x, y),对数据的特征进行ranking和support评定
eg
RFE selection
ranking support
SibSp 1 True
Parch 1 True
Cabin_No 1 True
Cabin_Yes 7 False
Embarked_C 2 False
Embarked_Q 3 False
Embarked_S 5 False
Sex_female 8 False
Sex_male 1 True
Pclass_1 4 False
Pclass_2 6 False
Pclass_3 1 True
Age_scaled 1 True
Fare_scaled 1 True
无监督学习通过sklern中的VarianceThreshold进行fit(x),根据x的方差进行特征评定
eg:
unsupervised VarianceThreshold
support
SibSp True
Parch True
Cabin_No True
Cabin_Yes True
Embarked_C True
Embarked_Q True
Embarked_S True
Sex_female True
Sex_male True
Pclass_1 True
Pclass_2 True
Pclass_3 True
Age_scaled True
Fare_scaled True
:param show: 是否在内部输出打印结果
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
确定传递self._do_cross_val_score中参数xy
以及装饰器使用的fiter_typeegttn_abu.feature_selection(fiter_type=ml.EMLFitType.E_FIT_REG)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
if self.is_supervised_learning():
selector = RFE(fiter)
selector.fit(x, y)
feature_df = pd.DataFrame({
'support': selector.support_, 'ranking': selector.ranking_}, index=self.df.columns[1:])
if show:
self.log_func('RFE selection')
self.log_func(feature_df)
else:
selector = VarianceThreshold()
selector.fit(x)
feature_df = pd.DataFrame({
'support': selector.get_support()}, index=self.df.columns[1:])
if show:
self.log_func('unsupervised VarianceThreshold')
self.log_func(feature_df)
return feature_df
@entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))
def importances_coef_pd(self, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))装饰,
即支持有监督学习回归和分类,根据fit后的feature_importances_或者coef_和原始self.df.columns
组成pd.DataFrame对象返回
eg
feature importance
7 Sex_female 0.0000
10 Pclass_2 0.0018
3 Cabin_Yes 0.0033
5 Embarked_Q 0.0045
9 Pclass_1 0.0048
4 Embarked_C 0.0098
6 Embarked_S 0.0105
1 Parch 0.0154
2 Cabin_No 0.0396
0 SibSp 0.0506
11 Pclass_3 0.0790
13 Fare_scaled 0.1877
12 Age_scaled 0.2870
8 Sex_male 0.3060
coef columns
0 [-0.344229036121] SibSp
1 [-0.1049314305] Parch
2 [0.0] Cabin_No
3 [0.902140498996] Cabin_Yes
4 [0.0] Embarked_C
5 [0.0] Embarked_Q
6 [-0.417254399259] Embarked_S
7 [1.95656682017] Sex_female
8 [-0.677432099492] Sex_male
9 [0.3411515052] Pclass_1
10 [0.0] Pclass_2
11 [-1.19413332987] Pclass_3
12 [-0.523782082975] Age_scaled
13 [0.0844326510536] Fare_scaled
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
以及装饰器使用的fiter_typeegttn_abu.importances_coef_pd(fiter_type=ml.EMLFitType.E_FIT_REG)
:return: pd.DataFrame对象
"""
if not hasattr(self, 'df'):
raise ValueError('please make a df func first!')
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
# 训练前进行clone(fiter)
fiter = clone(fiter)
fiter.fit(x, y)
# self.echo_info(fiter)
if hasattr(fiter, 'feature_importances_'):
return pd.DataFrame(
{'feature': list(self.df.columns)[1:], 'importance': fiter.feature_importances_}).sort_values(
'importance')
elif hasattr(fiter, 'coef_'):
return pd.DataFrame({"columns": list(self.df.columns)[1:], "coef": list(fiter.coef_.T)})
else:
self.log_func('fiter not hasattr feature_importances_ or coef_!')
@entry_wrapper(support=(EMLFitType.E_FIT_CLF,))
def train_test_split_xy(self, test_size=0.1, random_state=0, **kwargs):
"""
被entry_wrapper(support=(EMLFitType.E_FIT_CLF, ))装饰,即只支持分类
首先使用train_test_split将xy根据参数test_size切割训练集和测试集,
显示数据集,训练集,测试集的数量,针对训练集数据进行训练,使用训练好的
分类器对测试集x进行predict,对结果分别使用metrics.accuracy_score,
metrics.precision_score, metrics.recall_score度量准确率,查准率,
和召回率,多label的的情况下使用average = 'macro'对precision_score和
recall_score进行度量,最后显示分类结果混淆矩阵以及metrics.classification_report
情况
eg:
x-y:(891, 14)-(891,)
train_x-train_y:(801, 14)-(801,)
test_x-test_y:(90, 14)-(90,)
accuracy = 0.77
precision_score = 0.74
recall_score = 0.72
Predicted
| 0 | 1 |
|-----|-----|
0 | 41 | 10 |
Actual |-----|-----|
1 | 11 | 28 |
|-----|-----|
precision recall f1-score support
0.0 0.79 0.80 0.80 51
1.0 0.74 0.72 0.73 39
avg / total 0.77 0.77 0.77 90
:param test_size: 测试集占比例,float,默认0.1,即将数据分10份,一份做为测试集
:param random_state: 透传给train_test_split的随机参数
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
以及装饰器使用的fiter_typeegttn_abu.train_test_split_xy(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
train_x, test_x, train_y, test_y = train_test_split(x,
y,
test_size=test_size,
random_state=random_state)
self.log_func('x-y:{}-{}'.format(x.shape, y.shape))
self.log_func('train_x-train_y:{}-{}'.format(train_x.shape, train_y.shape))
self.log_func('test_x-test_y:{}-{}'.format(test_x.shape, test_y.shape))
fiter = self.get_fiter()
# 训练前进行clone(fiter)
fiter = clone(fiter)
# 针对训练集数据进行训练
clf = fiter.fit(train_x, train_y)
# 使用训练好的分类器对测试集x进行predict,结果y_predict
y_predict = clf.predict(test_x)
# 度量分类准确率
self.log_func("accuracy = %.2f" % (metrics.accuracy_score(test_y, y_predict)))
# precision_score和predictions在二分类的情况下使用binary
average = 'binary'
if len(np.unique(y)) != 2:
# “micro表示在多分类中的对所有label进行averaging计算平均precisionrecall以及F值等度量
average = 'macro'
# 度量分类查准率
self.log_func("precision_score = %.2f" % (metrics.precision_score(test_y, y_predict, average=average)))
# 度量分类召回率
self.log_func("recall_score = %.2f" % (metrics.recall_score(test_y, y_predict, average=average)))
# 混淆矩阵以及metrics.classification_report
self._confusion_matrix_with_report(test_y, y_predict, labels=np.unique(y))
def train_test_split_df(self, test_size=0.1, random_state=0, **kwargs):
"""
套接封装train_test_split_xy,外部传递pd.DataFrame参数时使用
:param test_size: 透传参数train_test_split_xy
:param random_state: 透传参数train_test_split_xy
:param kwargs: 通过 df = kwargs.pop('df', self.df)弹出传递的pd.DataFrame对象进行xy分解
y = matrix[:, 0],即硬编码分类y在第一列,外部传递的df对象需要遵循
以及装饰器使用的fiter_typeegttn_abu.train_test_split_df(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
df = kwargs.pop('df', self.df)
matrix = df.as_matrix()
y = matrix[:, 0]
x = matrix[:, 1:]
self.train_test_split_xy(test_size=test_size, random_state=random_state, x=x, y=y, **kwargs)
@entry_wrapper()
def fit(self, **kwargs):
"""
包装fit操作,根据是否是有监督学习来区别
使用fit(x, y)还是fit(x)
eg:
in: iris_abu.estimator.random_forest_classifier()
iris_abu.fit()
out:
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
max_depth=None, max_features='auto', max_leaf_nodes=None,
min_impurity_split=1e-07, min_samples_leaf=1,
min_samples_split=2, min_weight_fraction_leaf=0.0,
n_estimators=100, n_jobs=1, oob_score=False, random_state=None,
verbose=0, warm_start=False)
:param kwargs:
:return: fit(x, y)或者fit(x)操作后返回
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
if hasattr(fiter, 'fit'):
if self.is_supervised_learning():
fit_self = fiter.fit(x, y)
else:
fit_self = fiter.fit(x)
return fit_self
else:
self.log_func('{} not support fit'.format(fiter))
@entry_wrapper()
def fit_transform(self, **kwargs):
"""
被装饰器@entry_wrapper()装饰,默认参数即支持有监督和无监督学习,
内部通过检测isinstance(fiter, TransformerMixin) or hasattr(fiter, 'fit_transform')
来判定是否可以fit_transform
eg
input: ttn_abu.x.shape
output: (891, 14)
input: ttn_abu.fit_transform(fiter_type=ml.EMLFitType.E_FIT_PCA).shape
output: (891, 4)
input: ttn_abu.fit_transform(fiter_type=ml.EMLFitType.E_FIT_KMEAN).shape
output: (891, 2)
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
以及装饰器使用的fiter_typeegttn_abu.fit_transform(fiter_type=ml.EMLFitType.E_FIT_CLF)
:return: fit_transform后的转换结果矩阵
"""
fiter = self.get_fiter()
if isinstance(fiter, TransformerMixin) or hasattr(fiter, 'fit_transform'):
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
if self.is_supervised_learning():
trans = fiter.fit_transform(x, y)
else:
trans = fiter.fit_transform(x)
return trans
else:
self.log_func('{} not support fit_transform'.format(fiter))
def predict(self, x, pre_fit=True, **kwargs):
"""
call有监督和无监督学习的predict,套接self._predict_callback方法,其
被装饰器params_to_numpy装饰,将predict参数中所有可迭代序列变成numpy,
即统一将x转换numpy序列,
eg:
test_input = pd.DataFrame.from_dict({'x0': 6.8, 'x1': 3.5, 'x2': 5.4, 'x3': 2.2}, orient='index')
test_input:
0
x0 6.8
x1 3.5
x2 5.4
x3 2.2
iris_abu.predict(test_input)
params_to_numpy装饰后参数中的x转换为:array([[ 6.8, 3.5, 5.4, 2.2]]) numpy array
被装饰器entry_wrapper()装饰,默认参数即支持有监督和无监督学习
:param x: 可迭代序列,通过params_to_numpy装饰统一转换numpy
:param pre_fit: bool,默认pre_fit True, 代表每次predict前先fit
如在乎效率的情况下,需要在外部先fit后,参数pre_fit置False
:param kwargs: 装饰器使用的fiter_typeegttn_abu.predict(test_input, fiter_type=ml.EMLFitType.E_FIT_KMEAN)
:return: eg: array([2])
"""
return self._predict_callback('predict', x, pre_fit=pre_fit, **kwargs)
def predict_proba(self, x, pre_fit=True, **kwargs):
"""
call有监督和无监督学习的predict_proba,套接self._predict_callback方法,其
被装饰器params_to_numpy装饰,将predict参数中所有可迭代序列变成numpy,
即统一将x转换numpy序列,
eg:
test_input = pd.DataFrame.from_dict({'x0': 6.8, 'x1': 3.5, 'x2': 5.4, 'x3': 2.2}, orient='index')
test_input:
0
x0 6.8
x1 3.5
x2 5.4
x3 2.2
iris_abu.predict_proba(test_input, fiter_type=ml.EMLFitType.E_FIT_CLF)
params_to_numpy装饰后参数中的x转换为:array([[ 6.8, 3.5, 5.4, 2.2]]) numpy array
被装饰器entry_wrapper()装饰,默认参数即支持有监督和无监督学习
:param x: 通过params_to_numpy装饰统一转换numpy
:param pre_fit: bool,默认pre_fit True, 代表每次predict前先fit
如在乎效率的情况下,需要在外部先fit后,参数pre_fit置False
:param kwargs: 装饰器使用的fiter_typeegiris_abu.predict_proba(test_input, fiter_type=ml.EMLFitType.E_FIT_CLF)
:return: eg: array([[ 0.2, 0.3, 0.5]])
"""
return self._predict_callback('predict_proba', x, pre_fit=pre_fit, **kwargs)
def predict_proba_threshold(self, x, threshold, default_ret, pre_fit=True, **kwargs):
"""
eg
in: ttn_abu = AbuML.create_test_more_fiter()
in: ttn_abu.estimator.svc(probability=True)
in ttn_abu.search_match_pos_threshold(0.85, 0.80, fiter_type=ml.EMLFitType.E_FIT_CLF)
out: 0.770 satisfy require, accuracy:0.850, effect_rate:0.854
即通过search_match_pos_threshold获取了predict_proba的二分阀值为0.77时,分类的正确率达到0.85, 且覆盖80%样本
in: test = np.array([ 1. , 0. , 0. , 1. , 1. , 0. , 0. ,1. , 0. , 1.
, 0. , 0. , 0.8132, 0.5868])
in: ttn_abu.predict_proba(test)
out: array([[ 0.106, 0.894]])
使用predict_proba得到的是分类的概率
in: ttn_abu.predict_proba_threshold(test, threshold=0.77 ,default_ret=0)
out: 1
使用predict_proba_threshold将阀值threshold设定0.77后,可以得到输出为1,即概率 0.894 > 0.77, 标签1分类成立
in: test2 = np.array([ 0. , 1. , 1. , 0. , 1. , 1. , 0. ,1. , 0. , 0.
, 0. , 1. , 0.7832, 0.2868])
in: ttn_abu.predict_proba(test2)
out: array([[ 0.2372, 0.7628]])
in: ttn_abu.predict_proba_threshold(test2, threshold=0.77 ,default_ret=0)
out: 0
对test2做predict_proba_threshold返回0,因为0.7628 < 0.77, 标签1的分类不成立,返回default_ret
应用场景:比如对交易进行拦截,实行高放行率,低拦截率,0代表放行,1代表拦截,
上述predict_proba_threshold(test2, threshold=0.77 ,default_ret=0)
即可实行对较大概率的交易进行拦截,即把握大的进行拦截,把握不大的默认选择放行
:param x: 在predict_proba中通过params_to_numpy装饰统一转换numpy
:param threshold: 对predict_proba结果进行二值化的阀值 eg threshold=0.77
:param default_ret: 使用predict_proba返回的矢量和不等于1时,即没有进行有效投票时返回的值:
eg
proba = np.where(proba >= threshold, 1, 0)
if proba.sum() != 1:
# eg: proba = array([[ 0.2328, 0.7672]])->array([[0, 0]])
return default_ret
:param pre_fit: bool,默认pre_fit True, 代表每次predict前先fit
如在乎效率的情况下,需要在外部先fit后,参数pre_fit置False
:param kwargs: 装饰器使用的fiter_type
egiris_abu.predict_proba_threshold(test_input, , threshold=0.77 ,default_ret=0
fiter_type=ml.EMLFitType.E_FIT_CLF)
:return: intdefault_ret or proba.argmax()
"""
# 套接self.predict_proba对x所描述的特征进行概率proba
proba = self.predict_proba(x, pre_fit=pre_fit, **kwargs)
# egarray([[ 0.1063, 0.8937]]) -> array([[0, 1]])
# noinspection PyTypeChecker
proba = np.where(proba >= threshold, 1, 0)
if proba.sum() != 1:
# eg: proba = array([[ 0.2328, 0.7672]])->array([[0, 0]])
return default_ret
# 唯一最大值就是序列值为1的,通过argmax获取index,即y label
return proba.argmax()
@params_to_numpy
@entry_wrapper()
def _predict_callback(self, callback, x, pre_fit=True, **kwargs):
"""
统一封装predict和predict需要的流程,使用callback做为具体实现
:param callback: str字符类型,不是callable类型
:param x: 可迭代序列,通过params_to_numpy装饰统一转换numpy
:param pre_fit: bool,默认pre_fit True, 代表每次predict前先fit
如在乎效率的情况下,需要在外部先fit后,参数pre_fit置False
:param kwargs: 装饰器使用的fiter_typeegttn_abu.predict(test_input, fiter_type=ml.EMLFitType.E_FIT_KMEAN)
:return: eg: array([2])
"""
# 标准化输入x
x = x.reshape(1, -1)
if self.x[0].reshape(1, -1).shape != x.shape:
# predict中有check_input=True也check,返回训练集中的一个数据做为input x的示例
self.log_func('input x must similar with {}'.format(self.x[0]))
return
if pre_fit:
# 默认pre_fit True, 代表每次predict前先fit,如在乎效率的情况下,需要在外部先fit后,参数pre_fit置False
self.fit(**kwargs)
fiter = self.get_fiter()
if not isinstance(callback, six.string_types):
# callback必须是字符串类型
self.log_func('callback must str, not {}'.format(type(callback)))
return
if hasattr(fiter, callback):
if 'check_input' in list(signature(fiter.predict).parameters.keys()):
# 针对有check_input参数的,check_input True, 因为前面X.dtype np.float32等格式化问题
return getattr(fiter, callback)(x, check_input=True)
else:
return getattr(fiter, callback)(x)
else:
self.log_func('{} not support {}'.format(fiter, callback))
# TODO 需要重构这个类,太长了
def search_match_neg_threshold(self, accuracy_match=0, effect_rate_match=0, neg_num=50, **kwargs):
"""
套接self.cross_val_prob_accuracy_score,通过np.linspace(0.01, 0.50, num=neg_num)[::-1]生成
pb_threshold参数序列,这里linspace的start从0.01至0.50后[::-1]倒序,依次迭代生成的阀值参数
,当cross_val_prob_accuracy_score返回的正确率大于 参数中accuracy_match且返回的生效率大于参数中的effect_rate_match
匹配寻找成功,中断迭代操作,返回寻找到的满足条件的阀值,返回的阀值应用场景阅读predict_proba_threshold函数
eg:
in: ttn_abu.search_match_neg_threshold(0.85, 0.80, fiter_type=ml.EMLFitType.E_FIT_CLF)
out: 0.220 satisfy require, accuracy:0.852, effect_rate:0.844
:param accuracy_match: 寻找阀值条件,需要当cross_val_prob_accuracy_score返回的正确率大于accuracy_match
float 范围(0-1),默认值0
:param effect_rate_match: 寻找阀值条件,需要当cross_val_prob_accuracy_score返回的生效率大于effect_rate_match
float 范围(0-1),默认值0
:param neg_num: 透传neg_thresholds = np.linspace(0.01, 0.50, num=neg_num)[::-1]的参数,默认50
:param kwargs: 装饰器使用的fiter_type
eg: iris_abu.search_match_neg_threshold(0.85, 0.80, fiter_type=ml.EMLFitType.E_FIT_CLF)
:return: 返回寻找到的满足条件的阀值,float
"""
neg_thresholds = np.linspace(0.01, 0.50, num=neg_num)[::-1]
"""
eg: neg_thresholds
array([ 0.5 , 0.49, 0.48, 0.47, 0.46, 0.45, 0.44, 0.43, 0.42,
0.41, 0.4 , 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33,
0.32, 0.31, 0.3 , 0.29, 0.28, 0.27, 0.26, 0.25, 0.24,
0.23, 0.22, 0.21, 0.2 , 0.19, 0.18, 0.17, 0.16, 0.15,
0.14, 0.13, 0.12, 0.11, 0.1 , 0.09, 0.08, 0.07, 0.06,
0.05, 0.04, 0.03, 0.02, 0.01])
"""
with AbuProgress(len(neg_thresholds), 0, 'search neg threshold') as search_neg_progress:
for neg in neg_thresholds:
accuracy, _, effect_rate, _ = self.cross_val_prob_accuracy_score(neg, show=False, **kwargs)
search_neg_progress.show(ext='threshold:{:.2f} accuracy:{:.2f}, effect_rate:{:.2f}'.format(
neg, accuracy, effect_rate))
if accuracy >= accuracy_match and effect_rate >= effect_rate_match:
# eg: 0.500 satisfy require, accuracy:0.940, effect_rate:1.000
self.log_func('{:.3f} satisfy require, accuracy:{:.3f}, effect_rate:{:.3f}'.format(
neg, accuracy, effect_rate))
# 返回寻找到的满足条件的阀值
return neg
# 迭代完成所有neg_thresholds,没有找到符合参数需求的二分阀值
self.log_func('neg_thresholds no satisfy require, search failed!')
def search_match_pos_threshold(self, accuracy_match=0, effect_rate_match=0, pos_num=50, **kwargs):
"""
套接self.cross_val_prob_accuracy_score,通过np.linspace(0.50, 0.99, num=neg_num)生成
pb_threshold参数序列,这里linspace的start从0.50至0.99正序,依次迭代生成的阀值参数
,当cross_val_prob_accuracy_score返回的正确率大于 参数中accuracy_match且返回的生效率大于参数中的effect_rate_match
匹配寻找成功,中断迭代操作,返回寻找到的满足条件的阀值,返回的阀值应用场景阅读predict_proba_threshold函数
eg:
in: ttn_abu.search_match_pos_threshold(0.85, 0.80, fiter_type=ml.EMLFitType.E_FIT_CLF)
out: 0.770 satisfy require, accuracy:0.850, effect_rate:0.854
:param accuracy_match: 寻找阀值条件,需要当cross_val_prob_accuracy_score返回的正确率大于accuracy_match
float 范围(0-1),默认值0
:param effect_rate_match: 寻找阀值条件,需要当cross_val_prob_accuracy_score返回的生效率大于effect_rate_match
float 范围(0-1),默认值0
:param pos_num: 透传neg_thresholds = np.linspace(0.50, 0.99, num=neg_num)的参数,默认50
:param kwargs: 装饰器使用的fiter_type
eg: iris_abu.search_match_pos_threshold(0.85, 0.80, fiter_type=ml.EMLFitType.E_FIT_CLF)
:return: 返回寻找到的满足条件的阀值,float
"""
pos_thresholds = np.linspace(0.50, 0.99, num=pos_num)
"""
eg: array([ 0.5 , 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58,
0.59, 0.6 , 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67,
0.68, 0.69, 0.7 , 0.71, 0.72, 0.73, 0.74, 0.75, 0.76,
0.77, 0.78, 0.79, 0.8 , 0.81, 0.82, 0.83, 0.84, 0.85,
0.86, 0.87, 0.88, 0.89, 0.9 , 0.91, 0.92, 0.93, 0.94,
0.95, 0.96, 0.97, 0.98, 0.99])
"""
with AbuProgress(len(pos_thresholds), 0, 'search pos threshold') as search_pos_progress:
for neg in pos_thresholds:
accuracy, _, effect_rate, _ = self.cross_val_prob_accuracy_score(neg, show=False, **kwargs)
search_pos_progress.show(ext='threshold:{:.2f} accuracy:{:.2f}, effect_rate:{:.2f}'.format(
neg, accuracy, effect_rate))
if accuracy >= accuracy_match and effect_rate >= effect_rate_match:
# eg: 0.500 satisfy require, accuracy:0.940, effect_rate:1.000
self.log_func('{:.3f} satisfy require, accuracy:{:.3f}, effect_rate:{:.3f}'.format(
neg, accuracy, effect_rate))
# 返回寻找到的满足条件的阀值
return neg
# 迭代完成所有pos_thresholds,没有找到符合参数需求的二分阀值
self.log_func('pos_thresholds no satisfy require, search failed!')
@entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))
def plot_learning_curve(self, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))装饰,
即支持有监督学习回归和分类,绘制训练集数据的学习曲线,当训练集的y标签label非2分问题,
使用OneVsOneClassifier进行包装
:param kwargs:
外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
装饰器使用的fiter_type
eg:
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.plot_learning_curve(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
if self.fiter_type == EMLFitType.E_FIT_CLF and len(np.unique(y)) != 2:
# 多标签,使用OneVsOneClassifier进行包装,onevsreset_classifier参数assign默认是false
fiter = self.estimator.onevsreset_classifier(fiter)
ABuMLExecute.plot_learning_curve(fiter, x, y)
@entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))
def plot_graphviz_tree(self, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))装饰,
即支持有监督学习回归和分类,绘制决策树或者core基于树的分类回归算法的决策示意图绘制,查看
学习器本身hasattr(fiter, 'tree_')是否有tree_属性,如果没有使用决策树替换
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
装饰器使用的fiter_type
eg:
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.plot_graphviz_tree(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
if not hasattr(fiter, 'tree_'):
self.log_func('{} not hasattr tree_, use decision tree replace'.format(
fiter.__class__.__name__))
if isinstance(fiter, ClassifierMixin):
# FIXME 最好不要使用ClassifierMixin判定学习器类型,因为限定了sklearn
fiter = self.estimator.decision_tree_classifier(assign=False)
elif isinstance(fiter, RegressorMixin):
# # FIXME 最好不要使用RegressorMixin, AbuMLCreater中引用了hmmlearnxgboost等第三方库
fiter = self.estimator.decision_tree_regressor(assign=False)
else:
fiter = self.estimator.decision_tree_classifier(assign=False)
# 这里需要将self.df.columns做为名字传入
return ABuMLExecute.graphviz_tree(fiter, self.df.columns, x, y)
@entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))
def plot_visualize_tree(self, use_pca=True, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))装饰,
即支持有监督学习回归和分类, 绘制特征平面,由于特征平面需要x的维度只能是2维,所以对
x的特征列多于两个的进行降维操作,默认使用pca,还可以选择根据特征的重要, 程度选择两个importances
最重要的特征进行特征平面绘制
:param use_pca: 是否使用pca进行降维,bool,默认True
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
装饰器使用的fiter_type
eg:
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.plot_visualize_tree(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
# 进行降维
x = self._decomposition_2x(x, use_pca=use_pca)
ABuMLExecute.visualize_tree(fiter, x, y)
@entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))
def plot_decision_function(self, use_pca=True, **kwargs):
"""
被装饰器entry_wrapper(support=(EMLFitType.E_FIT_CLF, EMLFitType.E_FIT_REG))装饰,
即支持有监督学习回归和分类
:param use_pca: 是否使用pca进行降维,bool,默认True
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
装饰器使用的fiter_type
eg:
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.plot_decision_function(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
# 进行降维
x = self._decomposition_2x(x, use_pca=use_pca)
# 训练前进行clone(fiter)
fiter = clone(fiter)
fiter.fit(x, y)
ABuMLExecute.plot_decision_boundary(lambda p_x: fiter.predict(p_x), x, y)
@entry_wrapper(support=(EMLFitType.E_FIT_CLF,))
def plot_roc_estimator(self, pos_label=None, **kwargs):
"""
被entry_wrapper(support=(EMLFitType.E_FIT_CLF, ))装饰,即只支持分类
计算fpr, tpr, thresholds,最后绘制roc_auc曲线进行可视化操作
:param pos_label:
:param kwargs: 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
装饰器使用的fiter_type
eg:
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.plot_roc_estimator(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
ABuMLExecute.plot_roc_estimator(fiter, x, y, pos_label=pos_label)
@entry_wrapper(support=(EMLFitType.E_FIT_CLF,))
def plot_confusion_matrices(self, **kwargs):
"""
被entry_wrapper(support=(EMLFitType.E_FIT_CLF, ))装饰,即只支持分类
套接plot_confusion_matrices进行训练集测试集拆封分混淆矩阵计算且可视化
混淆矩阵
:param 外部可以传递x, y, 通过
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
装饰器使用的fiter_type
eg:
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.plot_confusion_matrices(fiter_type=ml.EMLFitType.E_FIT_CLF)
"""
x = kwargs.pop('x', self.x)
y = kwargs.pop('y', self.y)
fiter = self.get_fiter()
ABuMLExecute.plot_confusion_matrices(fiter, x, y)
def bagging_classifier_best(self, **kwargs):
"""
eg
bagging_classifier_best有param_grid参数调用:
param_grid = {'max_samples': np.arange(1, 5), 'n_estimators': np.arange(100, 300, 50)}
ttn_abu.bagging_classifier_best(param_grid=param_grid, n_jobs=-1)
out: BaggingClassifier(max_samples=4, n_estimators=100)
bagging_classifier_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.bagging_classifier_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'max_samples': np.arange(1, 5), 'n_estimators': np.arange(100, 300, 50)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的BaggingClassifier对象
"""
return self.estimator.bagging_classifier_best(self.x, self.y, **kwargs)
def bagging_regressor_best(self, **kwargs):
"""
eg
bagging_regressor_best有param_grid参数调用:
param_grid = {'max_samples': np.arange(1, 5), 'n_estimators': np.arange(100, 300, 50)}
ttn_abu.bagging_regressor_best(param_grid=param_grid, n_jobs=-1)
out: BaggingRegressor(max_samples=4, n_estimators=250)
bagging_regressor_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.bagging_regressor_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'max_samples': np.arange(1, 5), 'n_estimators': np.arange(100, 300, 50)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的BaggingRegressor对象
"""
return self.estimator.bagging_regressor_best(self.x, self.y, **kwargs)
def adaboost_regressor_best(self, **kwargs):
"""
eg
adaboost_regressor_best有param_grid参数调用:
param_grid = {'learning_rate': np.arange(0.2, 1.2, 0.2), 'n_estimators': np.arange(10, 100, 10)}
ttn_abu.adaboost_regressor_best(param_grid=param_grid, n_jobs=-1)
out: AdaBoostRegressor(learning_rate=0.8, n_estimators=40)
adaboost_regressor_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.adaboost_regressor_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'learning_rate': np.arange(0.2, 1.2, 0.2),
'n_estimators': np.arange(10, 100, 10)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的AdaBoostRegressor对象
"""
return self.estimator.adaboost_regressor_best(self.x, self.y, **kwargs)
def adaboost_classifier_best(self, **kwargs):
"""
eg
adaboost_classifier_best有param_grid参数调用:
param_grid = {'learning_rate': np.arange(0.2, 1.2, 0.2), 'n_estimators': np.arange(10, 100, 10)}
ttn_abu.adaboost_classifier_best(param_grid=param_grid, n_jobs=-1)
out: AdaBoostClassifier(learning_rate=0.6, n_estimators=70)
adaboost_classifier_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.adaboost_classifier_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'learning_rate': np.arange(0.2, 1.2, 0.2),
'n_estimators': np.arange(10, 100, 10)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的AdaBoostClassifier对象
"""
return self.estimator.adaboost_classifier_best(self.x, self.y, **kwargs)
def random_forest_classifier_best(self, **kwargs):
"""
eg
random_forest_classifier_best有param_grid参数调用:
param_grid = {'max_features': ['sqrt', 'log2', ], 'n_estimators': np.arange(50, 200, 20)}
ttn_abu.random_forest_classifier_best(param_grid=param_grid, n_jobs=-1)
out: RandomForestClassifier(max_features='sqrt', n_estimators=190)
random_forest_classifier_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.random_forest_classifier_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'max_features': ['sqrt', 'log2', ],
'n_estimators': np.arange(10, 150, 15)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的RandomForestClassifier对象
"""
return self.estimator.random_forest_classifier_best(self.x, self.y, **kwargs)
def random_forest_regressor_best(self, **kwargs):
"""
eg
random_forest_regressor_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.random_forest_regressor_best()
random_forest_regressor_best有param_grid参数调用:
param_grid = {'max_features': ['sqrt', 'log2', ], 'n_estimators': np.arange(10, 150, 15)}
ttn_abu.random_forest_regressor_best(param_grid=param_grid, n_jobs=-1)
out: RandomForestRegressor(max_features='log2', n_estimators=115)
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'max_features': ['sqrt', 'log2', ],
'n_estimators': np.arange(10, 150, 15)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的RandomForestRegressor对象
"""
return self.estimator.random_forest_regressor_best(self.x, self.y, **kwargs)
def xgb_classifier_best(self, **kwargs):
"""
eg
xgb_classifier_best有param_grid参数调用:
param_grid = {'learning_rate': np.arange(0.1, 0.5, 0.05), 'n_estimators': np.arange(50, 200, 10)}
ttn_abu.xgb_classifier_best(param_grid=param_grid, n_jobs=-1)
out: GradientBoostingClassifier(learning_rate=0.1, n_estimators=160)
xgb_classifier_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.xgb_classifier_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'learning_rate': np.arange(0.1, 0.5, 0.05),
'n_estimators': np.arange(50, 200, 10)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的GradientBoostingClassifier对象
"""
return self.estimator.xgb_classifier_best(self.x, self.y, **kwargs)
def xgb_regressor_best(self, **kwargs):
"""
eg
xgb_regressor_best有param_grid参数调用:
param_grid = {'learning_rate': np.arange(0.1, 0.5, 0.05), 'n_estimators': np.arange(10, 100, 10)}
ttn_abu.xgb_regressor_best(param_grid=param_grid, n_jobs=-1)
out: GradientBoostingRegressor(learning_rate=0.2, n_estimators=70)
xgb_regressor_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.xgb_regressor_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'learning_rate': np.arange(0.1, 0.5, 0.05),
'n_estimators': np.arange(10, 100, 10)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的GradientBoostingRegressor对象
"""
return self.estimator.xgb_regressor_best(self.x, self.y, **kwargs)
def decision_tree_classifier_best(self, **kwargs):
"""
eg
decision_tree_classifier_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.decision_tree_classifier_best()
decision_tree_classifier_best有param_grid参数调用:
param_grid = {'max_features': ['sqrt', 'log2', ], 'max_depth': np.arange(1, 10, 1)}
ttn_abu.decision_tree_classifier_best(param_grid=param_grid, n_jobs=-1)
out: DecisionTreeClassifier(max_features='sqrt', max_depth=7)
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'max_features': ['sqrt', 'log2', ],
'max_depth': np.arange(1, 10, 1)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的DecisionTreeClassifier对象
"""
return self.estimator.decision_tree_classifier_best(self.x, self.y, **kwargs)
def decision_tree_regressor_best(self, **kwargs):
"""
eg
decision_tree_regressor_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.decision_tree_regressor_best()
decision_tree_regressor_best有param_grid参数调用:
param_grid = {'max_features': ['sqrt', 'log2', ], 'max_depth': np.arange(1, 10, 1)}
ttn_abu.decision_tree_regressor_best(param_grid=param_grid, n_jobs=-1)
out: DecisionTreeRegressor(max_features='sqrt', max_depth=3)
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'max_features': ['sqrt', 'log2', ],
'max_depth': np.arange(1, 10, 1)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的DecisionTreeRegressor对象
"""
return self.estimator.decision_tree_regressor_best(self.x, self.y, **kwargs)
def knn_classifier_best(self, **kwargs):
"""
eg
knn_classifier_best有param_grid参数调用:
param_grid = {'algorithm': ['ball_tree', 'kd_tree', 'brute'], 'n_neighbors': np.arange(1, 26, 1)}
ttn_abu.knn_classifier_best(param_grid=param_grid, n_jobs=-1)
out: KNeighborsClassifier(algorithm='ball_tree', n_neighbors=14)
knn_classifier_best无param_grid参数调用:
from abupy import AbuML, ml
ttn_abu = AbuML.create_test_more_fiter()
ttn_abu.knn_classifier_best()
:param kwargs: 关键字可选参数param_grid: 最优字典关键字参数
egparam_grid = {'algorithm': ['ball_tree', 'kd_tree', 'brute'],
'n_neighbors': np.arange(1, 26, 1)}
关键字可选参数assign: 是否保存实例化后最优参数的学习器对象,默认True
关键字可选参数n_jobs: 并行执行的进程任务数量,默认-1, 开启与cpu相同数量的进程数
关键字可选参数show: 是否可视化最优参数搜索结果
:return: 通过最优参数构造的KNeighborsClassifier对象
"""
return self.estimator.knn_classifier_best(self.x, self.y, **kwargs)
def _confusion_matrix_with_report(self, y_true, y_predict, labels=None):
"""
封装metrics.confusion_matrix与metrics.classification_report,对分类
结果进行度量
:param y_true: 原始数据中的y序列值
:param y_predict: 使用分类器predict的y序列值
:param labels: y序列中的lable序列
"""
confusion_matrix = metrics.confusion_matrix(y_true, y_predict, labels=labels)
if len(labels) == 2:
# 只有二分问题Actual/Predicted
self.log_func(" Predicted")
self.log_func(" | 0 | 1 |")
self.log_func(" |-----|-----|")
self.log_func(" 0 | %3d | %3d |" % (confusion_matrix[0, 0],
confusion_matrix[0, 1]))
self.log_func("Actual |-----|-----|")
self.log_func(" 1 | %3d | %3d |" % (confusion_matrix[1, 0],
confusion_matrix[1, 1]))
self.log_func(" |-----|-----|")
else:
# 非二分问题直接显示confusion_matrix
self.log_func("Confusion Matrix: \n{}".format(confusion_matrix))
self.log_func(metrics.classification_report(y_true, y_predict))
def _decomposition_2x(self, x, use_pca):
"""
通过pca进行降维或者选中两个importances最大的特征将
x变成只有两个维度的特征矩阵
:param x: 进行降维的特征矩阵
:param use_pca: 是否使用pca进行特征降维
:return: 降维后的特征矩阵,降维后的矩阵只有两个维度
"""
if use_pca:
# 构造一个临时的pca进行降维,n_components=2只保留两个维度
pca_2n = self.estimator.pca_decomposition(n_components=2, assign=False)
x = pca_2n.fit_transform(x)
"""
eg:
x before fit_transform:
array([[ 1. , 0. , 1. , ..., 1. , -0.5614, -0.5024],
[ 1. , 0. , 0. , ..., 0. , 0.6132, 0.7868],
[ 0. , 0. , 1. , ..., 1. , -0.2677, -0.4889],
...,
[ 1. , 2. , 1. , ..., 1. , -0.9924, -0.1763],
[ 0. , 0. , 0. , ..., 0. , -0.2677, -0.0444],
[ 0. , 0. , 1. , ..., 1. , 0.1727, -0.4924]])
x fit_transform:
array([[ 0.3805, -1.0005],
[ 0.0586, 1.7903],
[-0.3162, -0.7404],
...,
[ 1.6132, -0.5185],
[-0.5952, 0.6252],
[-0.7428, -0.7119]])
"""
else:
# 选中两个importances最大的两个去画决策边界
importances = self.importances_coef_pd()
"""
feature importance
0 SibSp 0.0000
1 Parch 0.0000
3 Cabin_Yes 0.0000
4 Embarked_C 0.0000
5 Embarked_Q 0.0000
6 Embarked_S 0.0000
7 Sex_female 0.0000
9 Pclass_1 0.0000
10 Pclass_2 0.0000
12 Age_scaled 0.0000
13 Fare_scaled 0.0000
2 Cabin_No 0.0831
11 Pclass_3 0.1836
8 Sex_male 0.7333
"""
if importances is None:
self.log_func('self.importances_coef_pd() importances is None!!!')
return
# 根据importance排序特征重要程度,拿出最重要的两个维度index序列, eg: most_two=[8, 11]
most_two = sorted(importances.sort_values('importance').index[-2:].tolist())
# 从x中根据most_two拼接出一个新的x矩阵,只有两个维度
x = np.concatenate((x[:, most_two[0]][:, np.newaxis],
x[:, most_two[1]][:, np.newaxis]), axis=1)
return x
def _do_cross_val_score(self, x, y, cv, scoring):
"""
封装sklearn中cross_val_score方法, 参数x, y, cv, scoring透传cross_val_score
:param x: 训练集x矩阵,numpy矩阵
:param y: 训练集y序列,numpy序列
:param cv: 透传cross_val_scorecv参数,int
:param scoring: 透传cross_val_score, 使用的度量方法
:return: cross_val_score返回的score序列,
eg: array([ 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 1. , 0.9 , 0.95, 1. ])
"""
fiter = self.get_fiter()
"""
eg: fiter
DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
max_features=None, max_leaf_nodes=None,
min_impurity_split=1e-07, min_samples_leaf=1,
min_samples_split=2, min_weight_fraction_leaf=0.0,
presort=False, random_state=None, splitter='best')
"""
if scoring == _EMLScoreType.E_SCORE_ROC_AUC.value and len(np.unique(y)) != 2:
# roc auc的度量下且y的label数量不是2项分类,首先使用label_binarize进行处理
y_label_binarize = label_binarize(y, classes=np.unique(y))
"""
eg
np.unique(y) array([0, 1, 2])
y_label_binarize:
array([[1, 0, 0],
[1, 0, 0],
[1, 0, 0],
[1, 0, 0],
[1, 0, 0],
.........
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
[0, 1, 0],
.........
[0, 0, 1],
[0, 0, 1],
[0, 0, 1],
[0, 0, 1],
[0, 0, 1],
[0, 0, 1]])
"""
label_cnt = len(np.unique(y))
# one vs rest的score平均值的和
mean_sum = 0
# one vs rest中的最好score平均值
best_mean = 0
# 最好score平均值(best_mean)的score序列,做为结果返回
scores = list()
for ind in np.arange(0, label_cnt):
# 开始 one vs rest
_y = y_label_binarize[:, ind]
"""
eg: _y
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
"""
tmp_scores = cross_val_score(fiter, x, _y, cv=cv, scoring=scoring)
tmp_mean = np.mean(tmp_scores)
# one vs rest的score平均值进行叠加sum
mean_sum += tmp_mean
if len(scores) == 0 or tmp_mean > best_mean:
scores = tmp_scores
# one vs rest的score平均值的和 / label_cnt
mean_sc = mean_sum / label_cnt
else:
scores = cross_val_score(fiter, x, y, cv=cv, scoring=scoring)
# 计算度量的score平均值,做为log输出,结果返回的仍然是scores
mean_sc = -np.mean(np.sqrt(-scores)) if scoring == mean_squared_error_scorer \
else np.mean(scores)
self.log_func('{} score mean: {}'.format(fiter.__class__.__name__, mean_sc))
return scores