Python開發進階——數據集處理與機器學習初步


<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="font-size:12px;">科學家將研究數據集共享給其他研究人員使用,同時也期待數據有助於解決某些重要問題。其中之一的免費資源就是加利福尼亞州歐文分校的機器學習數據倉庫(http://archive.ics.uci.edu/ml)。本文采取了其中一個乳腺癌患者身上切除腫瘤的數據集(breast-cancer-wisconsin.data),讀者可自行前往下載。</span></span>

腫瘤學家研究切片組織並描述組織的各種特征,並決定腫瘤是良性還是惡性。那么本文研究的問題就確定了:基於腫瘤特征判定是惡性腫瘤還是良性腫瘤。研究數據中包括了699個患者的信息,其中包含9個腫瘤屬性和患者是否最終被診斷為良性或惡性癌症的結論。診斷結果與患者ID也包含在數據集中,故每個患者即每行數據有11個值。對於未知的患者,我們希望能通過腫瘤的切片數據屬性判定它是否為惡性腫瘤。


有很多方法可以解決這個問題。事實上,數據挖掘這一研究領域就是研究解決這類問題的方法。這些方法大多采用了較高層次的概念,我們要使用的就是創建一個分類器(即一個程序),輸入新的樣本,根據已有的樣本來確定新樣本的屬性,即屬於什么類型。


在這個問題中,分類器要使用已知類別的樣本進行訓練,在訓練過程中,分類器尋找確定分類的模式。模式確定后,在已知類別的新樣本上進行測試,從而判斷分類器的准確性。

在此例中,診斷結果是對患者腫瘤屬性的分類結果,每個患者信息都可用於建立一個關於模式的內部模型,模式旨在區分良性和惡性。訓練好分類器后,必須要測試分類器的有效性,通過提供新患者,異或只是訓練過程中沒有使用的患者數據,來查看分類器的預測的診斷結果。


本文在實踐中,將從上述網址下載的數據集創建兩個單獨的文件,大部分放入訓練文件,剩余放入測試文件。那么,如何編寫從訓練數據中發現分類模式的程序?

本文采取的是一個較簡單的模型,但事實證明它的分類相當有效。方法如下。每次查看患者的一個腫瘤屬性,然后結合所屬的類別意見作出決定。一個患者的9個屬性進行判定后,評估每個屬性得出判定結果,分類結果遵循少數服從多數的原則。

具體實現如下:對每個腫瘤屬性,設置兩個平均值。第一個是訓練數據中良性腫瘤患者的平均值,第二個是惡性腫瘤患者的平均值。采用如下方法構造分類器:對每個屬性的平均值,找出良性平均值和惡性平均值的中值。這個中值就是分類值。分類器中包括所有屬性的分類值,即9個分類值。如果新樣本中的某個屬性值低於該屬性的分類值,該屬性預測結果為良性。反之為惡性。要得到整體的分類預測結果,需要將每個屬性與該屬性的分類值進行比較。根據屬性值對屬性進行標記。對於患者的最后判斷,采用少數服從多數的原則。

本方法實現的Pyhon代碼如下:

import os
def makeDataSet(fileName):
    dataFile = open(fileName)
    dataSet = []
    for line in dataFile:
        line = line.strip()
        if "?" in line.split(","):
            continue
        id,a1,a2,a3,a4,a5,a6,a7,a8,a9,diag = line.split(",")
        if diag == "4":
            diagMorB = "m"
        else:
            diagMorB = "b"
        patientTuple = (id,diagMorB,int(a1),int(a2),int(a3),int(a4),\
                        int(a5),int(a6),int(a7),int(a8),int(a9))
        dataSet.append(patientTuple)
    return dataSet

def trainClassifier(trainSet):
    def sumLists(list1,list2):
        listOfSums = [0.0]*9
        for index in range(9):
            listOfSums[index] = list1[index] + list2[index]
        return listOfSums

    def makeAverages(listOfSums,total):
        averageList = [0.0]*9
        for index in range(9):
            averageList[index] = listOfSums[index]/float(total)
        return averageList

    benignSums = [0]*9
    benignCount = 0
    malignantSums = [0]*9
    malignantCount = 0

    for patientTup in trainSet:
        if patientTup[1] == "b":
            benignCount += 1
            benignSums = sumLists(benignSums,patientTup[2:])
        else:
            malignantCount += 1
            malignantSums = sumLists(malignantSums,patientTup[2:])
    benignAverageList = makeAverages(benignSums,benignCount)
    malignantAverageList = makeAverages(malignantSums,malignantCount)

    classifier = makeAverages(sumLists(benignAverageList,malignantAverageList),2)

    return classifier

def classifyTestSet(testSet,classifier):
    results = []
    for patient in testSet:
        benignCount = 0
        malignantCount = 0
        for index in range(9):
            if patient[index+2] > classifier[index]:
                malignantCount += 1
            else:
                benignCount += 1
        resultTuple = (patient[0],benignCount,malignantCount,patient[1])
        results.append(resultTuple)
    return results

def reportResults(results):
    totalCount = 0
    inaccurateCount = 0

    for r in results:
        totalCount += 1
        if r[1]>r[2]:
            if r[3] == "m":
                inaccurateCount += 1
        elif r[3] == "b":
            inaccurateCount += 1
    print "Of",totalCount,"patients,there were",inaccurateCount,"inaccuracies\n"
    print "Reported teh results"



def main():
    print "Reading in training data...."
    trainingFile = "breast-cancer-train.data"
    '''
    trainingFile = raw_input("Input trainingfile name:")
    while os.path.isfile(trainingFile):
        print "File error!\n"
        trainingFile = raw_input("Input trainingfile name:")
        '''
    trainingSet = makeDataSet(trainingFile)
    print "Done reading training data.\n"

    print "Training classifier..."
    classifier = trainClassifier(trainingSet)
    print "Done trainging classifier.\n"

    print "Rading in test data..."
    testFile = "breast-cancer-test.data"
    testSet = makeDataSet(testFile)
    print "Done reading test data.\n"

    print "Classifying records..."
    resultSet = classifyTestSet(testSet,classifier)
    print "Done classifying.\n"

    reportResults(resultSet)

    print "Program finished.\n"

main()

代碼中涉及細節,如對缺失數據"?"的處理等,不在贅述。如有疑問可與作者交流。對於上述數據,得到結果如下。


Reading in training data....
Done reading training data.


Training classifier...
Done trainging classifier.


Rading in test data...
Done reading test data.


Classifying records...
Done classifying.


Of 340 patients,there were 5 inaccuracies


Reported teh results
Program finished.


歡迎交流,

csdn blog:  http://blog.csdn.net/shaohuacheng
科學網blog: http://blog.sciencenet.cn/u/shaohuacheng

Email1:kou_sw@163.com Email2:kou_sw@qq.com



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com