基于FPGrowth挖掘算法的乳腺癌中医症型关联规则挖掘

挖掘的总体思路:


首先癌症有不同的发展期

不同发展期的癌症有不同的症型

这些症型都处于不同的严重程度。

因此收集病人样本930条,最终挖掘目标是:

找出这些严重程度不同的症型和癌症发展阶段(我们知道癌症有初期,中期,晚期等)之间的关系(也就是找到症状与疾病之间的关联规则)


数据来自书籍《Python数据分析与挖掘实战》的第8章

书籍《Python数据分析与挖掘实战》中使用了Apriori算法来得到结果,
敝文尝试使用另外一种关联规则挖掘算法:FP-Growth 来获得最终的挖掘结果。


敝文的前半部分代码来自《Python数据分析与挖掘实战》,

后半部分代码通过把挖掘算法Apriori修改为FP-Growth而得,

最终实验结果表明:FP-Growth可以获得与Apriori一样的挖掘效果,并且提升了挖掘速度。

挖掘总流程:

一(对应代码1)、

每人的6种症型(症状名字的代号是A~F,分别对应下面data.xls中的各种症型)都处于不同的严重程度,

每种症型按照严重程度高低用具体数字赋值,然后根据症型的严重程度不度,聚类为四个区间,并根据某病人的某种症状的严重程度对应的数值,归类到四个区间中的某一个区间(下面表格中的区间由后面代码中的Kmeans聚类后得到)。各个症型区间表格如下:




表格用法举例:

例如一个人的肝气郁结症型比较严重,我们可以给他A3或者A4,如果比较轻,我们给他A1或者A2

同样的,症型之间我们认为地位是等同的,一个症型就是一个6维矢量中的其中一维,6个症型构成了一个6维矢量,其实也就是数据挖掘算法眼中的集合。

由于每个病人都有六种症状的不同区间(例如A1,A2,A3,A4),因此每个病人都可以由一个6维矢量(矢量中的每一维代表一种症型)来表示,例如(A1,B3,C2,D2,E2,F4)

这些表格中的各个区间的边界数值都是怎么来的呢?由代码1运行时,通过Kmeans聚类而得

代码1:

# -*- coding: utf-8 -*-
'''
聚类离散化,最后的result的格式为:
      1           2           3           4
A     0    0.178698    0.257724    0.351843
An  240  356.000000  281.000000   53.000000
即(0, 0.178698]有240个,(0.178698, 0.257724]有356个,依此类推。
'''
from __future__ import print_function
import pandas as pd
from sklearn.cluster import KMeans  # 导入K均值聚类算法

datafile = '../data/data.xls'  #待聚类的数据文件
processedfile = '../tmp/data_processed.xls'  # 数据处理后文件
typelabel = {u'肝气郁结证型系数': 'A', u'热毒蕴结证型系数': 'B', u'冲任失调证型系数': 'C', u'气血两虚证型系数': 'D', u'脾胃虚弱证型系数': 'E', u'肝肾阴虚证型系数': 'F'}
k = 4  # 需要进行的聚类类别数

# 读取数据并进行聚类分析
data = pd.read_excel(datafile)  # 读取数据
keys = list(typelabel.keys())
result = pd.DataFrame()

if __name__ == '__main__':  # 判断是否主窗口运行,如果是将代码保存为.py后运行,则需要这句,如果直接复制到命令窗口运行,则不需要这句。
    for i in range(len(keys)):#每轮循环处理一个症状的聚类和数量统计
        print("i=", i)
        # 调用k-means算法,进行聚类离散化
        print(u'正在进行“%s”的聚类...' % keys[i])
        kmodel = KMeans(n_clusters=k, n_jobs=4)  # n_jobs是并行数,一般等于CPU数较好
        kmodel.fit(data[[keys[i]]].as_matrix())  # 训练模型

        r1 = pd.DataFrame(kmodel.cluster_centers_, columns=[typelabel[keys[i]]])  # 聚类中心
        print("r1=",r1)
        print("label=", typelabel[keys[i]])
        #
        #
        #
        r2 = pd.Series(kmodel.labels_).value_counts()  # 分类统计
        print("r2=",r2)
        print("-------------------------------------")
        r2 = pd.DataFrame(r2, columns=[typelabel[keys[i]] + 'number'])  # 转为DataFrame,记录各个类别的数目
        print("r2=", r2)#这一段用来统计聚类中各个类别的数量,并且写入一列中,并改改名字
        #
        #
        #
        #
        r=pd.concat([r1, r2], axis=1)
        print("排序前r=",r)
        r=r.sort_values(typelabel[keys[i]])
        print("排序后r=",r)
        r.index = [1, 2, 3, 4]#index指的是列标签,typelabel[keys[i]]指的是行标签
        #
        #
        #
        #
        print("----------------------------------------------------")
        print("计算均值前的表格r=",r)
        r[typelabel[keys[i]]] = pd.rolling_mean(r[typelabel[keys[i]]], 2)  # rolling_mean()用来计算相邻2列的均值,以此作为边界点。
        r[typelabel[keys[i]]][1] = 0.0  # 这两句代码将原来的聚类中心改为边界点.这里的用法类似于C语言中的r[i][j]
        print("计算均值后的表格r=",r)
        result = result.append(r.T)#旋转
        print("----------------------------------------------------")
        #
        #
        #
        #
    print("result=",result)
    result = result.sort_index()  # 以Index排序,即以A,B,C,D,E,F顺序排,A代表症状的名称,BCDE各自代表该症状的严重程度
    result.to_excel(processedfile)








运行代码1后得到聚类处理后的文件为data_processed.xls(各种症型的数据统计),得到上面的表格9~14,同时也得到统计结果:

输出的结果是:

 1234
A00.1786975890.25772406430.3518431814
Anumber24035628153
B00.15076622770.29663131310.4897045019
Bnumber32539618029
C00.20214872930.28906113770.4235365546
Cnumber29739420435
D00.17650463630.25711995250.3661899988
Dnumber30937121139
E00.15269780220.25754132230.3748694473
Enumber27331924296
F00.17914337550.26138639440.354642668
Fnumber200237265228

结合输入文件data.xls
由于得到了每种症状的各种严重程度的量化区间, 以把data.xls中的各个参数(例如A症状)转化为A1~A4
转化办法如下:
data.xls中,对每行的首单元进行按行排序,由于data.xls中第一列的各项数据处于data_processed.xls的四个区间中,
分别改为A1~A4,从而得到下一份代码需要的文件data.txt文件( 可从百度网盘下载: https://pan.baidu.com/s/1miZgHMo ),

举个例子说明data.txt中的的每行数据是什么意思:

例如,data.xls第一行的数据是:

0.175,0.682,0.171,0.535,0.419,0.447

由于Kmeans得到了“症型对应的数值的聚类中心”,得到的结果其实就是上文中的表8-9,8-10,8-11,8-12,8-13,8-14,

根据症型的数值查表,得到由于0.175在区间(0,0.179]中,靠近聚类中心0.179,所以0.175替换为A2,同样地:

0.682查表8-10,归类为B1

0.171查表8-11,归类为C3

0.535查表8-12,归类为D3

0.419查表8-13,归类为E1

0.447查表8-14,归类为F1

以此类推,把6维向量(0.175,0.682,0.171,0.535,0.419,0.447)转化成(A2,B1,C3,D3,E1,F1,H1)

用代码批量转化即可,转化结果为data.txt,可从百度网盘下载:

https://pan.baidu.com/s/1miZgHMo



二(对应代码2)、这里使用FP-Growth算法来进行挖掘,找出不同严重程度的症状和mammary cancer

发展时期之间的联系,也就是说,找出哪些症状(例如A3和B5)极有可能导致乳腺癌之间的某个特定的发展阶段(例如H5),例如,肾脏发炎和肝硬化有较大概率导致乳腺癌(这里只是举个例子,不一定符合真实情况)挖掘结束。




代码2:

#-*- encoding:utf-8 -*-
import sys
reload(sys)
import pyfpgrowth
sys.setdefaultencoding('utf-8')

path='./data.txt'
def read_data(path):
    data_lists=[]
    f = open(path)             # 返回一个文件对象  
    line = f.readline()             # 调用文件的 readline()方法
    
    for line in open(path):
        # print type(line)  
        print line                 # 后面跟 ',' 将忽略换行符  
        # print(line, end = '')   # 在 Python 3中使用 
        lists_cell=line.replace('\n','').split(",")#去掉回车键,以逗号作为分隔符   
        data_lists.append(lists_cell)
        line = f.readline()  
    f.close()
    return data_lists

transactions=read_data(path)
# print "transactions=",transactions
print len(transactions)
print type(transactions)

patterns = pyfpgrowth.find_frequent_patterns(transactions, 56)#2 这个位置的参数代表支持度,也就是说出现数量56次以上
rules = pyfpgrowth.generate_association_rules(patterns, 0.87)#0.7 这个位置的参数代表置信度


print "FPGrowth关联规则挖掘结果:"
for k,v in  rules.items(): 
        print k
        print v
        print"-"*20

代码运行结果:

FPGrowth关联规则挖掘结果:
('A3', 'F4')
(('H4',), 0.8795180722891566)
--------------------
('C3', 'F4')
(('H4',), 0.875)
--------------------
[Finished in 0.1s]

与书上P192结果进行比较,可以发现,虽然书上用的是Apriori,此处使用的是FPGrowth,挖掘得到的关联规则是一致的:


最后解释下实验结果:

顺便解释下基本概念:
下面的support指的是,‘并’的关系

Support(A=>B)=P(AUB)

置信度指的是:条件概率

Confidence(A=>B)=P(B|A)

那么FpGrowth的挖掘结果可以解释为:

当肝气郁结症型系数位于A3区间,并且 肝肾阴虚症型系数位于F4区间,在这两个前提的条件下,处于mammary cancer H4阶段的概率为0.8795180722891566

在总样本中,这种情况发生的概率是0.078495,代码中有个数字是56,设置办法是:930*0.078495=56



评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值