/*********************************************************************** Moses - factored phrase-based language decoder Copyright (C) 2010 University of Edinburgh This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ***********************************************************************/ #include #include #include #include #include "Hildreth.h" #include "Optimiser.h" #include "ScoreComponentCollection.h" using namespace std; using namespace Moses; using namespace Mira; namespace MosesTest { class MockSingleFeature : public StatelessFeatureFunction { public: MockSingleFeature(): StatelessFeatureFunction("MockSingle",1) {} std::string GetScoreProducerWeightShortName(unsigned) const {return "sf";} }; class MockMultiFeature : public StatelessFeatureFunction { public: MockMultiFeature(): StatelessFeatureFunction("MockMulti",5) {} std::string GetScoreProducerWeightShortName(unsigned) const {return "mf";} }; class MockSparseFeature : public StatelessFeatureFunction { public: MockSparseFeature(): StatelessFeatureFunction("MockSparse", ScoreProducer::unlimited) {} std::string GetScoreProducerWeightShortName(unsigned) const {return "sf";} }; struct MockProducers { MockProducers() {} MockSingleFeature single; MockMultiFeature multi; MockSparseFeature sparse; }; BOOST_AUTO_TEST_SUITE(hildreth_test) BOOST_FIXTURE_TEST_CASE(test_hildreth_1, MockProducers) { // Feasible example with 2 constraints cerr << "\n>>>>>Hildreth test, without slack and with 0.01 slack" << endl << endl; vector< ScoreComponentCollection> featureValueDiffs; vector< float> lossMinusModelScoreDiff; // initial weights float w[] = { 1, 1, 1, 1, 0 }; vector vec(w,w+5); ScoreComponentCollection weights; weights.PlusEquals(&multi, vec); // feature values (second is oracle) //float arr1[] = {0, -5, -27.0908, -1.83258, 0 }; //float arr2[] = {0, -5, -29.158, -1.83258, 0 }; //float arr3[] = {0, -5, -27.0908, -1.83258, 0 }; // feature value differences (to oracle) ScoreComponentCollection s1, s2, s3; float arr1[] = { 0, 0, -2.0672, 0, 0 }; float arr2[] = { 0, 0, 0, 0, 0 }; float arr3[] = { 0, 0, -2.0672, 0, 0 }; float loss1 = 2.34085; float loss2 = 0; float loss3 = 2.34085; vector vec1(arr1,arr1+5); vector vec2(arr2,arr2+5); vector vec3(arr3,arr3+5); s1.PlusEquals(&multi,vec1); s2.PlusEquals(&multi,vec2); s3.PlusEquals(&multi,vec3); featureValueDiffs.push_back(s1); featureValueDiffs.push_back(s2); featureValueDiffs.push_back(s3); cerr << "feature value diff: " << featureValueDiffs[0] << endl; cerr << "feature value diff: " << featureValueDiffs[1] << endl; cerr << "feature value diff: " << featureValueDiffs[2] << endl << endl; float oldModelScoreDiff1 = featureValueDiffs[0].InnerProduct(weights); float oldModelScoreDiff2 = featureValueDiffs[1].InnerProduct(weights); float oldModelScoreDiff3 = featureValueDiffs[2].InnerProduct(weights); cerr << "model score diff: " << oldModelScoreDiff1 << ", loss: " << loss1 << endl; cerr << "model score diff: " << oldModelScoreDiff2 << ", loss: " << loss2 << endl; cerr << "model score diff: " << oldModelScoreDiff3 << ", loss: " << loss3 << endl << endl; lossMinusModelScoreDiff.push_back(loss1 - oldModelScoreDiff1); lossMinusModelScoreDiff.push_back(loss2 - oldModelScoreDiff2); lossMinusModelScoreDiff.push_back(loss3 - oldModelScoreDiff3); vector< float> alphas1 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff); vector< float> alphas2 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff, 0.01); cerr << "\nalphas without slack:" << endl; for (size_t i = 0; i < alphas1.size(); ++i) { cerr << "alpha " << i << ": " << alphas1[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs1(featureValueDiffs); FVector totalUpdate1 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs1.size(); ++k) { featureValueDiffs1[k].MultiplyEquals(alphas1[k]); cerr << k << ": " << featureValueDiffs1[k].GetScoresVector() << endl; FVector update = featureValueDiffs1[k].GetScoresVector(); totalUpdate1 += update; } cerr << endl; cerr << "total update: " << totalUpdate1 << endl << endl; ScoreComponentCollection weightsUpdate1(weights); weightsUpdate1.PlusEquals(totalUpdate1); cerr << "new weights: " << weightsUpdate1 << endl << endl; float newModelScoreDiff1 = featureValueDiffs[0].InnerProduct(weightsUpdate1); float newModelScoreDiff2 = featureValueDiffs[1].InnerProduct(weightsUpdate1); float newModelScoreDiff3 = featureValueDiffs[2].InnerProduct(weightsUpdate1); cerr << "new model score diff: " << newModelScoreDiff1 << ", loss: " << loss1 << endl; cerr << "new model score diff: " << newModelScoreDiff2 << ", loss: " << loss2 << endl; cerr << "new model score diff: " << newModelScoreDiff3 << ", loss: " << loss3 << endl; cerr << "\n\nalphas with slack 0.01:" << endl; for (size_t i = 0; i < alphas2.size(); ++i) { cerr << "alpha " << i << ": " << alphas2[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs2(featureValueDiffs); FVector totalUpdate2 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs2.size(); ++k) { featureValueDiffs2[k].MultiplyEquals(alphas2[k]); cerr << k << ": " << featureValueDiffs2[k].GetScoresVector() << endl; FVector update = featureValueDiffs2[k].GetScoresVector(); totalUpdate2 += update; } cerr << endl; cerr << "total update: " << totalUpdate2 << endl << endl; ScoreComponentCollection weightsUpdate2(weights); weightsUpdate2.PlusEquals(totalUpdate2); cerr << "new weights: " << weightsUpdate2 << endl << endl; float newModelScoreDiff4 = featureValueDiffs[0].InnerProduct(weightsUpdate2); float newModelScoreDiff5 = featureValueDiffs[1].InnerProduct(weightsUpdate2); float newModelScoreDiff6 = featureValueDiffs[2].InnerProduct(weightsUpdate2); cerr << "new model score diff: " << newModelScoreDiff4 << ", loss: " << loss1 << endl; cerr << "new model score diff: " << newModelScoreDiff5 << ", loss: " << loss2 << endl; cerr << "new model score diff: " << newModelScoreDiff6 << ", loss: " << loss3 << endl; } BOOST_FIXTURE_TEST_CASE(test_hildreth_3, MockProducers) { // Unfeasible example with 21 constraints cerr << "\n>>>>>Hildreth test, without slack and with 0.01 slack" << endl << endl; vector< ScoreComponentCollection> featureValueDiffs; vector< float> lossMinusModelScoreDiff; // initial weights float w[] = { 1, 1, 0.638672, 1, 0 }; vector vec(w,w+5); ScoreComponentCollection weights; weights.PlusEquals(&multi, vec); int numberOfConstraints = 21; // feature value differences (to oracle) // NOTE: these feature values are only approximations ScoreComponentCollection s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21; float arr1[] = { 0, 0, -2.0672, 0, 0 }; float arr2[] = { 0, 0, 0, 0, 0 }; float arr3[] = { 0, 0, -2.08436, 1.38629, 0 }; float arr4[] = { 0, 0, -0.0171661, 1.38629, 0 }; float arr5[] = { 0, 0, 4.4283, 0, 0 }; float arr6[] = { 0, 0, 3.84829, 1.38629, 0 }; float arr7[] = { 0, 0, 6.83689, 0, 0 }; float arr8[] = { 0, 0, 0, 0, 0 }; float arr9[] = { 0, 0, -2.0672, 0, 0 }; float arr10[] = { 0, 0, -0.0171661, 1.38629, 0 }; float arr11[] = { 0, 0, -2.08436, 1.38629, 0 }; float arr12[] = { 0, 0, 4.4283, 0, 0 }; float arr13[] = { 3, 0, 2.41089, 0, 0 }; float arr14[] = { 3, 0, 2.32709, 0, 0 }; float arr15[] = { 0, 0, -2.0672, 0, 0 }; float arr16[] = { 0, 0, -2.08436, 1.38629, 0 }; float arr17[] = { 0, 0, 4.4283, 0, 0 }; float arr18[] = { 0, 0, 3.84829, 1.38629, 0 }; float arr19[] = { 0, 0, -0.0171661, 1.38629, 0 }; float arr20[] = { 0, 0, 0, 0, 0 }; float arr21[] = { 0, 0, 6.83689, 0, 0 }; vector losses; losses.push_back(2.73485); losses.push_back(0); losses.push_back(3.64118); losses.push_back(1.47347); losses.push_back(3.64118); losses.push_back(4.16278); losses.push_back(3.13952); losses.push_back(0); losses.push_back(2.73485); losses.push_back(1.47347); losses.push_back(3.64118); losses.push_back(3.64118); losses.push_back(2.51662); losses.push_back(2.73485); losses.push_back(2.73485); losses.push_back(3.64118); losses.push_back(3.64118); losses.push_back(4.16278); losses.push_back(1.47347); losses.push_back(0); losses.push_back(3.13952); vector vec1(arr1,arr1+5); vector vec2(arr2,arr2+5); vector vec3(arr3,arr3+5); vector vec4(arr4,arr4+5); vector vec5(arr5,arr5+5); vector vec6(arr6,arr6+5); vector vec7(arr7,arr7+5); vector vec8(arr8,arr8+5); vector vec9(arr9,arr9+5); vector vec10(arr10,arr10+5); vector vec11(arr11,arr11+5); vector vec12(arr12,arr12+5); vector vec13(arr13,arr13+5); vector vec14(arr14,arr14+5); vector vec15(arr15,arr15+5); vector vec16(arr16,arr16+5); vector vec17(arr17,arr17+5); vector vec18(arr18,arr18+5); vector vec19(arr19,arr19+5); vector vec20(arr20,arr20+5); vector vec21(arr21,arr21+5); s1.PlusEquals(&multi,vec1); s2.PlusEquals(&multi,vec2); s3.PlusEquals(&multi,vec3); s4.PlusEquals(&multi,vec4); s5.PlusEquals(&multi,vec5); s6.PlusEquals(&multi,vec6); s7.PlusEquals(&multi,vec7); s8.PlusEquals(&multi,vec8); s9.PlusEquals(&multi,vec9); s10.PlusEquals(&multi,vec10); s11.PlusEquals(&multi,vec11); s12.PlusEquals(&multi,vec12); s13.PlusEquals(&multi,vec13); s14.PlusEquals(&multi,vec14); s15.PlusEquals(&multi,vec15); s16.PlusEquals(&multi,vec16); s17.PlusEquals(&multi,vec17); s18.PlusEquals(&multi,vec18); s19.PlusEquals(&multi,vec19); s20.PlusEquals(&multi,vec20); s21.PlusEquals(&multi,vec21); featureValueDiffs.push_back(s1); featureValueDiffs.push_back(s2); featureValueDiffs.push_back(s3); featureValueDiffs.push_back(s4); featureValueDiffs.push_back(s5); featureValueDiffs.push_back(s6); featureValueDiffs.push_back(s7); featureValueDiffs.push_back(s8); featureValueDiffs.push_back(s9); featureValueDiffs.push_back(s10); featureValueDiffs.push_back(s11); featureValueDiffs.push_back(s12); featureValueDiffs.push_back(s13); featureValueDiffs.push_back(s14); featureValueDiffs.push_back(s15); featureValueDiffs.push_back(s16); featureValueDiffs.push_back(s17); featureValueDiffs.push_back(s18); featureValueDiffs.push_back(s19); featureValueDiffs.push_back(s20); featureValueDiffs.push_back(s21); vector oldModelScoreDiff; for (int i = 0; i < numberOfConstraints; ++i) { oldModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weights)); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "old model score diff: " << oldModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (oldModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; } for (int i = 0; i < numberOfConstraints; ++i) { lossMinusModelScoreDiff.push_back(losses[i] - oldModelScoreDiff[i]); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "A: " << featureValueDiffs[i] << ", b: " << lossMinusModelScoreDiff[i] << endl; } vector< float> alphas1 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff); vector< float> alphas2 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff, 0.01); cerr << "\nalphas without slack:" << endl; for (size_t i = 0; i < alphas1.size(); ++i) { cerr << "alpha " << i << ": " << alphas1[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs1(featureValueDiffs); FVector totalUpdate1 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs1.size(); ++k) { featureValueDiffs1[k].MultiplyEquals(alphas1[k]); cerr << k << ": " << featureValueDiffs1[k].GetScoresVector() << endl; FVector update = featureValueDiffs1[k].GetScoresVector(); totalUpdate1 += update; } cerr << endl; cerr << "total update: " << totalUpdate1 << endl << endl; ScoreComponentCollection weightsUpdate1(weights); weightsUpdate1.PlusEquals(totalUpdate1); cerr << "old weights: " << weights << endl; cerr << "new weights: " << weightsUpdate1 << endl << endl; vector newModelScoreDiff; for (int i = 0; i < numberOfConstraints; ++i) { newModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weightsUpdate1)); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "new model score diff: " << newModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (newModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; } cerr << "\n\nalphas with slack 0.01:" << endl; for (size_t i = 0; i < alphas2.size(); ++i) { cerr << "alpha " << i << ": " << alphas2[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs2(featureValueDiffs); FVector totalUpdate2 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs2.size(); ++k) { featureValueDiffs2[k].MultiplyEquals(alphas2[k]); cerr << k << ": " << featureValueDiffs2[k].GetScoresVector() << endl; FVector update = featureValueDiffs2[k].GetScoresVector(); totalUpdate2 += update; } cerr << endl; cerr << "total update: " << totalUpdate2 << endl << endl; ScoreComponentCollection weightsUpdate2(weights); weightsUpdate2.PlusEquals(totalUpdate2); cerr << "old weights: " << weights << endl; cerr << "new weights: " << weightsUpdate2 << endl << endl; newModelScoreDiff.clear(); for (int i = 0; i < numberOfConstraints; ++i) { newModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weightsUpdate2)); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "new model score diff: " << newModelScoreDiff[i] << ", loss: " << losses[i] << endl; } } BOOST_FIXTURE_TEST_CASE(test_hildreth_4, MockProducers) { // Feasible example with 8 constraints cerr << "\n>>>>>Hildreth test, without slack and with 0.01 slack" << endl << endl; vector< ScoreComponentCollection> featureValueDiffs; vector< float> lossMinusModelScoreDiff; // initial weights float w[] = { 1, 1, 0.638672, 1, 0 }; vector vec(w,w+5); ScoreComponentCollection weights; weights.PlusEquals(&multi, vec); int numberOfConstraints = 8; // feature value differences (to oracle) // NOTE: these feature values are only approximations ScoreComponentCollection s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21; float arr1[] = { 0, 0, -2.0672, 0, 0 }; float arr2[] = { 0, 0, 0, 0, 0 }; float arr3[] = { 0, 0, -2.08436, 1.38629, 0 }; float arr4[] = { 0, 0, -0.0171661, 1.38629, 0 }; // float arr5[] = { 0, 0, 4.4283, 0, 0 }; // float arr6[] = { 0, 0, 3.84829, 1.38629, 0 }; // float arr7[] = { 0, 0, 6.83689, 0, 0 }; float arr8[] = { 0, 0, 0, 0, 0 }; float arr9[] = { 0, 0, -2.0672, 0, 0 }; // float arr10[] = { 0, 0, -0.0171661, 1.38629, 0 }; // float arr11[] = { 0, 0, -2.08436, 1.38629, 0 }; // float arr12[] = { 0, 0, 4.4283, 0, 0 }; // float arr13[] = { 3, 0, 2.41089, 0, 0 }; // float arr14[] = { 3, 0, 2.32709, 0, 0 }; float arr15[] = { 0, 0, -2.0672, 0, 0 }; float arr16[] = { 0, 0, -2.08436, 1.38629, 0 }; // float arr17[] = { 0, 0, 4.4283, 0, 0 }; // float arr18[] = { 0, 0, 3.84829, 1.38629, 0 }; // float arr19[] = { 0, 0, -0.0171661, 1.38629, 0 }; // float arr20[] = { 0, 0, 0, 0, 0 }; // float arr21[] = { 0, 0, 6.83689, 0, 0 }; vector losses; losses.push_back(2.73485); losses.push_back(0); losses.push_back(3.64118); losses.push_back(1.47347); // losses.push_back(3.64118); // losses.push_back(4.16278); // losses.push_back(3.13952); losses.push_back(0); losses.push_back(2.73485); // losses.push_back(1.47347); // losses.push_back(3.64118); // losses.push_back(3.64118); // losses.push_back(2.51662); // losses.push_back(2.73485); losses.push_back(2.73485); losses.push_back(3.64118); // losses.push_back(3.64118); // losses.push_back(4.16278); // losses.push_back(1.47347); // losses.push_back(0); // losses.push_back(3.13952); vector vec1(arr1,arr1+5); vector vec2(arr2,arr2+5); vector vec3(arr3,arr3+5); vector vec4(arr4,arr4+5); // vector vec5(arr5,arr5+5); // vector vec6(arr6,arr6+5); // vector vec7(arr7,arr7+5); vector vec8(arr8,arr8+5); vector vec9(arr9,arr9+5); // vector vec10(arr10,arr10+5); // vector vec11(arr11,arr11+5); // vector vec12(arr12,arr12+5); // vector vec13(arr13,arr13+5); // vector vec14(arr14,arr14+5); vector vec15(arr15,arr15+5); vector vec16(arr16,arr16+5); // vector vec17(arr17,arr17+5); // vector vec18(arr18,arr18+5); // vector vec19(arr19,arr19+5); // vector vec20(arr20,arr20+5); // vector vec21(arr21,arr21+5); s1.PlusEquals(&multi,vec1); s2.PlusEquals(&multi,vec2); s3.PlusEquals(&multi,vec3); s4.PlusEquals(&multi,vec4); // s5.PlusEquals(&multi,vec5); // s6.PlusEquals(&multi,vec6); // s7.PlusEquals(&multi,vec7); s8.PlusEquals(&multi,vec8); s9.PlusEquals(&multi,vec9); // s10.PlusEquals(&multi,vec10); // s11.PlusEquals(&multi,vec11); // s12.PlusEquals(&multi,vec12); // s13.PlusEquals(&multi,vec13); // s14.PlusEquals(&multi,vec14); s15.PlusEquals(&multi,vec15); s16.PlusEquals(&multi,vec16); // s17.PlusEquals(&multi,vec17); // s18.PlusEquals(&multi,vec18); // s19.PlusEquals(&multi,vec19); // s20.PlusEquals(&multi,vec20); // s21.PlusEquals(&multi,vec21); featureValueDiffs.push_back(s1); featureValueDiffs.push_back(s2); featureValueDiffs.push_back(s3); featureValueDiffs.push_back(s4); // featureValueDiffs.push_back(s5); // featureValueDiffs.push_back(s6); // featureValueDiffs.push_back(s7); featureValueDiffs.push_back(s8); featureValueDiffs.push_back(s9); // featureValueDiffs.push_back(s10); // featureValueDiffs.push_back(s11); // featureValueDiffs.push_back(s12); // featureValueDiffs.push_back(s13); // featureValueDiffs.push_back(s14); featureValueDiffs.push_back(s15); featureValueDiffs.push_back(s16); // featureValueDiffs.push_back(s17); // featureValueDiffs.push_back(s18); // featureValueDiffs.push_back(s19); // featureValueDiffs.push_back(s20); // featureValueDiffs.push_back(s21); vector oldModelScoreDiff; for (int i = 0; i < numberOfConstraints; ++i) { oldModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weights)); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "old model score diff: " << oldModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (oldModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; } for (int i = 0; i < numberOfConstraints; ++i) { lossMinusModelScoreDiff.push_back(losses[i] - oldModelScoreDiff[i]); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "A: " << featureValueDiffs[i] << ", b: " << lossMinusModelScoreDiff[i] << endl; } vector< float> alphas1 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff); vector< float> alphas2 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff, 0.01); cerr << "\nalphas without slack:" << endl; for (size_t i = 0; i < alphas1.size(); ++i) { cerr << "alpha " << i << ": " << alphas1[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs1(featureValueDiffs); FVector totalUpdate1 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs1.size(); ++k) { featureValueDiffs1[k].MultiplyEquals(alphas1[k]); cerr << k << ": " << featureValueDiffs1[k].GetScoresVector() << endl; FVector update = featureValueDiffs1[k].GetScoresVector(); totalUpdate1 += update; } cerr << endl; cerr << "total update: " << totalUpdate1 << endl << endl; ScoreComponentCollection weightsUpdate1(weights); weightsUpdate1.PlusEquals(totalUpdate1); cerr << "old weights: " << weights << endl; cerr << "new weights: " << weightsUpdate1 << endl << endl; vector newModelScoreDiff; for (int i = 0; i < numberOfConstraints; ++i) { newModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weightsUpdate1)); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "new model score diff: " << newModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (newModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; } cerr << "\n\nalphas with slack 0.01:" << endl; for (size_t i = 0; i < alphas2.size(); ++i) { cerr << "alpha " << i << ": " << alphas2[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs2(featureValueDiffs); FVector totalUpdate2 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs2.size(); ++k) { featureValueDiffs2[k].MultiplyEquals(alphas2[k]); cerr << k << ": " << featureValueDiffs2[k].GetScoresVector() << endl; FVector update = featureValueDiffs2[k].GetScoresVector(); totalUpdate2 += update; } cerr << endl; cerr << "total update: " << totalUpdate2 << endl << endl; ScoreComponentCollection weightsUpdate2(weights); weightsUpdate2.PlusEquals(totalUpdate2); cerr << "old weights: " << weights << endl; cerr << "new weights: " << weightsUpdate2 << endl << endl; newModelScoreDiff.clear(); for (int i = 0; i < numberOfConstraints; ++i) { newModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weightsUpdate2)); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "new model score diff: " << newModelScoreDiff[i] << ", loss: " << losses[i] << endl; } } BOOST_FIXTURE_TEST_CASE(test_hildreth_5, MockProducers) { // Unfeasible example with 2 constraints cerr << "\n>>>>>Hildreth test, without slack and with 0.01 slack" << endl << endl; vector< ScoreComponentCollection> featureValueDiffs; vector< float> lossMinusModelScoreDiff; // initial weights float w[] = { 1, 1, 0.638672, 1, 0 }; vector vec(w,w+5); ScoreComponentCollection weights; weights.PlusEquals(&multi, vec); int numberOfConstraints = 2; // feature value differences (to oracle) // NOTE: these feature values are only approximations ScoreComponentCollection s1, s17; float arr1[] = { 0, 0, -2.0672, 0, 0 }; float arr17[] = { 0, 0, 4.4283, 0, 0 }; vector losses; losses.push_back(2.73485); losses.push_back(3.64118); vector vec1(arr1,arr1+5); vector vec17(arr17,arr17+5); s1.PlusEquals(&multi,vec1); s17.PlusEquals(&multi,vec17); featureValueDiffs.push_back(s1); featureValueDiffs.push_back(s17); vector oldModelScoreDiff; for (int i = 0; i < numberOfConstraints; ++i) { oldModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weights)); } float sumOfOldError = 0; for (int i = 0; i < numberOfConstraints; ++i) { cerr << "old model score diff: " << oldModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (oldModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; sumOfOldError += (losses[i] - oldModelScoreDiff[i]); } cerr << "sum of old error: " << sumOfOldError << endl; for (int i = 0; i < numberOfConstraints; ++i) { lossMinusModelScoreDiff.push_back(losses[i] - oldModelScoreDiff[i]); } for (int i = 0; i < numberOfConstraints; ++i) { cerr << "A: " << featureValueDiffs[i] << ", b: " << lossMinusModelScoreDiff[i] << endl; } vector< float> alphas1 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff); vector< float> alphas2 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff, 0.01); vector< float> alphas3 = Hildreth::optimise(featureValueDiffs, lossMinusModelScoreDiff, 0.1); cerr << "\nalphas without slack:" << endl; for (size_t i = 0; i < alphas1.size(); ++i) { cerr << "alpha " << i << ": " << alphas1[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs1(featureValueDiffs); FVector totalUpdate1 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs1.size(); ++k) { featureValueDiffs1[k].MultiplyEquals(alphas1[k]); cerr << k << ": " << featureValueDiffs1[k].GetScoresVector() << endl; FVector update = featureValueDiffs1[k].GetScoresVector(); totalUpdate1 += update; } cerr << endl; cerr << "total update: " << totalUpdate1 << endl << endl; ScoreComponentCollection weightsUpdate1(weights); weightsUpdate1.PlusEquals(totalUpdate1); cerr << "old weights: " << weights << endl; cerr << "new weights: " << weightsUpdate1 << endl << endl; vector newModelScoreDiff; for (int i = 0; i < numberOfConstraints; ++i) { newModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weightsUpdate1)); } float sumOfNewError = 0; for (int i = 0; i < numberOfConstraints; ++i) { cerr << "new model score diff: " << newModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (newModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; sumOfNewError += (losses[i] - newModelScoreDiff[i]); } cerr << "sum of new error: " << sumOfNewError << endl; cerr << "\n\nalphas with slack 0.01:" << endl; for (size_t i = 0; i < alphas2.size(); ++i) { cerr << "alpha " << i << ": " << alphas2[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs2(featureValueDiffs); FVector totalUpdate2 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs2.size(); ++k) { featureValueDiffs2[k].MultiplyEquals(alphas2[k]); cerr << k << ": " << featureValueDiffs2[k].GetScoresVector() << endl; FVector update = featureValueDiffs2[k].GetScoresVector(); totalUpdate2 += update; } cerr << endl; cerr << "total update: " << totalUpdate2 << endl << endl; ScoreComponentCollection weightsUpdate2(weights); weightsUpdate2.PlusEquals(totalUpdate2); cerr << "old weights: " << weights << endl; cerr << "new weights: " << weightsUpdate2 << endl << endl; newModelScoreDiff.clear(); for (int i = 0; i < numberOfConstraints; ++i) { newModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weightsUpdate2)); } sumOfNewError = 0; for (int i = 0; i < numberOfConstraints; ++i) { cerr << "new model score diff: " << newModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (newModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; sumOfNewError += (losses[i] - newModelScoreDiff[i]); } cerr << "sum of new error: " << sumOfNewError << endl; cerr << "\n\nalphas with slack 0.1:" << endl; for (size_t i = 0; i < alphas3.size(); ++i) { cerr << "alpha " << i << ": " << alphas3[i] << endl; } cerr << endl; cerr << "partial updates:" << endl; vector< ScoreComponentCollection> featureValueDiffs3(featureValueDiffs); FVector totalUpdate3 = ScoreComponentCollection::CreateFVector(); for (size_t k = 0; k < featureValueDiffs3.size(); ++k) { featureValueDiffs3[k].MultiplyEquals(alphas3[k]); cerr << k << ": " << featureValueDiffs3[k].GetScoresVector() << endl; FVector update = featureValueDiffs3[k].GetScoresVector(); totalUpdate3 += update; } cerr << endl; cerr << "total update: " << totalUpdate3 << endl << endl; ScoreComponentCollection weightsUpdate3(weights); weightsUpdate3.PlusEquals(totalUpdate3); cerr << "old weights: " << weights << endl; cerr << "new weights: " << weightsUpdate3 << endl << endl; newModelScoreDiff.clear(); for (int i = 0; i < numberOfConstraints; ++i) { newModelScoreDiff.push_back(featureValueDiffs[i].InnerProduct(weightsUpdate3)); } sumOfNewError = 0; for (int i = 0; i < numberOfConstraints; ++i) { cerr << "new model score diff: " << newModelScoreDiff[i] << ", loss: " << losses[i] << "\t" << (newModelScoreDiff[i] >= losses[i] ? 1 : 0) << endl; sumOfNewError += (losses[i] - newModelScoreDiff[i]); } cerr << "sum of new error: " << sumOfNewError << endl; } BOOST_AUTO_TEST_SUITE_END() }