KWT-2024/lab/lab_15.ipynb
Adam Stelmaszyk 6040e09fa8 finished
2024-06-22 12:22:36 +02:00

457 lines
21 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"id": "marine-termination",
"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> 15. <i>Korekta gramatyczna</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": "featured-afghanistan",
"metadata": {},
"source": [
"Ostatnią z omawianych przez nas technik stosowaną podczas wspomagania tłumaczenia jest korekta gramatyczna. Automatyczna korekta gramatyczna tekstu to ambitne zadanie odnalezienia możliwych błędów niezwiązanych bezpośrednio z pisownią. Są to między innymi:\n",
"* błędy gramatyczne\n",
"* źle użyte słowa\n",
"* złe połączenia wyrazowe\n",
"* błędy interpunkcyjne\n",
"* kolokwializmy\n",
"* redundancja (np. \"tylko i wyłącznie\")"
]
},
{
"cell_type": "markdown",
"id": "peaceful-kingston",
"metadata": {},
"source": [
"Warto zwrócić uwagę, iż systemy do korekcji gramatycznej można traktować jako klasyfikatory binarne. Przyjmijmy, że odpowiedź pozytywna korektora to wykrycie błędu w tekście, natomiast negatywna - brak błędu. Wówczas rozróżniamy dwa typy pomyłek: false positive oraz false negative. False positive to tzw. \"fałszywy alarm\" - zbyt duża ich ilość spowoduje wydłużenie czasu pracy użytkownika przez konieczność analizowania zgłoszeń, które w istocie błędami nie są. Co jednak jeszcze gorsze, zbyt duża ilość false positives powoduje spadek zaufania użytkownika do systemu oraz drastyczny spadek satysfakcji z używania systemu. Te drugie błędy - false negatives - to z kolei faktyczne błędy w tekście, które nie zostały wyłapane przez system korekty. Stare polskie porzekadło głosi, że \"czego oko nie widzi, tego sercu nie żal\". Niestety jednak problem pojawia się, kiedy dostrzeże to jakieś inne oko... Wysoka liczba false negatives wprawdzie skraca czas korekty (sic!), ale odbywa się to kosztem jakości całego procesu. Idealnie zatem byłoby zminimalizować zarówno liczbę false positives, jak i false negatives. Jak jednak łatwo się domyślić, nie jest to zawsze możliwe. Korektor gramatyczny, który jest bardzo restrykcyjny i raportuje wiele błędów, będzie miał tendencję do popełniania false positives. Natomiast korektor bardziej pobłażliwy niechybnie popełni wiele false negatives. Co zatem jest ważniejsze? Praktyka wskazuje, że oba parametry mają podobną wagę, ale jednak odrobinę ważniejsze jest powstrzymanie się od false positives."
]
},
{
"cell_type": "markdown",
"id": "soviet-highland",
"metadata": {},
"source": [
"Do najbardziej popularnych narzędzi wspomagających korektę gramatyczną tekstu należą Grammarly oraz LanguageTool. Na dzisiejszych zajęciach zajmiemy się tym drugim. LanguageTool został pierwotnie napisany jako praca dyplomowa Daniela Nabera, a następnie intensywnie rozwijany wspólnie z Marcinem Miłkowskim. Aż do dziś projekt jest ciągle rozwijany, zwiększana jest liczba obsługiwanych języków oraz dokładność działania."
]
},
{
"cell_type": "markdown",
"id": "arbitrary-reconstruction",
"metadata": {},
"source": [
"LanguageTool jest systemem opartym na regułach. W dobie wszechobecnej sztucznej inteligencji opartej na uczeniu maszynowym rozwiązanie to wydaje się nieco przestarzałe. Jednak to właśnie reguły stanowią o sile LanguageToola - pozwalają one na zwiększenie precyzji korektora poprzez minimalizację false positives. Warto wspomnieć, iż liczne reguły LanguageToola dotyczą również korekty pisowni. Czyni to z LanguageToola kompletne narzędzie do korekty tekstu. Polecam przejrzenie zestawu reguł LanguageToola dla języka angielskiego: https://community.languagetool.org/rule/list?lang=en"
]
},
{
"cell_type": "markdown",
"id": "piano-satellite",
"metadata": {},
"source": [
"Czas uruchomić to narzędzie. Skorzystajmy z Pythona."
]
},
{
"cell_type": "raw",
"id": "academic-crest",
"metadata": {},
"source": [
"pip3 install language_tool_python"
]
},
{
"cell_type": "markdown",
"id": "italian-cheese",
"metadata": {},
"source": [
"Następnie możemy użyć LanguageToola w programie Pythonowym: (przykład zaczerpnięty z oficjalnego tutoriala: https://pypi.org/project/language-tool-python/)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "relative-anaheim",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Downloading LanguageTool 6.4: 100%|██████████| 246M/246M [00:03<00:00, 66.2MB/s] \n",
"Unzipping /var/folders/x3/mzn7dtf55q5355g3c5003g_h0000gn/T/tmp5m6kri4j.zip to /Users/adamstelmaszyk/.cache/language_tool_python.\n",
"Downloaded https://www.languagetool.org/download/LanguageTool-6.4.zip to /Users/adamstelmaszyk/.cache/language_tool_python.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"[Match({'ruleId': 'EN_A_VS_AN', 'message': 'Use “an” instead of a if the following word starts with a vowel sound, e.g. an article, an hour.', 'replacements': ['an'], 'offsetInContext': 16, 'context': 'A sentence with a error in the Hitchhikers Guide tot he ...', 'offset': 16, 'errorLength': 1, 'category': 'MISC', 'ruleIssueType': 'misspelling', 'sentence': \"A sentence with a error in the Hitchhiker's Guide tot he Galaxy\"}),\n",
" Match({'ruleId': 'TOT_HE', 'message': 'Did you mean “to the”?', 'replacements': ['to the'], 'offsetInContext': 43, 'context': '... with a error in the Hitchhikers Guide tot he Galaxy', 'offset': 50, 'errorLength': 6, 'category': 'TYPOS', 'ruleIssueType': 'misspelling', 'sentence': \"A sentence with a error in the Hitchhiker's Guide tot he Galaxy\"})]\n"
]
}
],
"source": [
"import language_tool_python\n",
"import pprint\n",
"tool = language_tool_python.LanguageTool('en-US') \n",
"\n",
"text = 'A sentence with a error in the Hitchhikers Guide tot he Galaxy'\n",
"\n",
"pp = pprint.PrettyPrinter(depth=2)\n",
"errors = tool.check(text)\n",
"pp.pprint(errors)"
]
},
{
"cell_type": "markdown",
"id": "gorgeous-million",
"metadata": {},
"source": [
"Przeanalizujmy format zwracanego wyniku. Otrzymujemy listę obiektów Match - zawiadomień o potencjalnym błędzie. Razem z każdym błędem otrzymujemy m.in. identyfikator użytej reguły, opis błędu, rekomendancję poprawy, kontekst."
]
},
{
"cell_type": "markdown",
"id": "reasonable-cornwall",
"metadata": {},
"source": [
"### Ćwiczenie 1: Użyj LanguageTool do znalezienia jak największej liczby prawdziwych błędów na swoim ulubionym portalu internetowym. Skorzystaj z poznanych wcześniej technik web scrapingu. Uwaga - LanguageTool najprawdopodobniej oznaczy nazwy własne jako literówki - ten typ błędu nie powinien być brany pod uwagę."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "sound-teaching",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
" Specjalistk...rce znajdziesz\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
" Specjalistka ds. mediów społecznośc...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...absolwentka Wydziału Anglistyki. UAM na Pyrkonie 2024. Zapraszamy do obejrzenia fotorela...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...topnia oraz jednolite magisterskie. . . Scientific Advisory Board UAM obradowało po raz ko...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ... jednolite magisterskie. . . Scientific Advisory Board UAM obradowało po raz kolejny. Po...\n",
"\n",
"Error: Nietypowa kombinacja małych i dużych liter. Czy nie powinno być: \"beststudentcamp\"?\n",
"Context: ... laureatów konkursu Szkoła Letnia UAM BESTStudentCAMP 2024. Poznaj listę nagrodzonych! Stworz...\n",
"\n",
"Error: Spacje wokół dywizu (w przeciwieństwie do myślnika) są zbędne: \"UAM-Pyrkon\"; jeśli to miał być myślnik, to należy napisać \"UAM — Pyrkon\".\n",
"Context: ...wszy etap wdrażania planu. Fantastyczny UAM - Pyrkon 2024 „Człowiek w rzeczywistości AI: roz...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...rs recytatorski wierszy Czesława Miłosza . Uniwe...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...a i nauczanie wzajemnie się przenikają. . Jedna z inicjatyw UAM, w ramach której...\n",
"\n",
"Error: Nie wstawiamy spacji przed kropką\n",
"Context: ...zej uczelni Zobacz nasze ciekawe obiekty . Uniwer...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...asopismach ogólnopolskich i światowych. . Na UA...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...tecie im. Adama Mickiewicza w Poznaniu. . Na UA...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...a także ogłoszone zamówienia publiczne. . Uniwersytet im. Adama Mickiewicza w Po...\n",
"\n"
]
}
],
"source": [
"import requests\n",
"from bs4 import BeautifulSoup\n",
"from language_tool_python import LanguageTool\n",
"\n",
"def find_errors(website_url):\n",
" tool = LanguageTool('pl-PL')\n",
"\n",
" response = requests.get(website_url)\n",
" soup = BeautifulSoup(response.content, 'html.parser')\n",
"\n",
" text = ' '.join([p.get_text() for p in soup.find_all('p')])\n",
"\n",
" matches = tool.check(text)\n",
" \n",
" errors = [match for match in matches if 'Prawidłowa' not in match.ruleIssueType]\n",
" \n",
" return errors\n",
"\n",
"website_url = 'https://amu.edu.pl' \n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "coupled-extra",
"metadata": {},
"source": [
"### Ćwiczenie 2: Napisz skrypt, który poszuka błędów w komentarzach klasy Javowej (zwykłych // oraz w javadocach). Uruchom ten skrypt na źródłach wybranego opensourcowego projektu w Javie."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "settled-armor",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a incorrect comment\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a incorrect comment\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a incorrect comment\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a method that does something\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a method that does something\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a method that does something\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a method that does something\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a method that does something\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // This is a method that does something\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // Return the value of the sample field\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // Return the value of the sample field\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // Return the value of the sample field\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // Return the value of the sample field\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // Another bad comment here\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: // Another bad comment here\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This is a simple Java class demonstrating gr...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This is a simple Java class demonstrating gramm...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This is a simple Java class demonstrating grammatical er...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This is a simple Java class demonstrating grammatical errors in com...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This is a simple Java class demonstrating grammatical errors in comments. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...is is a simple Java class demonstrating grammatical errors in comments. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...le Java class demonstrating grammatical errors in comments. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...ass demonstrating grammatical errors in comments. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method does something very simple. ...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method does something very simple. * @par...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method does something very simple. * @param va...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method does something very simple. * @param value This i...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method does something very simple. * @param value This is a p...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ... * This method does something very simple. * @param value This is a paramete...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...This method does something very simple. * @param value This is a parameter that ...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...thod does something very simple. * @param value This is a parameter that take a i...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...es something very simple. * @param value This is a parameter that take a integer...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...ething very simple. * @param value This is a parameter that take a integer valu...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...g very simple. * @param value This is a parameter that take a integer value. ...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...y simple. * @param value This is a parameter that take a integer value. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ... * @param value This is a parameter that take a integer value. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...* @param value This is a parameter that take a integer value. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...m value This is a parameter that take a integer value. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...This is a parameter that take a integer value. */\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ... a parameter that take a integer value. */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method returns the value of sample fiel...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method returns the value of sample field. ...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method returns the value of sample field. * It sh...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method returns the value of sample field. * It should...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: /** * This method returns the value of sample field. * It should be a ...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...** * This method returns the value of sample field. * It should be a int...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...thod returns the value of sample field. * It should be a integer value. * @...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...turns the value of sample field. * It should be a integer value. * @retu...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...ns the value of sample field. * It should be a integer value. * @return the ...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ... of sample field. * It should be a integer value. * @return the value of samp...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...le field. * It should be a integer value. * @return the value of sampleFiel...\n",
"\n",
"Error: Prawdopodobna literówka: wiele spacji z rzędu\n",
"Context: ...d. * It should be a integer value. * @return the value of sampleField ...\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ... * It should be a integer value. * @return the value of sampleField */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...ould be a integer value. * @return the value of sampleField */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ... be a integer value. * @return the value of sampleField */\n",
"\n",
"Error: Wykryto prawdopodobny błąd pisowni\n",
"Context: ...integer value. * @return the value of sampleField */\n",
"\n",
"Error: Nietypowa kombinacja małych i dużych liter. Czy nie powinno być: \"samplefield\"?\n",
"Context: ...eger value. * @return the value of sampleField */\n",
"\n"
]
}
],
"source": [
"import re\n",
"from language_tool_python import LanguageTool\n",
"\n",
"def correct_java_grammar(java_file_path):\n",
" tool = LanguageTool('pl-PL')\n",
"\n",
" with open(java_file_path, 'r', encoding='utf-8') as file:\n",
" java_code = file.read()\n",
"\n",
" single_line_comments = re.findall(r'//.*', java_code)\n",
" javadocs = re.findall(r'/\\*\\*.*?\\*/', java_code, re.DOTALL)\n",
" \n",
" all_comments = single_line_comments + javadocs\n",
"\n",
" errors = []\n",
" for comment in all_comments:\n",
" matches = tool.check(comment)\n",
" errors.extend(matches)\n",
"\n",
" return errors\n",
"\n",
"java_file_path = 'java/sample_class.java'\n",
"errors = correct_java_grammar(java_file_path)\n",
"\n",
"for error in errors:\n",
" print(f\"Error: {error.message}\\nContext: {error.context}\\n\")\n"
]
}
],
"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.11.9"
},
"subtitle": "15. Korekta gramatyczna",
"title": "Komputerowe wspomaganie tłumaczenia",
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 5
}