From 9e978980fdfe663f28159cb95d59843ee34d355d Mon Sep 17 00:00:00 2001 From: Marek Susniak Date: Sat, 15 Jun 2024 13:12:26 +0200 Subject: [PATCH] Laboratorium #11. --- lab/lab_11.ipynb | 633 +++++++++++++++++++++++++++++++---------------- 1 file changed, 421 insertions(+), 212 deletions(-) diff --git a/lab/lab_11.ipynb b/lab/lab_11.ipynb index 0a8ce14..ae05990 100644 --- a/lab/lab_11.ipynb +++ b/lab/lab_11.ipynb @@ -1,214 +1,423 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "expanded-entrance", - "metadata": {}, - "source": [ - "# Komputerowe wspomaganie tłumaczenia" - ] + "cells": [ + { + "cell_type": "markdown", + "id": "expanded-entrance", + "metadata": { + "id": "expanded-entrance" + }, + "source": [ + "# Komputerowe wspomaganie tłumaczenia" + ] + }, + { + "cell_type": "markdown", + "id": "atlantic-greenhouse", + "metadata": { + "id": "atlantic-greenhouse" + }, + "source": [ + "# Zajęcia 11 - urównoleglanie" + ] + }, + { + "cell_type": "markdown", + "id": "hungarian-davis", + "metadata": { + "id": "hungarian-davis" + }, + "source": [ + "Na poprzednich zajęciach poznaliśmy techniki pozyskiwania tekstu z Internetu. Jeśli uda nam się w ten sposób pozyskać tekst w jednym języku oraz jego tłumaczenie na inny język, jesteśmy tylko o krok od uzyskania najbardziej przydatnego zasobu z punktu widzenia wspomagania tłumaczenia - pamięci tłumaczeń. Krokiem tym jest automatyczne urównoleglanie tekstu." + ] + }, + { + "cell_type": "markdown", + "id": "bronze-removal", + "metadata": { + "id": "bronze-removal" + }, + "source": [ + "Automatyczne urównoleglanie tekstu składa się z dwóch kroków:\n", + "1. Podziału tekstu źródłowego oraz docelowego na zdania.\n", + "2. Dopasowaniu zdań źródłowych do docelowych." + ] + }, + { + "cell_type": "markdown", + "id": "junior-works", + "metadata": { + "id": "junior-works" + }, + "source": [ + "Zdania, o których mowa w punkcie 1., powinniśmy rozumieć jako segmenty, tj. niekoniecznie kompletne zdania w sensie gramatycznym. Standardowym sposobem podziału tekstu na segmenty jest dzielenie po znaku nowej linii lub zaraz po kropce, o ile jest ona częścią sekwencji: \".[spacja][Wielka litera]\"" + ] + }, + { + "cell_type": "markdown", + "id": "legitimate-corrections", + "metadata": { + "id": "legitimate-corrections" + }, + "source": [ + "### Ćwiczenie 1: Zaimplementuj podstawowy algorytm segmentacji tekstu. Użyj odpowiedniego wyrażenia regularnego, łapiącego wielkie litery w dowolnym języku, np. \"Ż\" (użyj klasy unikodowej). Zwróć listę segmentów." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "german-dispute", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "german-dispute", + "outputId": "740c001c-1646-4464-9314-b0327fe927f7" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "['To', 'Jest', 'Przykładowy', 'Ź', 'Ź', 'Ź', 'Tekst', 'Wielkimi', 'Literami', 'Na', 'Początku', 'Segmentów', 'Ź', 'Ź', 'Ź']\n" + ] + } + ], + "source": [ + "import regex as re\n", + "\n", + "def sentence_split(text):\n", + " pattern = r'(?\n", + "\n", + " \n", + "
\n", + " \n", + " sample\n", + " KWT\n", + " KWT\n", + " 123\n", + " sample XLIFF file\n", + " \n", + "
\n", + " \n", + " \n", + " Hello world!\n", + " Hola mundo!\n", + " \n", + " \n", + " File\n", + " Archivo\n", + " \n", + " \n", + " New\n", + " Nuevo\n", + " \n", + " \n", + " Exit\n", + " Salir\n", + " \n", + " \n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "source": [ + "import requests\n", + "from bs4 import BeautifulSoup\n", + "\n", + "\n", + "def create_hunaligna_file(text_en, text_pl, output_file):\n", + " sentences_en = text_en.split('. ')\n", + " sentences_pl = text_pl.split('. ')\n", + "\n", + " with open(output_file, \"w\", encoding=\"utf-8\") as f:\n", + " f.write(\"# Sentence pairs\\n\")\n", + " for i, (en, pl) in enumerate(zip(sentences_en, sentences_pl)):\n", + " f.write(f\"{i}\\n\")\n", + " f.write(\"# Source\\n\")\n", + " f.write(f\"{en.strip()}\\n\")\n", + " f.write(\"# Target\\n\")\n", + " f.write(f\"{pl.strip()}\\n\")\n", + "\n", + "def main():\n", + " url_en = \"https://en.wikipedia.org/wiki/Main_Page\"\n", + " url_pl = \"https://pl.wikipedia.org/wiki/Strona_g%C5%82%C3%B3wna\"\n", + "\n", + " text_en = get_page_text(url_pl)\n", + " text_pl = get_page_text(url_en)\n", + "\n", + " with open(\"english.txt\", \"w\", encoding=\"utf-8\") as f_en:\n", + " f_en.write(text_en)\n", + "\n", + " with open(\"polish.txt\", \"w\", encoding=\"utf-8\") as f_pl:\n", + " f_pl.write(text_pl)\n", + "\n", + " create_hunaligna_file(text_en, text_pl, \"hunaligna.txt\")\n", + "\n", + " print(\"Texts have been saved to 'english.txt' and 'polish.txt'\")\n", + " print(\"Hunaligna file has been created as 'hunaligna.txt'\")\n", + "\n", + "main()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "yJFtZ0FwksXG", + "outputId": "867cfbf2-b2ad-405c-e8d0-19dcdaed82bd" + }, + "id": "yJFtZ0FwksXG", + "execution_count": 11, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Texts have been saved to 'english.txt' and 'polish.txt'\n", + "Hunaligna file has been created as 'hunaligna.txt'\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "id": "falling-greenhouse", + "metadata": { + "id": "falling-greenhouse" + }, + "source": [ + "### Ćwiczenie 4: Napisz konwerter formatu hunaligna na XLIFF." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "remarkable-pillow", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "remarkable-pillow", + "outputId": "59a072b2-79a0-4a57-8b00-cc704f9d1a7b" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "XLIFF file has been created as 'output.xliff'\n" + ] + } + ], + "source": [ + "import xml.etree.ElementTree as ET\n", + "\n", + "def parse_hunaligna_file(filepath):\n", + " segments = []\n", + " with open(filepath, 'r', encoding='utf-8') as file:\n", + " segment = {}\n", + " for line in file:\n", + " line = line.strip()\n", + " if line.startswith(\"# Source\"):\n", + " segment['source'] = next(file).strip()\n", + " elif line.startswith(\"# Target\"):\n", + " segment['target'] = next(file).strip()\n", + " segments.append(segment)\n", + " segment = {}\n", + " return segments\n", + "\n", + "def create_xliff(segments, source_lang, target_lang, output_file):\n", + " xliff = ET.Element('xliff', version=\"1.2\")\n", + " file_elem = ET.SubElement(xliff, 'file', {\n", + " 'source-language': source_lang,\n", + " 'target-language': target_lang,\n", + " 'datatype': \"plaintext\",\n", + " 'original': \"file.txt\"\n", + " })\n", + " body = ET.SubElement(file_elem, 'body')\n", + "\n", + " for i, segment in enumerate(segments):\n", + " trans_unit = ET.SubElement(body, 'trans-unit', id=str(i))\n", + " source = ET.SubElement(trans_unit, 'source')\n", + " source.text = segment['source']\n", + " target = ET.SubElement(trans_unit, 'target')\n", + " target.text = segment['target']\n", + "\n", + " tree = ET.ElementTree(xliff)\n", + " tree.write(output_file, encoding='UTF-8', xml_declaration=True)\n", + "\n", + "def convert2xliff(hunalign_file_name, xliff_file):\n", + " source_lang = 'en'\n", + " target_lang = 'pl'\n", + "\n", + " segments = parse_hunaligna_file(hunalign_file_name)\n", + " create_xliff(segments, source_lang, target_lang, xliff_file)\n", + " print(f\"XLIFF file has been created as '{xliff_file}'\")\n", + "\n", + "\n", + "convert2xliff('hunaligna.txt', 'output.xliff')" + ] + } + ], + "metadata": { + "author": "Rafał Jaworski", + "email": "rjawor@amu.edu.pl", + "lang": "pl", + "subtitle": "11. Urównoleglanie", + "title": "Komputerowe wspomaganie tłumaczenia", + "year": "2021", + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "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.8.10" + }, + "colab": { + "provenance": [] + } }, - { - "cell_type": "markdown", - "id": "atlantic-greenhouse", - "metadata": {}, - "source": [ - "# Zajęcia 11 - urównoleglanie" - ] - }, - { - "cell_type": "markdown", - "id": "hungarian-davis", - "metadata": {}, - "source": [ - "Na poprzednich zajęciach poznaliśmy techniki pozyskiwania tekstu z Internetu. Jeśli uda nam się w ten sposób pozyskać tekst w jednym języku oraz jego tłumaczenie na inny język, jesteśmy tylko o krok od uzyskania najbardziej przydatnego zasobu z punktu widzenia wspomagania tłumaczenia - pamięci tłumaczeń. Krokiem tym jest automatyczne urównoleglanie tekstu." - ] - }, - { - "cell_type": "markdown", - "id": "bronze-removal", - "metadata": {}, - "source": [ - "Automatyczne urównoleglanie tekstu składa się z dwóch kroków:\n", - "1. Podziału tekstu źródłowego oraz docelowego na zdania.\n", - "2. Dopasowaniu zdań źródłowych do docelowych." - ] - }, - { - "cell_type": "markdown", - "id": "junior-works", - "metadata": {}, - "source": [ - "Zdania, o których mowa w punkcie 1., powinniśmy rozumieć jako segmenty, tj. niekoniecznie kompletne zdania w sensie gramatycznym. Standardowym sposobem podziału tekstu na segmenty jest dzielenie po znaku nowej linii lub zaraz po kropce, o ile jest ona częścią sekwencji: \".[spacja][Wielka litera]\"" - ] - }, - { - "cell_type": "markdown", - "id": "legitimate-corrections", - "metadata": {}, - "source": [ - "### Ćwiczenie 1: Zaimplementuj podstawowy algorytm segmentacji tekstu. Użyj odpowiedniego wyrażenia regularnego, łapiącego wielkie litery w dowolnym języku, np. \"Ż\" (użyj klasy unikodowej). Zwróć listę segmentów." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "german-dispute", - "metadata": {}, - "outputs": [], - "source": [ - "def sentence_split(text):\n", - " return []" - ] - }, - { - "cell_type": "markdown", - "id": "continued-assessment", - "metadata": {}, - "source": [ - "### Ćwiczenie 2: Uruchom powyższy algorytm na treści wybranej przez siebie strony internetowej (do ściągnięcia treści strony wykorzystaj kod z laboratoriów nr 7). Zidentyfikuj co najmniej dwa wyjątki od ogólnej reguły podziału na segmenty i ulepsz algorytm." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "guilty-morocco", - "metadata": {}, - "outputs": [], - "source": [ - "def sentence_split_enhanced(text):\n", - " return []" - ] - }, - { - "cell_type": "markdown", - "id": "experimental-recipient", - "metadata": {}, - "source": [ - "Po podziale tekstu na segmenty po stronie źródłowej oraz docelowej, możemy przystąpić do kroku drugiego - dopasowania segmentów. Głównym wyzwaniem tego kroku jest fakt, iż po stronie źródłowej może być inna liczba segmentów, niż po stronie docelowej. Takie rozbieżności są bardzo częste, a wynikają między innymi z:\n", - "* tłumaczenia jednego zdania źródłowego przy użyciu więcej niż jednego zdania\n", - "* tłumaczenia więcej niż jednego zdania źródłowego przy użyciu jednego zdania\n", - "* pominięcia zdania podczas tłumaczenia\n", - "* rozbieżności pomiędzy wersjami tekstu źródłowego i docelowego (np. tekst źródłowy mógł być modyfikowany po przetłumaczeniu i tłumaczenie nie zostało zaktualizowane)\n", - "* przetłumaczenia tekstu źródłowego tylko częściowo" - ] - }, - { - "cell_type": "markdown", - "id": "australian-hundred", - "metadata": {}, - "source": [ - "Problemy te rozwiązwyane są na różne sposoby. Najpopularniejszym programem do przeprowadzania urównoleglania jest [Hunalign](https://github.com/danielvarga/hunalign). Wejściem do programu są dwa pliki, zawierające po jednym segmencie w linii. Wyjściem - plik urównoleglony w wewnętrznym formacie hunaligna." - ] - }, - { - "cell_type": "markdown", - "id": "russian-chambers", - "metadata": {}, - "source": [ - "### Ćwiczenie 3: Odnajdź dowolną stronę, która jest dostępna w wielu językach. Pobierz z tej strony tekst oryginalny (tylko ze strony głównej) oraz przetłumaczony na dowolny inny język. Przy użyciu Pythona przygotuj pliki dla Hunaligna i uruchom go." - ] - }, - { - "cell_type": "markdown", - "id": "controlled-pacific", - "metadata": {}, - "source": [ - "Wyjściem z Hunaligna jest plik w specjalnym formacie Hunaligna. Problem jednak w tym, że niestety nie można go w prosty sposób zaimportować do jakiegokolwiek narzędzia typu CAT. Potrzebna jest konwersja do któregoś z bardziej popularnych formatów, np. XLIFF." - ] - }, - { - "cell_type": "markdown", - "id": "divided-chain", - "metadata": {}, - "source": [ - "XLIFF jest formatem do przechowywania pamięci tłumaczeń, który opiera się na XML-u. Przykładowy plik XLIFF wygląda następująco:" - ] - }, - { - "cell_type": "raw", - "id": "appropriate-timber", - "metadata": {}, - "source": [ - "\n", - "\n", - " \n", - "
\n", - " \n", - " sample\n", - " KWT\n", - " KWT\n", - " 123\n", - " sample XLIFF file\n", - " \n", - "
\n", - " \n", - " \n", - " Hello world!\n", - " Hola mundo!\n", - " \n", - " \n", - " File\n", - " Archivo\n", - " \n", - " \n", - " New\n", - " Nuevo\n", - " \n", - " \n", - " Exit\n", - " Salir\n", - " \n", - " \n", - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "id": "falling-greenhouse", - "metadata": {}, - "source": [ - "### Ćwiczenie 4: Napisz konwerter formatu hunaligna na XLIFF." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "remarkable-pillow", - "metadata": {}, - "outputs": [], - "source": [ - "def convert2xliff(hunalign_file_name):\n", - " return 0" - ] - } - ], - "metadata": { - "author": "Rafał Jaworski", - "email": "rjawor@amu.edu.pl", - "lang": "pl", - "subtitle": "11. Urównoleglanie", - "title": "Komputerowe wspomaganie tłumaczenia", - "year": "2021", - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "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.8.10" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file