KWT-2024/lab/lab_03.ipynb

17 KiB

Logo 1

Komputerowe wspomaganie tłumaczenia

3. Terminologia [laboratoria]

Rafał Jaworski (2021)

Logo 2

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ź:

W dalszych ćwiczeniach skupimy się jednak na odszukaniu terminu specjalistycznego w tekście. W tym celu będą potrzebne dwie operacje:

  1. Przygotowanie słownika specjalistycznego.
  2. 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(dictionary, text):
    termValues = dict()
    for element in dictionary:
         values = []
         pattern = re.compile(r'\b{}\b'.format(re.escape(element)))
         for match in pattern.finditer(text.lower()):
            values.append((match.start(), match.end()))
         
         if len(values) != 0:
             termValues[element] = values
   
    return termValues

terminology_lookup(dictionary, text)

{'program': [(468, 475), (516, 523), (533, 540)],
 'application': [(80, 91), (164, 175)],
 'compile': [(56, 63), (504, 511)]}

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_)
 
for
all
Java
programmer
:
this
section
explain
how
to
compile
and
run
a
swing
application
from
the
command
line
.
for
information
on
compile
and
run
a
swing
application
use
NetBeans
IDE
,
see
run
Tutorial
Examples
in
NetBeans
IDE
.
the
compilation
instruction
work
for
all
Swing
program
—
applet
,
as
well
as
application
.
here
be
the
step
you
need
to
follow
:
install
the
late
release
of
the
Java
SE
platform
,
if
you
have
not
already
do
so
.
create
a
program
that
use
swing
component
.
compile
the
program
.
run
the
program
.

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(dictionary, text):
    termValues = dict()
    lowerText = text.lower()
    nlp = spacy.load("en_core_web_sm")

    splitText = nlp(lowerText)
    for findingWord in dictionary:
         values = []
         startFromIndex = 0

         for word in splitText:
             if word.lemma_ == findingWord:
                 textBegining = lowerText.index(word.text,startFromIndex)
                 textEnding = textBegining + len(word)
                 startFromIndex = textEnding
                 values.append((textBegining,textEnding))
         
         if len(values) != 0:
             termValues[findingWord] = values
   
    return termValues

terminology_lookup(dictionary, text)
{'program': [(291, 299), (468, 475), (516, 523), (533, 540)],
 'application': [(80, 91), (164, 175), (322, 334)],
 'applet': [(302, 309)],
 'compile': [(56, 63), (134, 143), (504, 511)]}

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.

import spacy

def get_nouns(text):
    nlp = spacy.load("en_core_web_sm")
    doc = nlp(text)
    nouns = [token.text for token in doc if token.pos_ == "NOUN"]
    return set(nouns)

get_nouns(text)
set()

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.

import spacy

def get_nouns(text):
    nlp = spacy.load("en_core_web_sm")
    doc = nlp(text)
    nouns = [token.lemma_ for token in doc if token.pos_ == "NOUN"]
    return set(nouns)

def getElementsNumbers(dictionary, text):
    termValues = dict()
    lowerText = text.lower()
    nlp = spacy.load("en_core_web_sm")

    splitText = nlp(lowerText)
    for findingWord in dictionary:
         elementNumber = 0

         for word in splitText:
             if word.lemma_ == findingWord:
                elementNumber = elementNumber +1
         
         if elementNumber != 0:
             termValues[findingWord] = elementNumber
   
    return termValues

def extract_terms(text):
    return getElementsNumbers(get_nouns(text), text)

extract_terms(text)
{'line': 1,
 'release': 1,
 'compilation': 1,
 'component': 1,
 'section': 1,
 'information': 1,
 'program': 4,
 'command': 1,
 'platform': 1,
 'applet': 1,
 'application': 3,
 'swing': 4,
 'instruction': 1,
 'step': 1,
 'programmer': 1}

Ćwiczenie 6: Rozszerz powyższy program o ekstrację czasowników i przymiotników.

def get_dictonery_by_type(text, type):
    nlp = spacy.load("en_core_web_sm")
    doc = nlp(text)
    nouns = [token.lemma_ for token in doc if token.pos_ == type]
    return set(nouns)


def extract_terms(text, type):
     return getElementsNumbers(get_dictonery_by_type(text, type), text)



extract_terms(text, 'VERB')
{'compile': 3,
 'work': 1,
 'install': 1,
 'create': 1,
 'explain': 1,
 'run': 4,
 'see': 1,
 'need': 1,
 'do': 1,
 'follow': 1,
 'use': 2}
extract_terms(text, 'ADJ')
{'late': 1}