ML - 貸款使用者逾期情況分析2 - 特徵工程1(資料預處理)
文章目錄
- 資料預處理 (判定貸款使用者是否逾期)
- 1. 刪除無用特徵
- 2. 資料格式化 - X_date
- 3. 資料處理 - 類別特徵 X_cate
- 4. 資料處理 - 其他非數值型特徵
- 5. 資料處理 - 數值型特徵 X_num
- 6. 特徵拼接與儲存
- 遇到的問題
- Reference
- More
資料預處理 (判定貸款使用者是否逾期)
給定金融資料,預測貸款使用者是否會逾期。
(status是標籤:0表示未逾期,1表示逾期。)
Task5(特徵工程1 - 資料預處理)
import numpy as np
import pandas as pd
# 資料集預覽
data = pd.read_csv('data.csv')
data.drop_duplicates(inplace=True) # 去重
y = data.status
X = data.drop('status', axis=1)
# 觀測正負樣本是否均衡
y.value_counts()
# 觀察變數型別
set(X.dtypes) # 輸出: {dtype('int64'), dtype('float64'), dtype('O')}
1. 刪除無用特徵
刪除原則
1)屬性值單一的特徵;
2)觀測特徵取值以及label意義, 挑選和預測無關的特徵
1)屬性值單一的特徵 - ‘bank_card_no’,'source’的取值無區分度
for col in X.columns:
if len(X[col].unique()) == 1:
print(col, X[col].unique())
X.drop(col, axis = 1, inplace = True)
輸出:
bank_card_no [‘卡號1’]
source [‘xs’]
2)觀測特徵取值以及label意義, 是否和預測無關 - ‘Unnamed: 0’, ‘custid’, 'trade_no’和id_name’與預測無關
for col in X.columns:
cnt = X[col].count() # 沒有統計缺失值
if len(list(X[col].unique())) in [cnt, cnt+1]:
print(col)
# X['Unnamed: 0']
# X['custid']
# X['trade_no]
# X['id_name'].value_counts()
X.drop(['Unnamed: 0', 'custid', 'trade_no', 'id_name'], axis=1, inplace=True)
2. 資料格式化 - X_date
(此處主要針對時間特徵, 且此處時間特徵僅包含日期特徵)
日期特徵處理流程
1)浮點型日期轉換成字串型
2)取出日期,構建年份、月份、周幾等特徵
3)進一步(特徵構建):groupby對特徵進行統計分析
dateFeatures = ['first_transaction_time', 'latest_query_time', 'loans_latest_time']
X_date = X[dateFeatures]
1)浮點型日期轉換成字串型
# 首先填充缺失值
X_date['first_transaction_time'].fillna(X_date['first_transaction_time'].median(), inplace = True)
# 轉成字串型日期
X_date['first_transaction_time'] = X_date['first_transaction_time'].apply(lambda x:str(x)[:4] + '-' + str(x)[4:6] + '-' + str(x)[6:8])
2) 提取特徵:年份、月份、星期幾
X_date['first_transaction_time_year'] = pd.to_datetime(X_date['first_transaction_time']).dt.year
X_date['first_transaction_time_month'] = pd.to_datetime(X_date['first_transaction_time']).dt.month
X_date['first_transaction_time_weekday'] = pd.to_datetime(X_date['first_transaction_time']).dt.weekday
X_date['latest_query_time_year'] = pd.to_datetime(X_date['latest_query_time']).dt.year
X_date['latest_query_time_month'] = pd.to_datetime(X_date['latest_query_time']).dt.month
X_date['latest_query_time_weekday'] = pd.to_datetime(X_date['latest_query_time']).dt.weekday
X_date['loans_latest_time_year'] = pd.to_datetime(X_date['loans_latest_time']).dt.year
X_date['loans_latest_time_month'] = pd.to_datetime(X_date['loans_latest_time']).dt.month
X_date['loans_latest_time_weekday'] = pd.to_datetime(X_date['loans_latest_time']).dt.weekday
# 填充缺失值
X_date['latest_query_time_year'].fillna(X_date['latest_query_time_year'].median(), inplace = True)
X_date['latest_query_time_month'].fillna(X_date['latest_query_time_month'].median(), inplace = True)
X_date['latest_query_time_weekday'].fillna(X_date['latest_query_time_weekday'].median(), inplace = True)
X_date['loans_latest_time_year'].fillna(X_date['loans_latest_time_year'].median(), inplace = True)
X_date['loans_latest_time_month'].fillna(X_date['loans_latest_time_month'].median(), inplace = True)
X_date['loans_latest_time_weekday'].fillna(X_date['loans_latest_time_weekday'].median(), inplace = True)
X_date.drop(dateFeatures, axis = 1, inplace=True)
3. 資料處理 - 類別特徵 X_cate
1)字元型類別特徵編碼
2)缺失值填充
3)類別特徵Label與One-Hot編碼
類別特徵缺失值填充常用方法:分箱處理(單獨填充為一個類別)、眾數填充
# 觀察取值和屬性名稱, 挑選類別特徵
for col in X:
cnt = len(X[col].unique())
if cnt < 15:
print(col, cnt, X[col].unique())
輸出
regional_mobility 6 [ 3. 4. 1. 2. 5. nan]
student_feature 3 [nan 1. 2.]
is_high_user 2 [0 1]
avg_consume_less_12_valid_month 13 [ 7. 5. 6. 8. 9. 3. 4. 11. 10. 0. 2. 1. nan]
top_trans_count_last_1_month 9 [0.15 0.05 0.65 1. 0.1 0.3 0.4 0.2 nan]
reg_preference_for_trad 6 [‘一線城市’ ‘三線城市’ ‘境外’ ‘二線城市’ ‘其他城市’ nan]
railway_consume_count_last_12_month 7 [ 0. 1. 2. 4. nan 3. 30.]
jewelry_consume_count_last_6_month 8 [ 0. 1. nan 2. 6. 3. 4. 5.]
categoryFeatures = ['regional_mobility', 'student_feature', 'is_high_user', 'avg_consume_less_12_valid_month', 'reg_preference_for_trad']
X_cate = X[categoryFeatures]
1)字元型類別特徵編碼
dic = {}
for i, val in enumerate(list(X_cate['reg_preference_for_trad'].unique())):
dic[val] = i
X_cate['reg_preference_for_trad'] = X_cate['reg_preference_for_trad'].map(dic)
2)缺失值填充:單獨填充為一個類別/眾數填充
student_feature 缺失佔比一般以上, 將其缺失值單獨填充為1個類別(用-1填充)。
X_cate['student_feature'].value_counts()
X_cate['student_feature'].fillna(-1, inplace = True)
其他特徵缺失值數目較少, 考慮用眾數填充
for col in X_cate.columns:
summ = X_cate[col].isnull().sum()
if summ:
X_cate[col].fillna(X_cate[col].mode()[0], inplace = True)
3)類別特徵Label與One-Hot編碼
編碼方法 | 介紹 | 優點 | 缺點 | 適用場景 |
---|---|---|---|---|
label encoding | 將類別變數中每一類別賦一數值,從而轉換成數值型 | 略 | 賦值沒有數值意義 | |
One-hot encoding | 它的值只有0/1,不同的型別儲存在垂直的空間 | xx | 當類別的數量很多時,特徵空間會變得非常大 | ①除了樹模型都要One-hot,因為label沒有數值意義 |
4. 資料處理 - 其他非數值型特徵
此處沒有額外的待處理非數字型特徵 ~
X_str = X.select_dtypes(include=['O']).copy()
X_str.head()
5. 資料處理 - 數值型特徵 X_num
1)缺失值處理
2)去掉取值變化小的特徵:統計各個列標準差,將標準差小於0.1的特徵剔除
連續特徵缺失值填充常用方法:中位數填充,平均數一般不用的(均值受極端值影響太大)。
X_num = X.select_dtypes(exclude=['O']).copy()
for col in X_num.columns:
if col in dateFeatures + categoryFeatures:
print(col)
X_num.drop(col, axis = 1, inplace = True)
1)缺失值處理
主要填充方法採用眾數、中位數和模型填充等,平均數一般不用的(均值受極端值影響太大)。
# 統計各列缺失值的比例
col_missing = {}
for col in X_num.columns:
summ = X_num[col].isnull().sum()
if summ:
col_missing[col] = float('%.4f'%(summ*100/len(data)))
col_missing = sorted(col_missing.items(), key = lambda d:-d[1])
for col, rate in col_missing[:10]:
print(rate, '%', col)
缺失特徵用中位數填充。
for col in X_num.columns:
summ = X_num[col].isnull().sum()
if summ:
X_num[col].fillna(X_num[col].median(), inplace = True)
2)去掉取值變化小的特徵
for col in X_num.columns:
rate = X_num[col].std()
if rate < 0.1:
print(col, rate)
X_num.drop(col, axis = 1, inplace = True)
3) 歸一化(此處只是示例,程式碼部分沒有實際執行)
歸一化, 可以加快梯度下降求最優解的速度, 也有利於提高精度
# 最大最小歸一化
# X_num = X_num.apply(lambda x: (x - np.min(x)) / (np.max(x) - np.min(x)))
6. 特徵拼接與儲存
X = pd.concat([X_date, X_cate, X_num], axis=1)
import pickle
with open('feature.pkl', 'wb') as f:
pickle.dump(X, f)
遇到的問題
特徵數目和行數相同, 肯定和預測無關嗎? 如果是屬於類似連續型特徵呢?
Reference
1)特徵工程處理
2)資料分析工具之Python大法(一)
3)機器學習-Label Encoding與One Hot的區別-20180513
More
程式碼參見Github: https://github.com/libihan/Exercise-ML