1. 程式人生 > >下采樣(處理資料不平衡問題)

下采樣(處理資料不平衡問題)

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的資料太多了。

目的:

用來處理資料不平衡問題。