1. 程式人生 > >MADlib——基於SQL的資料探勘解決方案(17)——迴歸之Cox比例風險迴歸

MADlib——基於SQL的資料探勘解決方案(17)——迴歸之Cox比例風險迴歸

一、Cox比例風險迴歸簡介

        Cox比例風險迴歸模型(Cox’s proportional hazards regression model),簡稱Cox迴歸模型,由英國統計學家D.R.Cox於1972年提出,主要用於腫瘤和其它慢性病的預後分析,也可用於佇列研究的病因探索。

1.  基本概念

  • 生存函式:又稱累計生存率,簡稱生存率,常用S(t)表示。代表被觀察物件的生存時間大於t時刻的概率,實際中t時刻的取值估算公式為:S(t) ≈ 生存時間長於t的患者數 / 患者總數 
  • 死亡概率函式:簡稱為死亡概率,常用F(t)表示。代表一個被觀察物件從開始觀察到時間t為止的死亡概率,它與生存函式的關係為:F(t) = 1 - S(t)。
  • 死亡密度函式:簡稱為密度函式,用f(t)表示。代表所有被觀察物件在t時刻的瞬時死亡率。
  • 風險函式:即生存時間已達到t的一群被觀察物件在t時刻的瞬時死亡率,用h(t)表示。代表已存活到時間t的每個觀察物件從t到t+∆t這一非常小的區間內死亡的概率極限,它與生存函式、死亡密度函式的關係為:h(t) = f(t) / S(t)。

2.  Cox迴歸模型結構

        Cox迴歸模型不直接考察生存函式與協變數(影響因素)的關係,而是用風險函式作為因變數。設有n名病人(i=1,2,...,n),第i名病人的生存時間為 ,同時該病人具有一組協變數 ,則模型為:

 :在時間t處的風險函式。

 :基準風險函式,為所有協變數取零時t時刻的風險函式,即沒有協變數下的風險函式。這是模型中的非引數部分,因此Cox迴歸是一種半引數分析方法。

 :協變數。

 :根據觀察值估算出的迴歸係數。

 :預後指數。大於0時表示該病人對應的危險度大於平均水平;等於0時為達到平均水平;小於0時表示該病人的危險度小於平均水平。

  • 迴歸係數  時,協變數的取值越大,風險函式  的值越大,表示病人死亡的風險越大。
  • 迴歸係數  時,表示協變數對風險函式  沒有影響。
  • 迴歸係數  時,協變數的取值越大,風險函式  的值越小,表示病人死亡的風險越小。

3.  Cox迴歸模型的前提條件

        Cox迴歸模型必須滿足比例風險假設(Proportional Hazards Assumption,PHA):

(1)任何兩個個體的風險函式之比,即風險比(HazardRatio,HR)保持一個恆定的比例,而與時間t無關。

(2)模型中協變數的效應不隨時間改變而改變。

        檢查某協變數是否滿足PHA,最簡單的方法是觀察該變數分組的生存曲線。若生存曲線交叉,表示不滿足PHA,此時可採用分層比例風險模型。

4.  引數估算與假設檢驗

        Cox迴歸的引數估計同邏輯迴歸分析一樣採用最大似然估計法。其基本思想是先建立偏似然函式或對數偏似然函式,求偏似然函式或對數偏似然函式達到極大時引數的取值,即為引數的最大似然估計值。

         假設檢驗的方法有時協變數法、線性相關檢驗法、加權殘差Score法等。這三種檢驗法有較高的準確率,且三種方法的檢驗效能相近。MADlib的Cox模型PHA檢驗函式使用線性相關檢驗法實現。

5.  Cox模型的注意事項

  • 研究的協變數在被研究物件中的分佈要適中,否則會給迴歸引數的估計帶來困難。
  • Cox模型應用較靈活,被觀察物件進入研究佇列的早晚、時間長短可以不一致,但如果研究的變數隨時間而變化,可以採用時依協變數模型進行分析。
  • 樣本含量不宜過小,一般應在40例以上,經驗上的做法是樣本含量為協變數個數的5-20倍。
  • 儘管可以分析刪失資料,但在觀察時,要儘量避免觀察物件的失訪,過多失訪容易造成結果的偏倚。
  • Cox模型對異常值較為敏感,所以在進行模型擬合時要注意擬合優度的檢驗。

二、MADlib中Cox比例風險迴歸相關函式

1.  訓練函式

(1)  語法

coxph_train( source_table,  
             output_table,  
             dependent_variable,  
             independent_variable,  
             right_censoring_status,  
             strata,  
             optimizer_params  
           ) 

 

(2)  引數

引數名稱

資料型別

描述

source_table

VARCHAR

包含訓練資料的源表名。

output_table

VARCHAR

儲存模型的輸出表名,主輸出表列和概要輸出表列分別如表2、表3所示。

dependent_variable

VARCHAR

因變數名稱,指死亡時間,不需要對資料進行預排序。

independent_variable

VARCHAR

自變數名稱陣列。

right_censoring_status(可選)

VARCHAR

預設值為TRUE。表示右刪失狀態的字串,如果無刪失則為TRUE,否則為FALSE。該引數可以包含是右刪失狀態的列名,或者是一個可以對每個觀察值進行評估的布林表示式,如‘column_name < 10’。

strata(可選)

VARCHAR

預設值為NULL,不做任何分層,可以是逗號分隔的列名。

optimizer_params(可選)

VARCHAR

預設值為NULL,此時使用預設的優化引數:max_iter=100, optimizer=newton, tolerance=1e-8, array_agg_size=10000000, sample_size=1000000。應該是一個逗號分隔的‘key=value’字串,引數含義如下:

l   max_iter:最大迭代數。如果迭代次數達到此數值則停止計算,這通常意味著無法收斂。

l   optimizer:優化方法,當前僅支援‘newton’。

l   tolerance:停止條件。當連續兩次迭代的對數似然值之差小於此引數,計算已經收斂並停止。

l   array_agg_size:為了加速計算,將原始資料表切分成多個數據片,每片資料聚合成一個大行。計算處理時,整個大行被匯入記憶體以提高運算速度。此引數控制一個大行中包含多少資料,引數值越大速度越快,但由於PostgreSQL資料庫的限制,一個大行的大小不能超過1G。

l   sample_size:為了將資料切分成大致相等的片,先進行資料取樣,然後利用取樣資料找出斷點。該引數值越大,產生的斷點越精確。

表1 coxph_train函式引數說明

列名

資料型別

描述

Coef

FLOAT8[]

迴歸係數向量。

loglikelihood

FLOAT8

極大似然估計的對數似然值。

std_err

FLOAT8[]

迴歸係數標準差向量。

stats

FLOAT8[]

迴歸係數統計向量。

p_values

FLOAT8[]

迴歸係數p值向量。

hessian

FLOAT8[]

Hessian矩陣。

num_iterations

INTEGER

優化器執行的迭代次數。

表2 coxph_train函式主輸出表列說明

        訓練函式在產生輸出表的同時,還會建立一個名為<output_table>_summary的概要表,具有以下列:

列名

資料型別

描述

method

VARCHAR

'coxph',描述模型的字串。

source_table

VARCHAR

源表名。

out_table

VARCHAR

模型表名。

dependent_varname

VARCHAR

因變量表達式。

independent_varname

VARCHAR

自變量表達式。

right_censoring_status

VARCHAR

右刪失狀態。

Strata

VARCHAR

分層列。

num_processed

INTEGER

處理行數。

num_missing_rows_skipped

INTEGER

跳過行數。

表3 coxph_train函式概要輸出表列說明

2.  比例風險假設檢驗函式

        cox_zph()函式檢驗Cox迴歸的比例風險假設,它通過計算coxph_train()輸出模型中殘差與時間的相關性驗證比例風險假設。

(1)  語法

cox_zph(cox_model_table, output_table)

 

(2)  引數

  • cox_model_table:TEXT型別,包含Cox模型的表名,應該是coxph_train()函式的輸出表。
  • output_table:TEXT型別,儲存測試結果的表名,主輸出表列和殘差輸出表列分別如表4、表5所示。

列名

資料型別

描述

covariate

TEXT

協變數。

rho

FLOAT8[]

生存時間與Schoenfeld殘差相關係數向量。

chi_square

FLOAT8[]

相關分析卡方檢驗統計量。

p_value

FLOAT8[]

卡方統計雙尾p值。

表4 cox_zph函式輸出表列說明

        檢驗函式還建立一個儲存殘差值的輸出表,名為<output_table>_residual,具有以下列:

列名

資料型別

描述

<dep_column_name>

FLOAT8

原始源表中存在的時間值(因變數)。

residual

FLOAT8[]

原始協變數與coxph_train模型中的期望協變數之差。

scaled_residual

FLOAT8[]

由係數的方差來衡量的殘差值。

表5 cox_zph函式殘差輸出表列說明

3.  預測函式

(1)  語法

coxph_predict(model_table,  
              source_table,  
              id_col_name,  
              output_table,  
              pred_type,  
              reference) 

 

(2)  引數

引數名稱

資料型別

描述

model_table

TEXT

包含cox模型的表名。

source_table

TEXT

包含預測資料的表名。

id_col_name

TEXT

id列名。

output_table

TEXT

儲存預測結果的輸出表名,輸出表具有以下列:

l   id:TEXT型別,id列。

l   predicted_result:FLOAT8型別,基於預測型別引數值的預測結果。

pred_type(可選)

TEXT

預測型別。預設為‘linear_predictors’,可以是‘linear_predictors’、‘risk’或‘terms’。

l   linear_predictors:計算自變數和係數的點積,也即預後指數。

l   risk:預後指數預測結果的指數值。

l   terms:每個協變數與它們相應的係數值的乘積,不求和。

reference(可選)

TEXT

用於中心預測。可以為‘strata’、‘overall’,預設值為‘strata’。

表6 coxph_predict函式引數說明

        注:Cox迴歸模型的因變數是風險函式,因此與其它模型的預測函式不同,它不直接返回生存時間的預測值。

三、示例

1.  檢視聯機幫助

select madlib.coxph_train();  
-- 訓練函式用法  
select madlib.coxph_train('usage');  
-- 示例  
select madlib.coxph_train('example'); 

 

2.  建立測試資料表並裝載原始資料

drop table if exists sample_data;  
create table sample_data (  
    id integer not null,    -- 邏輯主鍵  
    grp double precision,   -- 分組(治療方法)  
    wbc double precision,   -- 白細胞值  
    timedeath integer,      -- 生存天數  
    status boolean          -- 結局  
);  
copy sample_data from stdin with delimiter '|';  
  1 |   0 | 1.45 |        35 | t  
  2 |   0 | 1.47 |        34 | t  
  3 |   0 |  2.2 |        32 | t  
  4 |   0 | 1.78 |        25 | t  
  5 |   0 | 2.57 |        23 | t  
  6 |   0 | 2.32 |        22 | t  
  7 |   0 | 2.01 |        20 | t  
  8 |   0 | 2.05 |        19 | t  
  9 |   0 | 2.16 |        17 | t  
 10 |   0 |  3.6 |        16 | t  
 11 |   1 |  2.3 |        15 | t  
 12 |   0 | 2.88 |        13 | t  
 13 |   1 |  1.5 |        12 | t  
 14 |   0 |  2.6 |        11 | t  
 15 |   0 |  2.7 |        10 | t  
 16 |   0 |  2.8 |         9 | t  
 17 |   1 | 2.32 |         8 | t  
 18 |   0 | 4.43 |         7 | t  
 19 |   0 | 2.31 |         6 | t  
 20 |   1 | 3.49 |         5 | t  
 21 |   1 | 2.42 |         4 | t  
 22 |   1 | 4.01 |         3 | t  
 23 |   1 | 4.91 |         2 | t  
 24 |   1 |    5 |         1 | t  
\.

 

        說明:在這個假設的生存分析案例中,將24名患者分為兩組(如模擬兩種治療方法)進行觀察。協變數有兩個,分組與白細胞值,樣本量是協變數個數的12倍。因變數為生存天數。所有患者結局已知,不存在刪失情況。

3.  訓練模型

drop table if exists sample_cox, sample_cox_summary;  
select madlib.coxph_train( 'sample_data',  
                           'sample_cox',  
                           'timedeath',  
                           'array[grp,wbc]',  
                           'status'  
                         ); 

4.  查看回歸結果

\x on  
select * from sample_cox;

        結果:
-[ RECORD 1 ]--+----------------------------------------------------------------------------
coef           | {2.54407073265254,1.67172094779487}
loglikelihood  | -37.8532498733
std_err        | {0.677180599294897,0.387195514577534}
z_stats        | {3.7568570855419,4.31751114064138}
p_values       | {0.000172060691513886,1.5779844638453e-05}
hessian        | {{2.78043065745617,-2.25848560642414},{-2.25848560642414,8.50472838284472}}
num_iterations | 5

        經過5次迭代後求得兩個協變數的迴歸係數。z檢驗得到的p值很小,說明樣本間的差異由抽樣誤差所致的概率極小,具有顯著統計意義。

5.  檢驗所得模型的PHA

drop table if exists sample_zph_output, sample_zph_output_residual;  
select madlib.cox_zph( 'sample_cox',  
                       'sample_zph_output'  
                     );  
  
select * from sample_zph_output; 

 

        結果:

-[ RECORD 1 ]-----------------------------------------  
covariate  | array[grp,wbc]  
rho        | {0.00237308357328641,0.037560056884043}  
chi_square | {0.000100675718191977,0.0232317400546175}  
p_value    | {0.991994376850758,0.878855984657948} 

        madlib.cox_zph函式使用卡方線性相關法檢驗比例風險假設是否成立。它的原理很簡單:如果資料滿足比例風險假設,則Schoenfeld殘差和生存時間的秩次之間無相關性。計算步驟按以下3步進行:①用未刪失資料計算每個協變數Schoenfeld殘差;②將未刪失的生存時間排序,並以新變數(協變數殘差)記錄秩次1、2、3...,如出現相同生存時間(結點),則以平均秩次記錄。③進行假設檢驗,檢驗Schoenfeld殘差和生存時間秩次間的相關性(原假設為H0:r=0,無相關性)。若原假設被拒絕,則表明資料不滿足比例風險假設。

        從本例的檢驗p值結果看,協變數對應的雙尾p值接近於1,說明應該接受原假設,模型滿足比例風險假設。

6.  用模型進行預測

        本例使用源資料表演示預測。

(1)條目預測

\x off  
drop table if exists sample_pred_terms;  
select madlib.coxph_predict('sample_cox',  
                            'sample_data',  
                            'id',  
                            'sample_pred_terms',  
                            'terms');  
  
select id, terms, sum(c) linear_predictors  
  from (select id, terms, unnest(terms) c  
          from sample_pred_terms) t  
 group by id, terms  
 order by linear_predictors;

        結果:
 id |                  terms                   | linear_predictors    
----+------------------------------------------+--------------------  
  1 | {-0.848023577550848,-2.12308560369949}   |  -2.97110918125034  
  2 | {-0.848023577550848,-2.08965118474359}   |  -2.93767476229444  
  4 | {-0.848023577550848,-1.57141769092718}   |  -2.41944126847803  
  7 | {-0.848023577550848,-1.18692187293436}   |  -2.03494545048521  
  8 | {-0.848023577550848,-1.12005303502256}   |  -1.96807661257341  
  9 | {-0.848023577550848,-0.936163730765128}  |  -1.78418730831598  
  3 | {-0.848023577550848,-0.869294892853333}  |  -1.71731847040418  
 19 | {-0.848023577550848,-0.685405588595898}  |  -1.53342916614675  
  6 | {-0.848023577550848,-0.668688379117949}  |   -1.5167119566688  
  5 | {-0.848023577550848,-0.250758142169231}  |  -1.09878171972008  
 14 | {-0.848023577550848,-0.200606513735385}  |  -1.04863009128623  
 15 | {-0.848023577550848,-0.0334344189558975} | -0.881457996506746  
 16 | {-0.848023577550848,0.133737675823589}   | -0.714285901727259  
 12 | {-0.848023577550848,0.267475351647179}   | -0.580548225903669  
 13 | {1.6960471551017,-2.03949955630974}      | -0.343452401208047  
 10 | {-0.848023577550848,1.47111443405949}    |  0.623090856508639  
 11 | {1.6960471551017,-0.702122798073847}     |   0.99392435702785  
 17 | {1.6960471551017,-0.668688379117949}     |   1.02735877598375  
 21 | {1.6960471551017,-0.501516284338462}     |   1.19453087076323  
 18 | {-0.848023577550848,2.85864282072923}    |   2.01061924317838  
 20 | {1.6960471551017,1.28722512980205}       |   2.98327228490375  
 22 | {1.6960471551017,2.15652002265538}       |   3.85256717775708  
 23 | {1.6960471551017,3.66106887567077}       |   5.35711603077247  
 24 | {1.6960471551017,3.81152376097231}       |     5.507570916074  
(24 rows)

        條目預測的輸出是一個協變數陣列,每個元素值是對應協變數與迴歸係數的點積。

(2)預後指數預測

\x off  
drop table if exists sample_pred;  
select madlib.coxph_predict('sample_cox',  
                            'sample_data',  
                            'id',  
                            'sample_pred');  
  
select id, linear_predictors, exp(linear_predictors) risk  
  from sample_pred order by linear_predictors; 

        結果:
 id | linear_predictors  |        risk          
----+--------------------+--------------------  
  1 |  -2.97110918125034 | 0.0512464372091503  
  2 |  -2.93767476229444 |  0.052988797150351  
  4 |  -2.41944126847803 | 0.0889713146524469  
  7 |  -2.03494545048521 |  0.130687611255372  
  8 |  -1.96807661257341 |  0.139725343898993  
  9 |  -1.78418730831598 |  0.167933483703554  
  3 |  -1.71731847040418 |  0.179546963459175  
 19 |  -1.53342916614675 |  0.215794402223054  
  6 |   -1.5167119566688 |  0.219432204682558  
  5 |  -1.09878171972008 |   0.33327686110022  
 14 |  -1.04863009128623 |  0.350417460388247  
 15 | -0.881457996506746 |  0.414178600294289  
 16 | -0.714285901727259 |  0.489541567796517  
 12 | -0.580548225903669 |  0.559591499901242  
 13 | -0.343452401208048 |  0.709317242984782  
 10 |  0.623090856508639 |   1.86468261037507  
 11 |   0.99392435702785 |   2.70181658768287  
 17 |   1.02735877598375 |   2.79367735395697  
 21 |   1.19453087076323 |   3.30200833843654  
 18 |   2.01061924317838 |   7.46794038691976  
 20 |   2.98327228490375 |   19.7523463121038  
 22 |   3.85256717775708 |   47.1138577624205  
 23 |   5.35711603077247 |   212.112338046552  
 24 |     5.507570916074 |   246.551504798816  
(24 rows) 

        可以看到,1的風險度最小,24的風險度最大,並且預後指數預測的結果,就是對條目預測結果陣列的元素求和而得。

(3)風險預測

drop table if exists sample_pred_risk;  
select madlib.coxph_predict('sample_cox',  
                            'sample_data',  
                            'id',  
                            'sample_pred_risk',  
                            'risk');  
  
select * from sample_pred_risk order by risk;

        結果:
 id |        risk          
----+--------------------  
  1 | 0.0512464372091503  
  2 |  0.052988797150351  
  4 | 0.0889713146524469  
  7 |  0.130687611255372  
  8 |  0.139725343898993  
  9 |  0.167933483703554  
  3 |  0.179546963459175  
 19 |  0.215794402223054  
  6 |  0.219432204682558  
  5 |   0.33327686110022  
 14 |  0.350417460388247  
 15 |  0.414178600294289  
 16 |  0.489541567796517  
 12 |  0.559591499901242  
 13 |  0.709317242984782  
 10 |   1.86468261037507  
 11 |   2.70181658768287  
 17 |   2.79367735395697  
 21 |   3.30200833843654  
 18 |   7.46794038691976  
 20 |   19.7523463121038  
 22 |   47.1138577624205  
 23 |   212.112338046552  
 24 |   246.551504798816  
(24 rows)  

        可以看到,風險預測就是預後指數結果的指數值。