浅谈keras中自定义二分类任务评价指标metrics的方法以及代码
对于二分类任务,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中自定义二分类任务常用评价指标及其引用的代码如下
importtensorflowastf #精确率评价指标 defmetric_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) returnprecision #召回率评价指标 defmetric_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) returnrecall #F1-score评价指标 defmetric_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) returnF1score #编译阶段引用自定义评价指标示例 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy', metric_precision, metric_recall, metric_F1score])
补充知识:kerassklearn下两分类/多分类的技术杂谈(交叉验证和评价指标)
一.前言
这篇博客是为了记录论文补充实验中所遇到的问题,以及解决方法,主要以程序的形式呈现。
二.对象
深度学习框架:keras
研究对象:两分类/多分类
三.技术杂谈
1.K-FOLD交叉验证
1.概念
对一个模型进行K次训练,每次训练将整个数据集分为随机的K份,K-1作为训练集,剩余的1份作为验证集,每次训练结束将验证集上的性能指标保存下来,最后对K个结果进行平均得到最终的模型性能指标。
2.优缺点
优点:模型评估更加鲁棒
缺点:训练时间加大
3.代码
①sklearn与keras独立使用
fromsklearn.model_selectionimportStratifiedKFold importnumpy seed=7#随机种子 numpy.random.seed(seed)#生成固定的随机数 num_k=5#多少折 #整个数据集(自己定义) X= Y= kfold=StratifiedKFold(n_splits=num_k,shuffle=True,random_state=seed)#分层K折,保证类别比例一致 cvscores=[] fortrain,testinkfold.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结合使用
fromkeras.wrappers.scikit_learnimportKerasClassifier#使用keras下的sklearnAPI fromsklearn.cross_validationimportStratifiedKFold,cross_val_score importnumpyasnp seed=7#随机种子 numpy.random.seed(seed)#生成固定的随机数 num_k=5#多少折 #整个数据集(自己定义) X= Y= #创建模型 defmodel(): #可以用sequential或者function的方式建模(自己定义) model= returnmodel 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),错误率(errorrate),精确率(precision),召回率(recall)=真阳率(TPR)=灵敏度(sensitivity),F1-measure(包含了micro和macro两种),假阳率(FPR),特异度(specificity),ROC(receiveroperationcharacteristiccurve)(包含了micro和macro两种),AUC(areaundercurve),P-R曲线(precision-recall),混淆矩阵
①准确率和错误率
accuracy=(TP+TN)/(P+N)或者accuracy=(TP+TN)/(T+F)
errorrate=(FP+FN)/(P+N)或者(FP+FN)/(T+F)
accuracy=1-errorrate
可见:准确率、错误率是对分类器在整体数据上的评价指标。
②精确率
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.代码
注意:以下的代码是合在一起写的,有注释。
fromsklearnimportdatasets importnumpyasnp fromsklearn.preprocessingimportlabel_binarize fromsklearn.linear_modelimportLogisticRegression fromsklearn.metricsimportconfusion_matrix,precision_score,accuracy_score,recall_score,f1_score,roc_auc_score,precision_recall_fscore_support,roc_curve,classification_report importmatplotlib.pyplotasplt 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("predictlabel:",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)))#formacro #print('AUCy_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("AUCy_pred=proba:",auc) #画ROC曲线 print("one-hotlabelravelledshape:",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('FalsePostivieRate') plt.ylabel('TruePositiveRate') plt.legend() plt.show() #p-r曲线针对的是二分类,这里就不描述了 ans=classification_report(y,y_score,digits=5)#小数点后保留5位有效数字 print(ans)
以上这篇浅谈keras中自定义二分类任务评价指标metrics的方法以及代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。