1. 程式人生 > >機器學習 scikit-learn6 - 預測貸款使用者是否會逾期 - 特徵工程

機器學習 scikit-learn6 - 預測貸款使用者是否會逾期 - 特徵工程

文章目錄

說明

這次時間比較緊迫,還是按照以前的思路完成了這次小任務
參考連結: https://github.com/spareribs/kaggleSpareribs/tree/master/Overdue/ml/features

features 主要是資料的預處理

目前主要是簡單的資料處理, 主要是模型上面的訓練
1. 需要 直接刪除 的資料, 這些都是唯一的id標識, 會過擬合
    - bank_card_no:只有一個值 '卡號1' , 無區分度
    - source:只有一個值 'xs' , 無區分度
    - 'Unnamed: 0': 與預測值無關 
    - custid: 與預測值無關 
    - id_name:與預測值無關 
    - trade_no:與預測值無關 
    
2. 【類別特徵】需要 離散化處理 的資料
    - reg_preference_for_trad
    - regional_mobility
    - student_feature
    - is_high_user

3. 【日期】針對日期資料的處理(轉換成年月日)
    - first_transaction_time
    - latest_query_time
    - loans_latest_time

4. 【刪除部分特徵】:統計各個列標準差,將標準差小於0.1的特徵剔除
    
5. 【缺失值】缺失值的填充
    - 目前只是簡單的眾數填充 TODO
    - 缺失的資料作為一種新特徵,衡量資料的完整度

6. 歸一化處理所有資料
    - 目前直接使用StandardScaler方法處理, 沒搞明白 TODO

核心程式碼說明

1 去掉一部分對結果沒有影響的資料

def unique_drop(data):
    """ 
    1. count 跟 unique 一樣,需要刪除
    2. count 跟 unique 不一樣,只有單一值也是要刪除
    3. count 跟 unique 不一樣,但是 nan統計後,count 跟 unique 一樣 也需要刪除
    """
    for col in data.columns:
        count = len(list(data[col].unique()))
        if count == 1 or count ==
data.shape[0]: print(col) train.drop([col], inplace=True, axis=1) unique_drop(train)

這樣直接刪除這5列資料 Unnamed: 0, custid, trade_no, bank_card_no, source

2 字元特徵處理

def missing_count(train, feature):
    """
    1. 統計缺失值
    2. 統計unique
    """
    all_count = len(train)
    missing =
len(train[feature][pd.isnull(train[feature])]) unique_object = list(train[feature].unique()) print("缺失{1:>4}個 缺失率 {4:.2f}% 有{2:>4}個值 分別為 {3}等".format(all_count, missing, len(unique_object),unique_object[:7], missing/all_count, feature)) missing_count(train_object,"reg_preference_for_trad") missing_count(train_object,"id_name")
  1. reg_preference_for_trad: 城市,使用0來填充 用 one-hot 編碼
  2. id_name:名字,理論上需要對相同名字的人進行歸類, 這種做法先擱置了, 沒想到更好的解決方法,先刪除這一列資料
  3. latest_query_time和loans_latest_time 當作時間特徵來處理
# 缺失值2個,用眾數填充
train_object['reg_preference_for_trad'] = train_object['reg_preference_for_trad'].fillna(train_object['reg_preference_for_trad'].mode()[0])
# 轉換成數字
train_object['reg_preference_for_trad'] = train_object['reg_preference_for_trad'].map({'一線城市': 0, '二線城市': 1,'三線城市': 2,  '其他城市': 3, '境外': 4})
# one-hot編碼
train_object = pd.get_dummies(train_object,columns=["reg_preference_for_trad"],prefix="reg_preference_for_trad")

3 日期/時間型特徵

參考 https://blog.csdn.net/l75326747/article/details/84326897#字元型特徵

  1. 取出日期,可分別構建如 年、月、日、工作日、週數 等;
  2. 如有時間,可分別構建如 小時、分鐘 等;
  3. 兩兩日期或時間可根據業務知識相互做差,求出相差天數,小時數等
date_temp = pd.DataFrame()
date_temp['latest_query_time_year'] = pd.to_datetime(train_object['latest_query_time']).dt.year
date_temp['latest_query_time_month'] = pd.to_datetime(train_object['latest_query_time']).dt.month
date_temp['latest_query_time_day'] = pd.to_datetime(train_object['latest_query_time']).dt.day
date_temp['loans_latest_time_year'] = pd.to_datetime(train_object['loans_latest_time']).dt.year
date_temp['loans_latest_time_month'] = pd.to_datetime(train_object['loans_latest_time']).dt.month
date_temp['loans_latest_time_day'] = pd.to_datetime(train_object['loans_latest_time']).dt.day
date_temp.fillna(date_temp.median(), inplace=True)  # 使用中位數填充缺失值

4 數值特徵

製圖函式 - 與結果的關係

# 參考文章:
# https://zhuanlan.zhihu.com/p/33733586
# https://www.cnblogs.com/jin-liang/p/9011771.html
# https://blog.csdn.net/Jinlong_Xu/article/details/79769730
# https://www.jianshu.com/p/4b925654f506

import matplotlib.pyplot as plt

result = "status"
def sns_violinplot(train, feature, y_result=result):
    """ 類別特徵對應的特徵分佈 - 提琴圖 """
    sns.violinplot(x=y_result, y=feature, data=train)

sns_violinplot(train_num, "consfin_avg_limit") # 示例

確認缺失值的情況

train.isnull().sum().sort_values() / len(train) * 100

不難發現除了 student_feature 缺失值在 63% 以外,其餘的都不是非常多,這裡使用平均值來補充

  1. student_feature:使用0來填充
  2. other:使用均值來補充
train_num.fillna({'student_feature': 0}, inplace=True)
train_num.fillna(train_num.mode(), inplace=True) # 眾數
# train_num.fillna(train_num.mean(), inplace=True) # 均值
# train_num.fillna(train_num.median(), inplace=True) # 中位數

問題

  1. 問題1:dtype=object使用的問題,會全部轉換成字元型
train = pd.read_csv('{0}/data.csv'.format(PATH), encoding='gbk', dtype=object)  # 取消 dtype=object 的使用
  1. 問題2:時間日期的處理 有沒有更好的方法直接轉換
  2. 問題3:如何在一個for迴圈裡面製作所有的提琴圖,有待解決
for col in train_num.columns.tolist()
	sns_violinplot(train_num, "consfin_avg_limit") # 示例
  1. 整理文件1:各種圖形分析
  2. 整理文件2:pandas學習:對series和dataframe
  3. 整理文件3:資料分析中常用資料型別的處理方法

參考文件


[1] Feature Engineering for Machine Learning - 書本翻譯
[2] 特徵處理 - 七月線上
[3] 特徵選擇
[4] 缺失值處理