Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    def test_cross_validation(self):
        cfg = Config()
        axi = xapian.Database(cfg.axi)
        packages = ["gimp","aaphoto","eog","emacs","dia","ferret",
                    "festival","file","inkscape","xpdf"]
        path = "test_data/.sample_axi"
        sample_axi = SampleAptXapianIndex(packages,axi,path)
        rec = Recommender(cfg)
        rec.items_repository = sample_axi
        user = User({"gimp":1,"aaphoto":1,"eog":1,"emacs":1})

        metrics = []
        metrics.append(Precision())
        metrics.append(Recall())
        metrics.append(F1())

        validation = CrossValidation(0.3,5,rec,metrics,0.5)
        validation.run(user)
        print validation
Exemplo n.º 3
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

    ####### +++++ 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
Exemplo n.º 4
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')
Exemplo n.º 5
0
class Configuration(object):
    '''
    '''
    def __init__(self,
                 b_corpus,
                 cat_word_dict,
                 vocab,
                 voc_size,
                 dist_metric,
                 n_neighbours,
                 weighting='abs'):
        '''
        '''
        self.b_corpus = b_corpus
        self.__vocab = vocab[:voc_size]
        self.__metric = dist_metric
        self.__nn = n_neighbours
        self.__classifier = None
        self.__cross_validator = None

        # bow-matrices by category
        bow = BagOfWords(self.__vocab)
        self.category_bow_dict = bow.category_bow_dict(cat_word_dict)

        if weighting == 'abs':
            self.__wght = lambda x: x
        elif weighting == 'rel':
            self.__wght = RelativeTermFrequencies.weighting
        elif weighting == 'tfidf':
            tfidf = RelativeInverseDocumentWordFrequecies(
                self.__vocab, cat_word_dict)
            self.__wght = tfidf.weighting

    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)

    def eval(self, feature_trans=None):
        if feature_trans is None:
            feature_trans = IdentityFeatureTransform()
        return self.__cross_validator.validate(self.__classifier,
                                               feature_transform=feature_trans)


#
# class ExpConfigurations:
#
#     def __init__(self, vocabulary, cat_wordlist_dict, voc_sizes=[], weightings=[], metrices=[], neighbours=[], ):
#         self.__voc_szs = voc_sizes
#         self.__wghts = weightings
#         self.__mtrcs = metrices
#         self.__nghbrs = neighbours
#
#         self.__log = ["size", "weighting", "metric", "n_neighbours", "error"]
#         self.__classifier = None
#         self.__bow = None
#
#         self.__vocab = vocabulary
#         self.cat_wordlist_dict = cat_wordlist_dict
#
#
#     def run(self):
#         # all possible configurations
#         for vs in self.__voc_szs:
#             for wght in self.__wghts:
#                 for metric in self.__mtrcs:
#                     for nn in self.__nghbrs:
#                         # adding to the log
#                         self.__classifier = KNNClassifier(nn, metric)
#                         self.__log.append([vs, wght, metric, nn,
#                                            self.eval(vs, wght)])
#         # best result
#         return self.best()
#
#
#     def eval(self, vocab_size, weighting):
#         # bow
#         self.__bow = BagOfWords(self.__vocab[:vocab_size])
#         category_bow_dict = self.__bow.category_bow_dict(self.cat_wordlist_dict)
#
#         # weighting function
#         if weighting == 'abs':
#             wght = lambda x : x
#         elif weighting == 'rel':
#             wght = RelativeTermFrequencies.weighting
#         elif weighting == 'tfidf':
#             tfidf = RelativeInverseDocumentWordFrequecies(self.__vocab, self.cat_wordlist_dict)
#             wght = tfidf.weighting
#
#
#         wght_category_bow_dict = {cat : wght(category_bow_dict[cat])
#                                  for cat in category_bow_dict}
#         n_folds = 5
#
#         c_val = CrossValidation(category_bow_dict=wght_category_bow_dict, n_folds=n_folds)
#         return c_val.validate(self.__classifier)
#
#
#     def best(self):
#         res = self.__log[1:]
#         if res:
#             best = deepcopy(res[0])
#             for r in res[1:]:
#                 if best[4][0] > r[4][0]:
#                     best = deepcopy(r)
#             return best
#         return None
Exemplo n.º 6
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)
Exemplo n.º 7
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)
Exemplo n.º 8
0
from user import RandomPopcon,LocalSystem,PopconSystem

if __name__ == '__main__':
    cfg = Config()
    rec = Recommender(cfg)
    #user = LocalSystem()
    #user = RandomPopcon(cfg.popcon_dir)
    #user = RandomPopcon(cfg.popcon_dir,os.path.join(cfg.filters_dir,"desktopapps"))
    user = PopconSystem(os.path.expanduser("~/.app-recommender/popcon-entries/00/0001166d0737c6dffb083071e5ee69f5"))
    user.filter_pkg_profile(os.path.join(cfg.filters_dir,"desktopapps"))
    user.maximal_pkg_profile()
    begin_time = datetime.datetime.now()

    metrics = []
    metrics.append(Precision())
    metrics.append(Recall())
    metrics.append(F_score(0.5))
    metrics.append(Accuracy())
    metrics.append(FPR())
    validation = CrossValidation(0.9,20,rec,metrics,0.005)
    validation.run(user)
    print validation

    end_time = datetime.datetime.now()
    delta = end_time - begin_time
    logging.info("Cross-validation for user %s" % user.user_id)
    logging.info("Recommender strategy: %s" % rec.strategy.description)
    logging.debug("Cross-validation started at %s" % begin_time)
    logging.debug("Cross-validation completed at %s" % end_time)
    logging.info("Time elapsed: %d seconds." % delta.seconds)
Exemplo n.º 9
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!
    # *********************************************************************************

    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 , 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.
    

        
    normalized_words = WordListNormalizer().normalize_words(brown.words())[1]
#     vocabulary = BagOfWords.most_freq_words(normalized_words, 500)
#     word_bag = BagOfWords(vocabulary)
# 
#     bow_mat = {}
#     for cat in brown.categories():
#         bow_mat[cat] = [WordListNormalizer().normalize_words(brown.words(fileids=doc))[1] for doc in brown.fileids(categories=cat)]
#     category_dic = word_bag.category_bow_dict(bow_mat)
# 
#     cross_validator = CrossValidation(category_dic, 5)
# 
#     first_fold = cross_validator.corpus_fold(0)
#     second_fold = cross_validator.corpus_fold(1)
#     third_fold = cross_validator.corpus_fold(2)
#     fourth_fold = cross_validator.corpus_fold(3)
#     fifth_fold = cross_validator.corpus_fold(4)
# 
#     classificator = KNNClassifier(1, 'euclidean')
# 
#     classificator.estimate(first_fold[0], first_fold[1])
#     result_first_fold = classificator.classify(first_fold[2])
# 
#     classificator.estimate(second_fold[0], second_fold[1])
#     result_second_fold = classificator.classify(second_fold[2])
# 
#     classificator.estimate(third_fold[0], third_fold[1])
#     result_third_fold = classificator.classify(third_fold[2])
# 
#     classificator.estimate(fourth_fold[0], fourth_fold[1])
#     result_fourth_fold = classificator.classify(fourth_fold[2])
# 
#     classificator.estimate(fifth_fold[0], fifth_fold[1])
#     result_fifth_fold = classificator.classify(fifth_fold[2])
# 
#     eval_first_fold = ClassificationEvaluator(result_first_fold, first_fold[3])
#     eval_second_fold = ClassificationEvaluator(result_second_fold, second_fold[3])
#     eval_third_fold = ClassificationEvaluator(result_third_fold, third_fold[3])
#     eval_fourth_fold = ClassificationEvaluator(result_fourth_fold, fourth_fold[3])
#     eval_fifth_fold = ClassificationEvaluator(result_fifth_fold, fifth_fold[3])
# 
#     list_eval_folds =[]
#     list_eval_folds.append(eval_first_fold.error_rate()[0])
#     list_eval_folds.append(eval_second_fold.error_rate()[0])
#     list_eval_folds.append(eval_third_fold.error_rate()[0])
#     list_eval_folds.append(eval_fourth_fold.error_rate()[0])
#     list_eval_folds.append(eval_fifth_fold.error_rate()[0])
#     np_array_eval_folds = np.array(list_eval_folds)
#     print np_array_eval_folds
#     mittelwert = np.mean(np_array_eval_folds)
#     print "Mittelwert"
#     print mittelwert
#     print "++++++++++++"
#     print "Minimum"
#     print np.min(np_array_eval_folds, axis=0)


    # 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.

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

#     word_dic_category = {}
#     for cat in brown.categories():
#         word_dic_category[cat] = [WordListNormalizer().normalize_words(brown.words(fileids = doc))[1] for doc in brown.fileids(categories=cat)]
#     category_word_dic = word_bag.category_bow_dict(word_dic_category)
# 
#     category_weighted = {}
#     for key in category_word_dic:
#         category_weighted[key] = RelativeTermFrequencies.weighting(category_word_dic[key])

    # 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?

#    raise NotImplementedError('Implement me')


    # Evaluieren Sie die beste Klassifikationsleistung
    #
    # Ermitteln Sie nun die Parameter fuer die bester 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.
    print "+++++++++++++++++++++++++++++++++++++++++++++++"
    print "Testfunktion"
    
    vocab_size = 2000
    distance_function="cityblock"
    knn=6
    #print "vocabsize:"  + vocab_size +"; distance" + distance_function +"; knn" + knn
    vocabulary = BagOfWords.most_freq_words(normalized_words, vocab_size)
    word_bag = BagOfWords(vocabulary)

    bow_mat = {}
    for cat in brown.categories():
        bow_mat[cat] = [WordListNormalizer().normalize_words(brown.words(fileids=doc))[1] for doc in brown.fileids(categories=cat)]
    category_dic = word_bag.category_bow_dict(bow_mat)
    relative_category_dict = {}
    for key in category_dic:
        relative_category_dict[key] = RelativeTermFrequencies.weighting(category_dic[key])
    cross_validator = CrossValidation(relative_category_dict, 5)

    classificator = KNNClassifier(knn, distance_function)
    print cross_validator.validate(classificator)
Exemplo n.º 10
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.
    #
    # 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.
    
    zeilen, spalten = samples_2d.shape
    print zeilen, spalten
    mean_xy = np.mean(samples_2d, axis=0)
 
    samples_2d_mf = samples_2d - mean_xy
    kovarianz_mat = np.dot(samples_2d_mf.T, samples_2d_mf)/(zeilen-1)
     
    print "kovarianz ausgerechnet"
    print kovarianz_mat
  
    kovarianz_referenz = np.cov(samples_2d, rowvar=0)
    print "kovarianz referenz"
    print kovarianz_referenz
    
    
    #
    # 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. 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
    # 0 verschieden sind.
    #
    # 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? 
    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 im 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]])
    
    n_topics = 3
    top_feature_trans = TopicFeatureTransform(n_topics)
    top_feature_trans.estimate(bow_train, bow_train)
    bow_transformed = top_feature_trans.transform(bow_test)
    bow_train_transformed = top_feature_trans.transform(bow_train)
     
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    PCAExample.plot_sample_data(bow_train_transformed, annotations=bow_train, ax=ax)
    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_transformed, annotations=bow_test, ax=ax)
    PCAExample.set_axis_limits(ax, limits=((-1, 1), (-1, 1), (-1, 1)))
    plt.show()
        
    #
    # Warum lassen sich die Koeffizienten der Termvektoren so schwer interpretieren?
    # 
    # 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 die Funktion 'hold' des Axes Objekts mit dem Parameter 
    # 'True' aufrufen. 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. 
    
#     #Bag of words plots
#     fig = plt.figure()
#     ax = fig.add_subplot(111, projection='3d')
#     PCAExample.plot_sample_data(bow_train, color='r', annotations=bow_train, ax=ax)
#     fig.hold(True)
#     PCAExample.plot_sample_data(bow_test, color='g', annotations=bow_test, ax=ax)
#     PCAExample.set_axis_limits(ax, limits=((0, 10), (0, 10), (0,10)))
#     fig.hold()
#     
#     
#     #koeffizienten plot
# #     T_test, S_arr_test, D_test_ = np.linalg.svd(bow_test.T, full_matrices=False)
# #     S_test = np.diag(S_arr_test)
#     
#     n_topics = 3
#     top_feature_trans = TopicFeatureTransform(n_topics)
#     top_feature_trans.estimate(bow_train, None)
#     test_daten = top_feature_trans.transform(bow_test)
#     train_daten = top_feature_trans.transform(bow_train)
#     fig = plt.figure()
#     ax = fig.add_subplot(111, projection='3d')
#     PCAExample.plot_sample_data(D_.T, color='r', annotations=bow_train, ax=ax)
#     fig.hold(True)
#     PCAExample.plot_sample_data(D_test_.T, color='g', annotations=bow_test, ax=ax)
#     PCAExample.set_axis_limits(ax, limits=((-1, 1), (-1, 1), (-1,1)))
#     fig.hold()
    
        
    #
    # 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. 
    #
    
    n_topics = 2
    top_feature_trans = TopicFeatureTransform(n_topics)
    top_feature_trans.estimate(bow_train, bow_train)
    bow_transformed = top_feature_trans.transform(bow_test)
    bow_train_transformed = top_feature_trans.transform(bow_train)
     
    fig = plt.figure()
    ax = fig.add_subplot(111)
    PCAExample.plot_sample_data(bow_train_transformed, annotations=bow_train, ax=ax)
    PCAExample.set_axis_limits(ax, limits=((-1, 1), (-1, 1)))
     
    fig = plt.figure()
    ax = fig.add_subplot(111)
    PCAExample.plot_sample_data(bow_transformed, annotations=bow_test, ax=ax)
    PCAExample.set_axis_limits(ax, limits=((-1, 1), (-1, 1)))
    plt.show()
    
#     S_inv = np.linalg.inv(S)
#     S_inv_test = np.linalg.inv(S_test)
#     
#     T = T[:n_topics]
#     S_inv = S_inv[:n_topics,:n_topics]
#     T_test = T_test[:n_topics]
#     S_inv_test = S_inv_test[:n_topics,:n_topics]
#     
#     data_trans = np.dot(np.dot(bow_train, T.T), S_inv)
#     data_trans_test = np.dot(np.dot(bow_test, T_test.T), S_inv_test)
#     
    
#     fig = plt.figure()
#     ax = fig.add_subplot(111)
#     PCAExample.plot_sample_data(data_trans, color='r', annotations=bow_train, ax=ax)
#     fig.hold(True)
#     PCAExample.plot_sample_data(data_trans_test, color='g', annotations=bow_test, ax=ax)
#     PCAExample.set_axis_limits(ax, limits=((-1, 1), (-1, 1)))
#     fig.hold()
#     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()
    
    normalized_words = WordListNormalizer().normalize_words(brown.words())[1]
    
    vocab_size = 2000
    distance_function="cosine"
    knn=6
    vocabulary = BagOfWords.most_freq_words(normalized_words, vocab_size)
    word_bag = BagOfWords(vocabulary)

    bow_mat = {}
    for cat in brown.categories():
        bow_mat[cat] = [WordListNormalizer().normalize_words(brown.words(fileids=doc))[1] for doc in brown.fileids(categories=cat)]
    category_dic = word_bag.category_bow_dict(bow_mat)

    cross_validator = CrossValidation(category_dic, 5)

    classificator = KNNClassifier(knn, distance_function)
    print cross_validator.validate(classificator, TopicFeatureTransform(20))