📄 svm_struct_api.c
字号:
LABEL find_most_violated_constraint_slackrescaling(PATTERN x, LABEL y, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm){ /* Finds the label ybar for pattern x that that is responsible for the most violated constraint for the slack rescaling formulation. It has to take into account the scoring function in sm, especially the weights sm.w, as well as the loss function. The weights in sm.w correspond to the features defined by psi() and range from index 1 to index sm->sizePsi. Most simple is the case of the zero/one loss function. For the zero/one loss, this function should return the highest scoring label ybar, if ybar is unequal y; if it is equal to the correct label y, then the function shall return the second highest scoring label. If the function cannot find a label, it shall return an empty label as recognized by the function empty_label(y). */ LABEL ybar; /* insert your code for computing the label ybar here */ PyObject *pDict, *pFunc, *pArgs; static int has_not_warned = 1; /* Set up the call the Python function. */ pDict = PyModule_GetDict(pModule); pFunc = PyDict_GetItemString(pDict, PYTHON_FIND_MOST_VIOLATED); if (pFunc == NULL) { if (has_not_warned) { fprintf(stderr, "Warning: could not find function %s!\n", PYTHON_FIND_MOST_VIOLATED); has_not_warned = 0; } return classify_struct_example(x, sm, sparm); } pArgs = PyTuple_New(4); /* This is a new instance! */ Py_INCREF((PyObject*)x.py_pattern); Py_INCREF((PyObject*)y.py_label); PyTuple_SetItem(pArgs, 0, (PyObject*)x.py_pattern); PyTuple_SetItem(pArgs, 1, (PyObject*)y.py_label); PyTuple_SetItem(pArgs, 2, smToPythonObject(sm)); PyTuple_SetItem(pArgs, 3, sparmToPythonObject(sparm)); /* Call the embedded python function!! */ PYTHON_CALL(ybar.py_label, pFunc, pArgs); Py_DECREF(pArgs); return(ybar);}LABEL find_most_violated_constraint_marginrescaling(PATTERN x, LABEL y, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm){ /* Finds the label ybar for pattern x that that is responsible for the most violated constraint for the margin rescaling formulation. It has to take into account the scoring function in sm, especially the weights sm.w, as well as the loss function. The weights in sm.w correspond to the features defined by psi() and range from index 1 to index sm->sizePsi. Most simple is the case of the zero/one loss function. For the zero/one loss, this function should return the highest scoring label ybar, if ybar is unequal y; if it is equal to the correct label y, then the function shall return the second highest scoring label. If the function cannot find a label, it shall return an empty label as recognized by the function empty_label(y). */ /* insert your code for computing the label ybar here */ return find_most_violated_constraint_slackrescaling(x, y, sm, sparm);}int empty_label(LABEL y){ /* Returns true, if y is an empty label. An empty label might be returned by find_most_violated_constraint_???(x, y, sm) if there is no incorrect label that can be found for x, or if it is unable to label x at all */ return y.py_label == Py_None;}SVECTOR *psi(PATTERN x, LABEL y, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm){ /* Returns a feature vector describing the match between pattern x and label y. The feature vector is returned as a list of SVECTOR's. Each SVECTOR is in a sparse representation of pairs <featurenumber:featurevalue>, where the last pair has featurenumber 0 as a terminator. Featurenumbers start with 1 and end with sizePsi. Featuresnumbers that are not specified default to value 0. As mentioned before, psi() actually returns a list of SVECTOR's. Each SVECTOR has a field 'factor' and 'next'. 'next' specifies the next element in the list, terminated by a NULL pointer. The list can be though of as a linear combination of vectors, where each vector is weighted by its 'factor'. This linear combination of feature vectors is multiplied with the learned (kernelized) weight vector to score label y for pattern x. Without kernels, there will be one weight in sm.w for each feature. Note that psi has to match find_most_violated_constraint_???(x, y, sm) and vice versa. In particular, find_most_violated_constraint_???(x, y, sm) finds that ybar!=y that maximizes psi(x,ybar,sm)*sm.w (where * is the inner vector product) and the appropriate function of the loss + margin/slack rescaling method. See that paper for details. */ SVECTOR *fvec; /* insert code for computing the feature vector for x and y here */ PyObject *pDict, *pFunc, *pArgs, *pPsi; /* Set up the call the Python function. */ pDict = PyModule_GetDict(pModule); pFunc = PyDict_GetItemString(pDict, PYTHON_PSI); if (pFunc == NULL) { fprintf(stderr, "Could not find function %s!\n", PYTHON_PSI); Py_Exit(1); } pArgs = PyTuple_New(4); /* This is a new instance! */ Py_INCREF((PyObject*)x.py_pattern); Py_INCREF((PyObject*)y.py_label); PyTuple_SetItem(pArgs, 0, (PyObject*)x.py_pattern); PyTuple_SetItem(pArgs, 1, (PyObject*)y.py_label); PyTuple_SetItem(pArgs, 2, smToPythonObject(sm)); PyTuple_SetItem(pArgs, 3, sparmToPythonObject(sparm)); /* Call the embedded python function!! */ PYTHON_CALL(pPsi, pFunc, pArgs); Py_DECREF(pArgs); /* Convert this to a support vector. */ if (!(fvec = pythonObjectToSV(pPsi))) { fprintf(stderr, "Function %s returned a bad value!\n", PYTHON_PSI); Py_Exit(1); } Py_DECREF(pPsi); return(fvec);}double loss(LABEL y, LABEL ybar, STRUCT_LEARN_PARM *sparm){ static int has_not_warned = 1; PyObject *pDict, *pFunc, *pArgs, *pLoss; double theLoss; /* Set up the call the Python function. */ pDict = PyModule_GetDict(pModule); pFunc = PyDict_GetItemString(pDict, PYTHON_LOSS); if (pFunc == NULL) { /* We could not find the loss function! */ int lossResult; if (has_not_warned) { fprintf(stderr, "Warning: %s function missing. Defaulting to 0/1 based " "on equality.", PYTHON_LOSS); has_not_warned = 0; } /* Perform 0/1 loss based on Python object comparison. Equality is pretty good for everything except custom classes that don't specify how to handle the equality operator. */ lossResult=PyObject_RichCompareBool(y.py_label, ybar.py_label, Py_EQ); return (lossResult == 0) ? 1 : 0; } /* We have a loss function available? Great. Let's use it! */ pArgs = PyTuple_New(3); /* This is a new instance! */ Py_INCREF((PyObject*)y.py_label); Py_INCREF((PyObject*)ybar.py_label); PyTuple_SetItem(pArgs, 0, (PyObject*)y.py_label); PyTuple_SetItem(pArgs, 1, (PyObject*)ybar.py_label); PyTuple_SetItem(pArgs, 2, sparmToPythonObject(sparm)); /* Call the embedded python function!! */ PyErr_Clear(); PYTHON_CALL(pLoss, pFunc, pArgs); if (PyErr_Occurred()) { PyErr_Print(); Py_Exit(1); } Py_DECREF(pArgs); theLoss = PyFloat_AsDouble(pLoss); Py_DECREF(pLoss); return theLoss;}void print_struct_learning_stats(SAMPLE sample, STRUCTMODEL *sm, CONSTSET cset, double *alpha, STRUCT_LEARN_PARM *sparm){ /* This function is called after training and allows final touches to the model sm. But primarly it allows computing and printing any kind of statistic (e.g. training error) you might want. */ int i; PyObject *pDict, *pFunc, *pArgs, *pValue, *pConsts, *pAlpha; /* Set up the call to the Python method. */ pDict = PyModule_GetDict(pModule); pFunc = PyDict_GetItemString(pDict, PYTHON_PRINT_LEARNING_STATS); if (pFunc == NULL) { /*fprintf(stderr, "Warning: could not find function %s!\n", PYTHON_PRINT_LEARNING_STATS);*/ /* Do default behavior of outputting a list of the loss for all training examples under the current model. */ printf("["); for (i=0; i<sample.n; i++) { LABEL ypred = classify_struct_example(sample.examples[i].x, sm, sparm); double trainingLoss = loss(sample.examples[i].y, ypred, sparm); if (i) printf(", "); else printf(" "); printf("%g", trainingLoss); free_label(ypred); } printf(" ]\n"); return; } /* Build the constraint list. */ pConsts = PyTuple_New(cset.m); for (i=0; i<cset.m; ++i) { PyObject *constraint = PyTuple_New(2); PyTuple_SET_ITEM(constraint, 0, svToPythonObject(cset.lhs[i]->fvec)); PyTuple_SET_ITEM(constraint, 1, PyFloat_FromDouble(cset.rhs[i])); PyTuple_SET_ITEM(pConsts, i, constraint); } /* Build alpha. */#if defined(NUMERIC)||defined(NUMARRAY) pAlpha = PyArray_FromDimsAndData(1, (int*)&cset.m, PyArray_DOUBLE, (char*)alpha);#else pAlpha = PyTuple_New(cset.m); for (i=0; i<cset.m; ++i) PyTuple_SET_ITEM(pAlpha, i, PyFloat_FromDouble(alpha[i]));#endif /* Build the argument list. */ pArgs = PyTuple_New(5); PyTuple_SET_ITEM(pArgs, 0, sampleToPythonObject(sample)); PyTuple_SET_ITEM(pArgs, 1, smToPythonObject(sm)); PyTuple_SET_ITEM(pArgs, 2, pConsts); PyTuple_SET_ITEM(pArgs, 3, pAlpha); PyTuple_SET_ITEM(pArgs, 4, sparmToPythonObject(sparm)); /* Call the embedded python function!! */ PyErr_Clear(); PYTHON_CALL(pValue, pFunc, pArgs); if (PyErr_Occurred()) { PyErr_Print(); Py_Exit(1); } Py_DECREF(pArgs); Py_DECREF(pValue);}void print_struct_testing_stats(SAMPLE sample, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm, STRUCT_TEST_STATS *teststats){ /* This function is called after making all test predictions in svm_struct_classify and allows computing and printing any kind of evaluation (e.g. precision/recall) you might want. You can use the function eval_prediction to accumulate the necessary statistics for each prediction. */ PyObject *pDict, *pFunc, *pArgs, *pValue; if (sample.n==0) { /* If we have no test examples then py_stats would never have been initialized, even to None. */ teststats->py_stats = Py_None; } /* Set up the call to the Python method. */ pDict = PyModule_GetDict(pModule); pFunc = PyDict_GetItemString(pDict, PYTHON_PRINT_TESTING_STATS); if (pFunc == NULL) { /*fprintf(stderr, "Warning: could not find function %s!\n", PYTHON_PRINT_TESTING_STATS);*/ /* Do default behavior of printing out the teststats->py_stats object. */ PyObject_Print((PyObject*)teststats->py_stats, stdout, 0); printf("\n"); return; } /* Build the argument list. */ pArgs = PyTuple_New(4); Py_INCREF((PyObject*)teststats->py_stats); PyTuple_SetItem(pArgs, 0, sampleToPythonObject(sample)); PyTuple_SetItem(pArgs, 1, smToPythonObject(sm)); PyTuple_SetItem(pArgs, 2, sparmToPythonObject(sparm)); PyTuple_SetItem(pArgs, 3, (PyObject*)teststats->py_stats); /* Call the embedded python function!! */ PYTHON_CALL(pValue, pFunc, pArgs); Py_DECREF(pArgs); Py_DECREF(pValue);}void eval_prediction(long exnum, EXAMPLE ex, LABEL ypred, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm, STRUCT_TEST_STATS *teststats){ /* This function allows you to accumlate statistic for how well the predicition matches the labeled example. It is called from svm_struct_classify. See also the function print_struct_testing_stats. */ PyObject *pDict, *pFunc, *pArgs; if(exnum == 0) { /* this is the first time the function is called. So initialize the teststats */ teststats->py_stats = Py_None; } /* Set up the call to the Python method. */ pDict = PyModule_GetDict(pModule); pFunc = PyDict_GetItemString(pDict, PYTHON_EVAL_PREDICTION); if (pFunc == NULL) { PyObject *pList, *pNumber; /*fprintf(stderr, "Warning: could not find function %s!\n", PYTHON_EVAL_PREDICTION);*/ /* Do default behavior of accumulating the loss in a list. */ if (exnum == 0) { teststats->py_stats = PyList_New(0); } pList = (PyObject*)teststats->py_stats; pNumber = PyFloat_FromDouble(loss(ex.y, ypred, sparm)); PyList_Append(pList, pNumber); Py_DECREF(pNumber); return; } /* Build the argument list. */ pArgs = PyTuple_New(7); PyTuple_SetItem(pArgs, 0, PyInt_FromLong(exnum)); Py_INCREF((PyObject*)ex.x.py_pattern); Py_INCREF((PyObject*)ex.y.py_label); Py_INCREF((PyObject*)ypred.py_label); Py_INCREF((PyObject*)teststats->py_stats); PyTuple_SetItem(pArgs, 1, (PyObject*)ex.x.py_pattern); PyTuple_SetItem(pArgs, 2, (PyObject*)ex.y.py_label); PyTuple_SetItem(pArgs, 3, (PyObject*)ypred.py_label); PyTuple_SetItem(pArgs, 4, smToPythonObject(sm)); PyTuple_SetItem(pArgs, 5, sparmToPythonObject(sparm)); PyTuple_SetItem(pArgs, 6, (PyObject*)teststats->py_stats); /* Call the embedded python function!! */ PyErr_Clear(); PYTHON_CALL(teststats->py_stats, pFunc, pArgs); if (PyErr_Occurred()) { PyErr_Print(); Py_Exit(1); } Py_DECREF(pArgs);}void write_struct_model(char *file, STRUCTMODEL *sm, STRUCT_LEARN_PARM *sparm){ /* Writes structural model sm to file file. */ PyObject *pDict, *pFunc, *pArgs, *pValue, *pFile, *module, *pSm, *pArray; pSm = smToPythonObject(sm); pArray = PyObject_GetAttrString(pSm, "w"); pValue = PySequence_Tuple(pArray); Py_DECREF(pArray);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -