pip install numpy
pip install gensim
pip install tensorflow
mkdir embedding_models
Um normale Wordembeddings auf Tokenebene ohne POS Informationen oder Phrasen zu berechnen, kann das Script compute_models.py
verwendet werden.
Das Script kann entweder die Token direkt aus ES, der CWB oder einem tokenisierten Text (ein Token pro Zeile) berechnen.
Die Funktion für die WE-Berchnung ist folgende:
model = Word2Vec(texts,window=6,sorted_vocab=1,max_final_vocab=None,min_count=10,sample=1e-5,sg=1,workers=15)
Je nach Anwendungsfall müssen die Parameter angepasst werden, genauere Infos zu den Parametern: https://radimrehurek.com/gensim/models/word2vec.html#gensim.models.word2vec.Word2Vec.trainables
Der Code berechnet Wordembeddings und ruft den code get_data.py
auf um Daten aus Elasticsearch zu ziehen.
Der Code kann mehrere ES Abfragen machen, die key/value-Paare müssen beim Aufrufen einfach definiert werden:
pyhon3 compute_models.py -k source source source -v admin 20min blick -mn admin_20min_blick
Berechnet das WE-Modell für admin, 20min und blick zusammen und speichert das Modell unter embedding_models/admin_20min_blick.model
Für andere Parameter siehe -h Funktion.
get_data.py
Is the code that reads the specified data (lemma, ne, pos, words ... from the esclient)
Stream von Lemma mit <text>
Attributen aus der CWB lesen
$cwb-decode -Cx [CWB-Korpusname] -S text -P lemma
Damit die gewünschten Tokens direkt in das compute_models.py
script gelesen werden können:
$cwb-decode -Cx [CWB-Korpusname] -S text -P lemma | python3 compute_models.py -cwb True -mn cwb_test
Wenn -cwb
auf True gesetzt ist, bedeuted dass, das der Input ein Tokenstream aus der CWB ist, die -s
-flag bezieht sich auf das s-attribut, welches die Tokens auftrennt, default ist text aber es kann bei -s
definiert werden.
python3 compute_models.py -f [FILENAME]
Das File besteht aus einem Lemma/Wort pro Zeile.
Script: compute_pos_models.py
Berechnet WE nicht auf dem reinen Lemma aber auf Lemma_pos -> disambiguierung und einfachere Abfrage von Wortarten bei der Analyse von WE
-> Damit Artikelnamen etc. als 1 Token gesehen werden, Mehrwortausdrücke (MWA) werden so einfacher identifiziert
Dieser approach eignet sich sehr v.a. für romanische Sprachen, welche häufig MWA (Mehrwortausdrücke) haben. MWA lassen sich über Kookurrenzen herausfinden und gensim hat eine 'Phrase-Funktion', welche bigramme berechnen kann und die Wörter im Modell mit einem gewünschten Zeichen verbindet. Der wiederholte Aufruf der Funktion ermöglicht es ngramme zu finden und jeweils zusammenzufügen. Im Moment berechnet der Code bi und trigramme, aber wenn zwei bigramme aufeinanderfolgend signifikant sind werden auch 4gramme gebildet.
# mit -P word, wenn mal Zahlen etc. beibehalten will sonst mit -P lemma
$ cwb-decode -Cx [CWB-Korpusname] -S text -P lemma | python3 compute_phrase_models.py -cwb True -mn bbl_bge_all_de_trigram -max None
Folgender Teil des Codes berechnet ngramme:
phrases = Phrases(docs,min_count=5,threshold=10,delimiter=b"_")
bigram_phraser = Phraser(phrases)
phrased_texts = {}
for i in range(0,len(texts)-1):
tokens = bigram_phraser[texts[ids[i]]]
phrased_texts[ids[i]] = tokens
phr_docs = [doc for id_,doc in sorted(phrased_texts.items())]
tri_phrases = Phrases(phr_docs,min_count=5,threshold=5,delimiter=b"_")
trigram_pharser = Phraser(tri_phrases)
tri_phrased_texts = {}
count = 1
for i in range(0,len(texts)-1):
tokens = trigram_pharser[phrased_texts[ids[i]]]
tri_phrased_texts[ids[i]]=tokens
Die Funktion Phrases()
setzt die Parameter für die 'Erkennung' von Phrasen, also in welchen Texten (hier docs
), Mindestvorkommnis der Phrase (min_count=5
), der Mindestwert der Phrasenberechnung (eine Art Score, der die Signifikanz der Phrase bewertet, wenn es nicht ein NPMI scoring ist, dann ist ein Score zwischen 5 und 15 sinnvoll vgl. https://arxiv.org/abs/1310.4546 , NPMI geht nur von -1 bis 1, vgl. https://svn.spraakdata.gu.se/repos/gerlof/pub/www/Docs/npmi-pfd.pdf ), die entdeckten Phrasen werden mit dem Delimiter-Zeichen verbunden (hier delimiter=b'_'
), welches als byte encoded werden muss, darum das b vor dem String.
Nachdem die Phrasen berechnet wurden, werden sie mit der Phraser()
-Funktion angewendet. Dann iteriert man über den Text und es wird ein dictionary generiert in der Form {textid:"text"}, in einem ersten Schritt für bigramme.
Um auch längere Phrasen zu erkennen, wird ein neues Phrases Modell berechnet, mit einem nicht so hohen threshold (kann je nach Anwendungsfall angepasst werden), tendenziell sind aber längere Phrasen weniger signifikant, da sie weniger oft vorkommen.
Das neu generierte Korpus mit den markierten Phrasen wird als JSON file gespeichert und ein WE modell wird auf dem Text inkl. markierte Phrasen berechnet.
['Urteilskopf_88', 'IV123', '33', '.', 'Auszug_aus_dem', 'Urteil_des_Kassationshofes', 'vom_26', '.', 'Oktober_1962_i.S.', 'Schlüchter', 'gegen', 'Schrag', 'und', 'Verlag', 'des', 'Schweiz.', 'Kaufmännischen_Vereins', 'sowie', 'Staatsanwaltschaft_des_Kantons', 'Zürlch', '.', 'Regeste_Art.', '1', 'Abs._2', ',', 'Art._42_Ziff._1', 'lit._a', 'und', 'b', 'URG', '.', '1', '.', 'Das', 'Urheberrecht_an', 'einem', 'Lehrbuch', 'ist', 'auch', 'verletzt', ',', 'wenn', 'das_Werk', 'in', 'seinen_charakteristischen', 'Grundzügen', ',', 'namentlich_hinsichtlich', 'Planung', ',', 'Auswahl', 'und', 'Erfassen', 'des_Stoffes', 'oder', 'Anordnung', 'und', 'Gliederung', 'desselben', ',', 'übernommen', 'wird', '(_Erw.', '1', ')', '.', '2', '.', 'An', 'Übungen', 'und', 'Anleitungen', 'eines', 'Lehrbuches', 'für', 'Maschinenschreiben', 'besteht', 'Urheberrecht', ',', 'wenn_sie', 'originelles', 'Ergebnis', 'geistigen_Schaffens', 'sind', '(_Erw._2', ')', '.', '3', '.', 'Zum_Verhältnis', 'von', 'Art._42_Ziff._1', 'lit._a', 'zu', '43_Ziff.', '2_URG', '(_Erw._3', ')', '.', '4', '.', 'Mit', 'Werk_im_Sinne', 'des', 'Art._42_Ziff._1', 'lit._b', 'URG', 'ist', 'nicht', 'das', 'wiedergebende', ',', 'sondern', 'das', 'wiedergegebene', 'gemeint', '(_Erw._4', ')', '.', 'Sachverhalt_ab_Seite', '124', 'A._-', 'Fritz', 'Schrag', ',', 'Lehrer', 'an', 'der', 'Kantonalen', 'Handelsschule', 'in', 'Zürich', ',', 'verfasste', 'ein', 'Lehrbuch', 'für', 'Maschinenschreiben', ',', 'das', '1958', 'im', 'Verlag', 'des_Schweizerischen_Kaufmännischen', 'Vereins', 'in', 'neunter', 'Auflage', 'erschien', '.', 'Das', 'Kaufmännische', 'Lehrinstitut', 'in', 'Zürich', 'erteilte', 'unter', 'der', 'Leitung', 'von', 'Hans', 'Schlüchter', 'Fernkurse', 'für', 'Maschinenschreiben', ',', 'wobei', 'den', 'Schülern', 'fünf', 'Lehrhefte', 'zugestellt_wurden', '.', 'Das', 'letzte', 'Heft', ',', 'welches', 'die', 'Seiten', '55', 'bis', '71', 'des', 'Lehrganges', 'umfasste', ',', 'wurde', 'von', 'Heidi_Schlüchter', 'zusammengestellt', ',', 'vervielfältigt', 'und', 'bis', '1', '.', 'April_1958', 'an', 'ungefähr', 'zwanzig', 'Schüler', 'versandt', '.', 'Schrag', 'hielt', 'den', 'Lehrgang', 'Schlüchters', 'für', 'ein', 'Plagiat', 'seines', 'Lehrbuches', 'und', 'stellte', 'Strafantrag_wegen_Verletzung', 'von_Urheberrechten', '.', 'B._-', 'Das_Obergericht_des_Kantons', 'Zürich', 'erklärte', 'als_Berufungsinstanz', 'am', '4', '.', 'Mai_1961', 'Heidi_Schlüchter', 'der', 'Übertretung', 'von', 'Art._42_Ziff._1', 'lit._a', 'und', 'b', 'URG', 'schuldig', 'und', 'verurteilte_sie', 'zu', 'einer_bedingt_vorzeitig', 'löschbaren_Busse_von', 'Fr._150', '.', '-.', 'Den', 'Werkcharakter', 'des', 'Lehrbuches', 'von', 'Schrag', 'bejahte', 'es', 'vor_allem', 'aus_folgenden_Gründen', ':', 'Entscheidend_sei', ',', 'dass', 'über', 'ein_blosses', 'quantitatives', 'Zusammenstellen', 'eines_Stoffes', 'hinaus', 'eine', 'qualitative', 'und', 'einigermassen', 'originelle', 'wissenschaftliche_Bearbeitung', 'stattgefunden_habe', '.', 'Freilich', 'habe', 'die', 'Gebundenheit', 'an', 'die', 'Tastaturanordnung', ',', 'an', 'das', 'Zehnfingersystem', ',', 'an', 'die', 'Schrift', 'und', 'auch', 'an', 'den', 'Stoff', 'dem', 'individuell-schöpferischen', 'Schaffen', 'keinen', 'grossen_Spielraum', 'gelassen', ';', 'dennoch', 'sei', 'unverkennbar', ',',
Mit dem Code visualize_we.py
können die berechneten Modelle gleichzeitig visualisiert werden. Der Code greift auf alle vorberechneten Modelle im spezifizierten Ordner (default 'embedding_models') zu und wandelt sie in einen Tensorboard-Graphen um. Alle nötigen files werden, wenn nicht anderst definiert im Ordner 'tensorboard_test' abgespeichert. Es kann aber auch ein anderer Zielordner definiert werden.
Damit Tensorboard auf die Modelle zugreifen kann muss die Visualisierung gestartet werden. Mit dem Befehl:
tensorboard --logdir="tensorboard_test/" --port [SET PORT]
kann die Visualisierung gestartet werden.
Idealerweise startet man die Visualisierung in nohup, damit das tensorboard aktiv bleibt auch wenn man sich ausloggt:
$ nohup tensorboard --logdir="tensorboard_test/" --port [SET PORT] &
Das Script haben wir für die Rechtspopulismus Analyse gebraucht.
Script: compare_models.py
-> berechnet pro Wort in Modell 1 die cosine_sim zum gleichen Wort in Modell2
vgl. docs/populismus experiments.md
für mehr Infos.
Im Terminal den python3 interpreter starten: (das $-Zeichen zeigt eine Terminal eingabe an, muss nicht abgetippt werden)
Voraussetzung ist die Installation von gensim (https://radimrehurek.com/gensim/install.html) (normalerweise: pip3 install gensim/pip install gensim)
$ python3
[infos zu python3]
>>> from gensim.models.keyedvectors import KeyedVectors
>>> model = KeyedVectors.load('[MODELNAME.model]')
>>> model.most_similar('Digitalisierung')
[('Langzeitarchivierung', 0.8689799904823303), ('digital', 0.840603768825531), ('Bildplatte', 0.8246514797210693), ('multimedialen', 0.8082578182220459), ('Sammelauftrag', 0.8074219822883606), ('filmisch', 0.8007779717445374), ('Fernsehfilm', 0.8005862236022949), ('Computerspiel', 0.7991310358047485), ('Radiobereich', 0.7987841367721558), ('Spartenprogramm', 0.794711709022522)]
-> Zeigt die top 10 NN von 'Digitalisierung' an, inkl. Cosinus Ähnlichkeit
>>> model.most_similar('Person',topn=100)
# topn=INT -> anzahl der NN, die man sich anzeigenlassen will.
um den Interprerter zu beenden:
>>> exit()
Unter https://radimrehurek.com/gensim/models/keyedvectors.html hat es gute Beispiele für andere mögliche Abfragen mit gensim