forked from bfijalkowski/KWT-2024
401 lines
12 KiB
Plaintext
401 lines
12 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "continued-dinner",
|
|
"metadata": {},
|
|
"source": [
|
|
"![Logo 1](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech1.jpg)\n",
|
|
"<div class=\"alert alert-block alert-info\">\n",
|
|
"<h1> Komputerowe wspomaganie tłumaczenia </h1>\n",
|
|
"<h2> 2. <i>Zaawansowane użycie pamięci tłumaczeń</i> [laboratoria]</h2> \n",
|
|
"<h3>Rafał Jaworski (2021)</h3>\n",
|
|
"</div>\n",
|
|
"\n",
|
|
"![Logo 2](https://git.wmi.amu.edu.pl/AITech/Szablon/raw/branch/master/Logotyp_AITech2.jpg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "aggregate-listing",
|
|
"metadata": {},
|
|
"source": [
|
|
"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.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "golden-turkish",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Ć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."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "retired-burke",
|
|
"metadata": {},
|
|
"source": [
|
|
"Odpowiedź:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "961796fd-4463-4a17-ac15-afe712b3959e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"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."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "decimal-electricity",
|
|
"metadata": {},
|
|
"source": [
|
|
" Rozważmy przykładową pamięć tłumaczeń z poprzednich zajęć (można do niej dorzucić kilka przykładów):"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "confident-prison",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"translation_memory = [\n",
|
|
" ('Wciśnij przycisk Enter', 'Press the ENTER button'), \n",
|
|
" ('Sprawdź ustawienia sieciowe', 'Check the network settings'),\n",
|
|
" ('Drukarka jest wyłączona', 'The printer is switched off'),\n",
|
|
" ('Wymagane ponowne uruchomienie komputera', 'System restart required')\n",
|
|
" ]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "informal-breakdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Ć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)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "continental-submission",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def exact_match(sentence):\n",
|
|
" for key, entry in enumerate(translation_memory):\n",
|
|
" if entry[0] == sentence:\n",
|
|
" return key, entry[1]\n",
|
|
" return None, None\n",
|
|
"\n",
|
|
"\n",
|
|
"def has_exact_match_on_index(index, sentence):\n",
|
|
" return translation_memory[index][0] == sentence\n",
|
|
"\n",
|
|
"\n",
|
|
"def ice_lookup(sentence, prev_sentence, next_sentence):\n",
|
|
" index, match = exact_match(sentence)\n",
|
|
" trans_length = len(translation_memory)\n",
|
|
" if index is None:\n",
|
|
" return []\n",
|
|
" if next_sentence \\\n",
|
|
" and index < trans_length \\\n",
|
|
" and not has_exact_match_on_index(index + 1, next_sentence):\n",
|
|
" return []\n",
|
|
" if prev_sentence \\\n",
|
|
" and index > 0 \\\n",
|
|
" and not has_exact_match_on_index(index - 1, prev_sentence):\n",
|
|
" return []\n",
|
|
" return [match]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "figured-server",
|
|
"metadata": {},
|
|
"source": [
|
|
"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."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "beautiful-fancy",
|
|
"metadata": {},
|
|
"source": [
|
|
"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:\n",
|
|
"1. $\\forall_{x,y} d(x,y)\\geqslant 0$\n",
|
|
"2. $\\forall_{x,y} d(x,y)=0 \\Leftrightarrow x=y$\n",
|
|
"3. $\\forall_{x,y} d(x,y)=d(y,x)$\n",
|
|
"4. $\\forall_{x,y,z} d(x,y) + d(y,z)\\geqslant d(x,z)$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "square-usage",
|
|
"metadata": {},
|
|
"source": [
|
|
"Rozważmy następującą funkcję:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "fourth-pillow",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def sentence_distance(x,y):\n",
|
|
" return abs(len(y) - len(x))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "mediterranean-cosmetic",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Ćwiczenie 3: Czy to jest poprawna funkcja dystansu? Które warunki spełnia?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "graduate-theorem",
|
|
"metadata": {},
|
|
"source": [
|
|
"Odpowiedź: Nie. 1, 3, 4."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "native-amber",
|
|
"metadata": {},
|
|
"source": [
|
|
"A teraz spójrzmy na taką funkcję:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "continued-christopher",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def sentence_distance(x,y):\n",
|
|
" if (x == y):\n",
|
|
" return 0\n",
|
|
" else:\n",
|
|
" return 3"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "every-surveillance",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Ćwiczenie 4: Czy to jest poprawna funkcja dystansu? Które warunki spełnia?"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "metallic-leave",
|
|
"metadata": {},
|
|
"source": [
|
|
"Odpowiedź: Tak. 1, 2, 3, 4."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "executed-baptist",
|
|
"metadata": {},
|
|
"source": [
|
|
"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:\n",
|
|
"* dodanie znaku\n",
|
|
"* usunięcie znaku\n",
|
|
"* zamiana znaku na inny"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "square-brown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Ćwiczenie 5: Czy dystans Levenshteina jest poprawną funkcją dystansu? Uzasadnij krótko swoją odpowiedź sprawdzając każdy z warunków."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "bibliographic-stopping",
|
|
"metadata": {},
|
|
"source": [
|
|
"Odpowiedź: Tak.\n",
|
|
"1. Liczba operacji wykonanych nie może być ujemna.\n",
|
|
"2. Gdy x == y, nie są wymagane żadne operacje edycyjne, więc wynik funkcji to 0.\n",
|
|
"3. Zmiana jednego łańcucha znaków w drugi, wymaga tyle samo operacji edycji, co zmiana drugiego w pierwszy.\n",
|
|
" Studia -> Studiel = 2; Studiel -> Studia = 2; 2 == 2\n",
|
|
"4. Istnieją trzy opcje\n",
|
|
" - Jeżeli x == y == z, więc 0 + 0 == 0\n",
|
|
" - Jeżeli x == y, x != z, a x -> z = n, to y -> z = n więc albo 0 + n == n, albo n + n > 0\n",
|
|
" - Jeżeli x != y != z to im z jest bliżej do x, tym jest dalej od y (jednostką odległości jest liczba przekształceń). Można by to przedstawić graficznie jako trójkąt (x, y, z). z stanowi punkt na pośredniej drodze pomiędzy x i y, która nie może być dłuższa niż droga bezpośrednia - wynika to z własności trójkąta.\n",
|
|
" Studia -> Studiel = 2; Studiel -> udia = 4; udia -> Studia = 2;\n",
|
|
" 2 + 4 > 2; 2 + 2 == 4"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "attended-channels",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n",
|
|
"W Pythonie dostępna jest biblioteka zawierająca implementację dystansu Levenshteina. Zainstaluj ją w swoim systemie przy użyciu polecenia:\n",
|
|
"\n",
|
|
"`pip3 install python-Levenshtein`\n",
|
|
"\n",
|
|
"I wypróbuj:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "355e4914-08da-4bd4-b8a2-67b055831c30",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from Levenshtein import distance as levenshtein_distance\n",
|
|
"\n",
|
|
"levenshtein_distance(\"kotek\", \"kotki\")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "concrete-satellite",
|
|
"metadata": {},
|
|
"source": [
|
|
"Funkcja ta daje nam możliwość zdefiniowania podobieństwa pomiędzy zdaniami:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "associate-tuner",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def levenshtein_similarity(x,y):\n",
|
|
" return 1 - levenshtein_distance(x,y) / max(len(x), len(y))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "built-michael",
|
|
"metadata": {},
|
|
"source": [
|
|
"Przetestujmy ją!"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "focal-pathology",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"0.9166666666666666"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"levenshtein_similarity('Program jest uruchomiony', 'Program jest uruchamiany')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "roman-ceiling",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"0.9428571428571428"
|
|
]
|
|
},
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"levenshtein_similarity('Spróbuj wyłączyć i włączyć komputer', 'Spróbuj włączyć i wyłączyć komputer')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "raw",
|
|
"id": "4a47854f-df2e-451f-8e09-99f59210f86f",
|
|
"metadata": {},
|
|
"source": [
|
|
"levenshtein_similarity('Spróbuj wyłączyć i włączyć komputer', 'Nie próbuj wyłączać i włączać drukarki')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "administrative-phoenix",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Ć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."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "genetic-cradle",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def fuzzy_lookup(sentence, threshold):\n",
|
|
" results = []\n",
|
|
" for entry in translation_memory:\n",
|
|
" if levenshtein_similarity(entry[0], sentence) >= threshold:\n",
|
|
" results.append(entry[1])\n",
|
|
" return results"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"author": "Rafał Jaworski",
|
|
"email": "rjawor@amu.edu.pl",
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"lang": "pl",
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.9.2"
|
|
},
|
|
"subtitle": "2. Zaawansowane użycie pamięci tłumaczeń",
|
|
"title": "Komputerowe wspomaganie tłumaczenia",
|
|
"year": "2021"
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|