📄 corn.cpp
字号:
float C, D, T;
TCDT()
: C(0.0),
D(0.0),
T(0.0)
{}
};
void C_computeCDT(const vector<TCummulativeROC> &cummlists, vector<TCDT> &cdts)
{
cdts = vector<TCDT>(cummlists.size());
vector<TCDT>::iterator cdti (cdts.begin());
for (vector<TCummulativeROC>::const_iterator ci(cummlists.begin()), ce(cummlists.end()); ci!=ce; ci++, cdti++) {
pp low;
for (map<float, pp>::const_iterator cri((*ci).begin()), cre((*ci).end()); cri!=cre; cri++) {
const pp &thi = (*cri).second;
(*cdti).C += low.normal * thi.abnormal;
(*cdti).D += low.abnormal * thi.normal;
(*cdti).T += thi.normal * thi.abnormal;
low += thi;
}
}
}
PyObject *py_ROCCumulativeList(vector<TCummulativeROC> &cummlists, pp &totals)
{
PyObject *pyresults = PyList_New(cummlists.size());
int lrn = 0;
ITERATE(vector<TCummulativeROC>, ci, cummlists) {
PyObject *pclist = PyList_New((*ci).size());
int prb = 0;
ITERATE(TCummulativeROC, si, *ci)
PyList_SetItem(pclist, prb++, Py_BuildValue("f(ff)", (*si).first, (*si).second.normal, (*si).second.abnormal));
PyList_SetItem(pyresults, lrn++, pclist);
}
return Py_BuildValue("N(ff)", pyresults, totals.normal, totals.abnormal);
}
PyObject *py_computeROCCumulative(PyObject *, PyObject *arg)
{
PyTRY
PyObject *pyresults;
int classIndex = -1;
PyObject *pyuseweights = NULL;
if (!PyArg_ParseTuple(arg, "O|iO", &pyresults, &classIndex, &pyuseweights))
PYERROR(PyExc_TypeError, "computeROCCummulative: results and optionally the classIndex and 'useWeights' flag expected", PYNULL);
bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
ExperimentResults results(pyresults);
if (results.numberOfIterations>1)
PYERROR(PyExc_SystemError, "computeCDT: cannot compute CDT for experiments with multiple iterations", PYNULL);
pp totals;
vector<TCummulativeROC> cummlists;
C_computeROCCumulative(results, classIndex, totals, cummlists, useweights);
return py_ROCCumulativeList(cummlists, totals);
PyCATCH
}
PyObject *py_computeROCCumulativePair(PyObject *, PyObject *arg)
{
PyTRY
PyObject *pyresults;
int classIndex1, classIndex2;
PyObject *pyuseweights = NULL;
if (!PyArg_ParseTuple(arg, "Oii|O", &pyresults, &classIndex1, &classIndex2, &pyuseweights))
PYERROR(PyExc_TypeError, "computeROCCummulative: results and classIndices, and optional 'useWeights' flag expected", PYNULL);
bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
ExperimentResults results(pyresults);
if (results.numberOfIterations>1)
PYERROR(PyExc_SystemError, "computeCDT: cannot compute CDT for experiments with multiple iterations", PYNULL);
pp totals;
vector<TCummulativeROC> cummlists;
C_computeROCCumulativePair(results, classIndex1, classIndex2, totals, cummlists, useweights);
return py_ROCCumulativeList(cummlists, totals);
PyCATCH
}
PyObject *computeCDTList(vector<TCummulativeROC> &cummlists)
{
PyObject *res = NULL, *orngStatModule = NULL;
try {
vector<TCDT> cdts;
C_computeCDT(cummlists, cdts);
PyObject *orngStatModule = PyImport_ImportModule("orngStat");
if (!orngStatModule)
return PYNULL;
// PyModule_GetDict and PyDict_GetItemString return borrowed references
PyObject *orngStatModuleDict = PyModule_GetDict(orngStatModule);
Py_DECREF(orngStatModule);
orngStatModule = NULL;
PyObject *CDTType = PyDict_GetItemString(orngStatModuleDict, "CDT");
if (!CDTType)
PYERROR(PyExc_AttributeError, "orngStat does not define CDT class", PYNULL);
PyObject *res = PyList_New(cdts.size());
int i = 0;
ITERATE(vector<TCDT>, cdti, cdts) {
PyObject *inargs = Py_BuildValue("fff", (*cdti).C, (*cdti).D, (*cdti).T);
PyObject *indict = PyDict_New();
PyObject *PyCDT = PyInstance_New(CDTType, inargs, indict);
Py_DECREF(inargs);
Py_DECREF(indict);
if (!PyCDT) {
Py_XDECREF(res);
return PYNULL;
}
PyList_SetItem(res, i++, PyCDT);
}
return res;
}
catch (...) {
Py_XDECREF(res);
Py_XDECREF(orngStatModule);
throw;
}
}
PyObject *py_computeCDT(PyObject *, PyObject *arg)
{
PyTRY
PyObject *pyresults;
int classIndex = -1;
PyObject *pyuseweights = PYNULL;
if (!PyArg_ParseTuple(arg, "O|iO", &pyresults, &classIndex, &pyuseweights))
PYERROR(PyExc_TypeError, "computeROCCummulative: results and optionally the classIndex expected", PYNULL);
bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
ExperimentResults results(pyresults);
pp totals;
vector<TCummulativeROC> cummlists;
C_computeROCCumulative(results, classIndex, totals, cummlists, useweights);
return computeCDTList(cummlists);
PyCATCH
}
PyObject *py_computeCDTPair(PyObject *, PyObject *arg)
{
PyTRY
PyObject *pyresults;
int classIndex1, classIndex2;
PyObject *pyuseweights = PYNULL;
if (!PyArg_ParseTuple(arg, "Oii|O", &pyresults, &classIndex1, &classIndex2, &pyuseweights))
PYERROR(PyExc_TypeError, "computeROCCummulative: results, two class indices and optional flag for using weights", PYNULL);
bool useweights = pyuseweights && PyObject_IsTrue(pyuseweights)!=0;
ExperimentResults results(pyresults);
pp totals;
vector<TCummulativeROC> cummlists;
C_computeROCCumulativePair(results, classIndex1, classIndex2, totals, cummlists, useweights);
return computeCDTList(cummlists);
PyCATCH
}
PyObject *py_compare2ROCs(PyObject *, PyObject *arg)
{ PyTRY
PyObject *pyresults;
int roc1, roc2, classIndex = -1;
PyObject *pyuseweights;
if (!PyArg_ParseTuple(arg, "OiiiO", &pyresults, &roc1, &roc2, &classIndex, &pyuseweights))
PYERROR(PyExc_TypeError, "compare2ROCs: results and two integer indices (optionally also classIndex) expected", PYNULL);
bool useweights = PyObject_IsTrue(pyuseweights)!=0;
if (useweights)
PYERROR(PyExc_SystemError, "compare2ROCs: cannot use weights (weights not implemented yet)", PYNULL);
ExperimentResults results(pyresults);
if (results.numberOfIterations>1)
PYERROR(PyExc_SystemError, "computeCDT: cannot compute CDT for experiments with multiple iterations", PYNULL);
if (classIndex<0)
classIndex = results.baseClass;
if (classIndex<0)
classIndex = 1;
float e11[] = {0, 0}, e10[] = {0, 0}, e01[] = {0, 0};
float e11r = 0, e10r = 0, e01r = 0;
float th[] ={0, 0};
int m = 0, n = 0;
/* m is number of examples with class == classIndex, n are others
X_* represent example with class == classIndex, Y_* are others
*/
for (vector<TestedExample>::const_iterator i(results.results.begin()), e(results.results.end()); i!=e; i++)
if ((*i).actualClass != classIndex) {
n++;
}
else { // (*i).actualClass == classIndex
m++;
float X_i[] = {(*i).probabilities[roc1][classIndex], (*i).probabilities[roc2][classIndex]};
for (vector<TestedExample>::const_iterator j = i+1; j!=e; j++)
if ((*j).actualClass!=classIndex) {
float Y_j[] = {(*j).probabilities[roc1][classIndex], (*j).probabilities[roc2][classIndex]};
float diffs[] = { diff2(X_i[0], Y_j[0]), diff2(X_i[1], Y_j[1]) };
th[0] += diffs[0];
th[1] += diffs[1];
e11[0] += sqr(diffs[0]);
e11[1] += sqr(diffs[1]);
e11r += diffs[0]*diffs[1];
for (vector<TestedExample>::const_iterator k = j+1; k!=e; k++)
if ((*k).actualClass == classIndex) { // B_XXY
float X_k[] = { (*k).probabilities[roc1][classIndex], (*k).probabilities[roc2][classIndex] };
float diffsk[] = { diff2(X_k[0], Y_j[0]), diff2(X_k[1], Y_j[1]) };
e01[0] += diffs[0]*diffsk[0];
e01[1] += diffs[1]*diffsk[1];
e01r += diffs[0]*diffsk[1] + diffs[1]*diffsk[0];
}
else { // B_XYY
float Y_k[] = { (*k).probabilities[roc1][classIndex], (*k).probabilities[roc2][classIndex] };
float diffsk[] = { diff2(X_i[0], Y_k[0]), diff2(X_i[1], Y_k[1]) };
e10[0] += diffs[0]*diffsk[0];
e10[1] += diffs[1]*diffsk[1];
e10r += diffs[0]*diffsk[1] + diffs[1]*diffsk[0];
}
}
}
float n11 = float(m)*float(n), n01 = float(m)*float(n)*float(m-1)/2.0, n10 = float(m)*float(n)*float(n-1)/2.0;
th[0] /= n11;
th[1] /= n11;
e11[0] = e11[0]/n11 - sqr(th[0]);
e11[1] = e11[1]/n11 - sqr(th[1]);
e11r = e11r /n11 - th[0]*th[1];
e10[0] = e10[0]/n10 - sqr(th[0]);
e10[1] = e10[1]/n10 - sqr(th[1]);
e10r = e10r /n10 - th[0]*th[1];
e01[0] = e01[0]/n01 - sqr(th[0]);
e01[1] = e01[1]/n01 - sqr(th[1]);
e01r = e01r /n01 - th[0]*th[1];
float var[] = { ((n-1)*e10[0] + (m-1)*e01[0] + e11[0])/n11, ((n-1)*e10[1] + (m-1)*e01[1] + e11[1])/n11};
float SE[] = { sqrt(var[0]), sqrt(var[1]) };
float covar = ((n-1)*e10r + (m-1)*e01r + e11r) / n11;
float SEr = sqrt(var[0]+var[1]-2*covar*SE[0]*SE[1]);
return Py_BuildValue("(ff)(ff)(ff)", th[0], SE[0], th[1], SE[1], th[0]-th[1], SEr);
PyCATCH
}
inline float cmphalf(const float &x, const float &y)
{
if (x<y) return 0;
if (x==y) return 0.25;
return 0.5;
}
PyObject *py_mAUC(PyObject *, PyObject *arg)
{ PyTRY
PyObject *pyresults;
PyObject *pyuseweights = PYNULL;
if (!PyArg_ParseTuple(arg, "O|O:corn.mAUC", &pyresults, &pyuseweights))
PYERROR(PyExc_TypeError, "mAUC: results and optionally use weights flag expected", PYNULL);
bool useweights = pyuseweights && (PyObject_IsTrue(pyuseweights)!=0);
if (useweights)
PYERROR(PyExc_SystemError, "mAUC: cannot use weights (weights not implemented yet)", PYNULL);
ExperimentResults results(pyresults);
/* if (results.numberOfIterations>1)
PYERROR(PyExc_SystemError, "mAUC: cannot compute CDT for experiments with multiple iterations", PYNULL);
*/
const int nLearners = results.numberOfLearners;
vector<float> correctPairs(nLearners, 0.0);
int usefulPairs = 0;
for (vector<TestedExample>::const_iterator i1(results.results.begin()), e(results.results.end()); i1!=e; i1++)
for (vector<TestedExample>::const_iterator i2(i1); i2!=e; i2++) {
const int cls1 = (*i1).actualClass;
const int cls2 = (*i2).actualClass;
if (cls1 != cls2) {
usefulPairs++;
vector<float>::iterator cpi(correctPairs.begin());
vector<vector<float> >::const_iterator ep1i((*i1).probabilities.begin()), ep2i((*i2).probabilities.begin());
for(int cfr = nLearners; cfr--; cpi++, ep1i++, ep2i++)
*cpi += cmphalf((*ep1i)[cls1], (*ep2i)[cls1])
+ cmphalf((*ep2i)[cls2], (*ep1i)[cls2]);
}
}
PyObject *res = PyList_New(nLearners);
for(int cfr = 0; cfr<nLearners; cfr++)
PyList_SetItem(res, cfr, PyFloat_FromDouble(correctPairs[cfr]/usefulPairs));
return res;
PyCATCH
}
/* *********** AUXILIARY ROUTINES *************/
class CompCallbackLess {
public:
PyObject *py_compare;
CompCallbackLess(PyObject *apyc)
: py_compare(apyc)
{ Py_XINCREF(apyc); }
~CompCallbackLess()
{ Py_XDECREF(py_compare); }
int operator()(PyObject *obj1, PyObject *obj2)
{ PyObject *args = Py_BuildValue("OO", obj1, obj2);
PyObject *result = PyEval_CallObject(py_compare, args);
Py_DECREF(args);
if (!result)
throw pyexception();
bool res = PyInt_AsLong(result)<0;
Py_DECREF(result);
return res;
}
};
class CompCallbackEqual {
public:
PyObject *py_compare;
CompCallbackEqual(PyObject *apyc)
: py_compare(apyc)
{ Py_XINCREF(apyc); }
~CompCallbackEqual()
{ Py_XDECREF(py_compare); }
int operator()(PyObject *obj1, PyObject *obj2)
{ PyObject *args = Py_BuildValue("OO", obj1, obj2);
PyObject *result = PyEval_CallObject(py_compare, args);
Py_DECREF(args);
if (!result)
throw pyexception();
bool res = (PyInt_AsLong(result)==0);
Py_DECREF(result);
return res;
}
};
/* *********** EXPORT DECLARATIONS ************/
#define DECLARE(name) \
{#name, (binaryfunc)py_##name, METH_VARARGS},
PyMethodDef corn_functions[] = {
DECLARE(compare2ROCs)
DECLARE(computeROCCumulative)
DECLARE(computeROCCumulativePair)
DECLARE(computeCDT)
DECLARE(computeCDTPair)
DECLARE(mAUC)
{NULL, NULL}
};
#undef DECLARE
#undef PyTRY
#undef PyCATCH
#undef PYNULL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -