《机器学习》 逻辑回归 大批量数据的过采样 <9>

一、案例文件

同样使用上节课的银行贷款案例,其文件内容大致如下:(共28万多条,31列)

现在要继续接着上节课的内容对模型进行优化

 二、过采样流程

 

1、流程图示

2、具体流程介绍

1)数据切分

        将原始数据切分为70%的训练集和30%的测试集。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

2)数据增强

        对训练集中的class=1的数据进行人工拟合,扩充为与class=0的数据量相等。

# 假设augmented_data是在class=1的数据上进行增强得到的新数据
# 假设class_0_data是class=0的数据

# 将class=1的数据量扩充为class=0的数据量
augmented_data = generate_augmented_data(class_1_data, len(class_0_data))

# 人工拟合后,得到与class=0数据量相等的augmented_data

3)创建大数据集

        将数据增强后的训练集与原测试集合并,得到一个新的大数据集。

# 将增强后的训练集与原测试集合并
X_train_augmented = np.concatenate((X_train, augmented_data))
y_train_augmented = np.concatenate((y_train, np.ones(len(augmented_data))))

 

4)数据集切分

        将新的大数据集切分为训练集和测试集。

X_train_big, X_test_big, y_train_big, y_test_big = train_test_split(X_train_augmented, y_train_augmented, test_size=0.3, random_state=0)

5)k折交叉验证

        对训练集进行k折交叉验证,用于模型训练的选择和调优。

from sklearn.model_selection import KFold

kf = KFold(n_splits=5, shuffle=True, random_state=0)
for train_index, val_index in kf.split(X_train_big):
    X_train_fold, X_val_fold = X_train_big[train_index], X_train_big[val_index]
    y_train_fold, y_val_fold = y_train_big[train_index], y_train_big[val_index]
    
    # 在每个fold上进行模型训练和选择
    model = LogisticRegression()
    model.fit(X_train_fold, y_train_fold)
    # 在验证集上进行模型选择和调优

6)模型训练

        建立模型并对大数据集的训练集进行训练,得到训练完成的模型。

model = LogisticRegression()
model.fit(X_train_big, y_train_big)

7)模型测试

        使用之前切分出来的测试集和大数据集本身作为测试集,导入模型进行测试。

8)最优概率阈值

        根据测试结果,调整阈值以得到最优的预测概率。

from sklearn.metrics import precision_score, recall_score
# 假设y_pred_prob是模型预测的概率值
threshold = 0.5 # 初始阈值
best_threshold = threshold
best_f1_score = 0

for threshold in np.arange(0.1, 1.0, 0.1):
    y_pred_test_threshold = (y_pred_prob > threshold).astype(int)
    f1_score_test = f1_score(y_test_big, y_pred_test_threshold)
    
    if f1_score_test > best_f1_score:
        best_f1_score = f1_score_test
        best_threshold = threshold

print("Best threshold:", best_threshold)

三、完整代码实现

import time

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(r'./creditcard.csv')
data.head()  # 默认输出前5行,这里用来提示防止忘记代码了

# 设置字体,用来显示中文
mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei']
mpl.rcParams['axes.unicode_minus'] = False

# 同级class列中每个类型的数据个数,(这里的样本极度不均衡)
labels_count = pd.value_counts(data['Class'])
# 可视化上述分类数据的个数
# plt.title("正负例样本数")
# plt.xlabel('类别')
# plt.ylabel('频数')
# labels_count.plot(kind='bar')
# plt.show()

# 将Amount列的数据进行Z标准化,因为其余列的值有负值,所以不能使用0-1归一化
# 导入库的用法
from sklearn.preprocessing import StandardScaler
# z标准化
scaler = StandardScaler()  # 这是一个类,专门用来处理z标准化,适合处理大量数据的类,还有一种叫scale,适合对小部分数据进行z标准化
data['Amount'] = scaler.fit_transform(data[['Amount']])  # 对Amount整列数据进行z标准化后将其传入原data内,覆盖原来的列
data.head()

# 删除无用的列,Time列,axis=1表示列,axis=0表示行,然后再传入data文件
data = data.drop(['Time'],axis=1)


from sklearn.model_selection import train_test_split

x_whole = data.drop('Class',axis=1)  # 取出原始数据集特征值和标签
y_whole = data.Class
x_train,x_test,y_train,y_test = train_test_split(x_whole,y_whole,test_size=0.2,random_state=0)  # 对随机取出百分之20当做测试集

from imblearn.over_sampling import SMOTE  # 导入过采样方法

oversampler = SMOTE(random_state=0)  # 保证数据闭合效果,随机种子
os_x_train,os_y_train = oversampler.fit_resample(x_train,y_train)  # 对上述取出的百分之80原始数据的训练集进行过采样

labels_count = pd.value_counts(os_y_train)  # 计算过采样后的数据中各类别的数目
plt.title("正负例样本数")
plt.xlabel('类别')
plt.ylabel('频数')
labels_count.plot(kind='bar')
plt.show()

os_x_train_w,os_x_test_w,os_y_train_w,os_y_test_w = (   # 对过采样的数随机取出20%当做测试集,80%当做训练集
    train_test_split(os_x_train,os_y_train,test_size=0.2,random_state=0))



from sklearn.linear_model import LogisticRegression  # 导入逻辑回归模型
from sklearn.model_selection import cross_val_score  # k折交叉验证

scores = []  # 定义一个空列表,用来存放后面更改正则化强度后的每个C值计算结果对应的score值
c_param_range = [0.01,0.1,1,10,100] # 循环更改的C值
z = 1
for i in c_param_range:
    start_time = time.time()  # 开始时间
    lr = LogisticRegression(C=i,penalty='l2',solver='lbfgs',max_iter=1000)  # 循环遍历C值
    score = cross_val_score(lr,os_x_train_w,os_y_train_w,cv=5,scoring='recall')  # k折运算
    score_mean = sum(score)/len(score)
    scores.append(score_mean)
    end_time = time.time()   # 结束时间
    print("第{}次。。。".format(z))
    print("time spend:{:.2f}".format(end_time-start_time))
    print("recall:{}".format(score_mean))
    z+=1
    # print(score_mean)

best_c = c_param_range[np.argmax(scores)]  # 最优C值

lr = LogisticRegression(C=best_c,penalty='l2',max_iter=1000)
lr.fit(os_x_train_w,os_y_train_w)   # 对过采样随机取出的训练集数据进行训练

from sklearn import metrics   # 打印分类报告

train_predict_big = lr.predict(os_x_train_w)  # 将训练集自己导入模型进行测试
print(metrics.classification_report(os_y_train_w,train_predict_big))

test_predict_big = lr.predict(os_x_test_w)   # 对测试集进行测试
print(metrics.classification_report(os_y_test_w,test_predict_big))

train_predict = lr.predict(x_train)  # 对原始数据训练集进行测试
print(metrics.classification_report(y_train,train_predict))
cm_plot(y_train,train_predict).show()

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)

    y_predict_proba = pd.DataFrame(y_predict_proba)
    y_predict_proba = y_predict_proba.drop([0],axis=1)
    y_predict_proba[y_predict_proba[[1]] > i] = 1
    y_predict_proba[y_predict_proba[[1]] <= i] =0

    recall = metrics.recall_score(y_test,y_predict_proba[1])
    recalls.append(recall)
    print("{}Recall metric in the testing dataset:{:.3f}".format(i,recall))

其打印结果如下:

1)过采样后的数据结构

2)混淆矩阵可视化

3)结果的打印

四、总结

        大批量数据的过采样是一种数据预处理技术,用于解决数据不平衡问题。在数据集中,某些类别的样本数量明显少于其他类别,这会导致模型在训练时对少数类别的预测能力较差。过采样的目标是通过增加少数类别的样本数量,使得各个类别之间的样本数量更加均衡。

大批量数据的过采样可以通过以下步骤实现:

  1. 选择过采样方法:常见的过采样方法包括随机复制、SMOTE(合成少数类过采样技术)、ADASYN(自适应合成过采样技术)等。每种方法有不同的原理和适用场景,选择适合问题的方法是关键。

  2. 执行过采样:根据选择的过采样方法,对少数类别的样本进行复制或生成新样本。复制样本可以直接复制原始样本,生成样本则是根据少数类别样本的特征合成新样本。

  3. 调整过采样比例:过采样可能会导致样本数量过多,导致模型训练时间增加或者过度拟合。可以通过控制过采样比例来平衡样本数量,确保各个类别之间的样本数量接近而不过于失衡。

  • 19
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜就多练_0828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值