18 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 lub metal cabinet slides. Skorzystalem z dwoch slownikow oraz duzego modelu jezykowego.
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(txt, labels):
results = []
for label in labels:
results.append((
label,
[(m.start(), m.end() - 1) for m in re.finditer(label, txt)]
))
return results
terminology_lookup(text, dictionary)
[('program', [(14, 20), (291, 297), (468, 474), (516, 522), (533, 539)]), ('application', [(80, 90), (164, 174), (322, 332)]), ('applet', [(302, 307)]), ('compile', [(56, 62)])]
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, token.lemma_, token.idx)
0 For for 1 all all 5 Java Java 9 programmers programmer 14 : : 25 This this 27 section section 32 explains explain 40 how how 49 to to 53 compile compile 56 and and 64 run run 68 a a 72 Swing swing 74 application application 80 from from 92 the the 97 command command 101 line line 109 . . 113 For for 115 information information 119 on on 131 compiling compile 134 and and 144 running run 148 a a 156 Swing swing 158 application application 164 using use 176 NetBeans NetBeans 182 IDE IDE 191 , , 194 see see 196 Running run 200 Tutorial Tutorial 208 Examples Examples 217 in in 226 NetBeans NetBeans 229 IDE IDE 238 . . 241 The the 243 compilation compilation 247 instructions instruction 259 work work 272 for for 277 all all 281 Swing Swing 285 programs program 291 — — 300 applets applet 302 , , 309 as as 311 well well 314 as as 319 applications application 322 . . 334 Here here 336 are be 341 the the 345 steps step 349 you you 355 need need 359 to to 364 follow follow 367 : : 373 Install install 375 the the 383 latest late 387 release release 394 of of 402 the the 405 Java Java 409 SE SE 414 platform platform 417 , , 425 if if 427 you you 430 have have 434 n't not 438 already already 442 done do 450 so so 455 . . 457 Create create 459 a a 466 program program 468 that that 476 uses use 481 Swing swing 486 components component 492 . . 502 Compile compile 504 the the 512 program program 516 . . 523 Run run 525 the the 529 program program 533 . . 540
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.
import spacy
nlp = spacy.load("en_core_web_sm")
def terminology_lookup(txt, labels):
result = {};
doc = nlp(txt)
for token in doc:
if token.lemma_ in labels:
if token.lemma_ not in result:
result[token.lemma_] = []
result[token.lemma_].append((token.idx, token.idx + len(token)))
return result
terminology_lookup(text, dictionary)
{'compile': [(56, 63), (134, 143), (504, 511)], 'application': [(80, 91), (164, 175), (322, 334)], 'program': [(291, 299), (468, 475), (516, 523), (533, 540)], 'applet': [(302, 309)]}
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):
doc = nlp(text)
return [token.lemma_ for token in doc if token.pos_ == 'NOUN']
get_nouns(text)
['programmer', 'section', 'swing', 'application', 'command', 'line', 'information', 'swing', 'application', 'compilation', 'instruction', 'program', 'applet', 'application', 'step', 'release', 'platform', 'program', 'swing', 'component', 'program', 'program']
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 count_words(words):
word_count = {}
for word in words:
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
return word_count
def extract_terms(text):
return count_words(get_nouns(text))
extract_terms(text)
{'programmer': 1, 'section': 1, 'swing': 3, 'application': 3, 'command': 1, 'line': 1, 'information': 1, 'compilation': 1, 'instruction': 1, 'program': 4, 'applet': 1, 'step': 1, 'release': 1, 'platform': 1, 'component': 1}
Ćwiczenie 6: Rozszerz powyższy program o ekstrację czasowników i przymiotników.
def get_verbs(text):
doc = nlp(text)
return [token.lemma_ for token in doc if token.pos_ == 'VERB']
def get_adjectives(text):
doc = nlp(text)
return [token.lemma_ for token in doc if token.pos_ == 'ADJ']
def extract_terms(text):
return {
"nouns": get_nouns(text),
"verbs": get_verbs(text),
"adjectives": get_adjectives(text)
}
extract_terms(text)
{'nouns': ['programmer', 'section', 'swing', 'application', 'command', 'line', 'information', 'swing', 'application', 'compilation', 'instruction', 'program', 'applet', 'application', 'step', 'release', 'platform', 'program', 'swing', 'component', 'program', 'program'], 'verbs': ['explain', 'compile', 'run', 'compile', 'run', 'use', 'see', 'run', 'work', 'need', 'follow', 'install', 'do', 'create', 'use', 'compile', 'run'], 'adjectives': ['late']}