From f49ebcba9974a60ec3df2b6c97c7048186a5954d Mon Sep 17 00:00:00 2001 From: Chris Dyer Date: Thu, 11 Oct 2012 23:13:12 -0400 Subject: example external feature function --- example_extff/Makefile.am | 5 ++++ example_extff/README.md | 8 +++++++ example_extff/ff_example.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 example_extff/Makefile.am create mode 100644 example_extff/README.md create mode 100644 example_extff/ff_example.cc (limited to 'example_extff') 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 +#include + +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(256, -1)) { + SetStateSize(1); // number of bytes extra state required by this Feature + } + virtual void FinalTraversalFeatures(const void* context, + SparseVector* 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& 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(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(*reinterpret_cast(ant_contexts[j])); + fid = FD::Convert(feature_string.str()); + } + features->set_value(fid, 1.0); + *reinterpret_cast(context) = edge.Arity(); // save state + } + private: + mutable vector > 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); +} + + -- cgit v1.2.3