浅谈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 SQLAlchemy基本操作和常用技巧(包含大量实例,非常好)
May 06 Python
python使用append合并两个数组的方法
Apr 28 Python
Sanic框架安装与简单入门示例
Jul 16 Python
python实现决策树分类(2)
Aug 30 Python
Pandas DataFrame数据的更改、插入新增的列和行的方法
Jun 25 Python
Django REST Framework序列化外键获取外键的值方法
Jul 26 Python
numpy中三维数组中加入元素后的位置详解
Nov 28 Python
python中with语句结合上下文管理器操作详解
Dec 19 Python
pyautogui自动化控制鼠标和键盘操作的步骤
Apr 01 Python
Python Serial串口基本操作(收发数据)
Nov 06 Python
关于python中remove的一些坑小结
Jan 04 Python
使用Django实现商城验证码模块的方法
Jun 01 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
PHP中SESSION使用中的一点经验总结
2012/03/30 PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
2013/06/13 PHP
PHP之预定义接口详解
2015/07/29 PHP
PHP的邮件群发系统phplist配置方法详细总结
2016/03/30 PHP
分享PHP-pcntl 实现多进程代码
2016/09/30 PHP
Laravel框架实现利用中间件进行操作日志记录功能
2018/06/06 PHP
jQuery写的日历(包括日历的样式及功能)
2013/04/23 Javascript
鼠标左键单击冲突的问题解决方法(防止冒泡)
2014/05/14 Javascript
理解javascript中DOM事件
2015/12/25 Javascript
javascript轮播图算法
2016/10/21 Javascript
根据Bootstrap Paginator改写的js分页插件
2016/12/25 Javascript
vue2.0数据双向绑定与表单bootstrap+vue组件
2017/02/27 Javascript
BootStrap表单控件之文本域textarea
2017/05/23 Javascript
BootStrap Select清除选中的状态恢复默认状态
2017/06/20 Javascript
react项目实践之webpack-dev-serve
2018/09/14 Javascript
JSONObject与JSONArray使用方法解析
2020/09/28 Javascript
[05:31]干嘛呢兄弟!DOTA2 TI9语音轮盘部分出处
2019/05/14 DOTA
python获取网页状态码示例
2014/03/30 Python
python实现ping的方法
2015/07/06 Python
在Django框架中伪造捕捉到的URLconf值的方法
2015/07/18 Python
Python中的数学运算操作符使用进阶
2016/06/20 Python
Python数据结构与算法之使用队列解决小猫钓鱼问题
2017/12/14 Python
Django之路由层的实现
2019/09/09 Python
linux 下python多线程递归复制文件夹及文件夹中的文件
2020/01/02 Python
TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
2020/04/08 Python
浅谈Python中文件夹和python package包的区别
2020/06/01 Python
python集合能干吗
2020/07/19 Python
Feelunique澳大利亚:欧洲的化妆品零售电商
2019/12/18 全球购物
大学毕业后的十年规划
2014/01/07 职场文书
小型女装店的创业计划书
2014/01/09 职场文书
技校毕业生自荐书
2014/05/23 职场文书
国际经济与贸易专业求职信
2014/07/10 职场文书
公务员考察材料
2014/12/23 职场文书
教师考核表个人总结
2015/02/12 职场文书
2016五一劳动节慰问信
2015/11/30 职场文书
php随机生成验证码,php随机生成数字,php随机生成数字加字母!
2021/04/01 PHP