def test_knn(self):
     print 'knn_test'
     knn = KNNClassifier(k_neighbors=3, metric='cityblock')
     knn.estimate(self.__train_samples, self.__train_labels)
     result_labels = knn.classify(self.__test_samples)
     result_labels_ref = np.array([['C', 'C', 'C', 'A', 'C']]).T
     self.assertEqual(result_labels_ref.shape, result_labels.shape)
     self.assertEqual(result_labels_ref.dtype, result_labels.dtype)
     np.testing.assert_equal(result_labels, result_labels_ref)
示例#2
0
def test_data_dict_to_points_and_labels_returns_expected_values_and_labels():
    given = {
        (1, "Jogging"): ((70, 12), ),
        (1, "Downstairs"): (
            (85, 12),
            (81, 12),
            (70, 12),
        ),
        (2, "Jogging"): (),
        (3, "Jogging"): ((150, 30), )
    }
    points = (
        (70, 12),
        (85, 12),
        (81, 12),
        (70, 12),
        (150, 30),
    )
    labels = (
        "Jogging",
        "Downstairs",
        "Downstairs",
        "Downstairs",
        "Jogging",
    )
    expected = points, labels
    result = KNNClassifier.data_dict_to_points_and_labels(given)
    assert result == expected
示例#3
0
def test_sort_distances_and_labels_returns_expected():
    distances = (110.1, 5.1, 5.2, 17, 10.1, 10.2)
    labels = ('a', 'b', 'c', 'd', 'e', 'f')
    sorted_distances = (5.1, 5.2, 10.1, 10.2, 17, 110.1)
    sorted_labels = ('b', 'c', 'e', 'f', 'd', 'a')
    expected = (sorted_distances, sorted_labels)
    result = KNNClassifier.sort_distances_and_labels(distances, labels)
    assert result == expected
示例#4
0
    def evaluate(self, images, labels):
        print('Evaluate dataset on pre-trained model')

        pairData, pairLabels = None, None
        outputs = []
        outputs_probs = []
        for illum in config.illuminantTypes:
            for desc in self.descriptors:
                clfPath = config.classification_folder + 'model_' + illum + '_' + desc.lower(
                ) + '.pkl'
                if os.path.isfile(clfPath):
                    clf = KNNClassifier.load(clfPath)
                    testData, testLabels, _ = self.getTrainingData(images,
                                                                   desc,
                                                                   illum=illum)
                    if len(testData) > 0:
                        pairData, pairLabels = testData, testLabels
                        prediction = clf.predict(
                            testData, False) * config.descriptors_weights[desc]
                        outputs.append(prediction)
                        prediction = clf.predict(
                            testData, True) * config.descriptors_weights[desc]
                        outputs_probs.append(prediction)

        if pairData is not None:
            output = np.zeros(len(pairData))
            output_prob = np.zeros(len(pairData))

            for i in range(len(outputs)):
                predictions = outputs[i]
                output += predictions
                predictions_prob = outputs_probs[i]
                for j in range(len(predictions)):
                    output_prob[j] += predictions_prob[j][1]

            # If voting is majority, classify as fake
            counter = 0
            misclassified = 0

            scipy.io.savemat('classification_output.mat',
                             dict(labels=pairLabels, scores=output_prob))

            totalModels = len(outputs)
            for val in np.nditer(output):
                if val > totalModels / 2:
                    if pairLabels[counter] != 1:
                        misclassified += 1
                else:
                    if pairLabels[counter] != 0:
                        misclassified += 1
                counter += 1

            print('Number of classifiers: ' + str(totalModels))
            totalSamples = len(pairData)
            print('Misclassified: ' + str(misclassified) + '/' +
                  str(totalSamples))
            accuracy = (totalSamples - misclassified) / totalSamples
            print('Accuracy: ' + str(accuracy))
示例#5
0
 def test_knn(self):
     print 'knn_test'
     knn = KNNClassifier(k_neighbors=1, metric='cityblock')
     knn.estimate(self.__train_samples, self.__train_labels)
     result_labels = knn.classify(self.__test_samples)
     result_labels_ref = np.array([['A', 'A', 'C', 'A', 'C' ]]).T
     self.assertEqual(result_labels_ref.shape, result_labels.shape)
     self.assertEqual(result_labels_ref.dtype, result_labels.dtype)
     np.testing.assert_equal(result_labels, result_labels_ref)
     
     knn = KNNClassifier(k_neighbors=3, metric='cityblock')
     knn.estimate(self.__train_samples, self.__train_labels)
     result_labels = knn.classify(self.__test_samples)
     result_labels_ref = np.array([['C', 'C', 'C', 'A', 'C' ]]).T
     np.testing.assert_equal(result_labels, result_labels_ref)
    def fit(self):
        # initializing the classifier
        self.__classifier = KNNClassifier(self.__nn, self.__metric)

        # relative bow-matrices by category (weighted)
        rel_category_bow_dict = {
            cat: self.__wght(self.category_bow_dict[cat])
            for cat in self.category_bow_dict
        }

        # initializing the cross-validator (5 folds as in main)
        n_folds = 4
        self.__cross_validator = CrossValidation(
            category_bow_dict=rel_category_bow_dict, n_folds=n_folds)
示例#7
0
 def _test_ocr(self, train_file, test_file):
     # get data from images
     ground_truth = test_file.ground.classes
     test_file.remove_ground()
     # create OCR
     segmenter = ContourSegmenter(blur_y=5, blur_x=5)
     extractor = SimpleFeatureExtractor()
     classifier = KNNClassifier()
     ocr = OCR(segmenter, extractor, classifier)
     # train and test
     ocr.train(train_file)
     chars, classes, _ = ocr.ocr(test_file, show_steps=False)
     print chars
     print reconstruct_chars(ground_truth)
     self.assertEqual(chars, reconstruct_chars(ground_truth))
     self.assertEqual(list(classes), list(ground_truth))
示例#8
0
 def test_ocr_digits(self):
     # get data from images
     img1 = ImageFile('digits1')
     img2 = ImageFile('digits2')
     ground_truth = img2.ground.classes
     img2.remove_ground()
     # create OCR
     segmenter = ContourSegmenter()
     extractor = SimpleFeatureExtractor()
     classifier = KNNClassifier()
     ocr = OCR(segmenter, extractor, classifier)
     # train and test
     ocr.train(img1)
     chars, classes, _ = ocr.ocr(img2, show_steps=False)
     self.assertEqual(list(classes), list(ground_truth))
     self.assertEqual(chars, reconstruct_chars(ground_truth))
示例#9
0
def test_distances_to_points_returns_expected_values():
    point = (10, 10)
    points = (
        (-100.1, 10),
        (13, 14),
        (13, 6),
        (18, 25),
        (20, 10),
        (10, 20),
    )
    expected = (
        110.1,
        5,
        5,
        17,
        10,
        10,
    )
    result = KNNClassifier.distances_to_points(point, points)
    assert result == expected
示例#10
0
from unittest import TestCase

from classification import DocumentCollection, KNNClassifier, TextDocument

dir_train = "../data/20news-bydate/20news-bydate-train/"
dir_test = "../data/20news-bydate/20news-bydate-test/"

doc_collection_train = DocumentCollection.from_dir(dir_train)
classifier = KNNClassifier(n_neighbors=4)
classifier.fit(doc_collection_train)

train_docs = doc_collection_train.docid_to_doc.values()
vectorsOfTrainDocs = [(doc, doc_collection_train.tfidf(doc.token_counts))
                      for doc in train_docs]
test_doc = TextDocument.from_file(dir_test + 'alt.atheism/53068',
                                  'alt.atheism')
vecTestDoc = doc_collection_train.tfidf(test_doc.token_counts)
#2.1
dist = classifier.calculate_similarities(vecTestDoc, vectorsOfTrainDocs)
#2.2
ordered = classifier.order_nearest_to_farthest(dist)
#2.3
k_nearest_labels = classifier.labels_k_closest(ordered)
#2.4
label = classifier.choose_one(k_nearest_labels)


class ClassificationTest(TestCase):
    def test_01_calc_sims(self):
        sorted_dist = sorted(dist)
        self.assertEqual(sorted_dist[-1][1], 'alt.atheism')
示例#11
0
文件: main.py 项目: atddo/dokuanalyse
def aufgabe2():

    # Laden des Brown Corpus
    CorpusLoader.load()
    brown = CorpusLoader.brown_corpus()
    brown_categories = brown.categories()

    # In dieser Aufgabe sollen unbekannte Dokumente zu bekannten Kategorien
    # automatisch zugeordnet werden.
    #
    # Die dabei erforderlichen numerischen Berechnungen lassen sich im Vergleich
    # zu einer direkten Implementierung in Python erheblich einfacher mit
    # NumPy / SciPy durchfuehren. Die folgende Aufgabe soll Ihnen die Unterschiede
    # anhand eines kleinen Beispiels verdeutlichen.
    #
    # Geben Sie fuer jede Katgorie des Brown Corpus die durchschnittliche Anzahl
    # von Woertern pro Dokument aus. Bestimmen Sie auch die Standardabweichung.
    # Stellen Sie diese Statistik mit einem bar plot dar. Verwenden Sie dabei
    # auch Fehlerbalken (siehe visualization.hbar_plot)
    #
    # Berechnen Sie Mittelwert und Standardabweichung jeweils:
    #
    #  - nur mit Python Funktion
    #    hilfreiche Funktionen: sum, float, math.sqrt, math.pow
    #
    #  - mit NumPy
    #    hilfreiche Funktionen: np.array, np.mean, np.std
    #
    # http://docs.python.org/2/library/math.html
    # http://wiki.scipy.org/Tentative_NumPy_Tutorial
    # http://docs.scipy.org/doc/numpy/reference/generated/numpy.mean.html
    # http://docs.scipy.org/doc/numpy/reference/generated/numpy.std.html

    ####### +++++ Python Implementierung ++++
    print 'Python Implementierung'
    liste = []
    for i in brown_categories:
        a = len(brown.words(categories=i))/len(brown.fileids(categories=i))
        print i
        print a
        liste.append(a)


    mittelwert = sum(liste)/len(brown_categories)
    print 'Mittelwert:' + str(mittelwert)
    summe = 0
    for i in liste:
        summe +=math.pow(i-mittelwert,2)
    standard = math.sqrt(summe/len(brown_categories))

    #standard = math.sqrt(sum(list)/len(brown_categories))
    print 'Standardabweichung:'+str(standard)

    ####### +++++ Numpy Implementierung ++++
    print 'NumPy Implementierung'

    liste2 = np.array(liste)
    mittelwert2 = np.mean(liste2, axis=0)
    print 'Mittelwert:' + str(mittelwert2)
    standard2 = np.std(liste2, axis=0)
    print 'Standardabweichung:'+ str(standard2)

    hbar_plot(liste2, brown_categories, x_err=standard2, title="Words per document")

    # ********************************** ACHTUNG **************************************
    # Die nun zu implementierenden Funktionen spielen eine zentrale Rolle im weiteren
    # Verlauf des Fachprojekts. Achten Sie auf eine effiziente und 'saubere' Umsetzung.
    # Verwenden Sie geeignete Datenstrukturen und passende Python Funktionen.
    # Wenn Ihnen Ihr Ansatz sehr aufwaendig vorkommt, haben Sie vermutlich nicht die
    # passenden Datenstrukturen / Algorithmen / (highlevel) Python / NumPy Funktionen
    # verwendet. Fragen Sie in diesem Fall!
    #
    # Schauen Sie sich jetzt schon gruendlich die Klassen und deren Interfaces in den
    # mitgelieferten Modulen an. Wenn Sie Ihre Datenstrukturen von Anfang an dazu
    # passend waehlen, erleichtert dies deren spaetere Benutzung. Zusaetzlich bieten
    # diese Klassen bereits etwas Inspiration fuer Python-typisches Design, wie zum
    # Beispiel Duck-Typing.
    #
    # Zu einigen der vorgebenen Intefaces finden Sie Unit Tests in dem Paket 'test'.
    # Diese sind sehr hilfreich um zu ueberpruefen, ob ihre Implementierung zusammen
    # mit anderen mitgelieferten Implementierungen / Interfaces funktionieren wird.
    # Stellen Sie immer sicher, dass die Unit tests fuer die von Ihnen verwendeten
    # Funktionen erfolgreich sind.
    # Hinweis: Im Verlauf des Fachprojekts werden die Unit Tests nach und nach erfolg-
    # reich sein. Falls es sie zu Beginn stoert, wenn einzelne Unit Tests fehlschlagen
    # koennen Sie diese durch einen 'decorator' vor der Methodendefinition voruebergehend
    # abschalten: @unittest.skip('')
    # https://docs.python.org/2/library/unittest.html#skipping-tests-and-expected-failures
    # Denken Sie aber daran sie spaeter wieder zu aktivieren.
    #
    # Wenn etwas unklar ist, fragen Sie!
    # *********************************************************************************


    #
    # Klassifikation von Dokumenten
    #
    # Nachdem Sie sich nun mit der Struktur und den Eigenschaften des Brown
    # Corpus vertraut gemacht haben, soll er die Datengrundlage fuer die
    # Evaluierung von Algorithmen zur automatischen Klassifikation von
    # Dokumenten bilden.
    # In der Regel bestehen diese Algorithmen aus drei Schritten:
    #  - Vorverarbeitung
    #  - Merkmalsberechnung
    #  - Klassifikation
    #
    # Bei der Anwendung auf Dokumente (Texte) werden diese Schritte wie folgt
    # umgesetzt:
    #  - Vorverarbeitung: Filterung von stopwords und Abbildung von Woertern auf
    #                     Wortstaemme.
    #  - Merkmalsberechnung: Jedes Dokument wird numerisch durch einen Vektor
    #                        repraesentiert (--> NumPy), der moeglichst die
    #                        bzgl. der Klassifikation bedeutungsunterscheidenden
    #                        Informationen enthaehlt.
    #  - Klassifikation: Jedem Merkmalsvektor (Dokument) wird ein Klassenindex
    #                    (Kategorie) zugeordnet.
    #
    # Details finden Sie zum Beispiel in:
    # http://www5.informatik.uni-erlangen.de/fileadmin/Persons/NiemannHeinrich/klassifikation-von-mustern/m00-www.pdf (section 1.3)
    #
    # Eine sehr verbreitete Merkmalsrepraesentation fuer (textuelle) Dokumente sind
    # sogenannte Bag-of-Words.
    # Dabei wird jedes Dokument durch ein Histogram (Verteilung) ueber Wortfrequenzen
    # repraesentiert. Man betrachtet dazu das Vorkommen von 'typischen' Woertern, die
    # durch ein Vokabular gegeben sind.
    #
    # Bestimmen Sie ein Vokabular, also die typischen Woerter, fuer den Brown Corpus.
    # Berechnen Sie dazu die 500 haeufigsten Woerter (nach stemming und Filterung von
    # stopwords und Satzzeichen)

    normalized_words = WordListNormalizer().normalize_words(brown.words())[1]
    vocab = BagOfWords.most_freq_words(normalized_words, 500)
    


    # Berechnen Sie Bag-of-Words Repraesentationen fuer jedes Dokument des Brown Corpus.
    # Verwenden Sie absolute Frequenzen.
    # Speichern Sie die Bag-of-Word Repraesentationen fuer jede Kategorie in einem
    # 2-D NumPy Array. Speichern Sie den Bag-of-Words Vektor fuer jedes Dokument in
    # einer Zeile, so dass das Array (ndarray) folgende Dimension hat:
    #   |Dokument_kat| X |Vokabular|
    #
    # |Dokument_kat| entspricht der Anzahl Dokumente einer Kategorie.
    # |Vokabular| entspricht der Anzahl Woerter im Vokabular (hier 500).
    #
    # Eine einfache Zuordnung von Kategorie und Bag-of-Words Matrix ist durch ein
    # Dictionary moeglich.
    #
    # Implementieren Sie die Funktion BagOfWords.category_bow_dict im Modul features.

    bow_list = {}
    for cat in brown_categories:
        bow_list[cat] = [WordListNormalizer().normalize_words(brown.words(fileids=doc))[1] for doc in brown.fileids(categories=cat)]
    a = BagOfWords(vocab)

    print "Merkmalsvektoren erstellt"

    # Um einen Klassifikator statistisch zu evaluieren, benoetigt man eine Trainingsstichprobe
    # und eine Teststichprobe der Daten die klassifiziert werden sollen.
    # Die Trainingsstichprobe benoetigt man zum Erstellen oder Trainieren des Klassifikators.
    # Dabei werden in der Regel die Modellparameter des Klassifikators statistisch aus den
    # Daten der Traingingsstichprobe geschaetzt. Die Klassenzugehoerigkeiten sind fuer die
    # Beispiele aus der Trainingsstichprobe durch so genannte Klassenlabels gegeben.
    #
    # Nachdem man den Klassifikator trainiert hat, interessiert man sich normalerweise dafuer
    # wie gut er sich unter realen Bedingung verhaelt. Das heisst, dass der Klassifikator bei
    # der Klassifikation zuvor unbekannter Daten moeglichst wenige Fehler machen soll.
    # Dies simuliert man mit der Teststichprobe. Da auch fuer jedes Beispiel aus der Teststichprobe
    # die Klassenzugehoerigkeit bekannt ist, kann man am Ende die Klassifikationsergebnisse mit
    # den wahren Klassenlabels (aus der Teststichprobe) vergleichen und eine Fehlerrate angeben.


    # In dem gegebenen Brown Corpus ist keine Aufteilung in Trainings und Testdaten vorgegeben.
    #
    # Waehlen Sie daher die ersten 80% der Dokumente UEBER ALLE KATEGORIEN als Trainingstichprobe
    # und die letzten 20% der Dokumente UEBER ALLE KATEGORIEN als Teststichprobe.
    #
    # Erklaeren Sie, warum Sie die Stichproben ueber alle Kategorien zusammenstellen MUESSEN.
    #
    # Bitte beachten Sie, dass wir im Rahmen des Fachprojekts keinen Test auf unbekannten Testdaten
    # simulieren. Wir haben ja bereits fuer die Erstellung der Vokabulars (haeufigste Woerter,
    # siehe oben) den kompletten Datensatz verwendet.
    # Stattdessen betrachten wir hier ein so genanntes Validierungsszenario, in dem wir die
    # Klassifikationsleistung auf dem Brown Corpus optimieren. Die Ergebnisse lassen sich somit
    # nur sehr bedingt auf unbekannte Daten uebertragen.
    #
    # Erstellen Sie nun die NumPy Arrays train_samples, train_labels, test_samples und test_labels,
    # so dass diese mit den estimate und classify Methoden der Klassen im classificaton Modul
    # verwendet werden koennen. Teilen Sie die Daten wie oben angegeben zu 80% in
    # Trainingsdaten und 20% in Testdaten auf.
    #
    # Hinweis: Vollziehen Sie nach, wie die Klasse CrossValidation im evaluation Modul
    # funktioniert. Wenn Sie moechten, koennen die Klasse zur Aufteilung der Daten
    # verwenden.

    print "Arrays sind generiert"

    train_labels = np.array(brown_categories).reshape(len(brown_categories), 1)
    test_labels =np.array(brown_categories).reshape(len(brown_categories), 1)
    print "Reshaped"

    cv = CrossValidation(a.category_bow_dict(bow_list), 5)
    cv2 = cv.corpus_fold(1)
    train_samples = cv2[0]
    test_samples = cv2[2]
    train_labels = cv2[1]
    test_labels = cv2[3]



    # Klassifizieren Sie nun alle Dokumente der Teststichprobe nach dem Prinzip des k-naechste-
    # Nachbarn Klassifikators. Dabei wird die Distanz zwischen dem Merkmalsvektors eines
    # Testbeispiels und allen Merkmalsvektoren aus der Trainingstichprobe berechnet. Das
    # Klassenlabel des Testbeispiels wird dann ueber einen Mehrheitsentscheid der Klassenlabels
    # der k aehnlichsten Merkmalsvektoren aus der Trainingsstichprobe bestimmt.
    # http://www5.informatik.uni-erlangen.de/fileadmin/Persons/NiemannHeinrich/klassifikation-von-mustern/m00-www.pdf (Abschnitt 4.2.7)
    #
    # Verwenden Sie die Euklidische Distanz und betrachten Sie nur den naechsten Nachbarn (k=1).
    # http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cdist.html
    #
    # Implementieren Sie die Funktionen estimate und classify in der Klasse KNNClassifier
    # im Modul classification.

    classification = KNNClassifier(1, 'euclidean')
    classification.estimate(train_samples, train_labels)
    result_knnk = classification.classify(test_samples)


    # Nachdem Sie mit dem KNNClassifier fuer jedes Testbeispiel ein Klassenlabel geschaetzt haben,
    # koennen Sie dieses mit dem tatsaechlichen Klassenlabel vergleichen. Dieses koennen Sie wie
    # bei den Traingingsdaten dem Corpus entnehmen.
    #
    # Ermitteln Sie eine Gesamtfehlerrate und je eine Fehlerrate pro Kategorie.
    # Implementieren Sie dazu die Klasse ClassificationEvaluator im evaluation Modul.
    #
    # Warum ist diese Aufteilung der Daten in Training und Test problematisch? Was sagen die Ergebnisse aus?

    eval = ClassificationEvaluator(result_knnk, test_labels)
    error_overall = eval.error_rate()[0]
    error_cat_list = eval.category_error_rates()
    print "Error Overall"
    print error_overall
    print "Error Catlist"
    print error_cat_list
示例#12
0
from files import ImageFile
from segmentation import ContourSegmenter
from feature_extraction import SimpleFeatureExtractor
from classification import KNNClassifier
from ocr import OCR, accuracy, show_differences

segmenter = ContourSegmenter(blur_y=5, blur_x=5, block_size=11, c=10)
extractor = SimpleFeatureExtractor(feature_size=10, stretch=False)
classifier = KNNClassifier()
ocr = OCR(segmenter, extractor, classifier)

ocr.train(ImageFile('digits1'))

test_image = ImageFile('digits2')
test_chars, test_classes, test_segments = ocr.ocr(test_image, show_steps=True)

print("accuracy:", accuracy(test_image.ground.classes, test_classes))
print("OCRed text:\n", test_chars)
示例#13
0
def test_resolve_ties_handles_all_tied_case():
    labels = ('a', 'b', 'c', 'd', 'e', 'a', 'b')
    expected = 'a'
    result = KNNClassifier.resolve_ties(labels, 5)
    assert result == expected
示例#14
0
def aufgabe2():

    # Laden des Brown Corpus
    CorpusLoader.load()
    brown = CorpusLoader.brown_corpus()
    brown_categories = brown.categories()

    # In dieser Aufgabe sollen unbekannte Dokumente zu bekannten Kategorien
    # automatisch zugeordnet werden.
    #
    # Die dabei erforderlichen numerischen Berechnungen lassen sich im Vergleich
    # zu einer direkten Implementierung in Python erheblich einfacher mit
    # NumPy / SciPy durchfuehren. Die folgende Aufgabe soll Ihnen die Unterschiede
    # anhand eines kleinen Beispiels verdeutlichen.
    #
    # Geben Sie fuer jede Katgorie des Brown Corpus die durchschnittliche Anzahl
    # von Woertern pro Dokument aus. Bestimmen Sie auch die Standardabweichung.
    # Stellen Sie diese Statistik mit einem bar plot dar. Verwenden Sie dabei
    # auch Fehlerbalken (siehe visualization.hbar_plot)
    #
    # Berechnen Sie Mittelwert und Standardabweichung jeweils:
    #
    #  - nur mit Python Funktion
    #    hilfreiche Funktionen: sum, float, math.sqrt, math.pow
    #
    #  - mit NumPy
    #    hilfreiche Funktionen: np.array, np.mean, np.std
    #
    # http://docs.python.org/2/library/math.html
    # http://wiki.scipy.org/Tentative_NumPy_Tutorial
    # http://docs.scipy.org/doc/numpy/reference/generated/numpy.mean.html
    # http://docs.scipy.org/doc/numpy/reference/generated/numpy.std.html

    for cat in brown_categories:
        # python standard libs only
        # calculating the mean
        doc_words = 0
        docs = brown.fileids(categories=cat)
        n = float(len(docs))
        for doc in docs:
            doc_words += len(brown.words(doc))
        mean = float(doc_words) / n
        # claculating the std
        std = 0.
        for doc in docs:
            std += math.pow(float(len(brown.words(doc))) - mean, 2)
        std = math.sqrt(std / n)

        # using numpy
        arr_doc_words = np.array([
            len(brown.words(doc)) for doc in brown.fileids(categories=cat)
        ]).astype(float)
        np_std = np.std(arr_doc_words)

        # printing the std for each category
        print("{}\npython: {}, mean={}\nnp:{}, mean={}".format(
            cat, std, mean, np_std, np.mean(arr_doc_words)))

    # ********************************** ACHTUNG **************************************
    # Die nun zu implementierenden Funktionen spielen eine zentrale Rolle im weiteren
    # Verlauf des Fachprojekts. Achten Sie auf eine effiziente und 'saubere' Umsetzung.
    # Verwenden Sie geeignete Datenstrukturen und passende Python Funktionen.
    # Wenn Ihnen Ihr Ansatz sehr aufwaendig vorkommt, haben Sie vermutlich nicht die
    # passenden Datenstrukturen / Algorithmen / (highlevel) Python / NumPy Funktionen
    # verwendet. Fragen Sie in diesem Fall!
    #
    # Schauen Sie sich jetzt schon gruendlich die Klassen und deren Interfaces in den
    # mitgelieferten Modulen an. Wenn Sie Ihre Datenstrukturen von Anfang an dazu
    # passend waehlen, erleichtert dies deren spaetere Benutzung. Zusaetzlich bieten
    # diese Klassen bereits etwas Inspiration fuer Python-typisches Design, wie zum
    # Beispiel Duck-Typing.
    #
    # Zu einigen der vorgebenen Intefaces finden Sie Unit Tests in dem Paket 'test'.
    # Diese sind sehr hilfreich um zu ueberpruefen, ob ihre Implementierung zusammen
    # mit anderen mitgelieferten Implementierungen / Interfaces funktionieren wird.
    # Stellen Sie immer sicher, dass die Unit tests fuer die von Ihnen verwendeten
    # Funktionen erfolgreich sind.
    # Hinweis: Im Verlauf des Fachprojekts werden die Unit Tests nach und nach erfolg-
    # reich sein. Falls es sie zu Beginn stoert, wenn einzelne Unit Tests fehlschlagen
    # koennen Sie diese durch einen 'decorator' vor der Methodendefinition voruebergehend
    # abschalten: @unittest.skip('')
    # https://docs.python.org/2/library/unittest.html#skipping-tests-and-expected-failures
    # Denken Sie aber daran sie spaeter wieder zu aktivieren.
    #
    # Wenn etwas unklar ist, fragen Sie!
    # *********************************************************************************

    #
    # Klassifikation von Dokumenten
    #
    # Nachdem Sie sich nun mit der Struktur und den Eigenschaften des Brown
    # Corpus vertraut gemacht haben, soll er die Datengrundlage fuer die
    # Evaluierung von Algorithmen zur automatischen Klassifikation von
    # Dokumenten bilden.
    # In der Regel bestehen diese Algorithmen aus drei Schritten:
    #  - Vorverarbeitung
    #  - Merkmalsberechnung
    #  - Klassifikation
    #
    # Bei der Anwendung auf Dokumente (Texte) werden diese Schritte wie folgt
    # umgesetzt:
    #  - Vorverarbeitung: Filterung von stopwords und Abbildung von Woertern auf
    #                     Wortstaemme.
    #  - Merkmalsberechnung: Jedes Dokument wird numerisch durch einen Vektor
    #                        repraesentiert (--> NumPy), der moeglichst die
    #                        bzgl. der Klassifikation bedeutungsunterscheidenden
    #                        Informationen enthaehlt.
    #  - Klassifikation: Jedem Merkmalsvektor (Dokument) wird ein Klassenindex
    #                    (Kategorie) zugeordnet.
    #
    # Details finden Sie zum Beispiel in:
    # http://www5.informatik.uni-erlangen.de/fileadmin/Persons/NiemannHeinrich/klassifikation-von-mustern/m00-www.pdf (section 1.3)
    #
    # Eine sehr verbreitete Merkmalsrepraesentation fuer (textuelle) Dokumente sind
    # sogenannte Bag-of-Words.
    # Dabei wird jedes Dokument durch ein Histogram (Verteilung) ueber Wortfrequenzen
    # repraesentiert. Man betrachtet dazu das Vorkommen von 'typischen' Woertern, die
    # durch ein Vokabular gegeben sind.
    #
    # Bestimmen Sie ein Vokabular, also die typischen Woerter, fuer den Brown Corpus.
    # Berechnen Sie dazu die 500 haeufigsten Woerter (nach stemming und Filterung von
    # stopwords und Satzzeichen)

    normalizer = WordListNormalizer()
    normalized_words = normalizer.normalize_words(brown.words())
    vocabulary = BagOfWords.most_freq_words(normalized_words[1], 500)
    print(vocabulary)
    print('finished vocab')

    # Berechnen Sie Bag-of-Words Repraesentationen fuer jedes Dokument des Brown Corpus.
    # Verwenden Sie absolute Frequenzen.
    # Speichern Sie die Bag-of-Word Repraesentationen fuer jede Kategorie in einem
    # 2-D NumPy Array. Speichern Sie den Bag-of-Words Vektor fuer jedes Dokument in
    # einer Zeile, so dass das Array (ndarray) folgende Dimension hat:
    #   |Dokument_kat| X |Vokabular|
    #
    # |Dokument_kat| entspricht der Anzahl Dokumente einer Kategorie.
    # |Vokabular| entspricht der Anzahl Woerter im Vokabular (hier 500).
    #
    # Eine einfache Zuordnung von Kategorie und Bag-of-Words Matrix ist durch ein
    # Dictionary moeglich.
    #
    # Implementieren Sie die Funktion BagOfWords.category_bow_dict im Modul features.
    bow = BagOfWords(vocabulary)

    cat_word_dict = {
        cat: [brown.words(doc) for doc in brown.fileids(categories=cat)]
        for cat in brown_categories
    }
    print('calculating cat_to_bow')
    cat_to_bow = bow.category_bow_dict(cat_word_dict)
    print(cat_to_bow)

    # Um einen Klassifikator statistisch zu evaluieren, benoetigt man eine Trainingsstichprobe
    # und eine Teststichprobe der Daten die klassifiziert werden sollen.
    # Die Trainingsstichprobe benoetigt man zum Erstellen oder Trainieren des Klassifikators.
    # Dabei werden in der Regel die Modellparameter des Klassifikators statistisch aus den
    # Daten der Traingingsstichprobe geschaetzt. Die Klassenzugehoerigkeiten sind fuer die
    # Beispiele aus der Trainingsstichprobe durch so genannte Klassenlabels gegeben.
    #
    # Nachdem man den Klassifikator trainiert hat, interessiert man sich normalerweise dafuer
    # wie gut er sich unter realen Bedingung verhaelt. Das heisst, dass der Klassifikator bei
    # der Klassifikation zuvor unbekannter Daten moeglichst wenige Fehler machen soll.
    # Dies simuliert man mit der Teststichprobe. Da auch fuer jedes Beispiel aus der Teststichprobe
    # die Klassenzugehoerigkeit bekannt ist, kann man am Ende die Klassifikationsergebnisse mit
    # den wahren Klassenlabels (aus der Teststichprobe) vergleichen und eine Fehlerrate angeben.

    # In dem gegebenen Brown Corpus ist keine Aufteilung in Trainings und Testdaten vorgegeben.
    #
    # Waehlen Sie daher die ersten 80% der Dokumente UEBER ALLE KATEGORIEN als Trainingstichprobe
    # und die letzten 20% der Dokumente UEBER ALLE KATEGORIEN als Teststichprobe.
    #
    # Erklaeren Sie, warum Sie die Stichproben ueber alle Kategorien zusammenstellen MUESSEN.
    #
    # Bitte beachten Sie, dass wir im Rahmen des Fachprojekts keinen Test auf unbekannten Testdaten
    # simulieren. Wir haben ja bereits fuer die Erstellung der Vokabulars (haeufigste Woerter,
    # siehe oben) den kompletten Datensatz verwendet.
    # Stattdessen betrachten wir hier ein so genanntes Validierungsszenario, in dem wir die
    # Klassifikationsleistung auf dem Brown Corpus optimieren. Die Ergebnisse lassen sich somit
    # nur sehr bedingt auf unbekannte Daten uebertragen.
    #
    # Erstellen Sie nun die NumPy Arrays train_samples, train_labels, test_samples und test_labels,
    # so dass diese mit den estimate und classify Methoden der Klassen im classificaton Modul
    # verwendet werden koennen. Teilen Sie die Daten wie oben angegeben zu 80% in
    # Trainingsdaten und 20% in Testdaten auf.
    #
    # Hinweis: Vollziehen Sie nach, wie die Klasse CrossValidation im evaluation Modul
    # funktioniert. Wenn Sie moechten, koennen die Klasse zur Aufteilung der Daten
    # verwenden.

    cross_validator = CrossValidation(cat_to_bow, 5)
    train_samples, train_labels, test_samples, test_labels = cross_validator.corpus_fold(
        0)
    print('finished cross validation')

    # Klassifizieren Sie nun alle Dokumente der Teststichprobe nach dem Prinzip des k-naechste-
    # Nachbarn Klassifikators. Dabei wird die Distanz zwischen dem Merkmalsvektors eines
    # Testbeispiels und allen Merkmalsvektoren aus der Trainingstichprobe berechnet. Das
    # Klassenlabel des Testbeispiels wird dann ueber einen Mehrheitsentscheid der Klassenlabels
    # der k aehnlichsten Merkmalsvektoren aus der Trainingsstichprobe bestimmt.
    # http://www5.informatik.uni-erlangen.de/fileadmin/Persons/NiemannHeinrich/klassifikation-von-mustern/m00-www.pdf (Abschnitt 4.2.7)
    #
    # Bestimmen Sie die Distanzen von Testdaten zu Trainingsdaten mit cdist:
    # http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cdist.html
    # Bestimmen Sie die k-naechsten Nachbarn auf Grundlage der zuvor berechneten
    # Distanzen mit argsort:
    # http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
    # Ueberlegen Sie, welche zuvor von Ihnen implementierte Funktion Sie wiederverwenden
    # koennen, um den Mehrheitsentscheid umzusetzen.
    #
    # Implementieren Sie die Funktionen estimate und classify in der Klasse KNNClassifier
    # im Modul classification.
    #
    # Verwenden Sie die Euklidische Distanz und betrachten Sie zunaechst nur
    # den naechsten Nachbarn (k=1).
    #
    # HINWEIS: Hier ist zunaechst nur die Implementierung eines naechster Nachbar
    # Klassifikators erforderlich. Diese soll aber in der naechsten Aufgabe zu einer
    # Implementierung eines k-naechste Nachbarn Klassifikators erweitert werden.
    # Beruechsichtigen Sie das in ihrer Implementierung. Um die beiden Varianten
    # zu testen, finden Sie zwei Unit-Test Methoden test_nn und test_knn in dem Modul
    # test.classification_test
    #
    knn_1 = KNNClassifier(1, 'euclidean')
    knn_1.estimate(train_samples, train_labels)

    nearest_1 = knn_1.classify(test_samples)
    print(nearest_1)
    print('finished classification')

    # Nachdem Sie mit dem KNNClassifier fuer jedes Testbeispiel ein Klassenlabel geschaetzt haben,
    # koennen Sie dieses mit dem tatsaechlichen Klassenlabel vergleichen. Dieses koennen Sie wie
    # bei den Traingingsdaten dem Corpus entnehmen.
    #
    # Ermitteln Sie eine Gesamtfehlerrate und je eine Fehlerrate pro Kategorie.
    # Implementieren Sie dazu die Klasse ClassificationEvaluator im evaluation Modul.
    #
    # Warum ist diese Aufteilung der Daten in Training und Test problematisch? Was sagen die Ergebnisse aus?
    evaluator = ClassificationEvaluator(nearest_1, test_labels)

    cat_err_rates = evaluator.category_error_rates()
    print(evaluator.error_rate(None))
    print(cat_err_rates)
    print('done')
示例#15
0
def aufgabe4():

    #
    # Mit dem Naechster Nachbar Klassifikator wurde ein Dokumente zu einer Klassen zugeordnet,
    # indem zunaechst aehnliche Dokumente aus einer Trainingsdatenbank ermittelt wurden.
    # Ueber die Klassenzugehoerigkeit dieser aehnlichen Dokumente aus dem Training
    # wurde dann das unbekannte Dokument einer Klasse zugeordnet.
    # Dabei wurden aber noch keine Zusammenhaenge zwischen einzelnen Woertern analysiert
    # und beruecksichtigt. Daher geht es nun um Topic Modelle. Topic Modelle beschreiben
    # diese Zusammenhaenge durch einen mathematischen Unterraum. Die Vektoren, die
    # diesen Unterraum aufspannen, sind die Topics, die jeweils fuer typische Wort-
    # konfigurationen stehen. Dokumente werden nun nicht mehr durch Frequenzen von
    # Woertern repraesentiert, sondern als Linearkombination von Topics im Topic
    # Vektorraum. Es ist zu beachten, dass fuer die Topic-Modellierung keine Informationen
    # ueber die Dokumentenkategorien benoetigt wird.
    #
    # Um ein besseres Verstaendnis fuer diese mathematischen Unterraeume zu entwickeln,
    # schauen wir uns zunaechst die Hauptkomponentenanalyse an.
    #

    # Ein 3D Beispieldatensatz wird aus einer Normalverteilung generiert.
    # Diese ist durch einen Mittelwert und eine Kovarianzmatrix definiert
    mean = np.array([10, 10, 10])
    cov = np.array([[3, .2, .9], [.2, 5, .4], [.9, .4, 9]])
    n_samples = 1000
    limits_samples = ((0, 20), (0, 20), (0, 20))
    samples = np.random.multivariate_normal(mean, cov, n_samples)
    # Plotten der Beispieldaten
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    PCAExample.plot_sample_data(samples, ax=ax)
    PCAExample.set_axis_limits(ax, limits=limits_samples)

    # In der Klasse PCAExample wird ein Unterraum mittels Hauptkomponentenanalyse
    # statistisch geschaetzt. Der Vektorraum wird beispielhaft visualisiert.
    pca_example = PCAExample(samples, target_dim=3)
    pca_example.plot_subspace(limits=limits_samples,
                              color='r',
                              linewidth=0.05,
                              alpha=0.3)
    #plt.show()

    # Nun wird die Dimension des Unterraums reduziert.
    # Implementieren Sie die Reduktion im Konstruktor von PCAExample. Der neue
    # Vektorraum wird wieder visualisiert.
    pca_example_2d = PCAExample(samples, target_dim=2)
    pca_example_2d.plot_subspace(limits=limits_samples,
                                 color='b',
                                 linewidth=0.01,
                                 alpha=0.3)

    # Transformieren Sie nun die 3D Beispieldaten in den 2D Unterraum.
    # Implementieren Sie dazu die Methode transform_samples. Die Daten werden
    # dann in einem 2D Plot dargestellt.
    #
    # Optional: Verwenden Sie Unterraeume mit Dimensionen 3, 2 und 1. Transformieren
    # und plotten Sie die Daten.

    #pca_example_1d = PCAExample(samples, target_dim=1)
    #pca_example_1d.plot_subspace(limits=limits_samples, color='g', linewidth=0.01, alpha=0.3, ellipsoid=False)
    #samples_1d = pca_example_1d.transform_samples(samples)
    #fig = plt.figure()
    #ax = fig.add_subplot(111)
    #PCAExample.plot_sample_data(samples_1d, ax=ax)
    #PCAExample.set_axis_limits(ax, limits=((-10, 10), (-10, 10)))

    # Optional: Generieren und transformieren Sie weitere 3D Beispieldaten. Benutzen Sie
    # dabei auch andere Parameter fuer die Normalverteilung.
    #
    # Optional: Visualisieren Sie die transformierten 2D Daten auch in dem vorherigen
    # 3D Plot.
    samples_2d = pca_example_2d.transform_samples(samples)
    fig = plt.figure()
    ax = fig.add_subplot(111)
    PCAExample.plot_sample_data(samples_2d, ax=ax)
    PCAExample.set_axis_limits(ax, limits=((-10, 10), (-10, 10)))

    #plt.show()

    # Berechnen Sie nun die Kovarianzmatrix der transformierten Daten.
    # Welche Eigenschaften hat diese Matrix? (Dimension, etc.)
    # In welcher Groessenordnung liegen die einzelnen Eintraege? Erklaeren Sie das
    # anhand des vorherigen 2D Plots.
    # Vergleichen Sie das Ergebnis mit der Kovarianzmatrix, die oben zur Generierung
    # der Daten verwendet wurde.
    # Was erwarten Sie fuer den Mittelwert der transformierten Daten (noetig fuer
    # die Berechnung der Kovarianzmatrix) ?
    #
    # Verwenden Sie bei der Berechnung nicht die eingebaute numpy.cov Funktion
    # (hoechstens zur Kontrolle, achten Sie dabei auf den "bias" Parameter)
    # Verwenden Sie bei der Berechnung keine Schleifen, sondern nur Matrixoperationen.
    # Erklaeren Sie die Vorgehensweise.

    samples_mean = np.sum(samples_2d, axis=0) / n_samples
    X = samples_2d - samples_mean
    samples_2d_cov = np.dot(X.T, X) / n_samples
    print(samples_2d_cov)

    #
    # Latent Semantic Indexing
    #
    # Im folgenden soll ein Topic-Raum mittels Latent Semantic Indexing verwendet
    # werden. Das Prinzip geht unmittelbar auf die Hauptkomponentenanalyse zurueck.
    # Siehe: http://lsa.colorado.edu/papers/JASIS.lsi.90.pdf (Seite 12)
    # Grundsaetzlicher Unterschied ist, dass der Unterraum nicht durch eine Eigenewert-
    # analyse der Kovarianzmatrix bestimmt wird. Stattdessen ergibt sich der Unterraum
    # aus einer Zerlegung der Term-Dokument (!) Matrix mit einer Singulaerwertzerlegung.
    # Man kann zeigen, dass diese Singulaerwertzerlegung implizit einer Eigenwert-
    # analyse einer Termkorrelationsmatrix entspricht. Deren Berechnung unterscheidet
    # sich von der Berechnung der Kovarianzmatrix insbesondere darin, dass die Daten
    # nicht vom Mittelwert befreit werden.
    # Sei t die Anzahl der Terms (Groesse des Vokabulars), d die Anzahl der Dokumente,
    # m der Rang von X (Maximale Anzahl von Topics, die sich aus X bestimmen lassen).
    # D' ist die Transponierte von D.
    #
    #   X    =    T    *    S    *    D'
    # t x d     t x m     m x m     m x d
    #
    # In Analogie zur Hauptkomponentenanalyse findet man nun die Vektoren, die
    # den Unterraum aufspannen, in den Spalten von T. Die Matrix S hat nur Eintraege
    # auf der Diagonalen und enthaelt die Singulaerwerte zu den Spaltenvektoren in
    # T. (T und D enthalten die linken respektive rechten Singulaervektoren.)
    # Die Singulaerwerte entsprechen den Eigenwerten in der Hauptkomponentenanalyse.
    # Sie sind ein Mass fuer die Variabilitaet in den einzelnen Topics. Bei D handelt
    # es sich um die Koeffizienten der d Dokumente im Topic Raum (Ergebnis der
    # Transformation von den Bag-of-Words Repraesentationen aus X in den Topic Raum.)
    #
    #
    # Aus der Singulaerwertzerlegung (Formel oben) ergibt sich, wie man einen Topic-
    # Raum statistisch aus Beispieldaten schaetzt. Um den Topic-Raum aber mit unbekannten Daten
    # zu verwenden, muessen diese in den Topic-Raum transformiert werden.
    # Stellen Sie dazu die obige Formel nach D um.
    #
    #   D    =    X'    *    T    *   S^-1
    # d x m     d x t     t x m     m x m
    #
    # Die zu transformierenden Bag-of-Words
    # Repaesentationen koennen dann fuer X eingesetzt werden. Dabei ist wichtig zu
    # beachten:
    # Die Spaltenvektoren in T sind orthonormal (zueinander) T' * T = I
    # Die Spaltenvektoren in D sind orthonormal (zueinander) D' * D = I
    # Dabei ist I die Einheitsmatrix, T' und D' sind die Transponierten in T und D.
    # Fuer Matrizen A und B gilt: (A * B)' = B' * A'
    #
    # Ueberlegen Sie wie die Transponierte einer Matrix gebildet wird und was das
    # fuer eine Matrix bedeutet, deren Eintraege nur auf der Hauptdiagonalen von
    #
    # Antwort: Die Matrix wird an der Hauptdiagonalen gespiegelt, bzw. die Zeilen und Spalten werden
    #          vertauscht. Das bedeutet für die Hauptdiagonale, dass sie bei jeder Transponierung gleich bleibt
    #
    # Erlaeutern Sie die Funktion der einzelnen Matrizen in der sich ergebenden
    # Transformationsvorschrift.
    #

    # Das Schaetzen eines Topic-Raums soll an folgendem einfachen Beispiel veranschaulicht
    # werden. Sei dazu bow_train eine Dokument-Term Matrix mit 9 Dokumenten und 3 Terms.
    # Welcher Zusammenhang zwischen den Terms faellt Ihnen auf?
    #
    # Antwort: Der zweite Term scheint nicht besonders topic bezogen und kommt in jedem Dokument mind. 1 mal vor
    # die anderen beiden Terms sind dagegen eher topic bezogen, vor allem das dritte
    bow_train = np.array([[2, 5, 0], [4, 1, 0], [3, 3, 1], [9, 8,
                                                            2], [1, 5, 3],
                          [0, 7, 9], [2, 9, 6], [0, 2, 3], [5, 3, 3]])

    # Zerlegung der Dokument-Term Matrix mit der Singulaerwertzerlegung
    T, S_arr, D_ = np.linalg.svd(bow_train.T, full_matrices=False)
    S = np.diag(S_arr)
    print('Matrix T, Spaltenvektoren definieren Topic Raum')
    print(T)
    print('Matrix S, Singulaerwerte zu den Vektoren des Topic Raums')
    print(S)
    print('Matrix D, Koeffizienten der Termvektoren in bof Topic Raum')
    print(D_.T)

    # Transformieren Sie nun die folgenden Termvektoren in den Topic Raum
    # Was erwarten Sie fuer die Topic Zugehoerigkeiten?

    bow_test = np.array([[5, 0, 0], [0, 5, 0], [0, 0, 5], [5, 5, 0], [0, 5,
                                                                      5]])
    coefficients = np.dot(np.dot(bow_test, T), np.linalg.inv(S))
    print(coefficients)

    #
    # Warum lassen sich die Koeffizienten der Termvektoren so schwer interpretieren?
    # Antwort: extrem kleine Werte -> besser: visualisieren
    #
    # Um eine bessere Vorstellung von der Bedeutung der einzelnen Topics zu bekommen,
    # plotten Sie die Bag-of-Words Repraesentationen sowie die Topic-Koeffizienten der
    # Trainingsdaten (bow_train) und der Testdaten (bow_test) in verschiedenen Farben.
    # Erstellen Sie dazu jeweils einen Plot fuer Bag-of-Words Repraesentationen und einen
    # Plot fuer Topic-Koeffizienten. Achten Sie auf eine geeignete Skalierung der Axen.
    # Um die Datenpunkte in den beiden Plots besser einander zuordnen zu koennen, plotten
    # Sie zusaetzlich die Termfrequenzen neben jeden Datenpunkt (als Annotation).
    # Mehrere Daten (Trainings-, Testdaten, Annotationen) lassen sich in einem gemeinsamen
    # Plot darzustellen indem sie nacheinander zu dem gleichen Axis Objekt hinzugefuegt
    # werden. Zum Erstellen der Plots orientieren Sie sich an den entsprechenden
    # Funktionen aus dem Beispiel zur Hauptkomponentenanalyse (oben). Schauen Sie sich
    # auch deren weitere Parameter (und zusaetzlich vorhandene Hilfsfunktionen) an.

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    annotations_D_test = PCAExample.samples_coordinate_annotations(bow_test)
    annotations_D_train = PCAExample.samples_coordinate_annotations(bow_train)
    PCAExample.plot_sample_data(D_.T,
                                ax=ax,
                                annotations=annotations_D_train,
                                color='r')
    PCAExample.plot_sample_data(coefficients,
                                ax=ax,
                                annotations=annotations_D_test,
                                color='b')
    PCAExample.set_axis_limits(ax, limits=((-1, 1), (-1, 1), (-1, 1)))

    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    PCAExample.plot_sample_data(bow_train,
                                ax=ax,
                                color='b',
                                annotations=annotations_D_train)
    PCAExample.plot_sample_data(bow_test,
                                ax=ax,
                                color='r',
                                annotations=annotations_D_test)
    PCAExample.set_axis_limits(ax, limits=((0, 10), (0, 10), (0, 10)))

    #
    # Fuehren Sie nun eine Dimensionsreduktion der Trainings und Testdaten auf zwei
    # Dimensionen durch und plotten Sie die Topic-Koeffizienten (inkl. Bag-of-Words
    # Annotationen). Vergleichen Sie alle drei Plots miteinander. Welchen Effekt hat
    # die Topic Modellierung im Bezug auf typische Termkonfigurationen?
    #
    # Optional: Transformieren Sie die Daten in einen Topic-Raum mit Dimension Eins
    # und plotten Sie die Koeffizienten inkl. deren Bag-of-Words Annotationen.
    #

    T_2d = T[:, :2]
    S_2d = S[:2, :2]
    D_2d_test = np.dot(np.dot(bow_test, T_2d), np.linalg.inv(S_2d))
    D_2d_train = np.dot(np.dot(bow_train, T_2d), np.linalg.inv(S_2d))
    ax = fig.add_subplot(111)
    annotations_D_test = PCAExample.samples_coordinate_annotations(bow_test)
    annotations_D_train = PCAExample.samples_coordinate_annotations(bow_train)
    PCAExample.plot_sample_data(D_2d_train,
                                ax=ax,
                                annotations=annotations_D_train,
                                color='r')
    PCAExample.plot_sample_data(D_2d_test,
                                ax=ax,
                                annotations=annotations_D_test,
                                color='b')
    PCAExample.set_axis_limits(ax, limits=((-0.75, 0.75), (-0.75, 0.75)))
    plt.show()

    #
    # Integrieren Sie nun die Topic-Raum Modellierung mittels Singulaerwertzerlegung
    # in die Kreuzvalidierung auf dem Brown Corpus. Berechnen Sie dabei fuer
    # jede Aufteilung von Training und Test einen neuen Topic-Raum. Transformieren
    # Sie die Bag-of-Words Repraesentationen und fuehren Sie die Klassifikation
    # wie zuvor mit dem Naechster-Nachbar-Klassifikator durch. Verwenden Sie dabei
    # verschiedene Distanzmasse und evaluieren Sie die Klassifikationsfehlerrate
    # fuer verschiedene Dimensionalitaeten des Topic-Raums. Die anderen Parameter
    # waehlen Sie gemaess der besten bisherigen Ergebnisse.
    #
    # Implementieren Sie die Klasse TopicFeatureTransform im features Modul
    # und verwenden Sie sie mit der CrossValidation Klasse (evaluation Modul).
    #
    # Optional: Fuehren Sie eine automatische Gridsuche ueber den kompletten Paramterraum
    # durch. Legen Sie sinnvolle Wertebereiche und Schrittweiten fuer die einzelnen
    # Parameter fest. Wie lassen sich diese bestimmen?
    #
    # Optional: Passen Sie das Suchgrid dynamisch gemaess der Ergebnisse in den einzelnen
    # Wertebereichen an.

    CorpusLoader.load()
    brown = CorpusLoader.brown_corpus()
    brown_categories = brown.categories()
    brown_words = brown.words()

    words_normalizer = WordListNormalizer()
    filtered_list, stemmed_list = words_normalizer.normalize_words(brown_words)
    vocabulary = BagOfWords.most_freq_words(stemmed_list, 500)

    cat_word_dict = {}
    for category in brown_categories:
        words_of_all_documents = []
        for document in brown.fileids(category):
            filtered_list, stemmed_list = words_normalizer.normalize_words(
                brown.words(fileids=document))
            words_of_all_documents.append(stemmed_list)
        cat_word_dict[category] = words_of_all_documents
    bag_of_words = BagOfWords(vocabulary)
    category_bow_dict = bag_of_words.category_bow_dict(cat_word_dict)

    cross_validation = CrossValidation(category_bow_dict, 5)

    knn_classifier = KNNClassifier(k_neighbors=4, metric='cosine')

    topic_feature_transform = TopicFeatureTransform(topic_dim=25)

    overall_result, class_result = cross_validation.validate(
        knn_classifier, feature_transform=topic_feature_transform)

    print(overall_result)
    print(class_result)
示例#16
0
    def detect(self, img, detected_faces=None):
        filename = utils.getFilename(img)

        config.maps_folder = config.temp_folder
        config.faces_folder = config.temp_folder
        config.descriptors_folder = config.temp_folder

        print('Processing ' + filename)

        image = cv2.imread(img)
        if image is None:
            print('ERROR processing ' + filename + ': image not found')
            return -1

        #Check if image is colored
        try:
            _, _, channels = image.shape
            if channels < 3:
                raise Exception()
        except Exception as e:
            print(
                'ERROR: image is grayscale. Illuminant maps analysis cannot be performed.'
            )
            return -1

        #Loads classifier
        # Extracting image features
        # Extract the faces in the image
        faces, _ = self.extractFaces(img, detected_faces)

        #Prediction map
        predictions = {}
        counters = {}
        for i in range(len(faces)):
            predictions[i], counters[i] = 0, 0

        #Image is precessable if there are more than one image
        if len(faces) > 1:
            # If there are two or more faces, process the image
            # Extract maps
            self.extractIlluminationMaps(img)
            # Extract image descriptors and features
            for illum in config.illuminantTypes:
                for desc in self.descriptors:
                    clfPath = config.classification_folder + 'model_' + illum + '_' + desc.lower(
                    ) + '.pkl'
                    if os.path.isfile(clfPath):
                        clf = KNNClassifier.load(clfPath)
                        features = self.extractFeatures(img,
                                                        label=detected_faces,
                                                        faces=faces,
                                                        illum=illum,
                                                        descriptor=desc,
                                                        output=True)
                        #Predict over sample
                        for sample in features:
                            prediction = clf.predict(
                                np.array(sample.feature.split(),
                                         dtype=float).reshape((1, -1)),
                                True)[0][1]
                            predictions[sample.first] += prediction
                            predictions[sample.second] += prediction
                            counters[sample.first] += 1
                            counters[sample.second] += 1

            #Majority voting
            threshold = config.majorityVotingThreshold
            score = 0
            detected = False
            fakeFaces = []

            for i in predictions:
                if score < predictions[i] / counters[i]:
                    score = predictions[i] / counters[i]

                if predictions[i] / counters[i] > threshold:
                    fakeFaces.append(i)
                    print('\tFace ' + str(i + 1) + ' is FAKE. Score ' +
                          str(score))

                    if not detected:
                        detected = not detected
                else:
                    print('\tFace ' + str(i + 1) + ' is NORMAL. Score ' +
                          str(predictions[i] / counters[i]))

            if detected:
                print('Image is FAKE')
            else:
                print('Image is ORIGINAL')

            orig = cv2.imread(img, cv2.COLOR_BGR2GRAY)
            #Display spliced faces
            rows, cols, _ = orig.shape
            outputMask = np.zeros((rows, cols))

            faceScores = orig.copy()
            idx = 0
            font = cv2.FONT_HERSHEY_SIMPLEX
            for (x, y, w, h) in faces:
                face_score = predictions[idx] / counters[i]
                if idx not in fakeFaces:
                    cv2.rectangle(faceScores, (x, y), (x + w, y + h),
                                  (0, 255, 0), 8)
                    cv2.putText(faceScores, str("{:.3f}".format(face_score)),
                                (x, y + h + 80), font, 1.8, (0, 255, 0), 3)
                else:
                    cv2.rectangle(faceScores, (x, y), (x + w, y + h),
                                  (0, 0, 255), 8)
                    cv2.putText(faceScores, str("{:.3f}".format(face_score)),
                                (x, y + h + 80), font, 1.8, (0, 0, 255), 3)

                #Set score in detection map
                outputMask[y:y + h, x:x + w] = face_score
                idx += 1
            faceScores = utils.resizeImage(faceScores, 1000)

            if self.display_result:
                cv2.imshow('output', faceScores)
                cv2.waitKey()

            regionMask = np.zeros(orig.shape)
            regionMask[..., 0] = outputMask.copy()
            regionMask[..., 1] = outputMask.copy()
            regionMask[..., 2] = outputMask.copy()
            # Write output mask
            outputMask *= 255
            cv2.imwrite(config.faceOutputDetectionImage, outputMask)

            return score

        else:
            # discard the current image
            print('Not suitable number of faces found in the image')
            return -1
示例#17
0
    def train(self, images, labels):
        # Extract image features from each images in training set
        if self.extract_features or self.extract_maps:
            for i in range(len(images)):
                #Extract the faces in the image
                faces, _ = self.extractFaces(images[i], labels[i])
                if len(faces) > 1:
                    #If there are two or more faces, process the image
                    filename = utils.getFilename(images[i])
                    print('Processing ' + filename)
                    #Extract maps
                    if self.extract_maps:
                        self.extractIlluminationMaps(images[i])
                    #Extract face paired features
                    if self.extract_features:
                        # Extract image descriptors and features
                        for illum in config.illuminantTypes:
                            for desc in self.descriptors:
                                self.extractFeatures(images[i],
                                                     labels[i],
                                                     faces=faces,
                                                     illum=illum,
                                                     descriptor=desc)
                else:
                    #else discard the current image
                    print('Not suitable number of faces found in the image')

        # Sample training
        if not self.cross_validation:
            # Train one model for each descriptor
            for illum in config.illuminantTypes:
                for desc in self.descriptors:
                    trainingData, trainingLabels, _ = self.getTrainingData(
                        images, desc, illum=illum)
                    if len(trainingData) > 0:
                        # Creates an instance of Neighbours Classifier and fit the data.
                        clf = KNNClassifier(config.KNeighbours, 'uniform')
                        clf.train(trainingData, trainingLabels)
                        clf.store(config.classification_folder + 'model_' +
                                  illum + '_' + desc.lower() + '.pkl')
                        print(illum + "/" + desc.upper() +
                              ' classification model created correctly')

        else:
            #Crossvalidate dataset witk K-fold crossvalidation
            print('Evaluate dataset with crossvalidation')
            trainingDesc = {}

            for illum in config.illuminantTypes:
                for desc in self.descriptors:
                    key = illum + "_" + desc
                    trainingDesc[key] = self.getTrainingData(images,
                                                             desc,
                                                             illum=illum)

            #Counting misclassified samples for accuracy score
            misclassified = 0
            refKey = config.illuminantTypes[0] + "_" + self.descriptors[0]
            #Splits dataset in train and test for crossvalidation
            splits = splitDataset(trainingDesc[refKey][0], config.folds)

            outputs_labels = trainingDesc[refKey][1]
            outputs_scores = np.zeros(len(trainingDesc[refKey][0]))

            for (trainIndex, testIndex) in splits:
                classifiers = {}
                for illum in config.illuminantTypes:
                    for desc in self.descriptors:
                        key = illum + "_" + desc
                        trainingData, trainingLabels, _ = trainingDesc[key]
                        if len(trainingData) > 0 and len(trainingLabels) > 0:
                            trainingData = trainingData[trainIndex]
                            trainingLabels = trainingLabels[trainIndex]
                            #Training model for illum type and descriptor
                            clf = KNNClassifier(config.KNeighbours, 'uniform')
                            clf.train(trainingData, trainingLabels)
                            classifiers[key] = clf

                outputs = []
                outputs_probs = []

                for illum in config.illuminantTypes:
                    for desc in self.descriptors:
                        key = illum + "_" + desc
                        testData, _, _ = trainingDesc[key]
                        if len(testData) > 0:
                            testData = testData[testIndex]
                            prediction = classifiers[key].predict(
                                testData) * config.descriptors_weights[desc]
                            outputs.append(prediction)
                            prediction = classifiers[key].predict(
                                testData,
                                True) * config.descriptors_weights[desc]
                            outputs_probs.append(prediction)

                output = np.zeros(len(testIndex))
                output_prob = np.zeros(len(testIndex))

                for i in range(len(outputs)):
                    predictions = outputs[i]
                    output += predictions
                    predictions_prob = outputs_probs[i]
                    for j in range(len(predictions)):
                        output_prob[j] += predictions_prob[j][1]

                #If voting is majority, classify as fake
                outputs_scores[testIndex] = output_prob
                counter = 0
                _, trainingLabels, _ = trainingDesc[refKey]
                testLabels = trainingLabels[testIndex]
                totalModels = len(classifiers)

                for val in np.nditer(output):
                    if val > totalModels / 2:
                        if testLabels[counter] != 1:
                            misclassified += 1
                    else:
                        if testLabels[counter] != 0:
                            misclassified += 1
                    counter += 1

            scipy.io.savemat(
                'classification_output.mat',
                dict(labels=outputs_labels, scores=outputs_scores))

            print('Number of classifiers: ' + str(totalModels))
            totalSamples = len(trainingDesc[refKey][0])
            print('Misclassified: ' + str(misclassified) + '/' +
                  str(totalSamples))
            accuracy = (totalSamples - misclassified) / totalSamples
            print('Accuracy: ' + str(accuracy))
示例#18
0
def aufgabe3():

    # ********************************** ACHTUNG **************************************
    # Die nun zu implementierenden Funktionen spielen eine zentrale Rolle im weiteren
    # Verlauf des Fachprojekts. Achten Sie auf eine effiziente und 'saubere' Umsetzung.
    # Verwenden Sie geeignete Datenstrukturen und passende Python Funktionen.
    # Wenn Ihnen Ihr Ansatz sehr aufwaendig vorkommt, haben Sie vermutlich nicht die
    # passenden Datenstrukturen / Algorithmen / (highlevel) Python / NumPy Funktionen
    # verwendet. Fragen Sie in diesem Fall!
    #
    # Schauen Sie sich jetzt schon gruendlich die Klassen und deren Interfaces in den
    # mitgelieferten Modulen an. Wenn Sie Ihre Datenstrukturen von Anfang an dazu
    # passend waehlen, erleichtert dies deren spaetere Benutzung. Zusaetzlich bieten
    # diese Klassen bereits etwas Inspiration fuer Python-typisches Design, wie zum
    # Beispiel Duck-Typing.
    #
    # Zu einigen der vorgebenen Intefaces finden Sie Unit Tests in dem Paket 'test'.
    # Diese sind sehr hilfreich um zu ueberpruefen, ob ihre Implementierung zusammen
    # mit anderen mitgelieferten Implementierungen / Interfaces funktionieren wird.
    # Stellen Sie immer sicher, dass die Unit tests fuer die von Ihnen verwendeten
    # Funktionen erfolgreich sind.
    # Hinweis: Im Verlauf des Fachprojekts werden die Unit Tests nach und nach erfolg-
    # reich sein. Falls es sie zu Beginn stoert, wenn einzelne Unit Tests fehlschlagen
    # koennen Sie diese durch einen 'decorator' vor der Methodendefinition voruebergehend
    # abschalten: @unittest.skip('')
    # https://docs.python.org/2/library/unittest.html#skipping-tests-and-expected-failures
    # Denken Sie aber daran sie spaeter wieder zu aktivieren.
    #
    # Wenn etwas unklar ist, fragen Sie!
    # *********************************************************************************

    print('loading brown')
    CorpusLoader.load()
    brown = CorpusLoader.brown_corpus()

    # Um eine willkuerliche Aufteilung der Daten in Training und Test zu vermeiden,
    # (machen Sie sich bewusst warum das problematisch ist)
    # verwendet man zur Evaluierung von Klassifikatoren eine Kreuzvalidierung.
    # Dabei wird der gesamte Datensatz in k disjunkte Ausschnitte (Folds) aufgeteilt.
    # Jeder dieser Ausschnitte wird einmal als Test Datensatz verwendet, waehrend alle
    # anderen k-1 Ausschnitte als Trainings Datensatz verwendet werden. Man erhaehlt also
    # k Gesamtfehlerraten und k klassenspezifische Fehlerraten ide man jeweils zu einer
    # gemeinsamen Fehlerrate fuer die gesamte Kreuzvalidierung mittelt. Beachten Sie,
    # dass dabei ein gewichtetes Mittel gebildet werden muss, da die einzelnen Test Folds
    # nicht unbedingt gleich gross sein muessen.

    # Fuehren Sie aufbauend auf den Ergebnissen aus aufgabe2 eine 5-Fold Kreuzvalidierung
    # fuer den k-Naechste-Nachbarn Klassifikator auf dem Brown Corpus durch. Dazu koennen
    # Sie die Klasse CrossValidation im evaluation Modul verwenden.
    #
    # Vollziehen Sie dazu nach wie die Klasse die Daten in Trainging und Test Folds aufteilt.
    # Fertigen Sie zu dem Schema eine Skizze an. Diskutieren Sie Vorteile und Nachteile.
    # Schauen Sie sich an, wie die eigentliche Kreuzvalidierung funktioniert. Erklaeren Sie
    # wie das Prinzip des Duck-Typing hier angewendet wird.
    #
    # Hinweise:
    #
    # Die Klasse CrossValidator verwendet die Klasse ClassificationEvaluator, die Sie schon
    # fuer aufgabe2 implementieren sollten. Kontrollieren Sie Ihre Umsetzung im Sinne der
    # Verwendung im CrossValidator.
    #
    # Fuer das Verstaendnis der Implementierung der Klasse CrossValidator ist der Eclipse-
    # Debugger sehr hilfreich.

    brown_categories = brown.categories()

    n_neighbours = 1
    metric = 'euclidean'
    classifier = KNNClassifier(n_neighbours, metric)

    normalizer = WordListNormalizer()
    normalized_words = normalizer.normalize_words(brown.words())
    vocabulary = BagOfWords.most_freq_words(normalized_words[1], 500)
    bow = BagOfWords(vocabulary)
    cat_word_dict = {
        cat: [brown.words(doc) for doc in brown.fileids(categories=cat)]
        for cat in brown_categories
    }

    n_folds = 5
    category_bow_dict = bow.category_bow_dict(cat_word_dict)
    cross_validator = CrossValidation(category_bow_dict=category_bow_dict,
                                      n_folds=n_folds)

    crossval_overall_result, crossval_class_results = cross_validator.validate(
        classifier)
    print("ran cross validation for {}-nearest neighbour".format(n_neighbours))
    print(crossval_overall_result)
    print(crossval_class_results)

    # Bag-of-Words Weighting
    #
    # Bisher enthalten die Bag-of-Words Histogramme absolute Frequenzen.
    # Dadurch sind die Repraesentationen abhaengig von der absoluten Anzahl
    # von Woertern in den Dokumenten.
    # Dies kann vermieden werden, in dem man die Bag-of-Words Histogramme mit
    # einem Normalisierungsfaktor gewichtet.
    #
    # Normalisieren Sie die Bag-of-Words Histogramme so, dass relative Frequenzen
    # verwendet werden. Implementieren und verwenden Sie die Klasse RelativeTermFrequencies
    # im features Modul.
    #
    # Wie erklaeren Sie das Ergebnis? Schauen Sie sich dazu noch einmal die
    # mittelere Anzahl von Woertern pro Dokument an (aufgabe2).
    #
    # Wie in der Literatur ueblich, verwenden wir den
    # Begriff des "Term". Ein Term bezeichnet ein Wort aus dem Vokabular ueber
    # dem die Bag-of-Words Histogramme gebildet werden. Ein Bag-of-Words Histogramm
    # wird daher auch als Term-Vektor bezeichnet.

    rel_category_bow_dict = {
        cat: RelativeTermFrequencies.weighting(category_bow_dict[cat])
        for cat in category_bow_dict
    }

    cross_validator = CrossValidation(category_bow_dict=rel_category_bow_dict,
                                      n_folds=n_folds)
    crossval_overall_result, crossval_class_results = cross_validator.validate(
        classifier)
    print("ran cross validation for {}-nearest neighbour (relative)".format(
        n_neighbours))
    print(crossval_overall_result)
    print(crossval_class_results)

    # Zusaetzlich kann man noch die inverse Frequenz von Dokumenten beruecksichtigen
    # in denen ein bestimmter Term vorkommt. Diese Normalisierung wird als
    # inverse document frequency bezeichnet. Die Idee dahinter ist Woerter die in
    # vielen Dokumenten vorkommen weniger stark im Bag-of-Words Histogramm zu gewichten.
    # Die zugrundeliegende Annahme ist aehnlich wie bei den stopwords (aufgabe1), dass
    # Woerter, die in vielen Dokumenten vorkommen, weniger Bedeutung fuer die
    # Unterscheidung von Dokumenten in verschiedene Klassen / Kategorien haben als
    # Woerter, die nur in wenigen Dokumenten vorkommen.
    # Diese Gewichtung laesst sich statistisch aus den Beispieldaten ermitteln.
    #
    # Zusammen mit der relativen Term Gewichtung ergibt sich die so genannte
    # "term frequency inverse document frequency"
    #
    #                            Anzahl von term in document                       Anzahl Dokumente
    # tfidf( term, document )  = ----------------------------   x   log ( ---------------------------------- )
    #                             Anzahl Woerter in document              Anzahl Dokumente die term enthalten
    #
    # http://www.tfidf.com
    #
    # Eklaeren Sie die Formel. Plotten Sie die inverse document frequency fuer jeden
    # Term ueber dem Brown Corpus.
    #
    # Implementieren und verwenden Sie die Klasse RelativeInverseDocumentWordFrequecies
    # im features Modul, in der Sie ein tfidf Gewichtungsschema umsetzen.
    # Ermitteln Sie die Gesamt- und klassenspezifischen Fehlerraten mit der Kreuzvalidierung.
    # Vergleichen Sie das Ergebnis mit der absolten und relativen Gewichtung.
    # Erklaeren Sie die Unterschiede in den klassenspezifischen Fehlerraten. Schauen Sie
    # sich dazu die Verteilungen der Anzahl Woerter und Dokumente je Kategorie aus aufgabe1
    # an. In wie weit ist eine Interpretation moeglich?

    tfidf = RelativeInverseDocumentWordFrequecies(vocabulary, cat_word_dict)
    rel_category_bow_dict = {
        cat: tfidf.weighting(category_bow_dict[cat])
        for cat in category_bow_dict
    }

    cross_validator = CrossValidation(category_bow_dict=rel_category_bow_dict,
                                      n_folds=n_folds)
    crossval_overall_result, crossval_class_results = cross_validator.validate(
        classifier)
    print("ran cross validation for {}-nearest neighbour (relative-inverse)".
          format(n_neighbours))
    print(crossval_overall_result)
    print(crossval_class_results)

    # Evaluieren Sie die beste Klassifikationsleistung
    #
    # Ermitteln Sie nun die Parameter fuer die beste Klassifikationsleistung des
    # k-naechste-Nachbarn Klassifikators auf dem Brown Corpus mit der Kreuzvalidierung.
    # Dabei wird gleichzeitig immer nur ein Parameter veraendert. Man hat eine lokal
    # optimale Parameterkonfiguration gefunden, wenn jede Aenderung eines Parameters
    # zu einer Verschlechterung der Fehlerrate fuehrt.
    #
    # Erlaeutern Sie warum eine solche Parameterkonfiguration lokal optimal ist.
    #
    # Testen Sie mindestens die angegebenen Werte fuer die folgenden Parameter:
    # 1. Groesse des Vokabulars typischer Woerter (100, 500, 1000, 2000)
    # 2. Gewichtung der Bag-of-Words Histogramme (absolute, relative, relative with inverse document frequency)
    # 3. Distanzfunktion fuer die Bestimmung der naechsten Nachbarn (Cityblock, Euclidean, Cosine)
    # 4. Anzahl der betrachteten naechsten Nachbarn (1, 2, 3, 4, 5, 6)
    #
    # Erklaeren Sie den Effekt aller Parameter.
    #
    # Erklaeren Sie den Effekt zwischen Gewichtungsschema und Distanzfunktion.

    # vocabulary sizes as specified
    voc_sizes = (100, 500, 1000, 2000)
    # weightings as specified
    weightings = ('abs', 'rel', 'tfidf')
    # metrices as specified
    dists = ("cityblock", "euclidean", "cosine")
    # numbers of neighbours as specified
    neighbours = (1, 2, 3, 4, 5, 6)

    # indices of best options, to keep track
    idx_vs = 0
    idx_wghts = 0
    idx_dsts = 0
    idx_nn = 0

    normalizer = WordListNormalizer()
    cat_word_dict = normalizer.category_wordlists_dict(corpus=brown)
    # Flatten the category word lists for computing overall word frequencies
    # The * operator expands the list/iterator to function arguments
    # itertools.chain concatenates all its parameters to a single list
    print 'Building Bag-of-Words vocabulary...'
    wordlists = itertools.chain(*(cat_word_dict.itervalues()))
    normalized_words = itertools.chain(*wordlists)
    vocabulary = BagOfWords.most_freq_words(normalized_words)

    #     print("normalizing")
    #     # normalizing
    #     normalizer = WordListNormalizer()
    #     # normalized words
    #     normalized_words = normalizer.normalize_words(brown.words())[1]
    #     print("normalized words")
    #     # normalized wordlists
    #     cat_word_dict = normalizer.category_wordlists_dict(brown)
    #     print("normalized wordlists")
    #
    #     # initializing the vocabulary at maximum size and then taking slices
    #     vocabulary = BagOfWords.most_freq_words(normalized_words, 2000)

    #     print('initializing configuration')
    #
    #     exp_config = ExpConfigurations(vocabulary ,cat_word_dict,
    #                                    voc_sizes, weightings, dists, neighbours)
    #     print(exp_config.run())
    #     for row in exp_config.__log:
    #         print(row)

    config = Configuration(brown, cat_word_dict, vocabulary, voc_sizes[idx_vs],
                           dists[idx_dsts], neighbours[idx_nn],
                           weightings[idx_wghts])
    config.fit()
    err_overall = config.eval()[0]

    # list of configuration results
    config_table = [['voc_sizes', 'metric', 'neighbours', 'weightings', 'err'],
                    [
                        voc_sizes[idx_vs], dists[idx_dsts], neighbours[idx_nn],
                        weightings[idx_wghts], err_overall
                    ]]

    print('calculating size')
    # local optimum for vocabulary size
    for idx, _ in enumerate(voc_sizes[1:]):
        tmp_config = Configuration(brown, cat_word_dict, vocabulary,
                                   voc_sizes[idx + 1], dists[idx_dsts],
                                   neighbours[idx_nn], weightings[idx_wghts])
        tmp_config.fit()
        tmp_err = tmp_config.eval()[0]
        if err_overall > tmp_err:
            err_overall = deepcopy(tmp_err)
            idx_vs = deepcopy(idx + 1)

        config_table.append([
            voc_sizes[idx + 1], dists[idx_dsts], neighbours[idx_nn],
            weightings[idx_wghts], tmp_err
        ])
    print(voc_sizes[idx_vs])

    print('calculating weights')
    # local optimum for weighting
    for idx, _ in enumerate(weightings[1:]):
        tmp_config = Configuration(brown, cat_word_dict, vocabulary,
                                   voc_sizes[idx_vs], dists[idx_dsts],
                                   neighbours[idx_nn], weightings[idx + 1])
        tmp_config.fit()
        tmp_err = tmp_config.eval()[0]
        if err_overall > tmp_err:
            err_overall = deepcopy(tmp_err)
            idx_wghts = deepcopy(idx + 1)

        config_table.append([
            voc_sizes[idx_vs], dists[idx_dsts], neighbours[idx_nn],
            weightings[idx + 1], tmp_err
        ])
    print(weightings[idx_wghts])

    print('calculating metric')
    # local optimum for metric
    for idx, _ in enumerate(dists[1:]):
        tmp_config = Configuration(brown, cat_word_dict, vocabulary,
                                   voc_sizes[idx_vs], dists[idx + 1],
                                   neighbours[idx_nn], weightings[idx_wghts])
        tmp_config.fit()
        tmp_err = tmp_config.eval()[0]
        if err_overall > tmp_err:
            err_overall = deepcopy(tmp_err)
            idx_dsts = deepcopy(idx + 1)

        config_table.append([
            voc_sizes[idx_vs], dists[idx + 1], neighbours[idx_nn],
            weightings[idx_wghts], tmp_err
        ])
    print(dists[idx_dsts])

    print('calculating neighbours')
    # local optimum for neighbours
    for idx, _ in enumerate(neighbours[1:]):
        tmp_config = Configuration(brown, cat_word_dict, vocabulary,
                                   voc_sizes[idx_vs], dists[idx_dsts],
                                   neighbours[idx + 1], weightings[idx_wghts])
        tmp_config.fit()
        tmp_err = tmp_config.eval()[0]
        if err_overall > tmp_err:
            err_overall = deepcopy(tmp_err)
            idx_nn = deepcopy(idx + 1)

        config_table.append([
            voc_sizes[idx_vs], dists[idx_dsts], neighbours[idx + 1],
            weightings[idx_wghts], tmp_err
        ])
    print(neighbours[idx_nn])

    # ideal should be 2000, relative, cityblock, 4
    print('local optimum at\nsize: {}\nweight: {}\nmetric: {}\nneighbours: {}'.
          format(voc_sizes[idx_vs], weightings[idx_wghts], dists[idx_dsts],
                 neighbours[idx_nn]))
    for row in config_table:
        print(row)
示例#19
0
    args = parser.parse_args()

    verbose = args.verbose
    terse = args.terse
    force_train = args.retrain
    use_tesseract = args.tesseract
    tesslangpath = args.tesslangpath

    segmenter = MinContourSegmenter(blur_y=5,
                                    blur_x=5,
                                    min_width=5,
                                    block_size=17,
                                    c=6,
                                    max_ratio=4.0)
    extractor = SimpleFeatureExtractor(feature_size=10, stretch=False)
    classifier = KNNClassifier(k=3)
    ocr = OCR(segmenter, extractor, classifier)

    for file_to_train in args.trainfile:
        training_image = ImageFile(file_to_train)
        if not training_image.isGrounded() or force_train:
            #trainingsegmenter = ContourSegmenter(blur_y=1, blur_x=1, min_width=3, min_height=15, max_height=50, min_area=30, block_size=23, c=3) # tweaked for black font
            trainingsegmenter = ContourSegmenter(
                blur_y=1,
                blur_x=1,
                min_width=3,
                min_height=15,
                max_height=50,
                min_area=30,
                block_size=3,
                c=5,