00001 #ifndef ActiveLearnEngine_h
00002 #define ActiveLearnEngine_h
00003
00004 #include "Basis/ILog.h"
00005 #include "Core/Trec/ThreadSet.h"
00006 #include "Core/Table/SimilarityTableSet.h"
00007 #include "Util/Database.h"
00008
00009 #include "Basis/Timer.h"
00010
00011 namespace Impala {
00012
00013 namespace Samples {
00014
00015
00016
00017
00018 typedef Core::Table::TableTem<Core::Column::ColumnTem<Int32>, Core::Column::ColumnTem<double> > ShotWithWeight;
00019
00020 class ActiveLearnEngine
00021 {
00022 public:
00023 typedef Core::Trec::Thread Thread;
00024 typedef Core::Trec::ThreadSet ThreadSet;
00025 typedef Core::Trec::ShotResult ShotResult;
00026 typedef std::list<ShotResult> ShotResultList;
00027
00028 ActiveLearnEngine(ThreadSet *set, Thread *positiveAnnotations,
00029 Thread *negativeAnnotations)
00030 {
00031 mThreadSet = set;
00032 mPositive = positiveAnnotations;
00033 mNegative = negativeAnnotations;
00034 mAnnotations = new Core::Table::AnnotationTable();
00035 mTimer = new Timer();
00036 mTimer->Start();
00037 srand( time(NULL) );
00038 mInfoSent = false;
00039 mActiveID = "start";
00040 mAutoNegatives = true;
00041 mAutoNegativesNumber = 50;
00042 mErrCount = 0;
00043
00044 mALDatabase = new Util::Database("activelearning");
00045 mALDatabase->SetOverride(true);
00046 }
00047
00048 void
00049 PrepareNewID()
00050 {
00051 mActiveID = "al" + mTimer->SplitTimeStr();
00052 mInfoSent = false;
00053 }
00054
00055 std::string
00056 GetID()
00057 {
00058 return mActiveID;
00059 }
00060
00061 bool
00062 RequestSubmitted()
00063 {
00064 return mInfoSent;
00065 }
00066
00067 int
00068 GetErrCount()
00069 {
00070 return mErrCount;
00071 }
00072
00073 void
00074 PrepRequest()
00075 {
00076 if (mInfoSent)
00077 return;
00078
00079 PrepareNewID();
00080
00081 ILOG_DEBUG("SubmitRequest(), ID for submit = " << GetID());
00082
00083 mAnnotations->SetEmpty();
00084
00085 }
00086
00087 void
00088 AddAnnotations()
00089 {
00090 for (int i=0; i<mPositive->GetLength(); i++)
00091 {
00092 int shot = mPositive->GetShot(i);
00093 int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shot);
00094 Quid fquid = mThreadSet->GetKeyframes()->GetQuidFrame(keyframe);
00095
00096 mAnnotations->AddPositive(fquid);
00097 }
00098
00099 for (int i=0; i<mNegative->GetLength(); i++)
00100 {
00101 int shot = mNegative->GetShot(i);
00102 int keyframe = mThreadSet->GetKeyframes()->GetShotRKF(shot);
00103 Quid fquid = mThreadSet->GetKeyframes()->GetQuidFrame(keyframe);
00104
00105 mAnnotations->AddNegative(fquid);
00106 }
00107 ILOG_DEBUG("Added annotations, table now with " << mAnnotations->GetNrPositive() << " positive shots and " << mAnnotations->GetNrNegative() << " negative shots.");
00108 }
00109
00110 void
00111 AddPositive(Quid q)
00112 {
00113
00114 mAnnotations->AddPositive(q);
00115 }
00116
00117 void
00118 AddNegative(Quid q)
00119 {
00120
00121 mAnnotations->AddNegative(q);
00122 }
00123
00124 void
00125 AddRandomNegatives(int number)
00126 {
00127 ILOG_DEBUG("adding " << number << " random examples as negative...");
00128 for (int i=0; i<number; i++)
00129 {
00130 double rnd = ( (1.0 * rand()) / RAND_MAX);
00131 int randomkeyframe = rnd * (mThreadSet->GetKeyframes()->GetNrKeyframes()-1);
00132 Quid randomkeyquid = mThreadSet->GetKeyframes()->GetQuidFrame(randomkeyframe);
00133 AddNegative(randomkeyquid);
00134 }
00135 }
00136
00137 void
00138 SubmitRequest()
00139 {
00140 if (mInfoSent)
00141 return;
00142
00143 if (mAnnotations->GetNrPositive() == 0)
00144 {
00145 ILOG_WARN("No positive examples, ALE request not submitted.");
00146 return;
00147 }
00148
00149 if (mAnnotations->GetNrNegative() == 0)
00150 {
00151 if (mAutoNegatives) {
00152 ILOG_INFO("No negative examples given, selecting random subset...");
00153 AddRandomNegatives(mAutoNegativesNumber);
00154 } else {
00155 ILOG_WARN("No negative examples and random selection disabled, ALE request not submitted.");
00156 return;
00157 }
00158 }
00159
00160 ILOG_DEBUG("Using table with " << mAnnotations->GetNrPositive() << " positive shots and " << mAnnotations->GetNrNegative() << " negative shots.");
00161
00162 String dir = "Annotations/" + QuidClassToString(QUID_CLASS_FRAME) + "/" + "conceptsActiveLearn.txt";
00163 String filename = mALDatabase->GetFilePath(dir, GetID() + ".tab", true, false);
00164
00165 ILOG_DEBUG("Writing to " << filename << "...");
00166
00167 Core::Table::Write(mAnnotations, filename, mALDatabase, true);
00168
00169 ILOG_DEBUG("Signalling active learning engine...");
00170
00171 String startlearnfile = mALDatabase->GetFilePath(dir, "startlearner.txt", true, false);
00172
00173 Util::IOBuffer *slf = mALDatabase->GetIOBuffer(
00174 startlearnfile, false, false, "tmp");
00175 if (!slf)
00176 {
00177 ILOG_WARN("No startlearnfile, ALE request not submitted.");
00178 return;
00179 }
00180 slf->IOBuffer::Puts(GetID());
00181 delete slf;
00182
00183 ILOG_DEBUG("Signal sent.");
00184 mInfoSent = true;
00185 }
00186
00187 bool
00188 HasResults()
00189 {
00190 ILOG_DEBUG("Locating results...");
00191
00192 String dir =
00193 "SimilarityIndex/conceptsActiveLearn.txt/activelearn/activelearn";
00194
00195 String path = mALDatabase->GetFilePath(dir, "names.txt", false, false);
00196 Core::Table::SimilarityTableSet *conceptSet =
00197 Core::Table::SimilarityTableSet::MakeFromFile(path, mALDatabase);
00198
00199 Core::Table::SimilarityTableSet::RankTableType* rank = conceptSet->GetRankTable(GetID());
00200
00201
00202
00203 if (!rank)
00204 {
00205 ILOG_DEBUG("ID " << GetID() << " not (yet) found.");
00206 delete conceptSet;
00207 return false;
00208 }
00209 delete conceptSet;
00210 ILOG_DEBUG("ID " << GetID() << " found!");
00211 return true;
00212 }
00213
00214 ShotResultList
00215 RetrieveResults()
00216 {
00217 ILOG_DEBUG("Retrieving results...");
00218
00219 String dir =
00220 "SimilarityIndex/conceptsActiveLearn.txt/activelearn/activelearn";
00221
00222 String path = mALDatabase->GetFilePath(dir, "names.txt", false, false);
00223
00224 Core::Table::SimilarityTableSet *conceptSet =
00225 Core::Table::SimilarityTableSet::MakeFromFile(path, mALDatabase);
00226
00227 Core::Table::SimilarityTableSet::RankTableType* rank = conceptSet->GetRankTable(GetID());
00228
00229 ShotResultList out;
00230
00231 if (!rank)
00232 {
00233 ILOG_DEBUG("Could not find ID, no data present. :'(");
00234 delete conceptSet;
00235 return out;
00236 }
00237
00238 mInfoSent = false;
00239
00240 int results = 5000;
00241
00242 ILOG_DEBUG("Concept loaded, converting to list...");
00243
00244
00245 std::map<int,bool> noduplicates;
00246 int rrank = 1;
00247 mErrCount = 0;
00248 int dropcount = 0;
00249 for (int i=0; i<results; i++)
00250 {
00251
00252 Quid q = rank->Get1(i);
00253 if (QuidSet(q) == 23) {
00254 dropcount++;
00255
00256 mErrCount++;
00257 continue;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 int keyframe = mThreadSet->GetKeyframes()->GetFrameId(q);
00275
00276 if (keyframe < 0) {
00277 ILOG_WARN("erroneous result " << QuidObj(q) << " for this set, dropping.");
00278 mErrCount++;
00279 continue;
00280 }
00281
00282 int shot = mThreadSet->GetKeyframes()->GetShotId(keyframe);
00283
00284 if (shot > -1 && noduplicates.find(shot) == noduplicates.end())
00285 {
00286 ShotResult r;
00287 r.shotid = shot;
00288 r.rank = rrank++;
00289 r.score = conceptSet->GetSimTable(GetID())->Get1(conceptSet->FindQuid(q));
00290
00291
00292 noduplicates[shot] = true;
00293 out.push_back(r);
00294 }
00295 }
00296
00297 if (dropcount > 0)
00298 ILOG_DEBUG("there were " << dropcount << " silent drops from results");
00299 if (mErrCount > 0)
00300 ILOG_DEBUG("there were " << mErrCount << " errors while receiving results");
00301
00302 delete conceptSet;
00303
00304 return out;
00305 }
00306
00307 bool
00308 Ready()
00309 {
00310
00311
00312 return true;
00313 }
00314
00315 private:
00316
00317
00318 ThreadSet *mThreadSet;
00319 Thread *mPositive, *mNegative;
00320 std::string mActiveID;
00321 Core::Table::AnnotationTable *mAnnotations;
00322 Util::Database *mALDatabase;
00323 bool mInfoSent;
00324
00325 bool mAutoNegatives;
00326 int mAutoNegativesNumber;
00327 int mErrCount;
00328
00329 Timer* mTimer;
00330 ILOG_VAR_DEC;
00331
00332 };
00333 ILOG_VAR_INIT(ActiveLearnEngine, Core.Trec);
00334
00335
00336 }
00337
00338 }
00339
00340
00341 #endif