一、实例代码演示及详细解读
完整代码如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt # 用来可视化数据
from pylab import mpl
def cm_plot(y, yp): # 可视化混淆矩阵,网上都是包装好的,可以直接复制使用
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
cm = confusion_matrix(y, yp)
plt.matshow(cm, cmap=plt.cm.Blues)
plt.colorbar()
for x in range(len(cm)):
for y in range(len(cm)):
plt.annotate(cm[x, y], xy=(y, x), horizontalalignment='center',verticalalignment='center')
plt.ylabel('True label')
plt.xlabel('Predicted label')
return plt
data = pd.read_csv('creditcard.csv') # 打开文件,并将文件内容返回给data
data.head() # 默认输出前5行,这里用来提示防止忘记代码了
# 设置字体,用来显示中文
mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei']
mpl.rcParams['axes.unicode_minus'] = False
labels_count = pd.value_counts(data['Class']) # 同级class列中每个类型的数据个数,(这里的样本极度不均衡)
plt.title("正负例样本数") # 可视化上述分类数据的个数
plt.xlabel('类别')
plt.ylabel('频数')
labels_count.plot(kind='bar')
plt.show()
# 将Amount列的数据进行Z标准化,因为其余列的值有负值,所以不能使用0-1归一化
# 导入库的用法,之所以使用standerscaler是因为其处理大批量数据速度快,并且可以同时处理好几个特征值
from sklearn.preprocessing import StandardScaler
# z标准化
scaler = StandardScaler() # 这是一个类,专门用来处理z标准化,适合处理大量数据的类,还有一种叫scale,适合对小部分数据进行z标准化
a = data[['Amount']] # 取出Amount整列数据
data['Amount'] = scaler.fit_transform(data[['Amount']]) # 对Amount整列数据进行z标准化后将其传入原data内,覆盖原来的列
# 删除无用的列,Time列,axis=1表示列,axis=0表示行,然后再传入data文件
data = data.drop(['Time'],axis=1)
# 对数据集取出一部分数据用来当做训练集,一部分当做测试集
# 因为银行贷款可能随时间变化而变化,所以不能直接取前一半后一半的这种,需要对整体数据随机取出一部分当做训练和测试数据
from sklearn.model_selection import train_test_split
# 删除列Class后的数据赋值给 x,然后再将Class单独取出赋值给y
x = data.drop('Class',axis=1)
y = data.Class
# 使用train_test_split函数,放入参数 训练集和训练标签,以及需要取出的测试数据的百分比,以及定义一个随机种子,以保证下一次运行代码的结果不变
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3,random_state=0)
# 顺序返回四个参数,分别表示训练集特征值,测试集特征值,训练集标签,测试集标签
# test_size表示需要取出的测试集所占数据集百分比
# random_state表示随机种子,如果不设置随机种子,再次运行代码又会重新随机取一部分数据,最后的正确率可能会发生变化
# 设置随机种子后则会定死这些已经取出过的数据,保证最后结果的正确率保持不变
from sklearn.linear_model import LogisticRegression # 导入逻辑回归模型
from sklearn.model_selection import cross_val_score # 用来进行交叉验证
scores = [] # 定义一个空列表,用来存放后面更改正则化强度C值的后进行k折运算,产生的平均概率
c_param_range = [0.01,0.1,1,10,100] # 用来循环更改的C值
for i in c_param_range: # 遍历每一个设置好的C的值
lr = LogisticRegression(C=i,penalty='l2',solver='lbfgs',max_iter=1000) # 初始化参数,正则化方式采用l2正则化,使用拟牛顿方法lbfhs,并设置最大迭代次数为1000次
score = cross_val_score(lr,x_train,y_train,cv=8,scoring='recall') # 进行k折交叉验证,输入需要验证的模型,以及训练集数据,设置为8折交叉验证,最后求得的结果为召回率recall
score_mean = sum(score)/len(score) # 将求的8个召回率进行求平均,
scores.append(score_mean) # 将求得的均值存入列表scores
print(score_mean) # 打印求得的均值
best_c = c_param_range[np.argmax(scores)] # 使用np.argmax 返回最大值对应的第一个索引值,将索引值带入上述c值对应列表,得到最优的C值
lr = LogisticRegression(C = best_c,penalty='l2',max_iter=1000) # 再次初始化一个模型,设置参数,将上述最优参数C带入,并设置正则化方式以及最大迭代次数
lr.fit(x_train,y_train) # 导入训练集数据,开始训练
from sklearn import metrics # 用来打印数据集的分类报告,用来查看准确率、召回率、精确度等等,以及后面的直接打印召回值、、
train_predict = lr.predict(x_train) # 输入训练集特征数据,对其进行测试
print(metrics.classification_report(y_train,train_predict)) # 打印训练集的分类报告,输入参数为训练集的标签和训练集预测结果
cm_plot(y_train,train_predict).show() # 调用上面定义的函数cm_plot用来可视化混淆矩阵,参数为标签和测试结果
test_predict = lr.predict(x_test) # 对测试集进行预测
print(metrics.classification_report(y_test,test_predict)) # 同样打印分类报告
cm_plot(y_test,test_predict).show() # 可视化测试集的混淆矩阵
thresholds = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9] # 用来循环遍历阈值
recalls = [] # 定义一个空列表,用来存放更改阈值后得到新的召回率的值
for i in thresholds: # 遍历每一个阈值,来确定最优的阈值
y_predict_proba = lr.predict_proba(x_test) # 用来打印测试集特征值中的分类概率,即属于0类的概率,和属于1类的概率
y_predict_proba = pd.DataFrame(y_predict_proba) # 将上述得到的数据转换成二维数组的形式
y_predict_proba = y_predict_proba.drop([0],axis=1) # 因为数据种类个数的极大差距,所以删除极大数量的等于0类别的列
y_predict_proba[y_predict_proba[[1]] > i] = 1 # 对 等于1类别的数据进行更改阈值,如果概率大于i,那么将其更改为1类,此时会大大增加1类别的数目
y_predict_proba[y_predict_proba[[1]] <= i] =0 # 小于等于i的将其更改为0类
recall = metrics.recall_score(y_test,y_predict_proba[1]) # 使用metrics中的函数recall_score直接打印所有数据的召回率,参数为数据标签和测试类别的概率值
recalls.append(recall) # 将打印出来的概率值写入空列表
print("{}Recall metric in the testing dataset:{:.3f}".format(i,recall))
同样使用上节课的银行贷款案例,其文件内容大致如下:(共28万多条,31列)
其输出的结果为:
这是最原始的数据分类情况(在class列中体现),此时看不见1类,因为只有400多条,而0类有28万多条
这是训练集的混淆矩阵可视化:
这是测试集的混淆矩阵可视化:
以及最后的训练结果:(后续要进行数据的下采样或者过采样来提升召回率)
二、逻辑回归参数
# 逻辑回归模型的默认参数
LogicRegression(penalty='l2',dual=False,tol=0.0001,C=1.0,fit_intercept=True,intercept_scaling=1,class_weight=None,random_state=None,solver='liblinear',max_iter=100,multi_class='ovr',verbose=0,warm_start=False,n_jobs=1)
1、penalty:正则化方式
可以选择L1和L2两种,通常是指正则化项,用于控制模型的复杂度和防止过拟合。正则化是一种技术,通过向损失函数中添加一个惩罚项,以减小模型的权重参数,从而使模型更简单和泛化能力更好。
通过调整正则化参数(penalty parameter),我们可以控制正则化的强度,从而影响模型的拟合能力和泛化能力。具体详解可参考上节课后面内容。
1)L1正则化(L1 regularization)
将模型的权重参数的绝对值加到损失函数中。它鼓励模型的权重稀疏化,即使得一些权重变为零,从而达到特征选择和降维的效果,其公式为L1 = 1/2 * λ |θ| λ叫正则化系数
2)L2正则化(L2 regularization)
将模型的权重参数的平方和加到损失函数中。它鼓励模型的权重参数更加平滑,避免出现过大的权重值,从而降低模型的复杂度,其公式为:L2 = 1/2 * λ (θ)**2
2、dual:按照默认即可
一般用于衡量算法的收敛性或精度。通常情况下,算法会在每次迭代过程中计算某个指标(如损失函数或模型参数的变化量),然后将其与 "tol" 进行比较。如果变化量小于等于 "tol",则认为算法已经达到了足够的收敛性或精度,可以停止迭代,对偶方法,只能用在求解线性多核(liblinear)的L2惩罚项上,当样本数量>样本特征的时候,dual通常默认为False
3、tol :容忍度或公差float
默认值为1e-4,即0.0001,容许停止标准,即当你在山上下来到谷底往复运动的时候,其高度差小于等于这个数的时候可以停止,将那个位置当做是最低位置
4、C:正则化强度
浮点型数据,防止过拟合,用来衡量模型中正则化项(或惩罚项)的大小或强度,正则化系数λ的倒数,默认为1.0,可能是0.01,0.1,1,10,100等等,越小的数值表示越强的正则化,
5、fit_intercept:是否增加截距
fit_intercept是一个布尔值参数,用于控制是否在模型中添加截距或偏置项。截距是线性模型中的一个常数项,表示在自变量为0时,因变量的期望值,默认值为True。
当fit_intercept为True时,模型会自动添加截距项,即模型会对输入数据进行中心化操作,使得自变量的均值为0。这样可以更准确地描述数据的关系,尤其是在存在偏移的情况下。
当fit_intercept为False时,模型不会添加截距项,即模型不对输入数据进行中心化操作,自变量的均值可以保持不变。这在某些情况下可能是有意义的,例如当输入数据已经经过预处理或标准化时。
6、intercept_scaling:
用于缩放截距的影响。在机器学习中,正则化是一种用于控制模型复杂度的技术,可以防止过拟合问题的发生。
在模型中乘以截距项的值,以增加其对模型的重要性。通过调整intercept_scaling的值,可以调节截距项对模型的影响程度。
仅在正则化项为“liblinear”,且fit_intercept设置为True时有用,默认为1。
当intercept_scaling等于1时,截距项的影响保持不变。当intercept_scaling大于1时,截距项的影响得到增强。而当intercept_scaling小于1时,截距项的影响减弱。
7、class_weight:
用于调整每个类别的权重,以平衡不同类别样本的重要性。通常,较少样本的类别会被赋予较高的权重,以便模型更加关注这些样本。这样可以帮助模型更好地学习较少样本的类别,从而提高整体预测性能。
8、random_state:随机种子
控制随机数生成器行为的参数,当设置了random_state参数时,每次运行模型时都会得到相同的随机数生成过程,从而得到相同的结果。这对于调试代码、复现实验结果以及比较不同算法的性能非常有用。
9、solver:
通常用于指定模型的优化算法,以求解模型的参数或最小化损失函数。
{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’},默认为liblinear
1)liblinear:
适用于小数据集,使用坐标轴下降法来迭代优化损失函数。使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。
2)newton-cg:牛顿法
sag方法使用一阶导数,而牛顿法采用了二阶泰勒展开,这样缩减了迭代轮数,但是 需要计算Hsssian矩阵的逆,所以计算复杂度较高。【也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。】
3)Lbfgs:拟牛顿法
考虑到牛顿法的Hessian矩阵求逆太过复杂,尤其在高维问题中几乎不可行,想到了用较低的代价寻找Hessian矩阵的近似逆矩阵,便有了拟牛顿法。【拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。】
4)Sag:随机平均梯度下降
类似于我们的stocGradAscent1函数,思想是常用的一阶优化方法,是求解无约束优化问题最经典,最简单的方法之一,适用于大数据集,因为速度更快。【即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候。】
5)Saga:线性收敛的随机优化算法。
适用于大数据集,因为速度更快,【线性收敛的随机优化算法的的变种。】
10、max_iter 算法收敛的最大迭代次数
用于控制迭代的次数,以便在达到最大迭代次数之前找到算法的最优解或收敛到某个阈值。
迭代算法通过多次迭代来逐步优化模型的参数或逼近最优解,当算法达到最大迭代次数时,如果尚未收敛或找到最优解,可能会停止迭代并返回一个近似解。因此,合理设置max_iter参数很重要,以确保算法有足够的迭代次数来找到最优解。
需要注意的是,max_iter的合理取值通常取决于具体的算法、问题和数据集。对于简单的问题,较小的max_iter值可能已足够;而对于复杂的问题或大型数据集,较大的max_iter值可能是必要的。
11、multi_class 分类方式选择
可选参数为ovr和multinomial,默认为ovr
-
"ovr":使用一对多(One-vs-Rest)策略。对于每个类别,将其作为一个二分类问题,将该类别的样本与其他所有类别的样本合并,然后训练一个分类器。这样得到多个分类器,每个分类器都能够判断样本是否属于该类别。最终,根据分类器的输出进行预测。
-
"multinomial":使用多项式逻辑回归或softmax回归来解决多分类问题。在这种策略下,模型将直接优化并预测各个类别的概率分布。
12、verbose 日志冗长度
int类型,默认为0,就是不输出训练过程,1的时候偶尔输出结果,大于1则对每个子模型都会输出。
13、warm_start 热启动参数
bool类型,默认为False,用于控制是否使用之前训练好的模型作为初始化,继续训练新的模型。如果为True,算法会使用之前训练好的模型参数作为初始化参数,然后继续训练新的模型。这样做的好处是可以节省训练时间,特别是对于大型数据集或复杂的模型。
14、n_jobs 并行数
用于指定并行计算时使用的CPU核心数或线程数,默认为1.
三、交叉验证
original set :原始数据集,training set 训练集,test set 测试集,validation set 验证集
将原始数据划分为训练集和测试集,然后对这个分出来的训练集再次进行划分,一部分当做新的训练集,另一部分当做验证集,验证集用来调教参数,然后确定最强参数后将参数带入训练集进行训练,最后再使用最开始划分出来的测试集对其进行测试得到最优模型
K折交叉验证
将训练集切分成10份(k=10,k值自定义),将十份首先取出最后一份,将其当做验证集,验证得到其召回率或其他的概率,其余9份当做训练集,分别将10份的每一份都分别取出来,另外的9分当做训练集,一共做10次,最后对求出来的概率的结果做一个平均,找到最大概率对应的C的值,即可得到最优参数。此时每一份数据都参与了测试,也参与了测试,使得结果更加综合。
其目的是,全面综合的判断模型的好坏,例如当c=0.01时模型正确率,当c=0.1时正确率。。。依次得到最优参数。
四、修改阈值
将最初的阈值0.5更改为其他值,例如下图所示,修改后咸鱼概率小于0.2的都是0类,大于0.2的都是1类,以此来改变模型的性能。