Mục lục
Data Preparation
Tạo dữ liệu Dummy
Để tạo dữ liệu Dummy, ta sử dụng Macro:
%Data_dummy(nobs=1000000);
Với nobs là tham số để macro sinh ra dữ liệu gồm nobs quan sát. Có thể điều chỉnh nobs để phù hợp với cấu hình máy tính. Kết quả của macro là ba dữ liệu:
- Dữ liệu Train minh họa cho dữ liệu được dùng để xây dựng mô hình (có Yearmonth nằm trong đoạn 201901 đến 201903).
- Dữ liệu Outtime minh họa cho dữ liệu Out of time (có Yearmonth nằm trong đoạn 201904 đến 201912).
- Dữ liệu Variable_SQL minh họa cho dữ liệu import từ SQL.
Dữ liệu Train và Outtime được minh họa như sau:
ID | Y | X5 | X13 | X1 | … | X12 | Yearmonth | Obs_date | Bad | Good |
---|---|---|---|---|---|---|---|---|---|---|
2 | 0.002 | Primary School | -0.912 | … | 151304 | 201902 | 43497 | 0 | 1 | |
11 | 0.999 | Doctor | High School | -0.394 | … | -82483 | 201902 | 43497 | 1 | 0 |
15 | 0.999 | Nurse | Primary School | -0.849 | … | 201903 | 43525 | 1 | 0 | |
16 | 0.813 | Primary School | -0.739 | … | 201902 | 43497 | 1 | 0 | ||
18 | 0.999 | Worker | High School | 0.177 | … | -157401 | 201902 | 43497 | 1 | 0 |
19 | 0.000 | Worker | High School | -0.721 | … | 323650 | 201903 | 43525 | 0 | 1 |
Các biến trong dữ liệu Train và Outtime như sau:
- Biến ID minh họa cho Key của dữ liệu.
- Biến Y là biến liên tục trong khoảng (0,1) được tạo ra theo phân phối Beta(0.2, 0.2).
- Biến Good, Bad được định nghĩa dựa trên biến Y.
- Các biến X1-X13 được tạo ra ngẫu nhiên (có thể phụ thuộc hoặc không phụ thuộc Y). Trong đó hai biến X5 và X13 là biến chữ có độ dài lớn (255) và còn lại là các biến số.
- Biến Obs_date minh họa cho observation date và đang có định dạng sai (định dạng chữ thay vì datetime).
Dữ liệu Variable_SQL được minh họa như sau:
ID | ID_month | Z1 | Z2 | Z3 | Z4 |
---|---|---|---|---|---|
1 | 2 | 13.344 | 8.251 | -2.503 | -4.212 |
1 | 3 | 9.555 | -8.043 | -7.85 | -0.185 |
1 | 4 | -7.336 | 7.05 | -13.306 | -4.002 |
1 | 5 | 9.207 | -0.826 | -17.009 | -3.943 |
1 | 6 | 13.616 | 2.555 | -9.247 | 1.672 |
Các biến trong dữ liệu Variable_SQL như sau:
- Biến ID minh họa cho key của dữ liệu, được dùng để map với bảng Train và Outtime.
- Biến ID_month minh họa cho khoảng thời gian lấy dữ liệu của biến (xem thêm tại Data Aggregation).
- Biến Z1-Z4 là các biến số được sinh ra phụ thuộc vào biến Y và ID_MONTH.
Data Aggregation
Để tạo các biến từ dữ liệu SQL, ta sử dụng Macro:
%Data_aggregation(Ds_in=Variable_SQL,
Ds_out=Variable,
Max_time=12,
ID=ID,
Varlist= Z1 Z2 Z3);
Kết quả nhận được là dữ liệu Variable chứa các biến ba chiều.
ID | ID_month | Z1 | Z2 | Z3 | … |
---|---|---|---|---|---|
1 | 15.046 | 0.565 | 14.6 | 5.823 | … |
1 | -3.187 | 0.334 | -1.823 | 4.796 | … |
1 | 12.435 | -2.871 | 9.515 | 5.168 | … |
1 | 6.431 | 2.65 | 2.38 | -0.86 | … |
1 | 1.322 | -4.942 | -17.028 | 5.234 | … |
Giảm kích thước dữ liệu
Dữ liệu Train và Outtime có kích thước là 207MB và 622MB tương ứng. Biến Obs_date trong hai dữ liệu đang có định dạng sai. Ta thu gọn dữ liệu như sau:
%Data_reduce_size(Train, data.import, obs_date);
%Data_reduce_size(Outime, data.outtime, obs_date);
Kết quả nhận được là hai dữ liệu data.import và data.outtime với kích thước 37MB và 112MB. Ta tiến hành Join các biến vào dữ liệu Train và Validate:
Data data.import;
Merge data.import(In= data) Variable (In= var);
By ID;
If data;
Run;
Data data.outime;
Merge data.outtime(In= data) variable (In= var);
By ID;
If data;
Run;
Chia thành train/ Validate
Ta chia dữ liệu thành hai phần, 70% quan sát cho dữ liệu train và 30% quan sát cho dữ liệu validate. Cách làm như sau:
%Data_partition(Ds_in=data.import, train=data.train, valid=data.validate, percent=70, target=good);
Chương trình SAS hiện thông báo như sau:
Kết quả hiển thị nghĩa là :
- Có 124,710 quan sát với Good=1 và 125,670 quan sát với Good=0 trong dữ liệu đầu vào (DATA.IMPORT)
- Có 87,310 quan sát với Good=1 và 87,977 quan sát với Good=0 trong dữ liệu train (DATA.TRAIN)
Variable Analysis
Review Variables
Với dữ liệu train, ta sử dụng macro Var_review như sau:
%Var_review(Ds_train=data.train,
DS_outtime=data.outtime,
Numbin=20,
Exclude_varlist=Y Good Bad Yearmonth ID Obs_date);
Các biến bị loại khỏi phân tích là Y Good Bad (các biến target), Yearmonth ID (các biến ID) và Obs_date (ngày quan sát). Kết quả của dữ liệu được mô tả như trong Variable Review. Có thể thấy rằng nhiều biến interval có tính dự báo rất cao. Trong bước tiếp theo ta sẽ chỉ phân tích các biến X_
. Với các biến categorical, biến X13 hoàn toàn không có tính dự báo.
Variable Binning
Để phân tích các biến, ta sử dụng cú pháp như sáu:
%Var_bin(data=data.train, var=X1, numbin=20, group=7, libname=data);
Chú ý rằng Libname=data
nghĩa là các kết quả đầu ra của macro được lưu trong thư viện Data.
Kết quả như sau:
Với các biến có giá trị lớn (ví dụ X9) ta sử dụng tham số round:
%Var_bin(data=data.train, var=X11, numbin=20, group=6, libname=data, round=0);
Có thể thấy rằng kết quả nhóm biến chưa được tốt. Cụ thể là nên điều chỉnh nhóm các nhóm từ 1 đến 13 thành một nhóm. Ta mở data output Finalbin
và chỉnh sửa hai giá trị 1 thành 2:
Sau đó sử dụng macro Var_bin_manual:
%Var_bin_manual;
Kết quả như sau:
Tương tự với tất cả các biến. Ta có full code như sau:
%Var_bin(data=data.train, var=x1, numbin=20, group=7, libname=data);
%Var_bin(data=data.train, var=x2, numbin=20, group=7, libname=data);
%Var_bin(data=data.train, var=x3, numbin=20, group=4, libname=data);
%Var_bin(data=data.train, var=x4, numbin=20, group=4, libname=data, round=0);
%Var_bin(data=data.train, var=x5, numbin=20, group=8, libname=data);
%Var_bin(data=data.train, var=x6, numbin=20, group=8, libname=data);
%Var_bin(data=data.train, var=x7, numbin=20, group=8, libname=data);
%Var_bin(data=data.train, var=x8, numbin=20, group=8, libname=data, round=0);
%Var_bin(data=data.train, var=x9, numbin=20, group=6, libname=data, round=0);
%Var_bin_manual;
%Var_bin(data=data.train, var=x10, numbin=20, group=4, libname=data);
%Var_bin(data=data.train, var=x11, numbin=20, group=6, libname=data, round=0);
%Var_bin_manual;
%Var_bin(data=data.train, var=x12, numbin=20, group=8, libname=data, round=0);
%Var_bin(data=data.train, var=x13, numbin=20, group=8, libname=data);
Chú ý kết quả của bước này là các dữ liệu data.var_bin_mapping
sẽ được sử dụng ở bước sau.
Reporting
Để output kết quả phân tích biến ra file Excel, ta sử dụng Macro:
%Report_var_bin(Ds_fine=data.var_bin_fine,
ds_raw=data.var_bin_raw,
varlist=x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12);
Variable Transformation
Tại bước này, các biến sẽ được chuyển sang dạng Group (Grp) và WoE (WOE). Biến đổi này thực hiện trên cả ba dữ liệu train, validate, outtime. Cách làm như sau: Trước hết, ta chạy các format:
%Var_add_woe(train=data.train,
valid=data.validate,
test=data.outtime,
keep=Y Yearmonth,
varlist=x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12);
Kết quả của macro là các dữ liệu:
- Dữ liệu chứa group: Train_grp, valid_grp, outtime_grp.
- Dữ liệu chứa WoE: train_woe, valid_woe, outtime_woe.
- Dữ liệu chứa thông tin Mapping: train_mapping.
- Dữ liệu chứa thông tin WOE của các biến: Train_woedata
Variable Selection
Trước hết, ta cần chọn danh sách biến dưới dạng Macro bằng Proc SQL
như sau:
Proc contents data=data.train_woe (keep=woe_:) out=temp_woe_varlist noprint;
run;
Proc SQL noprint;
select name into :Woe_varlist separated by " " from temp_woe_varlist;
quit;
Các biến có dạng WOE_ đã được load vào biến macro &WOE_varlist. Ta thực hiện một số phương pháp chọn biến như sau:
Chọn biến bằng cách thử tất cả các tổ hợp biến
%Varselect_alll_combine(data=data.train_woe, varlist=&WOE_varlist, batch_size=10);
Chọn biến bằng phương pháp marginal IV
%Varselect_marIV(data=data.train_woe, WOE_varlist=&WOE_varlist, IV_entry=0.01, corr=0.7);
Chọn biến bằng phương pháp stepwise
%Varselect_stepwise(data=data.train_woe, slentry=0.0001, corr=0.7);
Với các phương pháp trên, ta chọn bộ biến cuối cùng là WOE_x1 WOE_x2 WOE_x3 WOE_x4 WOE_x5 WOE_x6 WOE_x8
.
Mô hình
Hồi quy mô hình
Để hồi quy mô hình với các biến WOE_x1 WOE_x2 WOE_x3 WOE_x4 WOE_x5 WOE_x6 WOE_x8
ta sử dụng code như sau:
%Let Final_varlist=
WOE_x1
WOE_x2
WOE_x3
WOE_x4
WOE_x5
WOE_x6
WOE_x8;
%Model_regression(ds_train=data.train_woe,
ds_valid=data.validate_woe,
ds_outtime=data.outtime_woe,
ds_woedata=data.train_woedata,
woe_varlist=&final_varlist,
libname=data);
Kết quả nhận được như sau:
Dữ liệu output gồm 4 dữ liệu: Model_reg_plot, Model_reg_gini, Model_reg_param, Model_scorecard
đã được mô tả ở hồi quy logistic.
Chấm điểm dữ liệu mới
Để chấm điểm dữ liệu mới (trong ví dụ này là data_all
ta làm như sau:
%Let varlist=x1 x2 x3 x4 x5 x6 x8;
Data data_all;
set data.train(keep=&varlist good bad yearmonth)
data.outtime(keep=&varlist good bad yearmonth);
run;
%Model_scoring(ds_mapping=data.train_mapping,
ds_param=data.model_reg_param,
ds_score=data_all,
ds_out=data_score,
varlist=x1 x2 x3 x4 x5 x6 x8,
keep=yearmonth good bad);
Kết quả nhận được là dữ liệu Data_all
chứa các biến ban đầu, các biến dạng group (grp_), các biến dạng WoE (WOE_) và Score.
Monitoring
Kiểm định tính ổn định
%Let data= data_score;
%Let param= data.model_reg_param;
%Let varlist=x1 x2 x3 x4 x5 x6 x8;
%Let devday=201903;
Proc format;
/* Score */
value scoreF
Low - 0.0000 = '[01] (-Inf; 0.0000]'
0.0000< - 0.0001 = '[02] (0.0000; 0.0001]'
0.0001< - 0.0053 = '[03] (0.0001; 0.0053]'
0.0053< - 0.0395 = '[04] (0.0053; 0.0395]'
0.0395< - 0.0814 = '[05] (0.0395; 0.0814]'
0.0814< - 0.1518 = '[06] (0.0814; 0.1518]'
0.1518< - 0.2702 = '[07] (0.1518; 0.2702]'
0.2702< - 0.4332 = '[08] (0.2702; 0.4332]'
0.4332< - 0.5748 = '[09] (0.4332; 0.5748]'
0.5748< - 0.6460 = '[10] (0.5748; 0.6460]'
0.6460< - 0.6851 = '[11] (0.6460; 0.6851]'
0.6851< - 0.7225 = '[12] (0.6851; 0.7225]'
0.7225< - 0.7618 = '[13] (0.7225; 0.7618]'
0.7618< - 0.7846 = '[14] (0.7618; 0.7846]'
0.7846< - 0.8111 = '[15] (0.7846; 0.8111]'
0.8111< - 0.8413 = '[16] (0.8111; 0.8413]'
0.8413< - 0.8614 = '[17] (0.8413; 0.8614]'
0.8614< - 0.8922 = '[18] (0.8614; 0.8922]'
0.8922< - 0.9419 = '[19] (0.8922; 0.9419]'
0.9419< - High = '[20] (0.9419 ; +Inf)';
run;
%Moni_stab;
Kiểm định tính phân biệt
%Let Data_GB= data_score;
%Let param= data.model_reg_param;
%Let varlist=x1 x2 x3 x4 x5 x6 x8;
Proc format;
/* Score */
value scoreF
Low - 0.0000 = '[01] (-Inf; 0.0000]'
0.0000< - 0.0001 = '[02] (0.0000; 0.0001]'
0.0001< - 0.0053 = '[03] (0.0001; 0.0053]'
0.0053< - 0.0395 = '[04] (0.0053; 0.0395]'
0.0395< - 0.0814 = '[05] (0.0395; 0.0814]'
0.0814< - 0.1518 = '[06] (0.0814; 0.1518]'
0.1518< - 0.2702 = '[07] (0.1518; 0.2702]'
0.2702< - 0.4332 = '[08] (0.2702; 0.4332]'
0.4332< - 0.5748 = '[09] (0.4332; 0.5748]'
0.5748< - 0.6460 = '[10] (0.5748; 0.6460]'
0.6460< - 0.6851 = '[11] (0.6460; 0.6851]'
0.6851< - 0.7225 = '[12] (0.6851; 0.7225]'
0.7225< - 0.7618 = '[13] (0.7225; 0.7618]'
0.7618< - 0.7846 = '[14] (0.7618; 0.7846]'
0.7846< - 0.8111 = '[15] (0.7846; 0.8111]'
0.8111< - 0.8413 = '[16] (0.8111; 0.8413]'
0.8413< - 0.8614 = '[17] (0.8413; 0.8614]'
0.8614< - 0.8922 = '[18] (0.8614; 0.8922]'
0.8922< - 0.9419 = '[19] (0.8922; 0.9419]'
0.9419< - High = '[20] (0.9419 ; +Inf)';
run;
%Moni_DCRM;