浅谈keras中自定义二分类任务评价指标metrics的方法以及代码


Posted in Python onJune 11, 2020

对于二分类任务,keras现有的评价指标只有binary_accuracy,即二分类准确率,但是评估模型的性能有时需要一些其他的评价指标,例如精确率,召回率,F1-score等等,因此需要使用keras提供的自定义评价函数功能构建出针对二分类任务的各类评价指标。

keras提供的自定义评价函数功能需要以如下两个张量作为输入,并返回一个张量作为输出。

y_true:数据集真实值组成的一阶张量。

y_pred:数据集输出值组成的一阶张量。

tf.round()可对张量四舍五入,因此tf.round(y_pred)即是预测值张量。

1-tf.round(y_pred)即是预测值张量取反。

1-y_true即是真实值张量取反。

tf.reduce_sum()可对张量求和。

由此可以根据定义构建出四个基础指标TP、TN、FP、FN,然后进一步构建出进阶指标precision、recall、F1score,最后在编译阶段引用上述自定义评价指标即可。

keras中自定义二分类任务常用评价指标及其引用的代码如下

import tensorflow as tf

#精确率评价指标
def metric_precision(y_true,y_pred): 
 TP=tf.reduce_sum(y_true*tf.round(y_pred))
 TN=tf.reduce_sum((1-y_true)*(1-tf.round(y_pred)))
 FP=tf.reduce_sum((1-y_true)*tf.round(y_pred))
 FN=tf.reduce_sum(y_true*(1-tf.round(y_pred)))
 precision=TP/(TP+FP)
 return precision

#召回率评价指标
def metric_recall(y_true,y_pred): 
 TP=tf.reduce_sum(y_true*tf.round(y_pred))
 TN=tf.reduce_sum((1-y_true)*(1-tf.round(y_pred)))
 FP=tf.reduce_sum((1-y_true)*tf.round(y_pred))
 FN=tf.reduce_sum(y_true*(1-tf.round(y_pred)))
 recall=TP/(TP+FN)
 return recall

#F1-score评价指标
def metric_F1score(y_true,y_pred): 
 TP=tf.reduce_sum(y_true*tf.round(y_pred))
 TN=tf.reduce_sum((1-y_true)*(1-tf.round(y_pred)))
 FP=tf.reduce_sum((1-y_true)*tf.round(y_pred))
 FN=tf.reduce_sum(y_true*(1-tf.round(y_pred)))
 precision=TP/(TP+FP)
 recall=TP/(TP+FN)
 F1score=2*precision*recall/(precision+recall)
 return F1score

#编译阶段引用自定义评价指标示例
model.compile(optimizer='adam',
	 loss='binary_crossentropy',
	 metrics=['accuracy',
	 		metric_precision,
	 		metric_recall,
	 		metric_F1score])

补充知识:keras sklearn下两分类/多分类的技术杂谈(交叉验证和评价指标)

一.前言

这篇博客是为了记录论文补充实验中所遇到的问题,以及解决方法,主要以程序的形式呈现。

二.对象

深度学习框架:keras

研究对象:两分类/多分类

三.技术杂谈

1.K-FOLD交叉验证

1.概念

对一个模型进行K次训练,每次训练将整个数据集分为随机的K份,K-1作为训练集,剩余的1份作为验证集,每次训练结束将验证集上的性能指标保存下来,最后对K个结果进行平均得到最终的模型性能指标。

2.优缺点

优点:模型评估更加鲁棒

缺点:训练时间加大

3.代码

① sklearn与keras独立使用

from sklearn.model_selection import StratifiedKFold
import numpy

seed = 7 # 随机种子
numpy.random.seed(seed) # 生成固定的随机数
num_k = 5 # 多少折

# 整个数据集(自己定义)
X = 
Y = 

kfold = StratifiedKFold(n_splits=num_k, shuffle=True, random_state=seed) # 分层K折,保证类别比例一致

cvscores = []
for train, test in kfold.split(X, Y):

	# 可以用sequential或者function的方式建模(自己定义)
	model = 
 model.compile() # 自定义
 
	# 模型训练
 model.fit(X[train], Y[train], epochs=150, batch_size=10, verbose=0)
 
 # 模型测试
 scores = model.evaluate(X[test], Y[test], verbose=0)
 
 print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100)) # 打印出验证集准确率
 
 cvscores.append(scores[1] * 100)
 
print("%.2f%% (+/- %.2f%%)" % (numpy.mean(cvscores), numpy.std(cvscores))) # 输出k-fold的模型平均和标准差结果

② sklearn与keras结合使用

from keras.wrappers.scikit_learn import KerasClassifier # 使用keras下的sklearn API
from sklearn.cross_validation import StratifiedKFold, cross_val_score
import numpy as np

seed = 7 # 随机种子
numpy.random.seed(seed) # 生成固定的随机数
num_k = 5 # 多少折

# 整个数据集(自己定义)
X = 
Y = 

# 创建模型
def model():
 # 可以用sequential或者function的方式建模(自己定义)
	model = 
	return model 

model = KerasClassifier(build_fn=model, epochs=150, batch_size=10)
kfold = StratifiedKFold(Y, n_folds=num_k, shuffle=True, random_state=seed)
results = cross_val_score(model, X, Y, cv=kfold)
print(np.average(results)) # 输出k-fold的模型平均结果

补充:引入keras的callbacks

只需要在①②中的model.fit中加入一个arg:callbacks=[keras.callbacks.ModelCheckpoint()] # 这样可以保存下模型的权重,当然了你也可以使用callbacks.TensorBoard保存下训练过程

2.二分类/多分类评价指标

1.概念

二分类就是说,一个目标的标签只有两种之一(例如:0或1,对应的one-hot标签为[1,0]或[0,1])。对于这种问题,一般可以采用softmax或者logistic回归来完成,分别采用cross-entropy和mse损失函数来进行网络训练,分别输出概率分布和单个的sigmoid预测值(0,1)。

多分类就是说,一个目标的标签是几种之一(如:0,1,2…)

2.评价指标

主要包含了:准确率(accuracy),错误率(error rate),精确率(precision),召回率(recall)= 真阳率(TPR)= 灵敏度(sensitivity),F1-measure(包含了micro和macro两种),假阳率(FPR),特异度(specificity),ROC(receiver operation characteristic curve)(包含了micro和macro两种),AUC(area under curve),P-R曲线(precision-recall),混淆矩阵

① 准确率和错误率

accuracy = (TP+TN)/ (P+N)或者accuracy = (TP+TN)/ (T+F)

error rate = (FP+FN) / (P+N)或者(FP+FN) / (T+F)

accuracy = 1 - error rate

可见:准确率、错误率是对分类器在整体数据上的评价指标。

② 精确率

precision=TP /(TP+FP)

可见:精确率是对分类器在预测为阳性的数据上的评价指标。

③ 召回率/真阳率/灵敏度

recall = TPR = sensitivity = TP/(TP+FN)

可见:召回率/真阳率/灵敏度是对分类器在整个阳性数据上的评价指标。

④ F1-measure

F1-measure = 2 * (recall * precision / (recall + precision))

包含两种:micro和macro(对于多类别分类问题,注意区别于多标签分类问题)

1)micro

计算出所有类别总的precision和recall,然后计算F1-measure

2)macro

计算出每一个类的precison和recall后计算F1-measure,最后将F1-measure平均

可见:F1-measure是对两个矛盾指标precision和recall的一种调和。

⑤ 假阳率

FPR=FP / (FP+TN)

可见:假阳率是对分类器在整个阴性数据上的评价指标,针对的是假阳。

⑥ 特异度

specificity = 1- FPR

可见:特异度是对分类器在整个阴性数据上的评价指标,针对的是真阴。

⑦ ROC曲线和AUC

作用:灵敏度与特异度的综合指标

横坐标:FPR/1-specificity

纵坐标:TPR/sensitivity/recall

AUC是ROC右下角的面积,越大,表示分类器的性能越好

包含两种:micro和macro(对于多类别分类问题,注意区别于多标签分类问题)

假设一共有M个样本,N个类别。预测出来的概率矩阵P(M,N),标签矩阵L (M,N)

1)micro

根据P和L中的每一列(对整个数据集而言),计算出各阈值下的TPR和FPR,总共可以得到N组数据,分别画出N个ROC曲线,最后取平均

2)macro

将P和L按行展开,然后转置为两列,最后画出一个ROC曲线

⑧ P-R曲线

横轴:recall

纵轴:precision

评判:1)直观看,P-R包围的面积越大越好,P=R的点越大越好;2)通过F1-measure来看

比较ROC和P-R: 当样本中的正、负比例不平衡的时候,ROC曲线基本保持不变,而P-R曲线变化很大,原因如下:

当负样本的比例增大时,在召回率一定的情况下,那么表现较差的模型必然会召回更多的负样本,TP降低,FP迅速增加(对于性能差的分类器而言),precision就会降低,所以P-R曲线包围的面积会变小。

⑨ 混淆矩阵

行表示的是样本中的一种真类别被预测的结果,列表示的是一种被预测的标签所对应的真类别。

3.代码

注意:以下的代码是合在一起写的,有注释。

from sklearn import datasets
import numpy as np
from sklearn.preprocessing import label_binarize
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, precision_score, accuracy_score,recall_score, f1_score,roc_auc_score, precision_recall_fscore_support, roc_curve, classification_report
import matplotlib.pyplot as plt

iris = datasets.load_iris()
x, y = iris.data, iris.target
print("label:", y)
n_class = len(set(iris.target))
y_one_hot = label_binarize(y, np.arange(n_class))

# alpha = np.logspace(-2, 2, 20) #设置超参数范围
# model = LogisticRegressionCV(Cs = alpha, cv = 3, penalty = 'l2') #使用L2正则化
model = LogisticRegression() # 内置了最大迭代次数了,可修改
model.fit(x, y)
y_score = model.predict(x) # 输出的是整数标签
mean_accuracy = model.score(x, y)
print("mean_accuracy: ", mean_accuracy)
print("predict label:", y_score)
print(y_score==y)
print(y_score.shape)
y_score_pro = model.predict_proba(x) # 输出概率
print(y_score_pro)
print(y_score_pro.shape)
y_score_one_hot = label_binarize(y_score, np.arange(n_class)) # 这个函数的输入必须是整数的标签哦
print(y_score_one_hot.shape)

obj1 = confusion_matrix(y, y_score) # 注意输入必须是整数型的,shape=(n_samples, )
print('confusion_matrix\n', obj1)

print(y)
print('accuracy:{}'.format(accuracy_score(y, y_score))) # 不存在average
print('precision:{}'.format(precision_score(y, y_score,average='micro')))
print('recall:{}'.format(recall_score(y, y_score,average='micro')))
print('f1-score:{}'.format(f1_score(y, y_score,average='micro')))
print('f1-score-for-each-class:{}'.format(precision_recall_fscore_support(y, y_score))) # for macro
# print('AUC y_pred = one-hot:{}\n'.format(roc_auc_score(y_one_hot, y_score_one_hot,average='micro'))) # 对于multi-class输入必须是proba,所以这种是错误的

# AUC值
auc = roc_auc_score(y_one_hot, y_score_pro,average='micro') # 使用micro,会计算n_classes个roc曲线,再取平均
print("AUC y_pred = proba:", auc)
# 画ROC曲线
print("one-hot label ravelled shape:", y_one_hot.ravel().shape)
fpr, tpr, thresholds = roc_curve(y_one_hot.ravel(),y_score_pro.ravel()) # ravel()表示平铺开来,因为输入的shape必须是(n_samples,)
print("threshold: ", thresholds)
plt.plot(fpr, tpr, linewidth = 2,label='AUC=%.3f' % auc)
plt.plot([0,1],[0,1], 'k--') # 画一条y=x的直线,线条的颜色和类型
plt.axis([0,1.0,0,1.0]) # 限制坐标范围
plt.xlabel('False Postivie Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.show()

# p-r曲线针对的是二分类,这里就不描述了
ans = classification_report(y, y_score,digits=5) # 小数点后保留5位有效数字
print(ans)

以上这篇浅谈keras中自定义二分类任务评价指标metrics的方法以及代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python性能优化技巧
Mar 09 Python
Python实现微信公众平台自定义菜单实例
Mar 20 Python
Python删除空文件和空文件夹的方法
Jul 14 Python
Django中处理出错页面的方法
Jul 15 Python
详解Python中的文件操作
Aug 28 Python
Python3简单实例计算同花的概率代码
Dec 06 Python
TensorFlow平台下Python实现神经网络
Mar 10 Python
python numpy 一维数组转变为多维数组的实例
Jul 02 Python
Python PO设计模式的具体使用
Aug 16 Python
详解pandas获取Dataframe元素值的几种方法
Jun 14 Python
如何在Windows中安装多个python解释器
Jun 16 Python
Python 如何测试文件是否存在
Jul 31 Python
Keras中的多分类损失函数用法categorical_crossentropy
Jun 11 #Python
Python 列表中的修改、添加和删除元素的实现
Jun 11 #Python
python中什么是面向对象
Jun 11 #Python
python实现凯撒密码、凯撒加解密算法
Jun 11 #Python
python新手学习可变和不可变对象
Jun 11 #Python
基于Keras 循环训练模型跑数据时内存泄漏的解决方式
Jun 11 #Python
什么是python的id函数
Jun 11 #Python
You might like
Mysql中limit的用法方法详解与注意事项
2008/04/19 PHP
简介WordPress中用于获取首页和站点链接的PHP函数
2015/12/17 PHP
PHP之图片上传类实例代码(加了缩略图)
2016/06/30 PHP
CI框架(CodeIgniter)实现的数据库增删改查操作总结
2018/05/23 PHP
Laravel第三方包报class not found的解决方法
2019/10/13 PHP
PHP实现图片防盗链破解操作示例【解决图片防盗链问题/反向代理】
2020/05/29 PHP
laravel开发环境homestead搭建过程详解
2020/07/03 PHP
js下用eval生成JSON对象
2010/09/17 Javascript
jquery中加载图片自适应大小主要实现代码
2013/08/23 Javascript
js操作iframe父子窗体示例
2014/05/22 Javascript
javascript实现加载xml文件的方法
2015/11/24 Javascript
javascript返回顶部的按钮实现方法
2016/01/09 Javascript
javascript数组去重小结
2016/03/07 Javascript
jQuery Dialog对话框事件用法实例分析
2016/05/10 Javascript
AngularJs Modules详解及示例代码
2016/09/01 Javascript
KnockoutJS 3.X API 第四章之表单textInput、hasFocus、checked绑定
2016/10/11 Javascript
jQuery progressbar通过Ajax请求实现后台进度实时功能
2016/10/11 Javascript
基于layer.js实现收货地址弹框选择然后返回相应的地址信息
2017/05/26 Javascript
AngularJS动态绑定ng-options的ng-model实例代码
2017/06/21 Javascript
JS实现图片预览的两种方式
2017/06/27 Javascript
小程序实现列表删除功能
2018/10/30 Javascript
[35:29]Secret vs VG 2018国际邀请赛淘汰赛BO3 第三场 8.23
2018/08/24 DOTA
Python常见文件操作的函数示例代码
2011/11/15 Python
wxPython中listbox用法实例详解
2015/06/01 Python
使用Python的Flask框架表单插件Flask-WTF实现Web登录验证
2016/07/12 Python
浅谈五大Python Web框架
2017/03/20 Python
Python cookbook(数据结构与算法)保存最后N个元素的方法
2018/02/13 Python
Python timeit模块的使用实践
2020/01/13 Python
django列表筛选功能的实现代码
2020/03/27 Python
Python 实现3种回归模型(Linear Regression,Lasso,Ridge)的示例
2020/10/15 Python
澳大利亚最大的网上油画销售画廊:Direct Art Australia
2018/04/15 全球购物
Unineed旗下时尚轻奢网站:FABHunt
2019/05/13 全球购物
英国羊皮鞋类领先品牌:Just Sheepskin
2019/12/12 全球购物
农业局党的群众路线教育实践活动整改方案
2014/09/20 职场文书
解除劳动合同通知书范本
2015/04/16 职场文书
高考诚信考试承诺书
2015/04/29 职场文书