浅谈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开发之for循环操作实例详解
Nov 12 Python
解析Python中的生成器及其与迭代器的差异
Jun 20 Python
Python实现将数据库一键导出为Excel表格的实例
Dec 30 Python
Python subprocess模块详细解读
Jan 29 Python
python实现快速排序的示例(二分法思想)
Mar 12 Python
python flask中静态文件的管理方法
Mar 20 Python
python实现连续图文识别
Dec 18 Python
浅谈Python中eval的强大与危害
Mar 13 Python
python中时间、日期、时间戳的转换的实现方法
Jul 06 Python
python对Excel按条件进行内容补充(推荐)
Nov 24 Python
python Popen 获取输出,等待运行完成示例
Dec 30 Python
Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中
Jan 13 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
用cookies来跟踪识别用户
2006/10/09 PHP
php array_map array_multisort 高效处理多维数组排序
2009/06/11 PHP
使用php shell命令合并图片的代码
2011/06/23 PHP
php环境套包 dedeampz 伪静态设置示例
2014/03/26 PHP
ThinkPHP数据操作方法总结
2015/09/28 PHP
谈谈 PHP7新增功能
2015/12/16 PHP
jquery插件之信息弹出框showInfoDialog(成功/错误/警告/通知/背景遮罩)
2013/01/09 Javascript
js读写(删除)Cookie实例详解
2013/04/17 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
JS实现table表格数据排序功能(可支持动态数据+分页效果)
2016/05/26 Javascript
深入理解ES6 Promise 扩展always方法
2017/09/26 Javascript
Swiper自定义分页器使用详解
2017/12/28 Javascript
微信小程序新手教程之启动页的重要性
2019/03/03 Javascript
node.js express捕获全局异常的三种方法实例分析
2019/12/27 Javascript
Vue单文件组件开发实现过程详解
2020/07/30 Javascript
浅谈vue.watch的触发条件是什么
2020/11/07 Javascript
[00:20]DOTA2荣耀之路7:-ah fu-抢盾
2018/05/31 DOTA
python 从远程服务器下载东西的代码
2013/02/10 Python
Python使用logging模块实现打印log到指定文件的方法
2018/09/05 Python
如何通过python画loss曲线的方法
2019/06/26 Python
Pandas 缺失数据处理的实现
2019/11/04 Python
关于Numpy数据类型对象(dtype)使用详解
2019/11/27 Python
Python 脚本的三种执行方式小结
2019/12/21 Python
Pytorch Tensor基本数学运算详解
2019/12/30 Python
Python生成器实现简单"生产者消费者"模型代码实例
2020/03/27 Python
利用python+request通过接口实现人员通行记录上传功能
2021/01/13 Python
H5新属性audio音频和video视频的控制详解(推荐)
2016/12/09 HTML / CSS
iPhoneX安全区域(Safe Area)底部小黑条在微信小程序和H5的屏幕适配
2020/04/08 HTML / CSS
比利时买床:Beter Bed
2017/12/06 全球购物
计算机专业大学生的自我评价
2013/11/14 职场文书
军训自我鉴定100字
2014/02/13 职场文书
支行行长竞聘演讲稿
2014/05/15 职场文书
保护环境建议书作文300字
2015/09/14 职场文书
导游词之包公祠
2019/11/25 职场文书
Nginx的基本概念和原理
2022/03/21 Servers
VUE解决跨域问题Access to XMLHttpRequest at
2022/05/06 Vue.js