机器学习归一化特征编码(一)+https://developer.aliyun.com/article/1544815?spm=a2c6h.13148508.setting.19.22454f0e4mZEBN
OneHotEncoder🏖️
当然,除了自然顺序编码外,常见的对离散变量的编码方式还有独热编码,独热编码的过程如下
不难发现,独热编码过程其实和我们此前介绍的哑变量创建过程一致(至少在sklearn中并无差别)。对于独热编码的过程,我们可以通过pd.get_dummies函数实现,也可以通过sklearn中OneHotEncoder评估器(转化器)来实现。
import numpy as np from sklearn.preprocessing import OneHotEncoder categories = np.array(['cat', 'dog', 'fish', 'cat', 'dog', 'bird']).reshape(-1, 1) encoder = OneHotEncoder(sparse=False) onehot = encoder.fit_transform(categories) print(onehot) print(encoder.categories_) [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.] [1. 0. 0.] [0. 1. 0.] [0. 0. 0.]] [array(['bird', 'cat', 'dog', 'fish'], dtype=object)]
对于独热编码的使用,有一点是额外需要注意的,那就是对于二分类离散变量来说,独热编码往往是没有实际作用的。例如对于上述极简数据集而言,Gender的取值是能是M或者F,独热编码转化后,某行Gender_F取值为1、则Gender_M取值必然为0,反之亦然。因此很多时候我们在进行独热编码转化的时候会考虑只对多分类离散变量进行转化,而保留二分类离散变量的原始取值。此时就需要将OneHotEncoder中drop参数调整为’if_binary’,以表示跳过二分类离散变量列
sklearn中逻辑回归的参数解释
- C 惩罚系数
- penalty 正则化项
相比原始损失函数,正则化后的损失函数有两处发生了变化,其一是在原损失函数基础上乘以了系数C,其二则是加入了正则化项。其中系数C也是超参数,需要人工输入,用于调整经验风险部分和结构风险部分的权重,C越大,经验风险部分权重越大,反之结构风险部分权重越大。此外,在L2正则化时,采用的表达式,其实相当于是各参数的平方和除以2,在求最小值时本质上和w的2-范数起到的作用相同,省去开平方是为了简化运算,而除以2则是为了方便后续求导运算,和2次方结果相消。
其实除了最小二乘法和梯度下降以外,还有非常多的关于损失函数的求解方法,而选择损失函数的参数,就是solver参数。
逻辑回归可选的优化方法包括:
- liblinear,这是一种坐标轴下降法,并且该软件包中大多数算法都有C++编写,运行速度很快,支持OVR+L1或OVR+L2;
- lbfgs,全称是L-BFGS,牛顿法的一种改进算法(一种拟牛顿法),适用于小型数据集,并且支持MVM+L2、OVR+L2以及不带惩罚项的情况;
- newton-cg,同样也是一种拟牛顿法,和lbfgs适用情况相同;
- sag,随机平均梯度下降,随机梯度下降的改进版,类似动量法,会在下一轮随机梯度下降开始之前保留一些上一轮的梯度,从而为整个迭代过程增加惯性,除了不支持L1正则化的损失函数求解以外(包括弹性网正则化)其他所有损失函数的求解;
- saga,sag的改进版,修改了梯度惯性的计算方法,使得其支持所有情况下逻辑回归的损失函数求解;
import pandas as pd import numpy as np import warnings warnings.filterwarnings('ignore') %matplotlib inline data = pd.read_csv("creditcard2.csv") from sklearn.preprocessing import MinMaxScaler data['normAmount'] = MinMaxScaler().fit_transform(data['Amount'].values.reshape(-1, 1)) data = data.drop(['Time','Amount'],axis=1) X = data.iloc[:, data.columns != 'Class'].values y = data.iloc[:, data.columns == 'Class']['Class'].values X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 114) def kflod_scores(X,y): fold = KFold(5,shuffle=False) c_param_range = [0.01, 0.1, 1] show_result = pd.DataFrame() recalls = [] cv = KFold(n_splits=5, shuffle=True, random_state=114) for c_param in c_param_range: lr_model = LogisticRegression(C=c_param, penalty="l2") print('-------------------------------------------') print('正则化惩罚力度: ', c_param) print('-------------------------------------------') print('') result = cross_validate( lr_model , X , y , cv=cv , scoring="recall" , verbose=True , n_jobs=-1 ) print(result["test_score"]) recalls.append(np.mean(result["test_score"])) show_result["c_param"] = list(c_param_range) show_result["recall"] = recalls return show_result kflod_scores(X_train,y_train)
刚刚进行的建模存在一些问题:
(1).过程不够严谨,诸如测试集中测试结果不能指导建模、参数选取及搜索区间选取没有理论依据等问题仍然存在;
(2).执行效率太低,如果面对更多的参数(这是更一般的情况),手动执行过程效率太低,无法进行超大规模的参数挑选;
(3).结果不够精确,一次建模结果本身可信度其实并不高,我们很难证明上述挑选出来的参数就一定在未来数据预测中拥有较高准确率。
网格搜索
sklearn中最常用的搜索策略就是使用GridSearchCV进行全搜索,即对参数空间内的所有参数进行搜索.
from sklearn.model_selection import GridSearchCV
GridSearchCV它的参数主要如下
from sklearn.datasets import load_iris X, y = load_iris(return_X_y=True) X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=114) param_grid_simple = {'penalty': ['l1', 'l2'], 'C': [1, 0.5, 0.1, 0.05, 0.01]} search = GridSearchCV(estimator=lgr, param_grid=param_grid_simple) search.fit(X_train, y_train) search.best_estimator_ search.best_estimator_.coef_ search.best_score_
在默认情况下(未修改网格搜索评估器中评估指标参数时),此处的score就是准确率。此处有两点需要注意:
- 其一:该指标和训练集上整体准确率不同,该指标是交叉验证时验证集准确率的平均值,而不是所有数据的准确率;
- 其二:该指标是网格搜索在进行参数挑选时的参照依据。