机器学习算法之逻辑回归下

上文:https://blog.csdn.net/2201_75573294/article/details/155826612?fromshare=blogdetail&sharetype=blogdetail&sharerId=155826612&sharerefer=PC&sharesource=2201_75573294&sharefrom=from_link

上文我们讲到参数C,lr=LogisticRegression(C=0.01)

其实这里的参数不仅仅有还有很多参数

1.其他参数

Penalty:正则化的方式,上述我们讲逻辑函数的说过,有两种,L1和L2两种。使用L2时只有三种优化算法(这里的优化是指优化逻辑回归)支持L2,lbfgs,newton-cg,sag

很多参数都是默认的,所以平时使用的时候并不需要特意去写

其中我们的C=1/,也就是上文损失函数中的,所以C越大惩罚力度越小,C越小惩罚力度越大。

还有一个max_iter:算法收敛最大迭代次数,默认是100,其实就是欠拟合的时候就设置大一点

2.C值的选择

平时我们写代码,设定另一个C值,运行代码,并输出预测集的召回率

然后在设置一个C值运行代码,输出预测集召回率

......多次这样去找到一个优化最好的C值

想法是正确的但是用测试集一点一点的推测c值,这就相当于把测试集当训练集了,这样是不行的,测试集只能用来最后测试,结果是一锤定音的

所以这时候我们需要一个验证集,验证集可以来自于训练集的一部分,用验证机去反复验证哪个c值更优,所以代码中我们会用到循环语句。

3.k折交叉验证

如果训练集拿出一部分作为验证集,这样我们训练集和之前比就会变少,是否会导致训练不到位?所以在验证c最优c值的时候我们采用k折交叉验证

k取值多少我们就把原来的训练集分为几份,c取某个值的时候每一份依次做验证集,这样就保证了分出去当验证集的数据也能当训练集训练模型,分成几份就会得到几个结果,把结果求平均值就可以作为该c值下的结果

去多个c值,把每一次c值得到的结果进行比较,选出最优c值

4.找出最优c值,提高召回率的实现

python 复制代码
import pandas as pd
import numpy as np
from sklearn.preprocessing import scale
from sklearn.model_selection import train_test_split#专门用来对数据集进行切分的函数
from sklearn.linear_model import LogisticRegression#逻辑回归的类,所有的算法都封装再这个类里面
from sklearn import metrics
from sklearn.model_selection import cross_val_score

'''绘制混淆矩阵'''#混淆矩阵的实现可以用大模型搜索,不做讲述
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中
data=pd.read_csv(r"E:\filedata\creditcard.csv")
data['Amount']=pd.DataFrame(scale(data['Amount']))#把Amount列也进行标准化
data=data.drop(['Time'],axis=1)#用不到的Time列删去

'''训练集使用采样数据,测试举使用原始数据集进行预测'''
X_data=data.drop('Class',axis=1)#前面我们已经处理过数据了
Y_data=data.Class
x_train, x_test, y_train, y_test = train_test_split(X_data, Y_data, test_size=0.3, random_state=1000)#随机种子

scores =[]#不同的c参数在验证集下的评分
c_s =[0.01,0.1,1,10,100]#参数
for i in c_s:
    lr = LogisticRegression(C= i, penalty = 'l2', solver='lbfgs', max_iter=1000)
    #这里的cv=8就是k=8,分八份
    score = cross_val_score(lr,x_train, y_train, cv=8,scoring='recall')#交叉验证
    # scoring:可选"accuracy"(精度)、recall(召回率)、roc_auc(roc值)、neg_mean_squarel
    score_mean=sum(score)/len(score)#求平均值
    scores.append(score_mean)#将不同的c参数的结果添加到scores列表中
    print(score_mean)#输出该值

best_c= c_s[np.argmax(scores)]#选出最优值
print('最优C值:{}'.format(best_c))#输出最优c值

lr=LogisticRegression(C=best_c,penalty='l2',max_iter=1000)#定义逻辑回归
lr.fit(x_train,y_train)#进行模型训练

train_pre=lr.predict(x_train)#训练集自测
print(metrics.classification_report(y_train,train_pre))
cm_plot(y_train,train_pre).show()

testpre=lr.predict(x_test)#预测集预测
complete=lr.score(x_test,y_test)
print(metrics.classification_report(y_test,testpre,digits=6))
cm_plot(y_test,testpre).show()

和上篇博客中代码用同样的数据但是更改了c值并找到了最优c值,训练召回率和预测召回率都提升了。

交叉验证不仅能用于逻辑回归,有不确定值都可以使用交叉验证

4.调整阈值增加召回率

除了找到最优c值能增加我们的召回率,我们也可以改变阈值进行

本来值为0.3......被归为0类的,在改变阈值后就属于1类了,这也算是强制实施了"宁可错杀也不放过"的原则

python 复制代码
import pandas as pd
import numpy as np
from sklearn.preprocessing import scale
from sklearn.model_selection import train_test_split#专门用来对数据集进行切分的函数
from sklearn.linear_model import LogisticRegression#逻辑回归的类,所有的算法都封装再这个类里面
from sklearn import metrics
from sklearn.model_selection import cross_val_score

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(r"E:\filedata\creditcard.csv")
data['Amount']=pd.DataFrame(scale(data['Amount']))#把Amount列也进行标准化
data=data.drop(['Time'],axis=1)#用不到的Time列删去

X_data=data.drop('Class',axis=1)
Y_data=data.Class
x_train, x_test, y_train, y_test = train_test_split\
    (X_data, Y_data, test_size=0.3, random_state=1000)#随机种子

scores =[]#不同的c参数在验证集下的评分
c_s =[0.01,0.1,1,10,100]#参数
for i in c_s:#第1词循环的时候C=0.01,5个逻辑回归模型
    lr = LogisticRegression(C= i, penalty = 'l2', solver='lbfgs', max_iter=1000)
    score = cross_val_score(lr,x_train, y_train, cv=8,scoring='recall')#交叉验证
    # scoring:可选"accuracy"(精度)、recall(召回率)、roc_auc(roc值)、neg_mean_squarel
    score_mean=sum(score)/len(score)#交又验证后的值召回率#里面保存了所有的交叉验证召回率
    scores.append(score_mean)#将不同的c参数分别传入模型,分别看看哪个模型效果更好,我们选c
print(score_mean)

best_c= c_s[np.argmax(scores)]
print('最优C值:{}'.format(best_c))

lr=LogisticRegression(C=best_c,penalty='l2',max_iter=1000)
lr.fit(x_train,y_train)

'''修改逻辑回归中的阈值'''#先训练在进行修改阈值操作
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_pre=lr.predict_proba(x_test)
    y_pre=pd.DataFrame(y_pre)
    y_pre=y_pre.drop([0],axis=1)
    y_pre[y_pre[[1]]>i]=1#预测的概率大于i,0.1,0.2预测的标签设置为1
    y_pre[y_pre[[1]]<=i]=0#当预测的概率小于等于i,预测标签设置0
    recall=metrics.recall_score(y_test,y_pre[1])
    recalls.append(recall)
print("{} recall metric in the testing dataset:{:.3f}".format(i,recall))

#训练集自测
train_pre=lr.predict(x_train)
print(metrics.classification_report(y_train,train_pre))
cm_plot(y_train,train_pre).show()

#测试集预测
testpre=lr.predict(x_test)
complete=lr.score(x_test,y_test)
print(metrics.classification_report(y_test,testpre,digits=6))
cm_plot(y_test,testpre).show()

从结果也可以看出,这样也能提高召回率

5.将不均衡的数据处理均衡增加召回率

1)下采样

python 复制代码
import pandas as pd
import numpy as np
from sklearn.preprocessing import scale
from sklearn.model_selection import train_test_split#专门用来对数据集进行切分的函数
from sklearn.linear_model import LogisticRegression#逻辑回归的类,所有的算法都封装再这个类里面
from sklearn import metrics
from sklearn.model_selection import cross_val_score

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(r"E:\filedata\creditcard.csv")
data['Amount']=pd.DataFrame(scale(data['Amount']))#把Amount列也进行标准化
data=data.drop(['Time'],axis=1)#用不到的Time列删去

value_count=pd.value_counts(data['Class'])#统计各类别的个数
print(value_count,type(value_count))#输出各类别个数

X_data=data.drop('Class',axis=1)
Y_data=data.Class
x_train, x_test, y_train, y_test = train_test_split\
    (X_data, Y_data, test_size=0.3, random_state=1000)#随机种子

x_train['Class']=y_train#将训练集加上class列
data_train1=x_train把加上class列的数据集定义为训练集

datanumber0=data_train1[data_train1['Class']==0]#抽取所有类别为0的数据
datanumber1=data_train1[data_train1['Class']==1]#抽取所有类型为1的数据
datanumber0=datanumber0.sample(len(datanumber1))#注意这里应该是类别0=类别1
#因为类别数据少,如果是类别1=类别0,那么将会报错显示数据集不够
data_train2=pd.concat([datanumber0,datanumber1])
#将抽取出条数相等的0类和1类组合作为我们的训练集

X=data_train2.drop('Class',axis=1)#对处理好的数据集进行数据和类别的划分
Y=data_train2.Class

scores =[]#加上交叉验证
c_s =[0.01,0.1,1,10,100]#参数
for i in c_s:
    lr = LogisticRegression(C= i, penalty = 'l2', solver='lbfgs', max_iter=1000)
    score = cross_val_score(lr,X, Y, cv=5,scoring='recall')#交叉验证
    score_mean=sum(score)/len(score)
    scores.append(score_mean)
    print(score_mean)

best_c= c_s[np.argmax(scores)]
print('最优C值:{}'.format(best_c))

lr=LogisticRegression(C=best_c,penalty='l2',max_iter=1000)
lr.fit(X,Y)

train_pre=lr.predict(X)
print(metrics.classification_report(Y,train_pre))
cm_plot(Y,train_pre).show()

testpre=lr.predict(x_test)
complete=lr.score(x_test,y_test)
print(metrics.classification_report(y_test,testpre,digits=6))
cm_plot(y_test,testpre).show()

很明显我们的召回率大幅度提升

2)过采样

如何拟合数据,我们需要用到一个函数:smote类

拟合数据无非就是在同一类中挑选俩个数据取中间的一些值,就像我们knn算法中,相同一类在一起那我们在同一类的内部拟合数据自然也就是这类的,拟合数据就是这样一个过程。

在使用之前我们需要下载一个第三方库imblearn然后调用smote类,调用前先初始化一个对象

python 复制代码
import pandas as pd
import numpy as np
from sklearn.preprocessing import scale
from sklearn.model_selection import train_test_split#专门用来对数据集进行切分的函数
from sklearn.linear_model import LogisticRegression#逻辑回归的类,所有的算法都封装再这个类里面
from sklearn import metrics
from sklearn.model_selection import cross_val_score
from imblearn.over_sampling import SMOTE#第三方库imblearn

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(r"E:\filedata\creditcard.csv")
data['Amount']=pd.DataFrame(scale(data['Amount']))#把Amount列也进行标准化
data=data.drop(['Time'],axis=1)#用不到的Time列删去

X_data=data.drop('Class',axis=1)
Y_data=data.Class
x_train, x_test, y_train, y_test = train_test_split\
    (X_data, Y_data, test_size=0.3, random_state=1000)#随机种子

oversampler=SMOTE(random_state=0)#初始化smote对象
X,Y=oversampler.fit_resample(x_train,y_train)
#fit_resample会对数据中数据少的类型自动识别这里就不需要分别挑出1和0类了
#对原来的训练集特征和标签也就是这里的x_train,y_train进行识别拟合数据,返回新的特征和标签
#这里也不需要组合起来了,因为没有分开类1和类0,这些数据始终都是在一起的
#注意这里拟合过整个训练集数据条数增加了一倍,数据多,训练自然就不会因为数据过少而欠拟合
#但是同时我们运行速度也会变慢

scores =[]
c_s =[0.01,0.1,1,10,100,1000]#参数
for i in c_s:
    lr = LogisticRegression(C= i, penalty = 'l2', solver='lbfgs', max_iter=1000)
    score = cross_val_score(lr,X, Y, cv=5,scoring='recall')#交叉验证
    score_mean=sum(score)/len(score)
    scores.append(score_mean)
    print(score_mean)

best_c= c_s[np.argmax(scores)]
print('最优C值:{}'.format(best_c))

lr=LogisticRegression(C=best_c,penalty='l2',max_iter=1000)
lr.fit(X,Y)

train_pre=lr.predict(X)
print(metrics.classification_report(Y,train_pre))
cm_plot(Y,train_pre).show()

testpre=lr.predict(x_test)
complete=lr.score(x_test,y_test)
print(metrics.classification_report(y_test,testpre,digits=6))
cm_plot(y_test,testpre).show()

过采样也能把召回率提升到零点九多

相关推荐
松果财经4 小时前
「直通」英伟达,蓝思科技补齐AI算力布局又一块拼图
人工智能
睿观·ERiC4 小时前
跨境电商合规预警:Keith 律所 TRO 诉讼(25-cv-15032)突袭,奇幻插画版权风险排查指南
大数据·人工智能·跨境电商
小小8程序员4 小时前
Premiere Pro 2025 让视频创作效率翻倍最新版本下载安装教程
人工智能
小苑同学5 小时前
PaperReading:《GPT-4 Technical Report》
人工智能·语言模型
十铭忘5 小时前
SAM2跟踪的理解7——mask decoder
人工智能·计算机视觉
古城小栈5 小时前
AI + 区块链:去中心化智能的未来形态
人工智能·去中心化·区块链
心疼你的一切5 小时前
自然语言处理_NLP与Transformer架构
人工智能·深度学习·目标检测·机器学习·计算机视觉·自然语言处理·transformer
望外追晚5 小时前
mask_color_map.json丢失,导致分割标签.png无法导入X-Anylabeling的解决办法
人工智能·计算机视觉·json·paddlepaddle
沫儿笙5 小时前
安川YASKAWA焊接机器人管材焊接节气
人工智能·机器人