Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suche nach Refinements auf der Basis von Bins #252

Closed
mrapp-ke opened this issue Sep 29, 2020 · 2 comments · Fixed by #254
Closed

Suche nach Refinements auf der Basis von Bins #252

mrapp-ke opened this issue Sep 29, 2020 · 2 comments · Fixed by #254
Labels
approximate conditions Affects the approximate condition finding algorithm enhancement New feature or request

Comments

@mrapp-ke
Copy link
Owner

mrapp-ke commented Sep 29, 2020

Als Teil von #226 muss eine Klasse implementiert werden, die nach dem besten Refinement einer Regel (für ein bestimmtes Feature) auf der Basis von Bins (der Datenstruktur aus #243) sucht.

Diese neue Klasse ApproximateRuleRefinementImpl (zu implementieren in boomer/common/cpp/rule_refinement.h/cpp) muss das Interface IRuleRefinement implementieren. Darauf ergibt sich folgendes Klassendiagram:

rule-refinement

rule-refinement.zip

Wie im Klassendiagram zu sehen besitzt die neue Klasse ApproximateRuleRefinementImpl folgende Klassenattributte, die als Konstruktorargument übergeben werden:

  • statistics_: Ein Pointer auf ein Objekt vom Typ AbstractStatistics, das zuvor mittels eines IHistogramBuilder erstellt wurde.
  • binArray_: Ein Pointer auf ein struct vom Typ BinArray. Dieses struct existiert aktuell noch nicht.
  • featureIndex_: Der Index des Features für das nach Refinements gesucht werden soll

Aktuell fehlt das struct BinArray noch. Es könnte folgendermaßen aussehen und sollte zu tuples.h hinzugefügt werden:

struct BinArray {
    uint32 numBins;
    Bin* bins;
};

Innerhalb der findRefinement-Methode muss über die Bins iteriert werden um mögliche Bedingungen zu evaluieren und letztendlich die beste Bedingung in Form eines structs vom Typ Refinement zurückzugeben. Als Pseudocode könnte das etwa folgendermaßen aussehen:

// Gesamtanzahl an verfügbaren Bins
numBins = binArray_->numBins;

// Lokale Variable um sich das beste Refinement zu merken
Refinement refinement;
// TODO Refinement initialisieren. Die Felder "indexedArray" und "indexedArrayWrapper" werden in Zukunft verschwinden, deshalb einfach auf NULL setzen

// Lokale Variable um sich den Head zu merken, der zum aktuell besten Refinement gehört
bestHead = currentHead;

// Erzeugt ein Objekt vom Typ `IStatisticsSubset`, das später an die `findHead`-Methode übergeben wird
// Indem man das Objekt in einen unique_ptr steckt, wird es automatisch deallokiert wenn diese Methode verlassen wird
std::unique_ptr<IStatisticsSubset> statisticsSubsetPtr;
statisticsSubsetPtr.reset(statistics_->createSubset(numLabelIndices, labelIndices));

// TODO Ersten Bin mit numExamples > 0 finden und `statisticsSubsetPtr.get()->addToSubset(r, 1)` aufrufen
r = // Index des gefundenen Bins
previousR = r;
previousValue = // maxValue des gefundenen Bins
numCoveredExamples = // numExamples des gefundenen Bins

// Über die verbleibenden Bins iterieren
for (r from r + 1 to numBins) {
    numExamples = // numExamples des aktuellen Bins

    if (numExamples > 0) { // Leere Bins ignorieren
        currentValue = // minValue des aktuellen Bins

        // Mögliche Bedingung mit Vergleichsoperator <= evaluieren
        currentHead = headRefinement->findHead(bestHead, refinement.head, labelIndices, statisticsSubsetPtr.get(), false, false)

        if (currentHead != NULL) {
            bestHead = currentHead
            refinement.comparator = LEQ
            refinement.threshold = (previousValue + currentValue) / 2.0
            refinement.start = 0  // Der Index des ersten Bin dessen Beispiele von der Bedingung abgedeckt werden
            refinement.end = r    // Der Index des letzten Bins dessen Beispiele abgedeckt werden (exklusiv)
            refinement.previous = previousR  // Der Index des letzten Bins mit numExamples > 0
            refinement.coveredWeights = numCoveredExamples  // Die Anzahl der Beispiele, die von der Bedingung abgedeckt werden
            refinement.covered = true
            // TODO Verbleibende Felder der Variable `refinement` aktualisieren
        }
        
        // Mögliche Bedinung mit Vergleichsoperator > evaluieren
        currentHead = headRefinement->findHead(bestHead, refinement.head, labelIndices, statisticsSubsetPtr.get(), true, false)

        if (currentHead != NULL) {
            bestHead = currentHead
            refinement.comparator = GR
            refinement.threshold = (previousValue + currentValue) / 2.0
            refinement.start = 0
            refinement.end = r
            refinement.previous = previousR
            refinement.coveredWeights = numCoveredExamples
            refinement.covered = false  // Zeigt an, dass die Bins in [refinement.start, refinement.end) NICHT abgedeckt werden, sondern alle verbleibenden Bins
            // TODO Verbleibende Felder der Variable `refinement` aktualisieren
        }

        previousValue = // maxValue des aktuellen Bins
        previousR = r
        numCoveredExamples += numExamples
        statisticsSubsetPtr.get()->addToSubset(r, 1)  // Markiert den aktuellen Bin als abgedeckt, jeder Bin hat ein Gewicht von 1
    }
}

return refinement
@mrapp-ke mrapp-ke added enhancement New feature or request approximate conditions Affects the approximate condition finding algorithm labels Sep 29, 2020
@LukasEberle
Copy link

Hallo,
ich weiß noch, dass es einen Grund gab einmal mit LEQ und einmal mit GR als Vergleichsoperator zu arbeiten. Aber ich bin mir nicht mehr sicher was das war. Kannst du mir das nochmal erklären?

@michael-rapp
Copy link
Collaborator

michael-rapp commented Oct 2, 2020

ich weiß noch, dass es einen Grund gab einmal mit LEQ und einmal mit GR als Vergleichsoperator zu arbeiten. Aber ich bin mir nicht mehr sicher was das war. Kannst du mir das nochmal erklären?

Stell dir vor du hast einige Beispiele (oder auch Bins), die nach einem bestimmten Feature sortiert sind. Wenn man jetzt eine neue Bedingung für dieses Feature finden will, dann geht man die Beispiele/Bins in der sortierten Reihenfolge durch und jeder Threshold zwischen zwei benachbarten Beispielen/Bins kommt im Frage um entweder eine Condition mit dem Operator <= (LEQ) oder > (GR) zu bilden. Der Grund warum man für jeden Threshold beide Fälle testet ist, dass eine Condition mit <= alle vorausgegangenen Beispiele (mit kleinerem Featurewert) abdeckt, während eine Condition mit > alle anderen Beispiele abdeckt. Würde man nur einen der beiden Fälle berücksichtigen, würde man die Hälfte der Möglichkeiten einfach ignorieren. Statt <= und > könnte man auch < und >= verwendet werden. Wichtig ist nur, dass sich die abgedeckten Bereiche nicht überlappen und die Vereinigung der Bereiche alle Beispiele umfasst.

@michael-rapp michael-rapp linked a pull request Oct 2, 2020 that will close this issue
@michael-rapp michael-rapp linked a pull request Oct 12, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approximate conditions Affects the approximate condition finding algorithm enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants