(青島科技大學(xué) 信息科學(xué)技術(shù)學(xué)院,山東 青島 266000)
根據(jù)國際腎病協(xié)會、歐洲腎病學(xué)會-歐洲透析和移植學(xué)會、美國腎病學(xué)會估計,全球至少有8.5億人患有腎病,占世界總?cè)丝诘?1%[1]。在2017年全球發(fā)布的腎臟地圖中,僅慢性腎病每10個人就有一個人是患者,由此可見慢性腎病占比之高。而慢性腎病的發(fā)展不可逆轉(zhuǎn),因而患者只能通過長期藥物治療來控制病情發(fā)展。若患者不盡早接受治療,極易出現(xiàn)病情惡化導(dǎo)致終末期腎臟病[2]。因此盡早進行診斷慢性腎病對于后期治療具有重大意義和價值。
隨著醫(yī)療信息化建設(shè)的推進,醫(yī)療數(shù)據(jù)量正在急劇膨脹,導(dǎo)致數(shù)據(jù)挖掘技術(shù)在醫(yī)療領(lǐng)域的應(yīng)用也更加廣泛。目前數(shù)據(jù)挖掘應(yīng)用于醫(yī)療領(lǐng)域主要是用來預(yù)防、診斷、治療和預(yù)后。應(yīng)用于預(yù)防是通過尋找疾病的誘病因子以及通過疾病早期篩查來預(yù)防疾病。應(yīng)用于診斷是利用電子病歷文本信息或圖像信息輔助[3]醫(yī)生對疾病進行診斷。應(yīng)用于治療是通過關(guān)聯(lián)規(guī)則等算法挖掘出藥物對疾病的治療作用并且能制定臨床路徑,方便醫(yī)生開處方。應(yīng)用于預(yù)后通過對原始數(shù)據(jù)的分析,能輔助預(yù)測患者手術(shù)后的身體指標(biāo)狀況,從而起到預(yù)警作用[4]。本文研究的慢性腎病輔助診斷是數(shù)據(jù)挖掘應(yīng)用于醫(yī)療診斷的體現(xiàn),并通過利用慢性腎病數(shù)據(jù)建立隨機森林分類模型對慢性腎病進行分類來建立慢性腎病輔助診斷系統(tǒng)。
本系統(tǒng)的主要工作是慢性腎病的輔助診斷,對于該系統(tǒng)的主要流程就是將患者的化驗信息以及患者的身份信息輸入到該系統(tǒng)中,通過已經(jīng)訓(xùn)練好的慢性腎病診斷模型,讓該模型對該患者進行診斷,判斷是否患有慢性腎病。本系統(tǒng)采用B/S架構(gòu)[5]進行設(shè)計,分為顯示層、業(yè)務(wù)層、服務(wù)層和數(shù)據(jù)層,系統(tǒng)架構(gòu)如圖1所示。
圖1 系統(tǒng)總體架構(gòu)圖
按圖1所示,表示層是系統(tǒng)用于界面交互的一層,其重要利用HtmL和js進行編寫,用jsp輔助傳值,實現(xiàn)數(shù)據(jù)交互;業(yè)務(wù)層采用SSM框架[6]進行設(shè)計,用于實現(xiàn)系統(tǒng)的功能邏輯;服務(wù)層利用tomcat服務(wù)器進行項目部署工作;數(shù)據(jù)層采用oracle數(shù)據(jù)庫對數(shù)據(jù)進行存儲和處理。
本系統(tǒng)的腎病輔助診斷功能如圖2所示。
圖2 腎病輔助診斷系統(tǒng)框架圖
由圖2可以看出,本系統(tǒng)在功能上應(yīng)具備以下幾個功能模塊。
2.1.1 化驗數(shù)據(jù)錄入模塊
該模塊的功能是將病人的基本信息和病人的本次化驗數(shù)據(jù)錄入系統(tǒng),提交診斷后進入后臺由腎病輔助診斷模型進行數(shù)據(jù)處理和慢性腎病診斷,最后將輸出結(jié)果0,1轉(zhuǎn)換成是否患有慢性腎病并輸出(0代表病人未患慢性腎病,1代表病人診斷結(jié)果為慢性腎病),并即時將結(jié)果顯示在頁面醒目的位置。
2.1.2 腎病輔助診斷模塊
該模塊有應(yīng)具備兩部分功能:1)是腎病診斷模型構(gòu)建功能,該模塊利用原始數(shù)據(jù)對慢性腎病輔助診斷模型進行構(gòu)建。首先將原始數(shù)據(jù)集分為訓(xùn)練數(shù)據(jù)集和測試數(shù)據(jù)集,然后利用訓(xùn)練集訓(xùn)練慢性腎病輔助診斷分類模型,利用測試集測試訓(xùn)練后的模型性能,根據(jù)測試結(jié)果調(diào)節(jié)模型參數(shù),以使模型達到最佳性能;2)是利用醫(yī)生輸入進來的基本信息和化驗項目參數(shù)封裝成實例對象通過慢性腎病輔助診斷模型進行診斷,并將診斷結(jié)果返回。
2.1.3 數(shù)據(jù)處理模塊
該模塊應(yīng)具備的主要功能有:存儲診斷結(jié)果及化驗項目信息的功能、能夠即時查看患者歷史診斷記錄的功能、提供患者診斷記錄增、刪、改的功能。
2.1.4 用戶管理模塊
該模塊的主要功能是提供添加、刪除、更改用戶信息的功能及密碼修改重置功能。
2.2.1 化驗指標(biāo)錄入模塊
該錄入模塊有病人基本信息(如化驗單號、姓名、年齡、性別等)5項,病人化驗指標(biāo)(如血壓、比重、白蛋白、血尿素、血清肌酐等)23項,用v1~v23表示。其中只有v1~v23作為模型訓(xùn)練的特征屬性被使用,病人基本信息只是為了方便醫(yī)生查找和數(shù)據(jù)庫記錄而被添加的。23項特征屬性如表1所示。
表1 慢性腎病輔助診斷模型特征屬性
由于純手工錄入這28個指標(biāo)會耗時較長,為了解決時耗問題,本實驗設(shè)計了自動填充功能,利用AJAX[7]傳值如下:
/*
自動填充病人信息
*/
function fillInfo(keyword,keydate){
.ajax({
url:'{sysPath}patient/patientInfoSearch.do',
type:'POST', //GET
async:true, //或false,是否異步
data:{
keyword:keyword,
keydate:keydate
},
//timeout:5000, //超時時間
dataType:'json', //返回的數(shù)據(jù)格式:json/xml/html/script/jsonp/text
success:function(data,textStatus,jqXHR){
(" sampleNo").val(data[0].sampleNo); //sampleNo,化驗單號
(" patientId").val(data[0].patientId);
(" patientName").val(data[0].patientName);
(" sex").val(data[0].sex);
(" age").val(data[0].age);
(" v1").val(data[0].v1);
(" v2").val(data[0].v2);
(" v3").val(data[0].v3);
(" v4").val(data[0].v4);
(" v5").val(data[0].v5);
(" v6").val(data[0].v6);
.......... //省略部分為v7~v23的填充項
},
error:function(xhr,textStatus){
alert("系統(tǒng)錯誤");
},
complete:function(){
console.log('結(jié)束')
}
});
}
2.2.2 慢性腎病輔助診斷模塊
此模塊主要功能是利用輸入的化驗指標(biāo)判斷該患者是否患有慢性腎病。因此該診斷模塊需要數(shù)據(jù)建模。本次慢性腎病輔助診斷建模利用隨機森林分類算法的建模方案如下:
1)隨機森林中決策樹的數(shù)目n是一個重要參數(shù),需要根據(jù)設(shè)置數(shù)目的模型準(zhǔn)確度反復(fù)調(diào)節(jié),一般設(shè)置為100~1 000,多次調(diào)節(jié)選取最優(yōu)參數(shù);
2)將慢性腎病數(shù)據(jù)按是否慢性腎病分別1:1的比例劃分出訓(xùn)練集和測試集,將腎病訓(xùn)練數(shù)據(jù)進行有放回的隨機抽樣,抽取n次,得到n個樣本,每個腎病訓(xùn)練數(shù)據(jù)樣本容量約為總樣本數(shù)的2/3;
3)屬性子集的選?。郝阅I病數(shù)據(jù)集的特征屬性有血壓、比重、白蛋白、血尿素、血清肌酐等共23個,設(shè)每次隨機選取的屬性子集中屬性的個數(shù)為x,log223約為4.5,取4,以4為屬性子集的屬性個數(shù)最小值,分別取4,5,6,7,8,9,10作為每次隨機選取的屬性子集中屬性的個數(shù)。以x=4為例,隨機抽取n個特征數(shù)目為4的特征子集進行建模實驗,用慢性腎病測試數(shù)據(jù)測試建模準(zhǔn)確率;x=5時也進行相同實驗,將所有x不同取值的模型準(zhǔn)確率進行對比,選擇最優(yōu)x的取值;
4)將n個樣本和n個屬性子集一對一組成n個決策樹;
5)將腎病測試樣本實例輸入到n個決策樹中,以投票法確認該測試實例的腎病類別即為隨機森林模型測得的腎病類別。
利用隨機森林算法建立慢性腎病輔助診斷模型的建模流程如圖3所示。
圖3 慢性腎病輔助診斷的隨機森林建模流程圖
本實驗按照上述隨機森林的腎病輔助診斷建模流程,利用weka[8]包里的隨機森林(randomForest)類建立分類模型,模型的訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù)來源于機器學(xué)習(xí)庫UCI的慢性腎病[9]數(shù)據(jù)集。該數(shù)據(jù)集共400條數(shù)據(jù)、24個特征屬性,2個診斷類別。本文將其分為200條訓(xùn)練數(shù)據(jù),200條測試數(shù)據(jù)對隨機森林模型進行訓(xùn)練[10]。模型訓(xùn)練測試設(shè)計如下:
public static void main(String[] args) throws Exception {
Classifier m_classifier = new WriteRandomForest();
File inputFile = new File("C:UsersAdministratorDesktopuciChronic_Kidney_Disease rain.csv.arff");
ArffLoader atf = new ArffLoader();
atf.setFile(inputFile);
Instances instancesTrain = atf.getDataSet(); // 讀入訓(xùn)練文件
inputFile = new File("C:UsersAdministratorDesktopuciChronic_Kidney_Disease est.csv.arff");//A類下的測試語料文件
atf.setFile(inputFile);
Instances instancesTest = atf.getDataSet(); // 讀入測試文件
instancesTest.setClassIndex(instancesTest.numAttributes()-1); //設(shè)置最后一行為分類類別行。instancesTest.numAttributes()可以取得屬性總數(shù)
double sum = instancesTest.numInstances(),//取實例數(shù)
right = 0.0f;
instancesTrain.setClassIndex(instancesTest.numAttributes()-1);
m_classifier.buildClassifier(instancesTrain); //訓(xùn)練
System.out.println(m_classifier);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:UsersAdministratorDesktop1RandomForest.model"));
oos.writeObject(m_classifier);
oos.flush();
oos.close();
// 保存模型
SerializationHelper.write("RandomForest.model", m_classifier);//參數(shù)一為模型保存文件,classifier4為要保存的模型
for(int i = 0;i { System.out.println(m_classifier.classifyInstance(instancesTest.instance(i))+","+instancesTest.instance(i).classValue()); if(m_classifier.classifyInstance(instancesTest.instance(i))==instancesTest.instance(i).classValue()) { right++;//正確值加1 } } // 獲取上面保存的模型 Classifier classifier8 = (Classifier) weka.core.SerializationHelper.read("RandomForest.model"); double right2 = 0.0f; for(int i = 0;i { if(classifier8.classifyInstance(instancesTest.instance(i))==instancesTest.instance(i).classValue()) { right2++;//正確值加1 } } Evaluation eval = new Evaluation(instancesTrain); //構(gòu)造評價器 eval.evaluateModel(m_classifier, instancesTest);//用測試數(shù)據(jù)集來評價m_classifier System.out.println(eval.toClassDetailsString("===ClassDetailsString===")); System.out.println(eval.toSummaryString("=== Summary ===",false)); //輸出信息 System.out.println(eval.toMatrixString("=== Confusion Matrix ==="));//Confusion Matrix } 該隨機森林模型的主要參數(shù)是m_numTrees和m_KValue。其中m_numTrees代表的是隨機森林模型中樹的數(shù)目,KValue代表的是每個結(jié)點建造時選擇隨機特征的數(shù)量。本實驗?zāi)J樹數(shù)目100,默認隨機特征數(shù)量為log2(data.numAttributes()-1)+1。為了確定最優(yōu)參數(shù),本文進行了多次實驗,將樹的數(shù)量分別設(shè)置為100,200,300,400,500,600,700,800,所得結(jié)果以折線圖的形式呈現(xiàn),見圖4。在樹的數(shù)量取到最優(yōu)的情況下,隨機特征的數(shù)量設(shè)置為4,5,6,7,8,9,10,所得結(jié)果見圖5。 圖4 隨機森林建模參數(shù)對照圖1 圖5 隨機森林建模參數(shù)對照圖2 由以上兩折線圖可以看出,當(dāng)樹的數(shù)量取400時,分類準(zhǔn)確率達到最優(yōu),此時準(zhǔn)確率為92.5%。在樹數(shù)量取400的前提下,隨機特征數(shù)量為5時模型達到最大值,準(zhǔn)確率為93.7%。因此當(dāng)m_numTrees=400且m_KValue=5時,本次慢腎病輔助診斷實驗的隨機森林模型達到最優(yōu)準(zhǔn)確率,為93.7%。本次慢性腎病輔助診斷系統(tǒng)設(shè)計將應(yīng)用最優(yōu)參數(shù)進行系統(tǒng)設(shè)計實現(xiàn)。 2.2.3 數(shù)據(jù)處理模塊 該模塊主要有兩個功能:(1)是讓醫(yī)生可以查看病人診斷歷史記錄,可以通過病人ID、病人姓名查看某患者在該系統(tǒng)的所有歷史診斷記錄,通過化驗單編號可查患者唯一記錄。在數(shù)據(jù)列表展示區(qū)點擊化驗單編號可以看到患者此次診斷的詳細化驗信息和診斷結(jié)果信息,并且具備修改和刪除以及導(dǎo)出功能;(2)是數(shù)據(jù)庫設(shè)計[11],本文數(shù)據(jù)庫表結(jié)構(gòu)如圖6所示。 圖6 腎病輔助診斷系統(tǒng)數(shù)據(jù)庫結(jié)構(gòu) 用戶管理及密碼修改模塊:用戶管理模塊為僅系統(tǒng)管理員可見模塊,該模塊主要有用戶添加、編輯功能、用戶科室配置功能、用戶修改密碼功能。修改密碼功能通過輸入原密碼、新密碼和確認新密碼后,點擊確定修改即可。該部分有原密碼校驗功能、新密碼和確認新密碼是否一致功能。密碼校驗功能代碼如下: /** * 校驗新舊密碼 */ function checkContent() { var oldPWD =.trim((" oldPWD").val());//舊密碼 var newPWD1 =.trim((" newPWD1").val());//新密碼 var newPWD2 =.trim((" newPWD2").val());//確認新密碼 if (oldPWD == null || oldPWD == undefined || oldPWD == "") { alert("舊密碼不能為空!"); return false; } if (newPWD1 == null || newPWD1 == undefined || newPWD1 == "") { alert("新密碼不能為空!"); return false; } if (newPWD2 == null || newPWD2 == undefined || newPWD2 == "") { alert("確認新密碼不能為空!"); return false; } if (oldPWD == newPWD1) { alert("新密碼與原密碼一致!"); return false; } if (newPWD1 != newPWD2) { alert("新密碼與確認密碼不一致!"); return false; } } 該模塊在用戶通過正確輸入用戶名和密碼,登錄成功后進入系統(tǒng)界面如圖7所示。 圖7 腎病輔助診斷系統(tǒng)主頁 從主界面上看該系統(tǒng)一共分為3部分,分別是指標(biāo)錄入平臺、選擇查詢平臺以及系統(tǒng)幫助平臺。指標(biāo)錄入平臺和選擇查詢平臺分別是對患者化驗項目指標(biāo)的錄入和對已經(jīng)診斷的患者記錄進行查詢。系統(tǒng)幫助平臺的本地用戶管理僅系統(tǒng)管理員可見,修改密碼功能普通用戶可使用。 指標(biāo)錄入模塊是醫(yī)生用來將患者的基本信息和化驗指標(biāo)輸入到系統(tǒng)中,該部分利用了AJAX傳值通過輸入患者化驗單號后使用自動填充功能,無需醫(yī)生再輸入患者的其他信息就可以將該患者的所有信息自動填充到頁面中。 慢性腎病輔助診斷指標(biāo)錄入頁面如圖8所示。 圖8 指標(biāo)錄入模塊頁面 該模塊通過錄入病人基本信息及化驗結(jié)果后點擊“診斷”按鈕,數(shù)據(jù)就會被后臺診斷功能接收并處理,并將診斷結(jié)果以JS彈框輸出,方便醫(yī)生查看輔助診斷結(jié)果。同時,診斷數(shù)據(jù)和診斷醫(yī)生也被保存到數(shù)據(jù)庫中,方便醫(yī)生查看歷史診斷記錄。 該模塊主要為用作醫(yī)生查看病人診斷歷史記錄,可以通過病人ID、病人姓名查看某患者在該系統(tǒng)的所有歷史診斷記錄,通過化驗單編號可查患者唯一記錄。在數(shù)據(jù)列表展示區(qū)點擊化驗單編號可以看到患者此次診斷的詳細化驗信息和診斷結(jié)果信息,并且具備修改和刪除以及導(dǎo)出功能。該模塊如圖9所示。 圖9 診斷結(jié)果查詢頁面 用戶管理模塊為僅系統(tǒng)管理員可見模塊,該模塊主要有用戶添加、編輯功能、用戶科室配置功能、用戶重置密碼功能。 用戶科室配置功能頁面如圖10所示,該功能在用戶點擊進入該頁面時先從session中調(diào)取用戶的科室,然后查詢除用戶所在科室以外的所有科室,將結(jié)果放入“未在科室”的控件中。通過“>>”可將用戶“所在科室”刪掉,并且“未在科室”會增加所刪內(nèi)容;通過“<<”可將“未在科室”中選中的內(nèi)容放入到用戶“已在科室”,即添加用戶“已在科室”,同時“未在科室”作相應(yīng)刪減。配置科室功能是為以后研究其他疾病的輔助診斷功能預(yù)留了空間[12]。 本文利用數(shù)據(jù)挖掘的隨機森林分類技術(shù)和web開發(fā)技術(shù)[13]構(gòu)建了慢性腎病輔助診斷系統(tǒng)[14]。該系統(tǒng)通過對病患的基本信息數(shù)據(jù)和化驗指標(biāo)數(shù)據(jù)的錄入,利用數(shù)據(jù)挖掘隨機森林分類模型對患者是否患有慢性腎病進行分類,并將 圖10 用戶科室配置頁面 分類結(jié)果通過JS彈框形式及時返回到頁面,直觀地便于醫(yī)生查看慢性腎病輔助診斷結(jié)果,同時將診斷信息存入數(shù)據(jù)庫以備醫(yī)生查詢該患者的歷史診斷記錄。該系統(tǒng)在功能上可以給經(jīng)驗不足的腎病醫(yī)生提供借鑒,從而幫助他們提高診斷技能,降低誤診率,從而使患者盡早進行正確的治療,避免慢性腎病治療延誤帶來的嚴重后果。3 系統(tǒng)效果
3.1 系統(tǒng)登錄模塊
3.2 腎病輔助診斷指標(biāo)錄入及診斷模塊
3.3 腎病診斷記錄查詢模塊
3.4 用戶管理及密碼修改模塊
4 結(jié)束語