How to draw interpolation precision feedback curve in python?

I drew a precision recall curve using the sklearn precision_recall_curve and matplotlib . For those of you who are familiar with the exact recall curve, you know that some scientific communities only accept it when it is interpolated, similar to this example here . Now my question is, do any of you know how to interpolate in python? I have been looking for a solution for a while, but without success! Any help would be greatly appreciated.

Solution: Both solutions from @francis and @ali_m are correct and together solved my problem. So, assuming you get the result of the precision_recall_curve function in sklearn , here is what I did to plot the graph:

  precision["micro"], recall["micro"], _ = precision_recall_curve(y_test.ravel(),scores.ravel()) pr = copy.deepcopy(precision[0]) rec = copy.deepcopy(recall[0]) prInv = np.fliplr([pr])[0] recInv = np.fliplr([rec])[0] j = rec.shape[0]-2 while j>=0: if prInv[j+1]>prInv[j]: prInv[j]=prInv[j+1] j=j-1 decreasing_max_precision = np.maximum.accumulate(prInv[::-1])[::-1] plt.plot(recInv, decreasing_max_precision, marker= markers[mcounter], label=methodNames[countOfMethods]+': AUC={0:0.2f}'.format(average_precision[0])) 

And these lines will build the interpolated curves if you put them in a for loop and pass them the data of each method at each iteration. Please note that this will not lead to the construction of uninterpreted precision recall curves.

+5
source share
2 answers

You can perform a reverse iteration to remove the growing parts in precision . Then the vertical and horizontal lines can be constructed as indicated by Bennett Brown's answer to the vertical and horizontal lines in matplotlib .

Here is a sample code:

 import numpy as np import matplotlib.pyplot as plt #just a dummy sample recall=np.linspace(0.0,1.0,num=42) precision=np.random.rand(42)*(1.-recall) precision2=precision.copy() i=recall.shape[0]-2 # interpolation... while i>=0: if precision[i+1]>precision[i]: precision[i]=precision[i+1] i=i-1 # plotting... fig, ax = plt.subplots() for i in range(recall.shape[0]-1): ax.plot((recall[i],recall[i]),(precision[i],precision[i+1]),'k-',label='',color='red') #vertical ax.plot((recall[i],recall[i+1]),(precision[i+1],precision[i+1]),'k-',label='',color='red') #horizontal ax.plot(recall,precision2,'k--',color='blue') #ax.legend() ax.set_xlabel("recall") ax.set_ylabel("precision") plt.savefig('fig.jpg') fig.show() 

And here is the result:

enter image description here

+1
source
Decision

@francis can be vectorized with np.maximum.accumulate .

 import numpy as np import matplotlib.pyplot as plt recall = np.linspace(0.0, 1.0, num=42) precision = np.random.rand(42)*(1.-recall) # take a running maximum over the reversed vector of precision values, reverse the # result to match the order of the recall vector decreasing_max_precision = np.maximum.accumulate(precision[::-1])[::-1] 

You can also use plt.step to get rid of the for loop used to build:

 fig, ax = plt.subplots(1, 1) ax.hold(True) ax.plot(recall, precision, '--b') ax.step(recall, decreasing_max_precision, '-r') 

enter image description here

+2
source

Source: https://habr.com/ru/post/1257654/


All Articles