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 " 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! " trainingFile = raw_input("Input trainingfile name:") """ trainingSet = makeDataSet(trainingFile) print "Done reading training data. " print "Training classifier..." classifier = trainClassifier(trainingSet) print "Done trainging classifier. " print "Rading in test data..." testFile = "breast-cancer-test.data" testSet = makeDataSet(testFile) print "Done reading test data. " print "Classifying records..." resultSet = classifyTestSet(testSet,classifier) print "Done classifying. " reportResults(resultSet) print "Program finished. " 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/shaohuachengEmail1:kou_sw@163.com Email2:kou_sw@qq.com