重生归来,我要成功 Python 高手--day32 逻辑回归
逻辑回归:解决分类问题(二分类)
基本思想:1.利用线性模型根据特征的重要性计算一个值
2,再用sigmoid 函数将f(X)的输出值映射为概率值
通过设置阈值例如0.5,将大于0.5的归为1 小于0.5的归于0
sigmoid 函数:把线性回归的输出作为逻辑回归的输入(0,1)之间的值
sigmoid函数的表达式为:1/1+e的-x次方
损失函数:极大似然估计函数的负数形式

损失函数:所有的样本的损失值(越小越好)
yi=真实值标签
pi=预测值
yi=1时
如预测值概率pi接近于1 log(1)=0 损失值越近与0 很好
如预测值概率pi接近于0 log(0)=趋近于无穷大 损失值非常大
yi=0时
如预测值概率pi接近于0 log(1)=0 损失值越近与0 很好
如预测值概率pi接近于1 log(0)=趋近于无穷大 损失值非常大
API演示
# 导包
from sklearn.model_selection import train_test_split,GridSearchCV #数据集划分
from sklearn.metrics import accuracy_score # 准确率
from sklearn.linear_model import LogisticRegression # 逻辑回归
from sklearn.neighbors import KNeighborsClassifier # 线性回归
from sklearn.preprocessing import StandardScaler # 标准化
import pandas as pd
import numpy as np
# 数据集的读取
data=pd.read_csv('../../data/breast-cancer-wisconsin.csv')
# 对数据集的默认值进行替换
data=data.replace('?',np.nan)
# 对空值的删除
data=data.dropna(axis=0)
# 对数据集的拆分
x=data.iloc[:,1:-1] # 特征
y=data.iloc[:,-1] # 标签
#对数据集划分
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=22)
# 对数据进行标准化
transfer=StandardScaler()
x_train=transfer.fit_transform(x_train)
x_test=transfer.transform(x_test)
# 使用逻辑回归
def 逻辑():
model=LogisticRegression()
# 模型的训练
model.fit(x_train,y_train)
# 模型的预测
y_pred=model.predict(x_test)
print(f'预测的结果是:{y_pred}')
# 模型的准确率
print(f'模型的准确率是:{accuracy_score(y_test,y_pred)}')
# 使用knn
def knn():
model=KNeighborsClassifier()
param_grid={
'n_neighbors':[i for i in range(1,11)]
}
# 网格搜索和交叉验证
model=GridSearchCV(model,param_grid,cv=4)
model.fit(x_train,y_train)
y_pred=model.predict(x_test)
print(f'预测的结果是:{y_pred}')
# 模型的准确率
print(f'模型的准确率是:{accuracy_score(y_test,y_pred)}')
print(f'最优评分{model.best_score_}')
print(f'最优组合{model.best_params_}')
if __name__=='__main__':
# 逻辑()
knn()
混淆矩阵: 用于展示真实值和预测值之间的正例和反例的情况,默认:会使用分类样本少的那一个
真正例(tp):预测值和真实值都是正例
真反例(TN):预测值和真实值都是反例
伪反例:(FN):真实结果为真例结果预测为 假例
伪正例:(FP):真实结果为假例结果预测为 真例
API实现:
import pandas as pd
from sklearn.metrics import confusion_matrix,precision_score,recall_score,f1_score
# 定义数据集 ,真实样本(10个,6个恶,4个良)
y_train=['恶性','恶性','恶性','恶性','恶性','恶性','良性','良性','良性','良性']
# 定义正反例
laber=['恶性','良性'] # 参数1:正例样本,参数2:负样本(反例)
df_laber=['恶性(正例)','良性(假例)']
# 定义模型A 预测对了3个恶性,4个良性
y_pre_A=['恶性','恶性','恶性','良性','良性','良性','良性','良性','良性','良性']
# 定义模型b 预测对了3个恶性,4个良性
y_pre_B=['恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','良性']
# 构建混淆矩阵
# 参数1:真实样本 参数2:预测样本 参数3:样本的标签,规定什么是正例,什么是假例
cm_A=confusion_matrix(y_train,y_pre_A,labels=laber)
print(f'混淆矩阵a{cm_A}')
# 封装为df对象
df_A=pd.DataFrame(cm_A,index=df_laber,columns=df_laber)
print(f'混淆矩阵a的df对象\n{df_A}')
print('*'*30)
cm_B=confusion_matrix(y_train,y_pre_B,labels=laber)
print(f'混淆矩阵a{cm_B}')
# 封装为df对象
df_B=pd.DataFrame(cm_B,index=df_laber,columns=df_laber)
print(f'混淆矩阵a的df对象\n{df_B}')
分类模型的评估指标:精确率,召回率,F1—score
精确率:对正例样本的预测准确率,真正例/(真正例+伪正利)
作用:模型判断为正例的结果中有多少为正确的,这个值越高说明模型预测为正例的结果中,真正正例的占比就越高
API:
from sklearn.metrics import precision_score
# 定义数据集 ,真实样本(10个,6个恶,4个良)
y_train=['恶性','恶性','恶性','恶性','恶性','恶性','良性','良性','良性','良性']
# 定义模型A 预测对了3个恶性,4个良性
y_pre_A=['恶性','恶性','恶性','良性','良性','良性','良性','良性','良性','良性']
# 定义模型b 预测对了3个恶性,4个良性
y_pre_B=['恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','良性']
# 精确率,参数1:真实标签 参数2:预测标签 参数3:二分类中的正类
resultA=precision_score(y_train,y_pre_A,pos_label='恶性')
print(f'A模型的精确率是:{resultA}')
resultB=precision_score(y_train,y_pre_B,pos_label='恶性')
print(f'B模型的精确率是:{resultB}')
召回率:预测为真正例样本占所有真实正例标签的样本的比重 真正例/真正例+伪反例
作用:降低把正例误判为反例的概率,这个值越高说明对正例样本的捕获性就越高,越不会误判
API:
from sklearn.metrics import recall_score
# 定义数据集 ,真实样本(10个,6个恶,4个良)
y_train=['恶性','恶性','恶性','恶性','恶性','恶性','良性','良性','良性','良性']
# 定义模型A 预测对了3个恶性,4个良性
y_pre_A=['恶性','恶性','恶性','良性','良性','良性','良性','良性','良性','良性']
# 定义模型b 预测对了3个恶性,4个良性
y_pre_B=['恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','良性']
# 精确率,参数1:真实标签 参数2:预测标签 参数3:二分类中的正类
resultA=recall_score(y_train,y_pre_A,pos_label='恶性')
print(f'A模型的召回率是:{resultA}')
resultB=recall_score(y_train,y_pre_B,pos_label='恶性')
print(f'B模型的召回率是:{resultB}')
F1-score: 对精确率和召回率都有要求综合考虑
F1-score=2*(精确率*召回率/精确率+召回率)
API:
from sklearn.metrics import f1_score
# 定义数据集 ,真实样本(10个,6个恶,4个良)
y_train=['恶性','恶性','恶性','恶性','恶性','恶性','良性','良性','良性','良性']
# 定义模型A 预测对了3个恶性,4个良性
y_pre_A=['恶性','恶性','恶性','良性','良性','良性','良性','良性','良性','良性']
# 定义模型b 预测对了3个恶性,4个良性
y_pre_B=['恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','恶性','良性']
# 精确率,参数1:真实标签 参数2:预测标签 参数3:二分类中的正类
resultA=f1_score(y_train,y_pre_A,pos_label='恶性')
print(f'A模型的f1分数是:{resultA}')
resultB=f1_score(y_train,y_pre_B,pos_label='恶性')
print(f'B模型的f1分数是:{resultB}')
POC曲线和AUC值:
ROC曲线:常用作评估分类模型的性能的可视化工具
X:假正率 Y:真正率
x:假正率(FPR):负样本中被预测为正样本的概率
=伪正例/伪正例+真假率
y:y:真正率(TPR): 正样本中被预测为正样本的概率
=真正率/真正例+伪反例
AUC值:ROC曲线的优劣可以通过ROC曲线下的面积也就是AUC值来衡量,这个面积越大说明分类器的性能越好
AUC=0.5:等同于随机猜想
AUC=1:分类器的性能完美
AUC=0:猜测为相反值
热编码:对于字符类型的需要通过热编码转化为数值型,是这个列为1,不是则为0
数据探索性分析EDA:
通过画图来展示特征和标签之间的关系
API:
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix,precision_score,recall_score,f1_score,roc_auc_score,classification_report #混淆矩阵
# # 数据集的读取
# data=pd.read_csv('../../data/churn.csv')
# 数据集的详情
# data.info()
#
# print(data.head())
#
# print(data.columns)
# # 进行种类的划分查看yes和no的个数
# a=y.value_counts()
# print(a)
# 通过数据集的展示后发现
"""
No 5174
Yes 1869
流失的为少数的所有为Yes正例,No为反例
"""
# 数据的预处理
# 热编码
#1、定义函数 实现:数据预处理
def dm01_数据预处理():
#1.1读取数据
data=pd.read_csv("../../data/churn.csv")
# data.info()
#1.2因为上述Churn、gender字段字符串类型。我们对其做热编码(one-hot)处理
#get_dummies
data=pd.get_dummies(data)
# data.info()
# print(data.head(2))
#1.3删除列
data.drop(['gender_Male','Churn_No'],axis=1,inplace=True)
# print(data.info())
#1.4 所以我要修改标签列名字flag
data.rename(columns={'Churn_Yes':'flag'},inplace=True)
data.info()
# print(data.head(2))
#1.5查看数据集 标签是否均衡 何为均衡:1:1
print(data.flag.value_counts()) #False 不流失 True流失
#2.定义函数 用于显示 :EDA 数据探索性分析
def dm02_会员流失可视化情况():
#1.读取数据
data=pd.read_csv("../data/churn.csv")
data=pd.get_dummies(data)
data.drop(['gender_Male', 'Churn_No'], axis=1, inplace=True)
data.rename(columns={'Churn_Yes': 'flag'}, inplace=True)
#通过计数柱状图 ,绘制月度会员流失情况
#参1:数据
# 参2 x轴的列名
#参3:hue 将数据进行分类
sns.countplot(data,x='Contract_Month',hue='flag') #Contract_Month复制,别手敲
plt.show()
def dm03_逻辑回归模型训练与评估():
# 1.1读取数据
data = pd.read_csv("../../data/churn.csv")
# 热编码
# 1.2因为上述Churn、gender字段字符串类型。我们对其做热编码(one-hot)处理
# get_dummies
data = pd.get_dummies(data)
# data.info()
# print(data.head(2))
# 1.3删除列
data.drop(['gender_Male', 'Churn_No'], axis=1, inplace=True)
# print(data.info())
# 1.4 所以我要修改标签列名字flag
data.rename(columns={'Churn_Yes': 'flag'}, inplace=True)
# 选择特征和标签
x=data.iloc[:,:-2]
y=data.flag
# # 对数据集的划分
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=22)
# 对数据进行标准化
t=StandardScaler()
x_train=t.fit_transform(x_train)
x_test=t.transform(x_test)
# 模型的训练,逻辑回归
model=LogisticRegression()
model.fit(x_train,y_train)
# 模型的预测
y_pred=model.predict(x_test)
# 输出预测结果
print(f'预测结果是{y_pred}')
print(f'模型的准确率为{accuracy_score(y_test,y_pred)}')
print(f"准确率:{accuracy_score(y_test, y_pred)}")
print(f"精确率:{precision_score(y_test, y_pred)}")
print(f"召回率:{recall_score(y_test, y_pred)}")
print(f"f1值:{f1_score(y_test, y_pred)}")
print(f'训练好的分类模型会自动记录类别顺序:{model.classes_}')
# #auc值为
# # 1. 先获取模型对测试集的类别概率(二维数组:[样本数, 2],列0=No的概率,列1=Yes的概率)
y_proba = model.predict_proba(x_test)[:,1] # 这是第二列的索引
print(f"roc曲线下面积:{roc_auc_score(y_test, y_proba)}")
print(f"分类评估报告:{classification_report(y_test, y_pred)}")
if __name__=='__main__':
# dm01_数据预处理()
dm03_逻辑回归模型训练与评估()
更多推荐
所有评论(0)