宫颈癌预测--随机森林
一、问题背景
采用集成学习中的一个算法框架(如:算法),随机森林被用于解决宫颈癌数据集的具体分类问题
二、数据集分析
- 宫颈癌数据集的下载来源为:http://archive.ics.uci.edu/ml/datasets/Cervical+cancer+(Risk+Factors)
- 宫颈癌数据集共计包含858个病例样本,在研究中涉及36个指标变量;这些病例被分类为四个不同的诊断类别:Hiselmann、Schiller、Citlolgy及Biopsy。
- 数据集中存在一定程度的缺失值情况,在分析过程中这些缺失信息均以问号'?'进行标记标注。
| 类型 | 属性 | 含义 |
|---|---|---|
| int | Age | 年龄 |
| int | Number of sexual partners | 性伴侣人数 |
| int | First sexual intercourse | age |
| int | Num of pregnancies | 怀孕次数 |
| bool | Smokes | 烟 |
| bool | Smokes (years) | 烟(年) |
| bool | Smokes (packs/year) | 烟(包/年) |
| bool | Hormonal Contraceptives | 激素避孕药 |
| int | Hormonal Contraceptives (years) | 激素避孕药(年) |
| bool | IUD | 宫内节育器 |
| int | IUD (years) | 宫内节育器(年) |
| bool | STDs | 性病 |
| int | STDs | number |
| bool | STDs:condylomatosis | 性病:尖锐湿疣 |
| bool | STDs:cervical condylomatosis | 性病:宫颈湿疣病 |
| bool | STDs:vaginal condylomatosis | 性病:阴道湿疣病 |
| bool | STDs:vulvo-perineal condylomatosis | 性病:外阴会阴尖锐湿疣病 |
| bool | STDs:syphilis | 性病:梅毒 |
| bool | STDs:pelvic inflammatory disease | 性病:盆腔炎病 |
| bool | STDs:genital herpes | 性病:生殖器疱疹 |
| bool | STDs:molluscum contagiosum | 性病:传染性软体动物 |
| bool | STDs:AIDS | 性病:艾滋病 |
| bool | STDs:HIV | 性传播疾病:艾滋病毒 |
| bool | STDs:Hepatitis B | 性病:乙型肝炎 |
| bool | STDs:HPV | 性病:人乳头瘤病毒 |
| int | STDs: Number of diagnosis | 性病:诊断数 |
| int | STDs: Time since first diagnosis | 性病:自首次诊断以来的时间 |
| int | STDs: Time since last diagnosis | 性病:自上次诊断以来的时间 |
| bool | Dx:Cancer | 诊断:癌症 |
| bool | Dx:CIN | CIN是子宫颈上皮细胞不典型增生,属于癌前病变 |
| bool | Dx:HPV | 诊断:是否患有HPV |
| bool | Dx | 诊断((数字0和1)) |
| bool | Hinselmann: target variableClass | 1925年由德国的Hans Hinselmann医生发明的阴道镜检测方法:目标变量 |
| bool | Schiller: target variableClass | 希勒碘试验(检测宫颈癌方法):目标变量 |
| bool | Cytology: target variableClass | 三阶梯”诊断法,即Cytology – Colposcopy–Histology ( CCH ),即细胞学- 阴道镜-组织病理学检查(检测方法):目标变量 |
| bool | Biopsy: target variableClass | 宫颈活检(Cervical biopsy)(检测方法):目标变量 |
三、代码实现
import sklearn
print(sklearn.__version__)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import label_binarize
from sklearn.model_selection import train_test_split
from sklearn import tree
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics
import warnings
warnings.filterwarnings("ignore")
mpl.rcParams['font.sans-serif'] = [u'SimHei'] # 用来正常显示中文标签
mpl.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
names = ['Age', 'Number of sexual partners', 'First sexual intercourse',
'Num of pregnancies', 'Smokes', 'Smokes (years)',
'Smokes (packs/year)', 'Hormonal Contraceptives',
'Hormonal Contraceptives (years)', 'IUD', 'IUD (years)', 'STDs',
'STDs (number)', 'STDs:condylomatosis',
'STDs:cervical condylomatosis', 'STDs:vaginal condylomatosis',
'STDs:vulvo-perineal condylomatosis', 'STDs:syphilis',
'STDs:pelvic inflammatory disease', 'STDs:genital herpes',
'STDs:molluscum contagiosum', 'STDs:AIDS', 'STDs:HIV',
'STDs:Hepatitis B', 'STDs:HPV', 'STDs: Number of diagnosis',
'STDs: Time since first diagnosis', 'STDs: Time since last diagnosis',
'Dx:Cancer', 'Dx:CIN', 'Dx:HPV', 'Dx', 'Hinselmann', 'Schiller',
'Citology', 'Biopsy']
data = pd.read_csv(r'C:\Users\bo.chen\Desktop\risk_factors_cervical_cancer.csv')
# 查看数据
print(data.shape)
# 划分数据集中的特征和目标值
X = data[names[0:-4]] # X = data.iloc[:,0:-4]
y = data[names[-4:]] # Y = data.iloc[:,-4:]
# 预测的目标有四个目标值:Hiselmann、Schiller、Citlolgy、Biopsy
print(type(X))
print(X.head())
print(y.head())
# 空值处理
X = X.replace("?", np.NAN)
# 使用SimpleImputerr给定缺省值,默认以mean也就是均值替换
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
X = imputer.fit_transform(X,y)
# 数据集分割
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=0)
print("训练样本数量:%d,特征属性数目:%d,目标属性数目:%d"\
%(X_train.shape[0],X_train.shape[1],y_train.shape[1]))
print ("测试样本数量:%d" % X_test.shape[0])
# 标准化
ss = MinMaxScaler()
# 分类模型,经常使用的是minmaxscaler归一化,回归模型经常用standardscaler
X_train = ss.fit_transform(X_train, y_train)
X_test = ss.transform(X_test)
# 模型构建
rf = RandomForestClassifier(n_estimators=50,criterion="gini",max_depth=1,\
random_state=10)
rf.fit(X_train,y_train)
# 模型效果评估
score = rf.score(X_test, y_test)
print("准确率:%.2f%%" %(score * 100))
#模型预测
rf_y_predict = rf.predict_proba(X_test)# prodict_proba输出概率
# print(rf_y_predict)
#计算ROC值
forest_fpr1, forest_tpr1, thresholds1 = \
metrics.roc_curve(label_binarize(y_test[names[-4]],classes=(0,1,2)).\
T[0:-1].T.ravel(), rf_y_predict[0].ravel())
forest_fpr2, forest_tpr2, thresholds2 = \
metrics.roc_curve(label_binarize(y_test[names[-3]],classes=(0,1,2)).\
T[0:-1].T.ravel(), rf_y_predict[1].ravel())
forest_fpr3, forest_tpr3, thresholds3 = \
metrics.roc_curve(label_binarize(y_test[names[-2]],classes=(0,1,2)).\
T[0:-1].T.ravel(), rf_y_predict[2].ravel())
forest_fpr4, forest_tpr4, thresholds4 = \
metrics.roc_curve(label_binarize(y_test[names[-1]],classes=(0,1,2)).\
T[0:-1].T.ravel(), rf_y_predict[3].ravel())
# AUC值
auc1 = metrics.auc(forest_fpr1, forest_tpr1)
auc2 = metrics.auc(forest_fpr2, forest_tpr2)
auc3 = metrics.auc(forest_fpr3, forest_tpr3)
auc4 = metrics.auc(forest_fpr4, forest_tpr4)
print ("Hinselmann目标属性AUC值:%.2f"%auc1)
print ("Schiller目标属性AUC值:%.2f"%auc2)
print ("Citology目标属性AUC值:%.2f"%auc3)
print ("Biopsy目标属性AUC值:%.2f"%auc4)
# 画图(ROC图)
plt.figure(figsize=(8, 6), facecolor='w')
plt.plot(forest_fpr1,forest_tpr1,c='r',lw=2,label=u'Hinselmann目标属性,AUC=%.3f' % auc1)
plt.plot(forest_fpr2,forest_tpr2,c='b',lw=2,label=u'Schiller目标属性,AUC=%.3f' % auc2)
plt.plot(forest_fpr3,forest_tpr3,c='g',lw=2,label=u'Citology目标属性,AUC=%.3f' % auc3)
plt.plot(forest_fpr4,forest_tpr4,c='y',lw=2,label=u'Biopsy目标属性,AUC=%.3f' % auc4)
plt.plot((0,1),(0,1),c='#a0a0a0',lw=2,ls='--')
plt.xlim(-0.001, 1.001)
plt.ylim(-0.001, 1.001)
plt.xticks(np.arange(0, 1.1, 0.1))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.xlabel('False Positive Rate(FPR)', fontsize=16)
plt.ylabel('True Positive Rate(TPR)', fontsize=16)
plt.grid(b=True, ls=':')
plt.legend(loc='lower right', fancybox=True, framealpha=0.8, fontsize=12)
plt.title(u'随机森林多目标属性分类ROC曲线', fontsize=18)
plt.show()

补充说明
① SimpleImputer 类
from sklearn.impute import SimpleImputer
- missing_values:缺失值占位标记(missing_values),其所有实例都将被估计出来(计算得出),可将其设定为整数值或NaN以确定缺失情况。
- strategy:插补策略(interpolation strategy),若选择mean,则沿轴计算并填充均值;若选择median,则计算并填充中位数;若选择most_frequent,则填充最常出现的值。
Examples
--------
>>> import numpy as np
>>> from sklearn.impute import SimpleImputer
>>> imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
>>> imp_mean.fit([[7, 2, 3], [4, np.nan, 6], [10, 5, 9]])
SimpleImputer()
>>> X = [[np.nan, 2, 3], [4, np.nan, 6], [10, np.nan, 9]]
>>> print(imp_mean.transform(X))
[[ 7. 2. 3. ]
[ 4. 3.5 6. ]
[10. 3.5 9. ]]
②X_train标准化是用fit_transform(),X_test标准化是用transform() ?
- fit_transform()负责完成两项任务:一是通过调用fit方法获取必要的转换规则;二是对这些规则进行标准化处理。
- transform的作用是将输入的数据经过归一化和标准化处理,并将其标准化应用到测试集上以保持一致性。这样做的好处是可以直接利用已经建立的转换模型而无需再次训练;如果不这样做的话,则会导致训练集和测试集在标准化后呈现出不同的参数分布。
归一化(Normalization)
④标准化(Standardization)
通过比例缩放使数据落入较小的特定区间内。标准化处理后得到的数据值可正可负且其绝对值通常不会过大。计算时分别针对每个属性或列进行处理:将各属性或列的数据按期属性(即按列)减去其均值,并除以其方差。经过这一过程后结果表明各属性或列的数据均聚居于0附近且具有单位方差。所采用的方法是Z-score规范化技术:对于任一数据点x其规范化表示为(x - mean(x)) / std(x)
四、集成学习
①概念:集成学习(Ensemble learning)是一种通过组合多个基础学习器以实现整体目标的技术框架,在机器学习领域具有重要地位,并被广泛应用于各种复杂问题的解决中。该方法通常由以下几部分构成:首先生成一组独立的学习模型(individual learners),然后通过某种集成策略将这些模型结合起来以提升性能。常用的结合策略包括简单平均法(simple averaging)、多数投票法(majority voting)以及基于委员会的学习方法(committee-based approaches)。
要实现良好的集成,个体学习器应各具特色。具体而言,在保证一定准确性要求的同时(即避免出现性能不佳的情况),各个体学习器之间必须具备多样性要求和差异性需求。
在集成学习模型中,若所有基学习器属于同一类型,则被称为同质;若不具备单一类型,则被称为异质。具有广泛的使用场景的一般集成方法特指于同质基学习器。而同质基学习器中使用最多的模型包括决策树(CART)决策树及其相关的神经网络等主要类型。

④同质个体学习器依据其生成机制将集成学习策略大致可分为两大类:
序列集成方法 ,其中各个学习器依次生成。各个学习器间具有较强的相互依存性,在实际应用中通常需要按一定顺序依次完成。通过赋予之前训练中被错误标记的样本其更高的重视程度,在提升整体预测效果的同时对应于一种称为Boosting的方法
并行集成方法 ,其中参与训练的多个个体学习器能够同时进行生成,并且这些个体学习器之间相互之间没有较强的依赖性。这种基于独立性的可并行化方法通常采用取其结果的平均值来显著减少预测错误的发生率。代表的方法包括Bagging以及随机森林
⑤集成学习的组合策略:
- 平均法:在数值型回归问题中常用的一种集成技术为均值融合方法;即通过计算多个弱估计器输出结果的算术平均值来获得最终预测结果。
- 投票机制:在分类任务中最为常用的方法之一;其中相对多票制是一种基于少数服从多数原则的基本实现方式;而绝对多票制则要求达到总票数一半以上才能获胜;更为复杂的加权多票制则是将各个分类器产生的票数乘以相应权重后求总和;最终票数最高的类别即为预测结果。
- Stacking算法:其代表性的方法是Stacking算法;在该算法中并不直接通过对各基模型(base learner)进行融合而是建立一个新的元模型(meta learner);该元模型会利用各基模型的学习结果作为输入并基于训练集输出结果重新训练以获得最终预测结论。
五、随机森林算法
随机森林属于集成学习的一种技术手段。它是通过将多棵决策树组合在一起形成一片"森林"来实现对数据的学习与预测过程。具体来说,在这种模型中每一棵决策树都作为一个独立的分类器发挥作用:针对每个输入样本而言,在这片"森林"中有多个决策树分别对其进行分析与判断。每棵决策树会生成一个独立的分类结果,在这片"森林"中总共有N个这样的分析结果需要进行汇总与综合判断。随机集合法(Random Forest)则通过汇总这些分析结果来决定最终输出的类别归属问题;其本质就是一种基于 Bootstrap aggregating(Bagging)的方法实现模型提升的技术框架
② Bagging方法中的弱学习器彼此之间没有直接关联。其核心特征是采用"有放回地随机抽样"(即 bootsrap 技术),具体表现为从训练集中有放回地抽取固定数量的样本进行建模。在实际操作中,在构建每一棵决策树时都会执行这一过程:每次从数据集中随机抽取一个样本并记录其标签后将其放回原数据集;随后在进行下一次抽样时仍有可能再次抽到之前已经被选中的样本。这种机制确保了每一轮抽样的独立性的同时也保证了数据利用率的有效性。根据Bagging算法的设计原则,在生成新的子数据集时通常会从训练集中有放回地随机抽取与原始训练数据集大小相当的数量的样本作为新的子数据集进行建模;这样处理的结果是生成的新子数据集与原始训练数据集合在容量上是相同的但具体的数据内容各不相同时期会有不同的组合方式从而提高了模型的整体泛化能力
(1)假设训练数据集大小为N,则对于每一棵决策树而言,在构建过程中会从训练集中有放回地随机抽取N个样本作为该树的训练数据集,并重复此过程共K次以获得K组不同的训练数据集。
(2)设每个特征向量的空间维度为M,则取一个远小于M的常数m,在所有特征中随机选择m个作为当前模型的基础。
(3)基于所选的m个关键特征让模型自由生长至最大深度,并在构建过程中省去任何剪枝操作。
随机森林分类器:
class sklearn.ensemble.RandomForestClassifier(n_tree=5, criterion='gini', max_depth=None, min_samples_split=2, min_leaf_samples=1, min_weight_fract leaf=0.0, max_features='auto', max_node_count=None, min_impurity_decrease = 0.0, min_impurity_split = None, bootstrap_method=True, oob_score=False, n_jobs=1, random_state=None, verbose=0, warm_start=False, class_weight=None)
主要参数:
n_estimators : 整数, 可选 (默认设置为10)。
criterion : 字符串, 可选 (默认设置为"gini")。
max_features : 整数、浮点数、字符串或无值, 可选 (默认设置为"auto")。
衡量特征分割效果的性能指标(函数)。受支持的标准包括基尼不纯度 ("gini") 和信息增益 ("entropy") (熵)。
max_depth: 整数或无值,默认可选参数(设为None)。它表示决策树的最大深度。若设置为None,则会递归地扩展节点直至所有叶结点达到纯度或样本数量受限。
