15 KiB
Komputerowe wspomaganie tłumaczenia
8. Wykorzystanie tłumaczenia automatycznego we wspomaganiu tłumaczenia [laboratoria]
Rafał Jaworski (2021)
W dzisiejszych czasach, niezwykle ważną techniką wspomagania tłumaczenia jest użycie tłumaczenia maszynowego. Tekst źródłowy do tłumaczenia jest najpierw tłumaczony całkowicie autommatycznie, a następnie tłumacz ludzki dokonuje korekty wyniku. Technologia tłumaczenia maszynowego jest już na tyle dojrzała, że oferuje bardzo wysoką jakość wyników. Coraz częstsze stają się scenariusze, w których ludzka korekta to niemal całkowicie machinalne (sic!) zatwierdzanie wyników tłumaczenia maszynowego. Na dzisiejszych zajęciach poznamy techniki ewaluacji tłumaczenia maszynowego oraz sprawdzania jego przydatności w procesie wspomagania tłumaczenia ludzkiego.
Jakość tłumaczenia maszynowego możemy oceniać na dwóch niezależnych płaszczyznach: dokładność i płynność. Płynność jest subiektywnie odbieranym odczuciem, że czytany tekst jest napisany językiem naturalnym i zrozumiałym. Systemy tłumaczenia maszynowego oparte na uczeniu głębokim z wykorzystaniem sieci neuronowych osiągają duży stopień płynności tłumaczenia. Niestety jednak ich dokładność nie zawsze jest równie wysoka.
Dokładność tłumaczenia maszynowego jest parametrem, który łatwiej zmierzyć. Wartość takich pomiarów daje obraz tego, jaka jest faktyczna jakość tłumaczenia maszynowego i jaka jest jego potencjalna przydatność we wspomaganiu tłumaczenia.
Najczęściej stosowaną techniką oceny tłumaczenia maszynowego jest ocena BLEU. Do obliczenia tej oceny potrzebny jest wynik tłumaczenia maszynowego oraz referencyjne tłumaczenie ludzkie wysokiej jakości.
Ćwiczenie 1: Zaimplementuj program do obliczania oceny BLEU dla korpusu w folderze data. Użyj implementacji BLEU z pakietu nltk. Dodatkowe wymaganie techniczne - napisz program tak, aby nie musiał rozpakwowywać pliku zip z korpusem na dysku.
#!pip install nltk
#from nltk.translate.bleu_score import sentence_bleu, corpus_bleu
#import zipfile
#archive = zipfile.ZipFile('./data/corpus_corrected.zip', 'r')
#reference1 = archive.read('corpus_the_human.txt')
#reference2 = archive.read('corpus_the_nmt.txt')
#translation = archive.read('corpus_en.txt')
# Prepare the reference sentences
#reference1 = ['I', 'love', 'eating', 'ice', 'cream']
#reference2 = ['I', 'enjoy', 'eating', 'ice', 'cream']
#translation = ['I', 'love', 'eating', 'ice', 'cream']
#bleu_score = sentence_bleu([reference1, reference2], translation)
#print("BLEU Score: ", bleu_score)
# Calculate the BLEU score for a single sentence
#def calculate_bleu(reference1,reference2,translation):
# bleu_score = sentence_bleu([reference1, reference2], translation)
# print("BLEU Score: ", bleu_score)
# return bleu_score
#
#calculate_bleu(reference1,reference2,translation)
# V2
from nltk.translate.bleu_score import sentence_bleu, corpus_bleu
# Define your desired weights (example: higher weight for bi-grams)
weights = (0.25, 0.25, 0, 0) # Weights for uni-gram, bi-gram, tri-gram, and 4-gram
# Reference and predicted texts (same as before)
reference = [["the", "picture", "is", "clicked", "by", "me"],
["this", "picture", "was", "clicked", "by", "me"]]
predictions = ["the", "picture", "the", "picture", "by", "me"]
# Calculate BLEU score with weights
score = sentence_bleu(reference, predictions, weights=weights)
print(score)
[1;31m---------------------------------------------------------------------------[0m [1;31mTypeError[0m Traceback (most recent call last) Cell [1;32mIn[6], line 35[0m [0;32m 32[0m predictions [38;5;241m=[39m [[38;5;124m"[39m[38;5;124mthe[39m[38;5;124m"[39m, [38;5;124m"[39m[38;5;124mpicture[39m[38;5;124m"[39m, [38;5;124m"[39m[38;5;124mthe[39m[38;5;124m"[39m, [38;5;124m"[39m[38;5;124mpicture[39m[38;5;124m"[39m, [38;5;124m"[39m[38;5;124mby[39m[38;5;124m"[39m, [38;5;124m"[39m[38;5;124mme[39m[38;5;124m"[39m] [0;32m 34[0m [38;5;66;03m# Calculate BLEU score with weights[39;00m [1;32m---> 35[0m score [38;5;241m=[39m [43msentence_bleu[49m[43m([49m[43mreference[49m[43m,[49m[43m [49m[43mpredictions[49m[43m,[49m[43m [49m[43mweights[49m[38;5;241;43m=[39;49m[43mweights[49m[43m)[49m [0;32m 36[0m [38;5;28mprint[39m(score) File [1;32m~\AppData\Local\Programs\Python\Python312\Lib\site-packages\nltk\translate\bleu_score.py:107[0m, in [0;36msentence_bleu[1;34m(references, hypothesis, weights, smoothing_function, auto_reweigh)[0m [0;32m 20[0m [38;5;28;01mdef[39;00m [38;5;21msentence_bleu[39m( [0;32m 21[0m references, [0;32m 22[0m hypothesis, [1;32m (...)[0m [0;32m 25[0m auto_reweigh[38;5;241m=[39m[38;5;28;01mFalse[39;00m, [0;32m 26[0m ): [0;32m 27[0m [38;5;250m [39m[38;5;124;03m"""[39;00m [0;32m 28[0m [38;5;124;03m Calculate BLEU score (Bilingual Evaluation Understudy) from[39;00m [0;32m 29[0m [38;5;124;03m Papineni, Kishore, Salim Roukos, Todd Ward, and Wei-Jing Zhu. 2002.[39;00m [1;32m (...)[0m [0;32m 105[0m [38;5;124;03m :rtype: float / list(float)[39;00m [0;32m 106[0m [38;5;124;03m """[39;00m [1;32m--> 107[0m [38;5;28;01mreturn[39;00m [43mcorpus_bleu[49m[43m([49m [0;32m 108[0m [43m [49m[43m[[49m[43mreferences[49m[43m][49m[43m,[49m[43m [49m[43m[[49m[43mhypothesis[49m[43m][49m[43m,[49m[43m [49m[43mweights[49m[43m,[49m[43m [49m[43msmoothing_function[49m[43m,[49m[43m [49m[43mauto_reweigh[49m [0;32m 109[0m [43m [49m[43m)[49m File [1;32m~\AppData\Local\Programs\Python\Python312\Lib\site-packages\nltk\translate\bleu_score.py:210[0m, in [0;36mcorpus_bleu[1;34m(list_of_references, hypotheses, weights, smoothing_function, auto_reweigh)[0m [0;32m 206[0m [38;5;28;01mfor[39;00m references, hypothesis [38;5;129;01min[39;00m [38;5;28mzip[39m(list_of_references, hypotheses): [0;32m 207[0m [38;5;66;03m# For each order of ngram, calculate the numerator and[39;00m [0;32m 208[0m [38;5;66;03m# denominator for the corpus-level modified precision.[39;00m [0;32m 209[0m [38;5;28;01mfor[39;00m i [38;5;129;01min[39;00m [38;5;28mrange[39m([38;5;241m1[39m, max_weight_length [38;5;241m+[39m [38;5;241m1[39m): [1;32m--> 210[0m p_i [38;5;241m=[39m [43mmodified_precision[49m[43m([49m[43mreferences[49m[43m,[49m[43m [49m[43mhypothesis[49m[43m,[49m[43m [49m[43mi[49m[43m)[49m [0;32m 211[0m p_numerators[i] [38;5;241m+[39m[38;5;241m=[39m p_i[38;5;241m.[39mnumerator [0;32m 212[0m p_denominators[i] [38;5;241m+[39m[38;5;241m=[39m p_i[38;5;241m.[39mdenominator File [1;32m~\AppData\Local\Programs\Python\Python312\Lib\site-packages\nltk\translate\bleu_score.py:368[0m, in [0;36mmodified_precision[1;34m(references, hypothesis, n)[0m [0;32m 364[0m [38;5;66;03m# Ensures that denominator is minimum 1 to avoid ZeroDivisionError.[39;00m [0;32m 365[0m [38;5;66;03m# Usually this happens when the ngram order is > len(reference).[39;00m [0;32m 366[0m denominator [38;5;241m=[39m [38;5;28mmax[39m([38;5;241m1[39m, [38;5;28msum[39m(counts[38;5;241m.[39mvalues())) [1;32m--> 368[0m [38;5;28;01mreturn[39;00m [43mFraction[49m[43m([49m[43mnumerator[49m[43m,[49m[43m [49m[43mdenominator[49m[43m,[49m[43m [49m[43m_normalize[49m[38;5;241;43m=[39;49m[38;5;28;43;01mFalse[39;49;00m[43m)[49m [1;31mTypeError[0m: Fraction.__new__() got an unexpected keyword argument '_normalize'
Ćwiczenie 2: Oblicz wartość bleu na różnych fragmentach przykładowego korpusu (np. na pierwszych 100 zdaniach, zdaniach 500-600). Czy w jakimś fragmencie korpusu jakość tłumaczenia znacząco odbiega od średniej?
def analyze_bleu():
return []
Inną metodą oceny jakości tłumaczenia maszynowego jest parametr WER - Word Error Rate. Definiuje się on w następujący sposób:
$WER = \frac{S+D+I}{N}=\frac{S+D+I}{S+D+C}$
gdzie:
- S - liczba substytucji (słów)
- D - liczba usunięć
- I - liczba wstawień
- C - liczba poprawnych śłów
- N - liczba słów w tłumaczeniu referencyjnym (N=S+D+C)
Miara ta jest zwykle używana w do oceny systemów automatycznego rozpoznawania mowy, jednak w kontekście wspomagania tłumaczenia może być rozumiana jako wielkość nakładu pracy tłumacza nad poprawieniem tłumaczenia maszynowego.
Ćwiczenie 3: Oblicz wartość WER dla przykładowego korpusu. Skorzystaj z gotowej implementacji WER.
def calculate_wer():
return 0
Poza wymienionymi powyżej, stosować można jeszcze inne miary oparte na porównywaniu tłumaczenia maszynowego z ludzkim. Przypomnijmy sobie jedną, którą stosowaliśmy wcześniej.
Ćwiczenie 4: Oblicz średnią wartość dystansu Levenshteina pomiędzy zdaniami przetłumaczonymi automatycznie oraz przez człowieka. Użyj implementacji z ćwiczeń nr 2.
def calculate_levenshtein():
return 0
A teraz sprawdźmy coś jeszcze. W danych przykładowego korpusu znajduje się także angielski tekst źródłowy. Teoretycznie, dobre tłumaczenie niemieckie powinno zawierać jak najwięcej słów z angielskiego źródła. Wykonajmy najstępujący eksperyment:
Ćwiczenie 5: Dla każdej trójki zdań z korpusu przykładowego wykonaj następujące kroki:
- Przetłumacz każde angielskie słowo na niemiecki przy użyciu modułu PyDictionary.
- Sprawdź, które z niemieckich tłumaczeń zawiera więcej spośród tych przetłumaczonych słów - automatyczne, czy ludzkie. Następnie wypisz statystyki zbiorcze. Które tłumaczenie zawiera więcej słownikowych tłumaczeń słów ze źródła?
def analyze_translations():
return []