KWT-2024/lab/lab_02.ipynb
2024-04-21 12:32:38 +02:00

15 KiB
Raw Blame History

Wiemy już, do czego służy pamięć tłumaczeń. Spróbujmy przeprowadzić mały research, którego celem będzie odkrycie, w jaki sposób do pamięci tłumaczeń podchodzą najwięksi producenci oprogramowania typu CAT.

Ćwiczenie 1: Wykonaj analizę funkcjonalności pamięci tłumaczeń w programach SDL Trados Studio 2021 oraz Kilgray memoQ. Dla obu programów wypisz funkcje, które są związane z TM oraz zaznacz, które funkcje są wspólne dla obu programów oraz których funkcji Tradosa brakuje w memoQ oraz odwrotnie.

Odpowiedź:

Jedną z funkcji dostępnych we wszystkich większych programach do wspomagania tłumaczenia jest znajdowanie bardzo pewnych dopasowań w pamięci tłumaczeń. Są one zwane ICE (In-Context Exact match) lub 101% match. Są to takie dopasowania z pamięci tłumaczeń, dla których nie tylko zdanie źródłowe z TM jest identyczne z tłumaczonym, ale także poprzednie zdanie źródłowe z TM zgadza się z poprzednim zdaniem tłumaczonym oraz następne z TM z następnym tłumaczonym.

Rozważmy przykładową pamięć tłumaczeń z poprzednich zajęć (można do niej dorzucić kilka przykładów):

translation_memory = [
                      ('Wciśnij przycisk Enter', 'Press the ENTER button'), 
                      ('Sprawdź ustawienia sieciowe', 'Check the network settings'),
                      ('Drukarka jest wyłączona', 'The printer is switched off'),
                      ('Wymagane ponowne uruchomienie komputera', 'System restart required')
                     ]

Ćwiczenie 2: Zaimplementuj funkcję ice_lookup, przyjmującą trzy parametry: aktualnie tłumaczone zdanie, poprzednio tłumaczone zdanie, następne zdanie do tłumaczenia. Funkcja powinna zwracać dopasowania typu ICE. Nie pozwól, aby doszło do błędów podczas sprawdzania pierwszego i ostatniego przykładu w pamięci (ze względu na brak odpowiednio poprzedzającego oraz następującego przykładu).

def tm_lookup(sentence):
    return [entry[1] for entry in translation_memory if entry[0].lower() == sentence.lower()]

def ice_lookup(sentence, prev_sentence, next_sentence):
    if (not prev_sentence) or (not next_sentence):
        return 'no context'
    
    if not sentence:
        return 'enter your sentence'
    
    #Dobrze prawie ale tutaj zwracane są listy. wszystko okey, gdy zdanie poprzedzające i następne mają tamą ilość słów. JEST zdecydowanie błędny gdy zdania mają różną ilość słów!
    if tm_lookup(prev_sentence) and tm_lookup(next_sentence):
        return [entry[0] for entry in translation_memory if entry[0].lower() == sentence.lower()]
    else:
        return ""
    
ice_lookup('Wciśnij przycisk Enter','Sprawdź ustawienia sieciowe','Drukarka jest wyłączona')
['Wciśnij przycisk Enter']
ice_lookup('Wciśnij przycisk Enter','Sprawdź ustawienia sieciowe','')
'no context'
ice_lookup('','Sprawdź ustawienia sieciowe','Drukarka jest wyłączona')
'enter your sentence'
ice_lookup('Wciśnij przycisk Enter','','Drukarka jest wyłączona')
'no context'

Inną powszechnie stosowaną techniką przeszukiwania pamięci tłumaczeń jest tzw. fuzzy matching. Technika ta polega na wyszukiwaniu zdań z pamięci, które są tylko podobne do zdania tłumaczonego. Na poprzednich zajęciach wykonywaliśmy funkcję tm_lookup, która pozwalała na różnicę jednego słowa.

Zazwyczaj jednak funkcje fuzzy match posiadają znacznie szersze możliwości. Ich działanie opiera się na zdefiniowaniu funkcji $d$ dystansu pomiędzy zdaniami $x$ i $y$. Matematycznie, funkcja dystansu posiada następujące właściwości:

  1. $\forall_{x,y} d(x,y)\geqslant 0$
  2. $\forall_{x,y} d(x,y)=0 \Leftrightarrow x=y$
  3. $\forall_{x,y} d(x,y)=d(y,x)$
  4. $\forall_{x,y,z} d(x,y) + d(y,z)\geqslant d(x,z)$

Rozważmy następującą funkcję:

def sentence_distance(x,y):
    return abs(len(y) - len(x))

Ćwiczenie 3: Czy to jest poprawna funkcja dystansu? Które warunki spełnia?

Odpowiedź:

    1. spełnia warunek: dzięki zastosowaniu funkcji abs()
    1. spełnia warunek: przemienność w tym przypadku również zawdzięczamy funkcj abs()
    1. spełnia warunek:(z uproszczeniem że x i y i z to len(z danej zmiennej) -> |y-x| + |z-y| >= |z-x| =
  • = |y - y - x + z| >= |z-x| = |z-x| >= |z-x|

2 nie jest spełnione, ponieważ x i y muszą być tymi samymi zdaniami aby odległość była równa 0. A wyżej wymieniona funckja spełnia ten warunek dla wszytskich zdań które mają taką samą ilość znaków.

A teraz spójrzmy na taką funkcję:

def sentence_distance(x,y):
    if (x == y):
        return 0
    else:
        return 3

Ćwiczenie 4: Czy to jest poprawna funkcja dystansu? Które warunki spełnia?

Odpowiedź:

    1. spełnia warunek, ponieważ zwróci wartość 0 lub 3 które są >= 0
    1. spełnia waurenk, ponieważ gdy zdanie x jest takie samo jak y = to odległość jest zwracana jako 0
    1. spełnia warunek, ponieważ sprawdzenia wygląda w taki sposób, że porównujemy czy x == y (co jest tożsame z y == x) w przeciwnym wypadku zawsze zwracamy tą samą wartość
    1. spełnia warunek, ponieważ gdy xyz są takie same to mamy 0>=0 | gdy wszystkie są różne to mamy 6>=3 | gdy jedna para się różni 6>=0 lub 3>=0

Wprowadźmy jednak inną funkcję dystansu - dystans Levenshteina. Dystans Levenshteina pomiędzy dwoma łańcuchami znaków definiuje się jako minimalną liczbę operacji edycyjnych, które są potrzebne do przekształcenia jednego łańcucha znaków w drugi. Wyróżniamy trzy operacje edycyjne:

  • dodanie znaku
  • usunięcie znaku
  • zamiana znaku na inny

Ćwiczenie 5: Czy dystans Levenshteina jest poprawną funkcją dystansu? Uzasadnij krótko swoją odpowiedź sprawdzając każdy z warunków.

Odpowiedź: Jest funckją dystansu

    1. spełnia warunek Liczba wymaganych operacji edycyjnych nie może być mniejsza niż zero. W przypadku gdy zdania są sobie równe d(x,y) = 0
    1. spełnia warunek Gdy zdania są sobie równe d(x,y) = 0
    1. spełnia warunek nie ważne czy zrobimy d(x,y) czy d(y,x) nadal liczba operacji edycyjnych będzie taka sama pa->papa (+2) | papa -> pa (-2)
    1. spełnia warunek: (z uproszczeniem że x i y i z to liczba wymaganych zmian -> |y?x| + |z?y| >= |z?x| =
  • = x + y >= x

W Pythonie dostępna jest biblioteka zawierająca implementację dystansu Levenshteina. Zainstaluj ją w swoim systemie przy użyciu polecenia:

pip3 install python-Levenshtein

I wypróbuj:

pip3 install python-Levenshtein
  Cell In [8], line 1
    pip3 install python-Levenshtein
         ^
SyntaxError: invalid syntax
from Levenshtein import distance as levenshtein_distance

levenshtein_distance("kotek", "kotki")

Funkcja ta daje nam możliwość zdefiniowania podobieństwa pomiędzy zdaniami:

def levenshtein_similarity(x,y):
    return 1 - levenshtein_distance(x,y) / max(len(x), len(y))

Przetestujmy ją!

levenshtein_similarity('Program jest uruchomiony', 'Program jest uruchamiany')
levenshtein_similarity('Spróbuj wyłączyć i włączyć komputer', 'Spróbuj włączyć i wyłączyć komputer')
levenshtein_similarity('Spróbuj wyłączyć i włączyć komputer', 'Nie próbuj wyłączać i włączać drukarki')

Ćwiczenie 6: Napisz funkcję fuzzy_lookup, która wyszuka w pamięci tłumaczeń wszystkie zdania, których podobieństwo Levenshteina do zdania wyszukiwanego jest większe lub równe od ustalonego progu.

def fuzzy_lookup(sentence, threshold):
   
    answer = []
    
    for entry in translation_memory:
        if levenshtein_similarity(sentence.lower(),entry[0].lower()) >= threshold:
            answer.append(entry[1])
            
    return answer
#'Wciśnij przycisk Enter'
fuzzy_lookup('KlikNiJ przycisK EnTeR', 0.86)
#'Sprawdź ustawienia sieciowe'
fuzzy_lookup('Sprawdź ustawienia sieci', 0.885)