20 KiB
Komputerowe wspomaganie tłumaczenia
3. Terminologia [laboratoria]
Rafał Jaworski (2021)
Na dzisiejszych zajęciach zajmiemy się bliżej słownikami używanymi do wspomagania tłumaczenia. Oczywiście na rynku dostępnych jest bardzo wiele słowników w formacie elektronicznym. Wiele z nich jest gotowych do użycia w SDL Trados, memoQ i innych narzędziach CAT. Zawierają one setki tysięcy lub miliony haseł i oferują natychmiastową pomoc tłumaczowi.
Problem jednak w tym, iż często nie zawierają odpowiedniej terminologii specjalistycznej - używanej przez klienta zamawiającego tłumaczenie. Terminy specjalistyczne są bardzo częste w tekstach tłumaczonych ze względu na następujące zjawiska:
- Teksty o tematyce ogólnej są tłumaczone dość rzadko (nikt nie tłumaczy pocztówek z pozdrowieniami z wakacji...)
- Te same słowa mogą mieć zarówno znaczenie ogólne, jak i bardzo specjalistyczne (np. "dziedziczenie" w kontekście prawnym lub informatycznym)
- Klient używa nazw lub słów wymyślonych przez siebie, np. na potrzeby marketingowe.
Nietrywialnymi zadaniami stają się: odnalezienie terminu specjalistycznego w tekście źródłowym oraz podanie prawidłowego tłumaczenia tego terminu na język docelowy
Brzmi prosto? Spróbujmy wykonać ręcznie tę drugą operację.
Ćwiczenie 1: Podaj tłumaczenie terminu "prowadnice szaf metalowych" na język angielski. Opisz, z jakich narzędzi skorzystałaś/eś.
Odpowiedź: "metal cabinet guides". https://translate.google.pl/
W dalszych ćwiczeniach skupimy się jednak na odszukaniu terminu specjalistycznego w tekście. W tym celu będą potrzebne dwie operacje:
- Przygotowanie słownika specjalistycznego.
- Detekcja terminologii przy użyciu przygotowanego słownika specjalistycznego.
Zajmijmy się najpierw krokiem nr 2 (gdyż jest prostszy). Rozważmy następujący tekst:
text = " For all Java programmers:"
text += " This section explains how to compile and run a Swing application from the command line."
text += " For information on compiling and running a Swing application using NetBeans IDE,"
text += " see Running Tutorial Examples in NetBeans IDE. The compilation instructions work for all Swing programs"
text += " — applets, as well as applications. Here are the steps you need to follow:"
text += " Install the latest release of the Java SE platform, if you haven't already done so."
text += " Create a program that uses Swing components. Compile the program. Run the program."
Załóżmy, że posiadamy następujący słownik:
dictionary = ['program', 'application', 'applet', 'compile']
Ćwiczenie 2: Napisz program, który wypisze pozycje wszystkich wystąpień poszczególnych terminów specjalistycznych. Dla każdego terminu należy wypisać listę par (pozycja_startowa, pozycja końcowa).
import re
def terminology_lookup():
result = []
regex = ''
for word in dictionary:
if regex != '':
regex += '|'
regex += '(' + word + ')'
for occurrence in re.finditer(regex, text, re.I):
result.append((occurrence.group(), occurrence.start(), occurrence.end()))
return result
Zwykłe wyszukiwanie w tekście ma pewne wady. Na przykład, gdy szukaliśmy słowa "program", złapaliśmy przypadkiem słowo "programmer". Złapaliśmy także słowo "programs", co jest poprawne, ale niepoprawnie podaliśmy jego pozycję w tekście.
Żeby poradzić sobie z tymi problemami, musimy wykorzystać techniki przetwarzania języka naturalnego. Wypróbujmy pakiet spaCy:
pip3 install spacy
oraz
python3 -m spacy download en_core_web_sm
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp(text)
for token in doc:
print(token.lemma_)
[1;31m---------------------------------------------------------------------------[0m [1;31mKeyboardInterrupt[0m Traceback (most recent call last) Cell [1;32mIn[1], line 1[0m [1;32m----> 1[0m [38;5;28;01mimport[39;00m [38;5;21;01mspacy[39;00m [0;32m 2[0m nlp [38;5;241m=[39m spacy[38;5;241m.[39mload([38;5;124m"[39m[38;5;124men_core_web_sm[39m[38;5;124m"[39m) [0;32m 4[0m doc [38;5;241m=[39m nlp(text) File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\__init__.py:13[0m [0;32m 10[0m [38;5;66;03m# These are imported as part of the API[39;00m [0;32m 11[0m [38;5;28;01mfrom[39;00m [38;5;21;01mthinc[39;00m[38;5;21;01m.[39;00m[38;5;21;01mapi[39;00m [38;5;28;01mimport[39;00m Config, prefer_gpu, require_cpu, require_gpu [38;5;66;03m# noqa: F401[39;00m [1;32m---> 13[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m [38;5;28;01mimport[39;00m pipeline [38;5;66;03m# noqa: F401[39;00m [0;32m 14[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m [38;5;28;01mimport[39;00m util [0;32m 15[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mabout[39;00m [38;5;28;01mimport[39;00m __version__ [38;5;66;03m# noqa: F401[39;00m File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\pipeline\__init__.py:1[0m [1;32m----> 1[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mattributeruler[39;00m [38;5;28;01mimport[39;00m AttributeRuler [0;32m 2[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mdep_parser[39;00m [38;5;28;01mimport[39;00m DependencyParser [0;32m 3[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01medit_tree_lemmatizer[39;00m [38;5;28;01mimport[39;00m EditTreeLemmatizer File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\pipeline\attributeruler.py:8[0m [0;32m 6[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m [38;5;28;01mimport[39;00m util [0;32m 7[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m[38;5;21;01merrors[39;00m [38;5;28;01mimport[39;00m Errors [1;32m----> 8[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m[38;5;21;01mlanguage[39;00m [38;5;28;01mimport[39;00m Language [0;32m 9[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m[38;5;21;01mmatcher[39;00m [38;5;28;01mimport[39;00m Matcher [0;32m 10[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m[38;5;21;01mscorer[39;00m [38;5;28;01mimport[39;00m Scorer File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\language.py:43[0m [0;32m 41[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mlang[39;00m[38;5;21;01m.[39;00m[38;5;21;01mtokenizer_exceptions[39;00m [38;5;28;01mimport[39;00m BASE_EXCEPTIONS, URL_MATCH [0;32m 42[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mlookups[39;00m [38;5;28;01mimport[39;00m load_lookups [1;32m---> 43[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mpipe_analysis[39;00m [38;5;28;01mimport[39;00m analyze_pipes, print_pipe_analysis, validate_attrs [0;32m 44[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mschemas[39;00m [38;5;28;01mimport[39;00m ( [0;32m 45[0m ConfigSchema, [0;32m 46[0m ConfigSchemaInit, [1;32m (...)[0m [0;32m 49[0m validate_init_settings, [0;32m 50[0m ) [0;32m 51[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mscorer[39;00m [38;5;28;01mimport[39;00m Scorer File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\pipe_analysis.py:6[0m [0;32m 3[0m [38;5;28;01mfrom[39;00m [38;5;21;01mwasabi[39;00m [38;5;28;01mimport[39;00m msg [0;32m 5[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01merrors[39;00m [38;5;28;01mimport[39;00m Errors [1;32m----> 6[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mtokens[39;00m [38;5;28;01mimport[39;00m Doc, Span, Token [0;32m 7[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mutil[39;00m [38;5;28;01mimport[39;00m dot_to_dict [0;32m 9[0m [38;5;28;01mif[39;00m TYPE_CHECKING: [0;32m 10[0m [38;5;66;03m# This lets us add type hints for mypy etc. without causing circular imports[39;00m File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\tokens\__init__.py:1[0m [1;32m----> 1[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m_serialize[39;00m [38;5;28;01mimport[39;00m DocBin [0;32m 2[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mdoc[39;00m [38;5;28;01mimport[39;00m Doc [0;32m 3[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mmorphanalysis[39;00m [38;5;28;01mimport[39;00m MorphAnalysis File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\tokens\_serialize.py:14[0m [0;32m 12[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m[38;5;21;01merrors[39;00m [38;5;28;01mimport[39;00m Errors [0;32m 13[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m[38;5;21;01mutil[39;00m [38;5;28;01mimport[39;00m SimpleFrozenList, ensure_path [1;32m---> 14[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m.[39;00m[38;5;21;01mvocab[39;00m [38;5;28;01mimport[39;00m Vocab [0;32m 15[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01m_dict_proxies[39;00m [38;5;28;01mimport[39;00m SpanGroups [0;32m 16[0m [38;5;28;01mfrom[39;00m [38;5;21;01m.[39;00m[38;5;21;01mdoc[39;00m [38;5;28;01mimport[39;00m DOCBIN_ALL_ATTRS [38;5;28;01mas[39;00m ALL_ATTRS File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\vocab.pyx:1[0m, in [0;36minit spacy.vocab[1;34m()[0m File [1;32mj:\.AppData\Python\Python310\site-packages\spacy\tokens\doc.pyx:1[0m, in [0;36minit spacy.tokens.doc[1;34m()[0m File [1;32m<frozen importlib._bootstrap>:404[0m, in [0;36mparent[1;34m(self)[0m [1;31mKeyboardInterrupt[0m:
Sukces! Nastąpił podział tekstu na słowa (tokenizacja) oraz sprowadzenie do formy podstawowej każdego słowa (lematyzacja).
Ćwiczenie 3: Zmodyfikuj program z ćwiczenia 2 tak, aby zwracał również odmienione słowa. Na przykład, dla słowa "program" powinien znaleźć również "programs", ustawiając pozycje w tekście odpowiednio dla słowa "programs". Wykorzystaj właściwość idx tokenu.
def terminology_lookup():
result = []
for token in doc:
if token.lemma_ in dictionary:
result.append((token, token.idx, token.idx + len(token)))
return result
Teraz czas zająć się problemem przygotowania słownika specjalistycznego. W tym celu napiszemy nasz własny ekstraktor terminologii. Wejściem do ekstraktora będzie tekst zawierający specjalistyczną terminologię. Wyjściem - lista terminów.
Przyjmijmy następujące podejście - terminami specjalistycznymi będą najcześćiej występujące rzeczowniki w tekście. Wykonajmy krok pierwszy:
Ćwiczenie 4: Wypisz wszystkie rzeczowniki z tekstu. Wykorzystaj możliwości spaCy.
def get_nouns(text):
result = []
doc = nlp(text)
for token in doc:
if token.pos_ == 'NOUN':
result.append(token)
return result
Teraz czas na podliczenie wystąpień poszczególnych rzeczowników. Uwaga - różne formy tego samego słowa zliczamy razem jako wystąpienia tego słowa (np. "program" i "programs"). Najwygodniejszą metodą podliczania jest zastosowanie tzw. tally (po polsku "zestawienie"). Jest to słownik, którego kluczem jest słowo w formie podstawowej, a wartością liczba wystąpień tego słowa, wliczając słowa odmienione. Przykład gotowego tally:
tally = {"program" : 4, "component" : 1}
Ćwiczenie 5: Napisz program do ekstrakcji terminologii z tekstu według powyższych wytycznych.
def extract_terms(text):
result = {}
doc = nlp(text)
for token in doc:
if token.pos_ == 'NOUN':
if result.get(token.lemma_) is None:
result[token.lemma_] = 1
else:
result[token.lemma_] += 1
return result
Ćwiczenie 6: Rozszerz powyższy program o ekstrację czasowników i przymiotników.
def extract_terms(text):
result = {}
doc = nlp(text)
for token in doc:
if token.pos_ in ['NOUN', 'VERB', 'ADJ']:
if result.get(token.lemma_) is None:
result[token.lemma_] = 1
else:
result[token.lemma_] += 1
return result