KWT-2024/lab/lab_03.ipynb
2024-04-20 19:58:36 +02:00

20 KiB
Raw Blame History

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

  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():
    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_)
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[1], line 1
----> 1 import spacy
      2 nlp = spacy.load("en_core_web_sm")
      4 doc = nlp(text)

File j:\.AppData\Python\Python310\site-packages\spacy\__init__.py:13
     10 # These are imported as part of the API
     11 from thinc.api import Config, prefer_gpu, require_cpu, require_gpu  # noqa: F401
---> 13 from . import pipeline  # noqa: F401
     14 from . import util
     15 from .about import __version__  # noqa: F401

File j:\.AppData\Python\Python310\site-packages\spacy\pipeline\__init__.py:1
----> 1 from .attributeruler import AttributeRuler
      2 from .dep_parser import DependencyParser
      3 from .edit_tree_lemmatizer import EditTreeLemmatizer

File j:\.AppData\Python\Python310\site-packages\spacy\pipeline\attributeruler.py:8
      6 from .. import util
      7 from ..errors import Errors
----> 8 from ..language import Language
      9 from ..matcher import Matcher
     10 from ..scorer import Scorer

File j:\.AppData\Python\Python310\site-packages\spacy\language.py:43
     41 from .lang.tokenizer_exceptions import BASE_EXCEPTIONS, URL_MATCH
     42 from .lookups import load_lookups
---> 43 from .pipe_analysis import analyze_pipes, print_pipe_analysis, validate_attrs
     44 from .schemas import (
     45     ConfigSchema,
     46     ConfigSchemaInit,
   (...)
     49     validate_init_settings,
     50 )
     51 from .scorer import Scorer

File j:\.AppData\Python\Python310\site-packages\spacy\pipe_analysis.py:6
      3 from wasabi import msg
      5 from .errors import Errors
----> 6 from .tokens import Doc, Span, Token
      7 from .util import dot_to_dict
      9 if TYPE_CHECKING:
     10     # This lets us add type hints for mypy etc. without causing circular imports

File j:\.AppData\Python\Python310\site-packages\spacy\tokens\__init__.py:1
----> 1 from ._serialize import DocBin
      2 from .doc import Doc
      3 from .morphanalysis import MorphAnalysis

File j:\.AppData\Python\Python310\site-packages\spacy\tokens\_serialize.py:14
     12 from ..errors import Errors
     13 from ..util import SimpleFrozenList, ensure_path
---> 14 from ..vocab import Vocab
     15 from ._dict_proxies import SpanGroups
     16 from .doc import DOCBIN_ALL_ATTRS as ALL_ATTRS

File j:\.AppData\Python\Python310\site-packages\spacy\vocab.pyx:1, in init spacy.vocab()

File j:\.AppData\Python\Python310\site-packages\spacy\tokens\doc.pyx:1, in init spacy.tokens.doc()

File <frozen importlib._bootstrap>:404, in parent(self)

KeyboardInterrupt: 

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