浅谈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内置函数bin() oct()等实现进制转换
Dec 30 Python
使用Python的urllib2模块处理url和图片的技巧两则
Feb 18 Python
解析Python中的生成器及其与迭代器的差异
Jun 20 Python
Python学习笔记之解析json的方法分析
Apr 21 Python
用pickle存储Python的原生对象方法
Apr 28 Python
Python编程实现粒子群算法(PSO)详解
Nov 13 Python
Python shutil模块用法实例分析
Oct 02 Python
双向RNN:bidirectional_dynamic_rnn()函数的使用详解
Jan 20 Python
python3+opencv生成不规则黑白mask实例
Feb 19 Python
python GUI库图形界面开发之PyQt5工具栏控件QToolBar的详细使用方法与实例
Feb 28 Python
python os模块在系统管理中的应用
Jun 22 Python
pytorch下的unsqueeze和squeeze的用法说明
Feb 06 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
为查询结果建立向后/向前按钮
2006/10/09 PHP
php警告Creating default object from empty value 问题的解决方法
2014/04/02 PHP
php多进程并发编程防止出现僵尸进程的方法分析
2020/02/28 PHP
Firefox+FireBug使JQuery的学习更加轻松愉快
2010/01/01 Javascript
JavaScript中使用构造器创建对象无需new的情况说明
2012/03/01 Javascript
如何在node的express中使用socket.io
2014/12/15 Javascript
基于javascript html5实现多文件上传
2016/03/03 Javascript
原生javascript+css3编写的3D魔方动画旋扭特效
2016/03/14 Javascript
Kindeditor在线文本编辑器如何过滤HTML
2016/04/14 Javascript
js改变透明度实现轮播图的算法
2020/08/24 Javascript
Bootstrap CSS组件之输入框组
2016/12/17 Javascript
jQuery实现获取table中鼠标click点击位置行号与列号的方法
2017/10/09 jQuery
微信小程序实现页面跳转传值的方法
2017/10/12 Javascript
nodejs实现一个word文档解析器思路详解
2018/08/14 NodeJs
轻松解决JavaScript定时器越走越快的问题
2019/05/13 Javascript
jQuery实现input[type=file]多图预览上传删除等功能
2019/08/02 jQuery
vue+moment实现倒计时效果
2019/08/26 Javascript
Vue移动端用淘宝弹性布局lib-flexible插件做适配的方法
2020/05/26 Javascript
[01:20]辉夜杯背景故事宣传片《辉夜传说》
2015/12/25 DOTA
详解Python下ftp上传文件linux服务器
2018/06/21 Python
python实现任意位置文件分割的实例
2018/12/14 Python
python操作openpyxl导出Excel 设置单元格格式及合并处理代码实例
2019/08/27 Python
Python matplotlib绘制饼状图功能示例
2019/09/10 Python
Django values()和value_list()的使用
2020/03/31 Python
numpy库reshape用法详解
2020/04/19 Python
python和node.js生成当前时间戳的示例
2020/09/29 Python
python如何构建mock接口服务
2021/01/28 Python
俄罗斯童装网上商店:BebaKids
2020/06/06 全球购物
大整数数相乘的问题
2012/07/22 面试题
行政总经理岗位职责
2013/12/05 职场文书
技校毕业生的自我评价
2013/12/27 职场文书
师德演讲稿范文
2014/05/06 职场文书
股东大会通知
2015/04/24 职场文书
2016年七夕情人节宣传语
2015/11/25 职场文书
Canvas跟随鼠标炫彩小球的实现
2021/04/11 Javascript
图文详解nginx日志切割的实现
2022/01/18 Servers