文章目录
- 精确率和召回率
- 分类器性能评估
- 混淆矩阵
- 分类模型
- sklearn.metrics.classification_report
- 决策树
- 认识决策树
- 优缺点
- 信息的度量和作用
- 信息熵
- 决策树划分依据之信息增益
- api
- 实战
- method
- 决策树优缺点分析
- 实例
- 随机森林
- 集成方法(分类)之随机森林
- 学习算法
- sklearn.ensemble,集成方法模块
- 属性
- 方法
- 集成学习方法
- 随机森林优点
精确率和召回率
分类器性能评估
在许多实际问题中,衡量分类器任务的成功程度是通过固定的性能指标来获取。一般最常见使用的是准确率,即预测结果正确的百分比。然而有时候,我们关注的是负样本是否被正确诊断出来。例如,关于肿瘤的的判定,需要更加关心多少恶性肿瘤被正确的诊断出来。也就是说,在二类分类任务下,预测结果(Predicted Condition)与正确标记(True Condition)之间存在四种不同的组合,构成混淆矩阵。
在二类问题中,如果将一个正例判为正例,那么就可以认为产生了一个真正例(True Positive,TP);如果对一个反例正确的判为反例,则认为产生了一个真反例(True Negative,TN)。相应地,两外两种情况则分别称为伪反例(False Negative,FN,也称)和伪正例(False Positive,TP),四种情况如下图:
混淆矩阵
在分类中,当某个类别的重要性高于其他类别时,我们就可以利用上述定义出多个逼错误率更好的新指标。第一个指标就是正确率(Precision),它等于TP/(TP+FP),给出的是预测为正例的样本中占真实结果总数的比例。第二个指标是召回率(Recall)。它等于TP/(TP+FN),给出的是预测为正例的真实正例占所有真实正例的比例。
那么除了正确率和精确率这两个指标之外,为了综合考量召回率和精确率,我们计算这两个指标的调和平均数,得到F1指标(F1 measure):
分类模型
sklearn.metrics.classification_report
sklearn中metrics中提供了计算四个指标的模块,也就是classification_report。
classification_report(y_true, y_pred, labels=None, target_names=None, digits=2)"""计算分类指标:param y_true:真实目标值:param y_pred:分类器返回的估计值:param target_names:可选的,计算与目标类别匹配的结果:param digits:格式化输出浮点值的位数:return :字符串,三个指标值"""
from sklearn.metrics import classification_report
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
target_names = ['class 0', 'class 1', 'class 2']
print(classification_report(y_true, y_pred, target_names=target_names))precision recall f1-score supportclass 0 0.50 1.00 0.67 1class 1 0.00 0.00 0.00 1class 2 1.00 0.67 0.80 3avg / total 0.70 0.60 0.61 5
决策树
认识决策树
决策树是一种基本的分类方法,当然也可以用于回归。我们一般只讨论用于分类的决策树。决策树模型呈树形结构。在分类问题中,表示基于特征对实例进行分类的过程,它可以认为是if-then规则的集合。在决策树的结构中,每一个实例都被一条路径或者一条规则所覆盖。通常决策树学习包括三个步骤:特征选择、决策树的生成和决策树的修剪
优缺点
优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理逻辑回归等不能解决的非线性特征数据
缺点:可能产生过度匹配问题
适用数据类型:数值型和标称型
特征选择
特征选择在于选取对训练数据具有分类能力的特征。这样可以提高决策树学习的效率,如果利用一个特征进行分类的结果与随机分类的结果没有很大差别,则称这个特征是没有分类能力的。经验上扔掉这样的特征对决策树学习的京都影响不大。通常特征选择的准则是信息增益,这是个数学概念。通过一个例子来了解特征选择的过程。
我们希望通过所给的训练数据学习一个贷款申请的决策树,用以对文莱的贷款申请进行分类,即当新的客户提出贷款申请是,根据申请人的特征利用决策树决定是否批准贷款申请。特征选择其实是决定用那个特征来划分特征空间。下图中分别是按照年龄,还有是否有工作来划分得到不同的子节点
问题是究竟选择哪个特征更好些呢?那么直观上,如果一个特征具有更好的分类能力,是的各个自己在当前的条件下有最好的分类,那么就更应该选择这个特征。信息增益就能很好的表示这一直观的准则。这样得到的一棵决策树只用了两个特征就进行了判断
信息的度量和作用
我们常说信息有用,那么它的作用如何客观、定量地体现出来呢?信息用途的背后是否有理论基础呢?这个问题一直没有很好的回答,直到1948年,香农在他的论文“通信的数学原理”中提到了“信息熵”的概念,才解决了信息的度量问题,并量化出信息的作用。
一条信息的信息量与其不确定性有着直接的关系,比如我们要搞清一件非常不确定的事,就需要大量的信息。相反如果对某件事了解较多,则不需要太多的信息就能把它搞清楚 。所以从这个角度看,可以认为,信息量就等于不确定的多少。那么如何量化信息量的度量呢?2022年举行世界杯,大家很关系谁是冠军。假如我错过了看比赛,赛后我问朋友 ,“谁是冠军”?他不愿意直接告诉我,让我每猜一次给他一块钱,他告诉我是否猜对了,那么我需要掏多少钱才能知道谁是冠军?我可以把球编上号,从1到32,然后提问:冠 军在1-16号吗?依次询问,只需要五次,就可以知道结果。所以谁是世界杯冠军这条消息只值五块钱。当然香农不是用钱,而是用“比特”这个概念来度量信息量。一个比特是 一位二进制数,在计算机中一个字节是8比特。
那么如果说有一天有64支球队进行决赛阶段的比赛,那么“谁是世界杯冠军”的信息量就是6比特,因为要多猜一次,有的同学就会发现,信息量的比特数和所有可能情况的对数函数log有关,(log32=5,log64=6)
另外一方面你也会发现实际上我们不需要猜五次就能才出冠军,因为像西班牙、巴西、德国、意大利这样的球队夺得冠军的可能性比南非、尼日利亚等球队大得多,因此第一次猜测时不需要把32支球队等分成两个组,而可以把少数几支最有可能的球队分成一组,把其他球队分成一组。然后才冠军球队是否在那几支热门队中。这样,也许三次就猜出结果。因此,当每支球队夺冠的可能性不等时,“谁是世界杯冠军”的信息量比5比特少。香农指出,它的准确信息量应该是:
其中,p1…p32为这三支球队夺冠的概率。H的专业术语称之为信息熵,单位为比特,当这32支球队夺冠的几率相同时,对应的信息熵等于5比特,这个可以通过计算得出。有一个特性就是,5比特是公式的最大值。那么信息熵(经验熵)的具体定义可以为如下:
信息熵
信息熵越大,不确定越大
决策树划分依据之信息增益
api
class sklearn.tree.DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_split=1e-07, class_weight=None, presort=False)""":param max_depth:int或None,可选(默认=无)树的最大深度。如果没有,那么节点将被扩展,直到所有的叶子都是纯类,或者直到所有的叶子都包含少于min_samples_split样本:param random_state:random_state是随机数生成器使用的种子"""
实战
首先我们导入类,以及数据集,还有将数据分成训练数据集和测试数据集两部分
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
estimator = DecisionTreeClassifier(max_leaf_nodes=3, random_state=0)
estimator.fit(X_train, y_train
method
apply 返回每个样本被预测的叶子的索引
estimator.apply(X)array([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,5, 5, 15, 5, 5, 5, 5, 5, 5, 10, 5, 5, 5, 5, 5, 10, 5,5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 16, 16,16, 16, 16, 16, 6, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,8, 16, 16, 16, 16, 16, 16, 14, 16, 16, 11, 16, 16, 16, 8, 8, 16,16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16])
decision_path 返回树中的决策路径
dp = estimator.decision_path(X_test)
fit_transform(X,y=None,fit_params)** 输入数据,然后转换
predict(X) 预测输入数据的类型,完整代码
estimator.predict(X_test)
array([2, 1, 0, 2, 0, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0,0, 1, 0, 0, 1, 1, 0, 2, 1, 0, 1, 2, 1, 0, 2])print y_testarray([2, 1, 0, 2, 0, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 1, 0, 0, 2, 1, 0,0, 2, 0, 0, 1, 1, 0, 2, 1, 0, 2, 2, 1, 0, 1])
score(X,y,sample_weight=None) 返回给定测试数据的准确精度
estimator.score(X_test,y_test)0.89473684210526316
决策树优缺点分析
决策树的一些优点是:
简单的理解和解释。树木可视化。
需要很少的数据准备。其他技术通常需要数据归一化,需要创建虚拟变量,并删除空值。但请注意,此模块不支持缺少值。
使用树的成本(即,预测数据)在用于训练树的数据点的数量上是对数的。
决策树的缺点包括:
决策树学习者可以创建不能很好地推广数据的过于复杂的树。这被称为过拟合。修剪(目前不支持)的机制,设置叶节点所需的最小采样数或设置树的最大深度是避免此问题的必要条件。
决策树可能不稳定,因为数据的小变化可能会导致完全不同的树被生成。通过使用合奏中的决策树来减轻这个问题。
实例
def decision():"""决策树对泰坦尼克号进行预测生死:return: None"""# 获取数据titan=pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")#处理数据,找出特征值和目标值x=titan[['pclass','age','sex']]y=titan['survived']print(x)#缺失值处理x['age'].fillna(x['age'].mean(),inplace=True)#分割数据集为训练集和测试集x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25,random_state=33)# 进行处理(特征工程)特征-》类别-》one_hot编码vec=DictVectorizer(sparse=False)x_train=vec.fit_transform(x_train.to_dict(orient='record'))print(vec.get_feature_names)x_test=vec.transform(x_test.to_dict(orient='record'))print(vec.get_feature_names)print(x_train)#用决策树进行预测dec=DecisionTreeClassifier()dec.fit(x_train,y_train)y_predict = dec.predict(x_test)#预测准确率print("预测的准确率",dec.score(x_test,y_test))print(classification_report(y_predict, y_test, target_names=['died', 'surveved']))C:\Users\HP\Anaconda3\python.exe D:/PycharmProjects/untitled2/算法/算法3.pypclass age sex
0 1st 29.0000 female
1 1st 2.0000 female
2 1st 30.0000 male
3 1st 25.0000 female
4 1st 0.9167 male
5 1st 47.0000 male
6 1st 63.0000 female
7 1st 39.0000 male
8 1st 58.0000 female
9 1st 71.0000 male
10 1st 47.0000 male
11 1st 19.0000 female
12 1st NaN female
13 1st NaN male
14 1st NaN male
15 1st 50.0000 female
16 1st 24.0000 male
17 1st 36.0000 male
18 1st 37.0000 male
19 1st 47.0000 female
20 1st 26.0000 male
21 1st 25.0000 male
22 1st 25.0000 male
23 1st 19.0000 female
24 1st 28.0000 male
25 1st 45.0000 male
26 1st 39.0000 male
27 1st 30.0000 female
28 1st 58.0000 female
29 1st NaN male
... ... ... ...
1283 3rd NaN female
1284 3rd NaN male
1285 3rd NaN male
1286 3rd NaN male
1287 3rd NaN male
1288 3rd NaN male
1289 3rd NaN male
1290 3rd NaN male
1291 3rd NaN male
1292 3rd NaN male
1293 3rd NaN female
1294 3rd NaN male
1295 3rd NaN male
1296 3rd NaN male
1297 3rd NaN male
1298 3rd NaN male
1299 3rd NaN male
1300 3rd NaN male
1301 3rd NaN male
1302 3rd NaN male
1303 3rd NaN male
1304 3rd NaN female
1305 3rd NaN male
1306 3rd NaN female
1307 3rd NaN female
1308 3rd NaN male
1309 3rd NaN male
1310 3rd NaN male
1311 3rd NaN female
1312 3rd NaN male[1313 rows x 3 columns]
C:\Users\HP\Anaconda3\lib\site-packages\pandas\core\generic.py:6130: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrameSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copyself._update_inplace(new_data)
<bound method DictVectorizer.get_feature_names of DictVectorizer(dtype=<class 'numpy.float64'>, separator='=', sort=True,sparse=False)>
<bound method DictVectorizer.get_feature_names of DictVectorizer(dtype=<class 'numpy.float64'>, separator='=', sort=True,sparse=False)>
[[31.19418104 0. 0. 1. 0. 1. ][31.19418104 1. 0. 0. 1. 0. ][31.19418104 0. 0. 1. 0. 1. ]...[12. 0. 1. 0. 1. 0. ][18. 0. 1. 0. 0. 1. ][31.19418104 0. 0. 1. 1. 0. ]]
预测的准确率 0.7811550151975684precision recall f1-score supportdied 0.91 0.78 0.84 236surveved 0.58 0.80 0.67 93micro avg 0.78 0.78 0.78 329macro avg 0.74 0.79 0.75 329
weighted avg 0.81 0.78 0.79 329Process finished with exit code 0
随机森林
def randomforest():"""随机森林对泰坦尼克号进行预测生死:return: None"""# 获取数据titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")# 处理数据,找出特征值和目标值x = titan[['pclass', 'age', 'sex']]y = titan['survived']print(x)# 缺失值处理x['age'].fillna(x['age'].mean(), inplace=True)# 分割数据集到训练集合测试集x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)# 进行处理(特征工程)特征-》类别-》one_hot编码dict = DictVectorizer(sparse=False)x_train = dict.fit_transform(x_train.to_dict(orient="records"))print(dict.get_feature_names())x_test = dict.transform(x_test.to_dict(orient="records"))rf=RandomForestClassifier()yd=rf.fit(x_train,y_train)y_predit=rf.predict(x_test)param={"n_estimators":[120, 200, 300, 500, 800, 1200], "max_depth": [5, 8, 15, 25, 30]}# 网格搜索与交叉验证gc=GridSearchCV(rf,param_grid=param,cv=2)gc.fit(x_train,y_train)print("准确率:", gc.score(x_test, y_test))print("查看选择的参数模型:", gc.best_params_)print(classification_report(y_predit, y_test, target_names=['died', 'surveved']))return NoneC:\Users\HP\Anaconda3\python.exe D:/PycharmProjects/untitled2/算法/算法3.pypclass age sex
0 1st 29.0000 female
1 1st 2.0000 female
2 1st 30.0000 male
3 1st 25.0000 female
4 1st 0.9167 male
5 1st 47.0000 male
6 1st 63.0000 female
7 1st 39.0000 male
8 1st 58.0000 female
9 1st 71.0000 male
10 1st 47.0000 male
11 1st 19.0000 female
12 1st NaN female
13 1st NaN male
14 1st NaN male
15 1st 50.0000 female
16 1st 24.0000 male
17 1st 36.0000 male
18 1st 37.0000 male
19 1st 47.0000 female
20 1st 26.0000 male
21 1st 25.0000 male
22 1st 25.0000 male
23 1st 19.0000 female
24 1st 28.0000 male
25 1st 45.0000 male
26 1st 39.0000 male
27 1st 30.0000 female
28 1st 58.0000 female
29 1st NaN male
... ... ... ...
1283 3rd NaN female
1284 3rd NaN male
1285 3rd NaN male
1286 3rd NaN male
1287 3rd NaN male
1288 3rd NaN male
1289 3rd NaN male
1290 3rd NaN male
1291 3rd NaN male
1292 3rd NaN male
1293 3rd NaN female
1294 3rd NaN male
1295 3rd NaN male
1296 3rd NaN male
1297 3rd NaN male
1298 3rd NaN male
1299 3rd NaN male
1300 3rd NaN male
1301 3rd NaN male
1302 3rd NaN male
1303 3rd NaN male
1304 3rd NaN female
1305 3rd NaN male
1306 3rd NaN female
1307 3rd NaN female
1308 3rd NaN male
1309 3rd NaN male
1310 3rd NaN male
1311 3rd NaN female
1312 3rd NaN male[1313 rows x 3 columns]
C:\Users\HP\Anaconda3\lib\site-packages\pandas\core\generic.py:6130: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrameSee the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copyself._update_inplace(new_data)
['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male']
C:\Users\HP\Anaconda3\lib\site-packages\sklearn\ensemble\forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22."10 in version 0.20 to 100 in 0.22.", FutureWarning)
准确率: 0.8419452887537994
查看选择的参数模型: {'max_depth': 5, 'n_estimators': 1200}precision recall f1-score supportdied 0.92 0.82 0.87 238surveved 0.64 0.81 0.71 91micro avg 0.82 0.82 0.82 329macro avg 0.78 0.82 0.79 329
weighted avg 0.84 0.82 0.83 329Process finished with exit code 0
集成方法(分类)之随机森林
在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。利用相同的训练数搭建多个独立的分类模型,然后通过投票的方式,以少数服从多数的原则作出最终的分类决策。例如, 如果你训练了5个树, 其中有4个树的结果是True, 1个数的结果是False, 那么最终结果会是True.
在前面的决策当中我们提到,一个标准的决策树会根据每维特征对预测结果的影响程度进行排序,进而决定不同的特征从上至下构建分裂节点的顺序,如此以来,所有在随机森林中的决策树都会受这一策略影响而构建的完全一致,从而丧失的多样性。所以在随机森林分类器的构建过程中,每一棵决策树都会放弃这一固定的排序算法,转而随机选取特征。
学习算法
根据下列算法而建造每棵树:
用N来表示训练用例(样本)的个数,M表示特征数目。
输入特征数目m,用于确定决策树上一个节点的决策结果;其中m应远小于M。
从N个训练用例(样本)中以有放回抽样的方式,取样N次,形成一个训练集(即bootstrap取样),并用未抽到的用例(样本)作预测,评估其误差。
对于每一个节点,随机选择m个特征,决策树上每个节点的决定都是基于这些特征确定的。根据这m个特征,计算其最佳的分裂方式
sklearn.ensemble,集成方法模块
sklearn.ensemble提供了准确性更加好的集成方法,里面包含了主要的RandomForestClassifier(随机森林)方法。
class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’, max_depth=None, bootstrap=True, oob_score=False, n_jobs=1, random_state=None)""":param n_estimators:integer,optional(default = 10) 森林里的树木数量。:param criteria:string,可选(default =“gini”)分割特征的测量方法:param max_depth:integer或None,可选(默认=无)树的最大深度:param bootstrap:boolean,optional(default = True)是否在构建树时使用自举样本。
属性
classes_:shape = [n_classes]的数组或这样的数组的列表,类标签(单输出问题)或类标签数组列表(多输出问题)。
featureimportances:array = [n_features]的数组, 特征重要性(越高,功能越重要)。
方法
fit(X,y [,sample_weight]) 从训练集(X,Y)构建一棵树林。
predict(X) 预测X的类
score(X,y [,sample_weight]) 返回给定测试数据和标签的平均精度。
decision_path(X) 返回森林中的决策路径
集成学习方法