{ "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", "
\n", "

Komputerowe wspomaganie tłumaczenia

\n", "

2. Zaawansowane użycie pamięci tłumaczeń [laboratoria]

\n", "

Rafał Jaworski (2021)

\n", "
\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": "markdown", "id": "existing-approval", "metadata": {}, "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": 92, "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": 93, "id": "continental-submission", "metadata": {}, "outputs": [], "source": [ "def prepare_dictionary(sentences):\n", " dict = {}\n", "\n", " for entry in sentences:\n", " dict[entry[0].lower()] = entry\n", "\n", " return dict\n", "\n", "memory_dict = prepare_dictionary(translation_memory)\n", "\n", "def ice_lookup(input, prev_sentence, next_sentence): \n", " sentence = input.lower()\n", "\n", " if prev_sentence.lower() in memory_dict and next_sentence.lower() in memory_dict and sentence in memory_dict:\n", " return memory_dict[sentence]\n", "\n", " return []" ] }, { "cell_type": "code", "execution_count": 94, "id": "bdc1df76", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('Wciśnij przycisk Enter', 'Press the ENTER button')" ] }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ice_lookup(\"Wciśnij przycisk Enter\", \"Sprawdź ustawienia sieciowe\", \"Drukarka jest wyłączona\")" ] }, { "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": 95, "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, nie jest poprawna. Cechy:\n", "- nieujemna (abs > 0)\n", "- identyfikacja nie jest spelniona -> moga miec taka sama dlugosc, a byc inne\n", "- symetryczna - wynik z wartosci bezwglednej\n", "- nierownosc trojkata nie jest spelniona" ] }, { "cell_type": "markdown", "id": "native-amber", "metadata": {}, "source": [ "A teraz spójrzmy na taką funkcję:" ] }, { "cell_type": "code", "execution_count": 96, "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ź: z punktu widzenia cech, wszystkie cechy sa spelnione, jednak funkcja sama w sobie jest bezuyteczna poprzez to, ze wartosci sa stale. " ] }, { "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, poniewaz spelnia cechy: \n", "- nieujemnosci - zawsze dodatni lub zero gdy a i b jest rowny sobie\n", "- symetria - dystans od a i b jest taki sam jak b i a\n", "- nierownosc trojkata - dystans od ciągu A do C przez B jest zawsze mniejszy lub równy sumie dystansów od A do B i od B do C" ] }, { "cell_type": "markdown", "id": "attended-channels", "metadata": {}, "source": [ "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": 97, "id": "secondary-wrist", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "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": 98, "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": 99, "id": "focal-pathology", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9166666666666666" ] }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "levenshtein_similarity('Program jest uruchomiony', 'Program jest uruchamiany')" ] }, { "cell_type": "code", "execution_count": 100, "id": "roman-ceiling", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9428571428571428" ] }, "execution_count": 100, "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": "code", "execution_count": 101, "id": "invisible-cambodia", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.631578947368421" ] }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "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": 102, "id": "genetic-cradle", "metadata": {}, "outputs": [], "source": [ "def fuzzy_lookup(sentence, threshold):\n", " col = []\n", "\n", " for entry in translation_memory:\n", " if (levenshtein_similarity(entry[0], sentence)) >= threshold:\n", " col.append(entry)\n", " \n", " return col" ] }, { "cell_type": "code", "execution_count": 103, "id": "57fb39b9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fuzzy_lookup('Spróbuj wyłączyć i włączyć komputer', 0.7)" ] }, { "cell_type": "code", "execution_count": 104, "id": "94e1b3be", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('Wciśnij przycisk Enter', 'Press the ENTER button')]" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fuzzy_lookup('Wciśnij przycisk escape', 0.7)" ] } ], "metadata": { "author": "Rafał Jaworski", "email": "rjawor@amu.edu.pl", "kernelspec": { "display_name": "Python 3", "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.7.9" }, "subtitle": "2. Zaawansowane użycie pamięci tłumaczeń", "title": "Komputerowe wspomaganie tłumaczenia", "year": "2021" }, "nbformat": 4, "nbformat_minor": 5 }