下采样(处理数据不平衡问题)

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import StandardScaler#去均值,方差归一化,类似于特征缩放
from sklearn.model_selection import train_test_split#分为训练集和测试集
from sklearn.model_selection import GridSearchCV#自动调参,并行参数搜索
from sklearn.linear_model import LogisticRegression#逻辑回归
from sklearn.metrics import classification_report#精确度、召回率
def load_and_analyse_data():
    data = pd.read_csv('./data/creditcard.csv')
    # ----------------------查看样本分布情况----------------------------------
    count_classes = pd.value_counts(data['Class'])#也可以pd.value_counts(data['Class'],sort=False).sort_index(axis=0)其中,pd.valueC_counts对数据分类并计算,class为对数据中的标注"class"进行分类并计算,sort表布尔值,表计算结果按升序排序还是降序排序,sort_index是按索引进行排序,这里axis = 1不行
   # print(count_classes)# negative 0 :284315   positive 1 :492
    count_classes.plot(kind='bar')#柱状图画图
    plt.title('Fraud class histogram')
    plt.xlabel('Class')
    plt.ylabel('Frequency')
    plt.show()
    # --------------------------------------------------------------------------
    # ----------------------预处理---------------------------------------------
    # ----------------------标准化Amount列---------
    data['normAmout'] = StandardScaler().fit_transform(data['Amount'].values.reshape(-1, 1))#增加一列标注为"normAmount",内容为Amount中数据的标准归一化,值的范围设为(-1,1),在原数据文件中不会增加这一列,但可以在代码中引用“normAmount”中的值。
    data = data.drop(['Time', 'Amount'], axis=1)#去掉Time和Amount列,原数据文件不会改变,但程序中改了
    #print(data['normAmout'])
    # ----------------------------------------------
    X = data.ix[:, data.columns != 'Class']#ix表数据搜索到的位置
    y = data.ix[:, data.columns == 'Class']#ix表数据搜索到的位置,y为class这一列
    positive_number = len(y[y.Class == 1])  # 492
    negative_number = len(y[y.Class == 0])  # 284315
    # print(y.Class==1)#输出布尔语句
    # print(y[y.Class==1])#布尔语句也可以当索引,输出的是y中类别被1的数据
    positive_indices = np.array(y[y.Class == 1].index)#.index是取出y=1对应的索引,并转化成np形式
   # print(positive_indices)
    negative_indices = np.array(y[y.Class == 0].index)#.index是取出y=0对应的索引,并转化成np形式

    # ----------------------采样-------------------
    random_negative_indices = np.random.choice(negative_indices, positive_number, replace=False)#从negative_indices中选择出positive_number个数来,replace=false表没有重复替换的随机采样,也就是采出来的数据如果是一样的,不替换,也就是独立的。
    random_negative_indices = np.array(random_negative_indices)#选出来的数做成np格式
    under_sample_indices = np.concatenate([positive_indices, random_negative_indices])#把两个数组串联起来
    #print(positive_indices)
    #print(random_negative_indices)
    #print(under_sample_indices)
    under_sample_data = data.iloc[under_sample_indices, :]#取出数据中标签对应的样本
    X_sample = under_sample_data.ix[:, under_sample_data.columns != 'Class']#将取出的样本划分
    y_sample = under_sample_data.ix[:, under_sample_data.columns == 'Class']#将取出的样本划分
    print(y)
    print(np.array(y))
    print(np.array(y).reshape(len(y)))
    print(X)
    print(np.array(X))
    return np.array(X), np.array(y).reshape(len(y)), np.array(X_sample), np.array(y_sample).reshape(len(y_sample))

if __name__ == '__main__':
    X, y, X_sample, y_sample = load_and_analyse_data()
    _, X_test, _, y_test = train_test_split(X, y, test_size=0.3, random_state=30)#random_state为随机数种子,用来测试最后最好参数的模型,其中_表空,不用这个数据。
    X_train, X_dev, y_train, y_dev = train_test_split(X_sample, y_sample, test_size=0.3, random_state=1)


    print("X_train:{}  X_dev:{}  X_test:{}".format(len(y_train),len(y_dev),len(y_test)))
    model = LogisticRegression()#引入逻辑回归
    parameters = {'C': [0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3, 10]}#字典,所有的超参数
    gs = GridSearchCV(model, parameters,  verbose=5,cv=5)#model是模型,paramaters是参数,cv是5-fold交叉验证,verbose表输出训练过程。
    gs.fit(X_train, y_train)#训练数据导入模型
    print('最佳模型:', gs.best_params_, gs.best_score_)
    print('在采样数据上的性能表现:')
    print(gs.score(X_dev, y_dev))
    y_dev_pre = gs.predict(X_dev)
    print(classification_report(y_dev, y_dev_pre))
    print('在原始数据上的性能表现:')
    print(gs.score(X_test, y_test))
    y_pre = gs.predict(X_test)
    print(classification_report(y_test, y_pre))

数据集:

链接: https://pan.baidu.com/s/1OlZ-nkS4sbjSgoaetqqOGg 提取码: ggr8

缺点:

丢失大量数据,浪费。

优点:

更加均衡,把类别0和1都考虑的比较完整,如果直接用原始数据而不采样,则会偏向0,因为类别为0的数据太多了。

目的:

用来处理数据不平衡问题。

猜你喜欢

转载自blog.csdn.net/weixin_40849273/article/details/83106179