summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dyer <cdyer@cab.ark.cs.cmu.edu>2012-10-11 23:13:12 -0400
committerChris Dyer <cdyer@cab.ark.cs.cmu.edu>2012-10-11 23:13:12 -0400
commit070d51e5554cc9840d97556d04bfa64a3d60b38c (patch)
tree47523b625a341baa4faf40fdc8a65a26e279d2a7
parent05ca9a263291f1ce48b09689d10199a68e7ea3b3 (diff)
example external feature function
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac1
-rw-r--r--example_extff/Makefile.am5
-rw-r--r--example_extff/README.md8
-rw-r--r--example_extff/ff_example.cc56
5 files changed, 72 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index c0826532..3e0103a8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,7 +14,8 @@ SUBDIRS = \
dpmert \
pro-train \
rampion \
- minrisk
+ minrisk \
+ example_extff
#gi/pyp-topics/src gi/clda/src gi/posterior-regularisation/prjava
diff --git a/configure.ac b/configure.ac
index 967b657c..03a0ee87 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,6 +125,7 @@ AC_CONFIG_FILES([klm/util/Makefile])
AC_CONFIG_FILES([klm/lm/Makefile])
AC_CONFIG_FILES([mira/Makefile])
AC_CONFIG_FILES([dtrain/Makefile])
+AC_CONFIG_FILES([example_extff/Makefile])
AC_CONFIG_FILES([python/setup.py])
diff --git a/example_extff/Makefile.am b/example_extff/Makefile.am
new file mode 100644
index 00000000..ac2694ca
--- /dev/null
+++ b/example_extff/Makefile.am
@@ -0,0 +1,5 @@
+AM_CPPFLAGS = -DBOOST_TEST_DYN_LINK -W -Wno-sign-compare $(GTEST_CPPFLAGS) -I.. -I../mteval -I../utils -I../klm -I../decoder
+
+lib_LTLIBRARIES = libff_example.la
+libff_example_la_SOURCES = ff_example.cc
+libff_example_la_LDFLAGS = -version-info 1:0:0 -module
diff --git a/example_extff/README.md b/example_extff/README.md
new file mode 100644
index 00000000..f2aba487
--- /dev/null
+++ b/example_extff/README.md
@@ -0,0 +1,8 @@
+This is an example of an _external_ feature function which is loaded as a dynamically linked library at run time to compute feature functions over derivations in a hypergraph. To load feature external feature functions, you can specify them in your `cdec.ini` configuration file as follows:
+
+ feature_function=External /path/to/libmy_feature.so
+
+Any extra options are passed to the external library.
+
+*Note*: the build system uses [GNU Libtool](http://www.gnu.org/software/libtool/) to create the shared library. This may be placed in a hidden directory called `./libs`.
+
diff --git a/example_extff/ff_example.cc b/example_extff/ff_example.cc
new file mode 100644
index 00000000..51ebf364
--- /dev/null
+++ b/example_extff/ff_example.cc
@@ -0,0 +1,56 @@
+#include "ff.h"
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+// example of a "stateful" feature made available as an external library
+// This feature looks nodes and their daughters and fires an indicator based
+// on the arities of the rules involved.
+// (X (X a) b (X c)) - this is a 2 arity parent with children of 0 and 0 arity
+// so you get MAF_2_0_0=1
+class ParentChildrenArityFeatures : public FeatureFunction {
+ public:
+ ParentChildrenArityFeatures(const string& param) : fids(16, vector<int>(256, -1)) {
+ SetStateSize(1); // number of bytes extra state required by this Feature
+ }
+ virtual void FinalTraversalFeatures(const void* context,
+ SparseVector<double>* features) const {
+ // Goal always is arity 1, so there's no discriminative value of
+ // computing a feature
+ }
+ protected:
+ virtual void TraversalFeaturesImpl(const SentenceMetadata& smeta,
+ const Hypergraph::Edge& edge,
+ const std::vector<const void*>& ant_contexts,
+ FeatureVector* features,
+ FeatureVector* estimated_features,
+ void* context) const {
+ unsigned child_arity_code = 0;
+ for (unsigned j = 0; j < ant_contexts.size(); ++j) {
+ child_arity_code <<= 4;
+ child_arity_code |= *reinterpret_cast<const unsigned char*>(ant_contexts[j]);
+ }
+ int& fid = fids[edge.Arity()][child_arity_code]; // reference!
+ if (fid < 0) {
+ ostringstream feature_string;
+ feature_string << "MAF_" << edge.Arity();
+ for (unsigned j = 0; j < ant_contexts.size(); ++j)
+ feature_string << '_' <<
+ static_cast<int>(*reinterpret_cast<const unsigned char*>(ant_contexts[j]));
+ fid = FD::Convert(feature_string.str());
+ }
+ features->set_value(fid, 1.0);
+ *reinterpret_cast<unsigned char*>(context) = edge.Arity(); // save state
+ }
+ private:
+ mutable vector<vector<int> > fids;
+};
+
+// IMPORTANT: this function must be implemented by any external FF library
+// if your library has multiple features, you can use str to configure things
+extern "C" FeatureFunction* create_ff(const string& str) {
+ return new ParentChildrenArityFeatures(str);
+}
+
+