初识机器学习(逻辑回归) 一、十种常用的机器学习算法本篇主要分享逻辑回归算法Logistic Regression。逻辑回归虽然名字里带“回归”二字但它实际上是一种分类算法主要用于解决二分类问题。逻辑回归也是机器学习中最基础且应用最广泛的算法之一。二、逻辑回归2.1 什么是逻辑回归逻辑回归Logistic Regression是一种用于解决分类问题的经典算法。简单来说它是在线性回归的基础上增加了一个Sigmoid函数也叫逻辑函数将线性回归的输出结果压缩到0 到 1 之间从而表示某个事件发生的概率。核心思想逻辑回归通过现有数据找到一条分类边界决策边界然后利用这条边界对新样本进行分类。同时它还能给出样本属于某个类别的概率值而不仅仅是类别标签。2.2 逻辑回归的基本原理2.2.1 sigmoid函数逻辑回归的核心就是Sigmoid函数也称逻辑函数它的公式如下其中也就是线性回归的输出。Sigmoid函数的图像呈S形曲线它将任意实数输入映射到(0, 1)区间内。当 z 趋近于正无穷时g(z) 趋近于1当 z 趋近于负无穷时g(z) 趋近于0当 z0z0 时g(z)0.5g(z)0.5。将线性回归的结果 z 代入Sigmoid函数后得到这里的表示样本属于类别1的概率。如果我们预测样本属于类别1如果则预测属于类别0。2.2.2 决策边界决策边界是逻辑回归用来区分不同类别的分界线。对于二维数据来说决策边界通常是一条直线或曲线对于高维数据则是一个超平面。逻辑回归的决策边界由参数决定公式为。当时预测为正类当时预测为负类。2.3 损失函数与优化方法2.3.1 损失函数代价函数线性回归常用的损失函数是均方误差MSE但逻辑回归如果使用均方误差会导致损失函数非凸容易陷入局部最优解。因此逻辑回归使用的是对数损失函数Log Loss也叫交叉熵损失Cross-Entropy Loss它是一个凸函数存在全局最优解。对于二分类问题损失函数定义如下其中m 是样本数量y(i) 是第 i 个样本的真实标签0或1是第 i 个样本的预测概率。当真实标签 y1 时损失函数为预测概率越接近1损失越小当真实标签 y0 时损失函数为预测概率越接近0损失越小。2.3.2 梯度下降法为了最小化损失函数我们通常使用梯度下降法Gradient Descent来更新模型参数。梯度下降的更新公式为其中是学习率Learning Rate控制每次更新的步长。梯度下降的步骤初始化参数将权重初始化为0或随机值计算预测值计算当前参数下的预测概率计算损失计算当前参数下的损失函数值计算梯度计算损失函数对每个参数的偏导数更新参数根据梯度方向更新参数重复迭代重复步骤2到5直到损失函数收敛或达到最大迭代次数2.4 逻辑回归的优缺点2.4.1 优点实现简单模型结构简单易于理解和实现计算效率高计算代价不高训练速度快存储资源消耗低可解释性强可以从特征的权重直接看出不同特征对结果的影响程度输出概率不仅能给出分类结果还能给出属于某个类别的概率2.4.2 缺点容易欠拟合模型形式简单分类精度可能不高对非线性问题处理能力有限当特征与目标之间存在复杂非线性关系时效果可能不佳对特征独立性有一定要求特征之间相关性较强时可能影响效果2.5 逻辑回归算法实现2.5.1 数据的准备与处理数据片段如下图所示其中标签包含Time,V1-V28,Amount可以看到数据相当多且混乱我们可以对数据进行可视化观察数据的特点。# 数据可视化模板 def cm_plot(y,yp): cm confusion_matrix(y,yp) plt.matshow(cm,cmapplt.cm.Blues) plt.colorbar() for x in range(len(cm)): for y in range(len(cm)): plt.annotate(cm[x,y],xy(y,x),horizontalalignmentcenter,verticalalignmentcenter) plt.ylabel(True label) plt.xlabel(Predicted label) return plt然后我们对数据进行Z-标准化处理并且划分出训练集与测试集以便后面使用。# 读取数据 data pd.read_csv(rE:\new_learning\machine_learning\code\day11\creditcard.csv) # Z-标准化 scaler StandardScaler() data[Amount] scaler.fit_transform(data[[Amount]]) data data.drop([Time],axis1) # 对数据进行切分划分出训练集与测试集 x data.drop(Class,axis1) y data.Class x_train,x_test,y_train,y_test train_test_split(x,y,test_size0.3,random_state0)2.5.2 建立模型数据处理好就可以开始建立模型前面我们都是直接建立模型然后得到结果没有考虑其他因素会不会对模型优劣产生影响如下所示model LogisticRegression(C5,l1_ratio0,max_iter1000) model.fit(x_train,y_train)通过观察可以看到在模型中还含有许多参数可以调节所以在正式建立模型之前我们需要调参。那如何进行调参呢那不得不提到交叉验证了。交叉验证Cross-Validation是一种用于评估机器学习模型泛化能力的统计学方法其核心目的是解决单次划分训练集和测试集所带来的评估结果不稳定的问题。在之前的实践中我们通常将数据集划分为训练集和测试集比如 80% 训练 20% 测试。这种做法虽然简单但存在一个致命的隐患测试集划分的随机性。假如我们运气不好那 20% 的测试集中恰好包含了极难预测的离群点或样本或者恰好全是特别简单的样本那么计算出的准确率就会有巨大的波动。我们无法确定这个准确率是模型本身优秀还是只是运气好碰到了简单的测试集。交叉验证的核心思想不把希望寄托在一次随机的数据划分上而是多次划分、多次训练、多次评估最后取平均成绩。这样得出的评估结果更加稳定、可信。# 优化模型进行交叉验证 scores [] c_param_range [0.001,0.01,0.1,1,10,100] for i in c_param_range: model LogisticRegression(Ci,l1_ratio0,solverlbfgs,max_iter1000) score cross_val_score(model,x_train,y_train,cv8,scoringrecall) score_mean sum(score)/len(score) scores.append(score_mean) print(score_mean)经过交叉验证后我们得到了最优的参数Cbest_c将它代入模型之中model LogisticRegression(Cbest_c,l1_ratio0,max_iter1000) model.fit(x_train,y_train)2.5.3 检验模型# 自测绘制混淆矩阵 train_pred model.predict(x_train) print(metrics.classification_report(y_train,train_pred)) # 自测 cm_plot(y_train,train_pred).show() # 使用测试集进行测试 test_pred model.predict(x_test) print(metrics.classification_report(y_test,test_pred,digits6)) cm_plot(y_test,test_pred).show()完整代码如下import pandas as pd import matplotlib.pyplot as plt import numpy as np from sklearn.metrics import confusion_matrix from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score from sklearn import metrics # 数据可视化模板 def cm_plot(y,yp): cm confusion_matrix(y,yp) plt.matshow(cm,cmapplt.cm.Blues) plt.colorbar() for x in range(len(cm)): for y in range(len(cm)): plt.annotate(cm[x,y],xy(y,x),horizontalalignmentcenter,verticalalignmentcenter) plt.ylabel(True label) plt.xlabel(Predicted label) return plt # 读取数据 data pd.read_csv(rE:\new_learning\machine_learning\code\day11\creditcard.csv) # Z-标准化 scaler StandardScaler() data[Amount] scaler.fit_transform(data[[Amount]]) data data.drop([Time],axis1) # 对数据进行切分划分出训练集与测试集 x data.drop(Class,axis1) y data.Class x_train,x_test,y_train,y_test train_test_split(x,y,test_size0.3,random_state0) # 优化模型进行交叉验证 scores [] c_param_range [0.001,0.01,0.1,1,10,100] for i in c_param_range: model LogisticRegression(Ci,l1_ratio0,solverlbfgs,max_iter1000) score cross_val_score(model,x_train,y_train,cv8,scoringrecall) score_mean sum(score)/len(score) scores.append(score_mean) print(score_mean) best_c c_param_range[np.argmax(scores)] print(*****************最优惩罚因子为{}****************.format(best_c)) # 建立最优模型 model LogisticRegression(Cbest_c,l1_ratio0,max_iter1000) model.fit(x_train,y_train) # 自测绘制混淆矩阵 train_pred model.predict(x_train) print(metrics.classification_report(y_train,train_pred)) # 自测 cm_plot(y_train,train_pred).show() # 使用测试集进行测试 test_pred model.predict(x_test) print(metrics.classification_report(y_test,test_pred,digits6)) cm_plot(y_test,test_pred).show()