add data files, fill Klaudia Marciniak data files, add script to fasten filling the data files
This commit is contained in:
parent
74e9eb31a8
commit
e7dbe327c4
24
data/dialog-13-04-01.tsv
Normal file
24
data/dialog-13-04-01.tsv
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
user Co proszę?
|
||||||
|
system Witam w systemie rezerwacji hotelu. Gdzie chciałbyś się wybrać?
|
||||||
|
user W jakim kraju mogę zarezerwować hotel?
|
||||||
|
system Mamy szeroki wybór hoteli na całym świecie.
|
||||||
|
user Przedstaw proszę oferty z obszaru Górnego Karabachu
|
||||||
|
system Na ile osób?
|
||||||
|
user 3
|
||||||
|
system W jakim budżecie chciałbyś się zmieścić?
|
||||||
|
user 1000 USD na osobę
|
||||||
|
system W jakim terminie?
|
||||||
|
user Ostatni tydzień maja 2023 na 6 dni
|
||||||
|
system Jakie chciałbyś udogodnienia w hotelu?
|
||||||
|
user Gorąca woda i bezpieczna okolica
|
||||||
|
system Przygotowałam 2 propozycje: -XX - hotel 3 gwiazdkowy, położony w jednej z najbezpieczniejszych okolic miasta, oferujący restauracje, 15 min pieszo od wody -YY - hotel 4 gwiazdkowy, położony blisko wody, 15 minut komunikacja miejscą do centrum
|
||||||
|
user Podaj proszę kosztorys dla hotelu YY
|
||||||
|
system Pokój 3 osobowy w hotelu YY w terminie 29.05-03.06 kosztuje 2700USD za pobyt.
|
||||||
|
user Czy jest to cena łączna dla 3 osób?
|
||||||
|
system Tak, jest to łączna cena za pokój 3 osobowy na 6 dni w podanym terminie dla 3 osób. Cena obejmuje śniadania.
|
||||||
|
user Czy oferta zawiera ubezpieczenie?
|
||||||
|
system ubezpieczenie można dokupić osobno
|
||||||
|
user Ile wynosi łączna cena z ubezpieczeniem dla 3 osób?
|
||||||
|
system 2800USD
|
||||||
|
user Rezygnuję z rezerwacji. Potrzebuję więcej czasu do namysłu.
|
||||||
|
system Dobrze, w razie czego służę pomocą.
|
|
11
data/dialog-13-06-01.tsv
Normal file
11
data/dialog-13-06-01.tsv
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
user witam
|
||||||
|
system Witam w systemie rezerwacji hoteli. Gdzie chciałbyś się wybrać?
|
||||||
|
user chciałbym zwiedzić coś egzotycznego. Co możesz mi zaproponować?
|
||||||
|
system Proponuję Dominikanę
|
||||||
|
user tam jest trochę za zimno
|
||||||
|
system Brazylia może?
|
||||||
|
user brzmi bardzo fajnie! Jakie są ceny hoteli w Brazylii?
|
||||||
|
system Ceny są różne, jakie udogodnienia chciałbyś mieć w hotelu?
|
||||||
|
user Chciałbym aby to był pokój dla 2 osób i doga
|
||||||
|
system Oferuję : -hotel YY - hotel połozony w stolicy Brazylii, oferujący transport w miejsca tropikalne pokazujące faune i flore Brazylii, pokoje dostosowane do pobytu zwierzaka -hotel XX- polozony na obrzezach stolicy Brazylii, oferujący kompleks spa oraz prywatny ogród tropikalny, w okolicy jest wiele lokalnych restauracji oraz spokojna okolica
|
|
13
data/dialog-13-08-01.tsv
Normal file
13
data/dialog-13-08-01.tsv
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
user Dzień dobry
|
||||||
|
system Witam w systemie rezerwacji hoteli. Gdzie chciałbys się wybrać?
|
||||||
|
user Dzień dobry. Chciałbym wybrać się do warszawy na przyszły weekend. Szukam pokoi dla dwóch osób w cenie do 500 zł za noc.
|
||||||
|
system Jakie udogodnienia chciałbys w hotelu?
|
||||||
|
user Zależałoby mi na śniadaniu oraz na tym żeby hotel był blisko centrum miasta. Miło by było jakby był dostępny basen.
|
||||||
|
system Oferuję 2 hotele: -hotel ZZ - w ścisłym centrum, z basenem oraz śniadaniami -hotel YY - nieco tańszy, 5 minut spacerkiem do centrum miasta, oferujący kompleks spa oraz śniadania
|
||||||
|
user Poproszę w takim wypadku o rezerwację w hotelu YY.
|
||||||
|
system Proszę podać termin rezerwacji.
|
||||||
|
user 31.03-02.04
|
||||||
|
system Dobrze, w takim razie hotel YY dla dwóch osób w terminie 31.03 do 02.04, czy wszystko się zgadza?
|
||||||
|
user Tak, dziękuję
|
||||||
|
system Dobrze, rezerwacja hotelu YY dla dwóch osób w terminie 31.03 do 02.04 potwierdzona. Numer rezerwacji: 1234567890. Życzę miłego pobytu!
|
||||||
|
user Dziękuję!
|
|
21
data/dialog-13-12-01.tsv
Normal file
21
data/dialog-13-12-01.tsv
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
user Dzień dobry, jakiego rodzaju kuchnię państwo oferujecie?
|
||||||
|
system Witam jesteśmy systemem do rezerwacji hotelu. Gdzie chciałbyś się wybrać?
|
||||||
|
user Dzień dobry, szukam ofert wycieczek wakacyjnych last minute, czy mają państwo jakieś w ofercie?
|
||||||
|
system Jesteśmy systemem do rezerwacji hoteli. niestety nie oferjemy wycieczek. Jednak jeśli byłbyś zainteresowany ofertą wycieczek możemy znaleźć hotel, który oferuje takie udogodnienie.
|
||||||
|
user Interesowałaby mnie Chorwacja, Grecja lub Cypr. Czy któryś z tych krajów wchodzi w grę?
|
||||||
|
system Tak oczywiście, mamy szeroki wybór hoteli w wielu zakątkach świata. Na ile osób przewidziana byłay rezerwacja?
|
||||||
|
user Szukam pokoju dla dwóch osób. Proszę o polecenie kilku z powyższych krajów
|
||||||
|
system Czy chciałbyś hotele bliżej wody czy w centrum?
|
||||||
|
user Hotel w zabytkowym centrum miasta położonego nad morzem
|
||||||
|
system W jakim budżecie?
|
||||||
|
user Maksymalna cena za jedną dobę to 300 złotych
|
||||||
|
system Oferuję: -hotel YY w Grecji, Kos - położony przy plaży, z restauracją oraz kompleksem spa, blisko słynnego pierwszego szpitala na świecie -hotel ZZ w Chorwacji - połozony na wyspie Korcula, blisko miasteczka oferującego wiele udogodnień oraz zabytków -hotel XX na Cyprze - położony poza miastem, oferujący kompleks spa oraz bezpośredni dostęp do wody, hotel oferuje wiele wycieczek dodatkowo płatnych po wyspie
|
||||||
|
user Znalazłaby się jakaś alternatywa dla hotelu na Cyprze z wycieczką w cenie?
|
||||||
|
system Hotel XXY położony niedaleko hotelu XX jest trochę tańszą alternatywą, jednak nie posiada bezpośredniego dostępu do wody
|
||||||
|
user A co z wycieczką?
|
||||||
|
system wycieczki są dostępne w ofercie hotelu
|
||||||
|
user Hmmm, to może ten ze szpitalem jednak
|
||||||
|
system W jakim terminie chciałbyś dokonać rezerwacji?
|
||||||
|
user Od przyszłego poniedziałku do piątku
|
||||||
|
system Dobrze w takim razie hotel YY na Kos dla dwóch osób, w terminie 27.03 do 31.03
|
||||||
|
system czy wszystko się zgadza?
|
|
13
data/dialog-13-14-01.tsv
Normal file
13
data/dialog-13-14-01.tsv
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
user Hej, chciałbym zamówić pokój w Las Vegas na termin 25.03 - 17.04
|
||||||
|
system Witam w systemie rezerwacji hotelu. Na ile osób przewidziana jest rezerwacja?
|
||||||
|
user na 9
|
||||||
|
system Czy pokoje mają być 2 czy 3 osobowe?
|
||||||
|
user jeśli jest możliwość to 1 osobowe, a jak nie to 2
|
||||||
|
system Dobrze. Czy masz przewidziany budżet na całość rezerwacji?
|
||||||
|
user budżet to nie problem
|
||||||
|
system Jakie chciałbyś udogodnienia w hotelu?
|
||||||
|
user chciałbym żeby był all inclusive i przede wszystkim był blisko kasyna
|
||||||
|
system Przygotowałam 3 oferty: -XXX - 5 gwiazdkowy hotel, z basenem, położony blisko centrum oraz wielu kasyn -YYY - 5 gwiazdkowy hotel, z centrum spa, położony w kultowej lokalizacji Las Vegas, blisko najlepszych atrakcji, w okolicy równiez znajdują sie 2 kasyna -ZZZ - 4 gwiazdkowy hotel, z pięknym widokiem na całe miasto, w spokojnej okolicy, 10 minut pieszo do centrum Las Vegas
|
||||||
|
user Poproszę zarezerwować pokój xxx w takim razie
|
||||||
|
system Dobrze. Hotel XXX dla 9 osób w terminie 25.03-17.04 zarezerwowany. Będą to 5 pokoi jednoosobowych oraz 2 pokoje 2 osobowe. Numer rezerwacji : 1234567890. Miłego pobytu!
|
||||||
|
user Dziękuję! Pobyt na pewno będzie miły
|
|
18
data/dialog-13-18-01.tsv
Normal file
18
data/dialog-13-18-01.tsv
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
user Dzień dobry
|
||||||
|
system Witam w systemie rezerwacji hotelu. Gdzie chciałbyś się wybrać?
|
||||||
|
user Dzień dobry, chciałbym zarezerwować nocleg w jakimś tanim hotelu we Włoskich Alpach
|
||||||
|
system Na ile osób przewidziana jest rezerwacja?
|
||||||
|
user 1 osoba
|
||||||
|
system W jakim budżecie chciałbys się zmieścic?
|
||||||
|
user Chciałbym mieć nocleg na 5 dni, maksymalnie 200 euro za noc.'
|
||||||
|
system Czy chciałbyś jakieś udogodnienia w hotelu?
|
||||||
|
user Przydała by się sauna oraz jacuzzi.
|
||||||
|
system Oferuję: -hotel XX w Marileva - piękny hotel, oferujący kompleks spa oraz niebiańskie widoki na Alpy, hotel oferuje również śniadania za opłatą - hotel YY w Madonna di Campligo - przepiękny ośrodek , w około wiele atrakcji. hotel oferuje basen oraz kompleks spa oraz oferuje dodatkową płatną restauracje ala carte Oba hotele mieszczą się w budzecie 180 euro za noc na osobe
|
||||||
|
user Czy w cenę hotelu wchodzą może skipassy?
|
||||||
|
system Niestety nie, jednak hotele oferują zniżki na skipass w ośrodku narciarskim oraz darmowy skibus do wyciągów.
|
||||||
|
user O super! Który by Pani hotel wybrała? Wolę miejsca gdzie wieczorem jest się gdzie pobawić...
|
||||||
|
system W takim razie polecam Madonnę
|
||||||
|
user Super! Proszę o rezerwację i życzę miłego dnia
|
||||||
|
system W jakim terminie chciałbyś się wybrać?
|
||||||
|
user A no tak, to też ważna kwestia... interesuje mnie pierwszy tydzień grudnia tego roku.
|
||||||
|
system Dobrze. Hotel YY dla jednej osoby w terminie 1.12-08.12 zarezerwowany. Życzę miłego wypoczynku.
|
|
0
data/dialog-14-01-01.tsv
Normal file
0
data/dialog-14-01-01.tsv
Normal file
|
0
data/dialog-14-03-01.tsv
Normal file
0
data/dialog-14-03-01.tsv
Normal file
|
0
data/dialog-14-05-01.tsv
Normal file
0
data/dialog-14-05-01.tsv
Normal file
|
0
data/dialog-14-07-01.tsv
Normal file
0
data/dialog-14-07-01.tsv
Normal file
|
0
data/dialog-14-09-01.tsv
Normal file
0
data/dialog-14-09-01.tsv
Normal file
|
0
data/dialog-14-11-01.tsv
Normal file
0
data/dialog-14-11-01.tsv
Normal file
|
0
data/dialog-14-13-01.tsv
Normal file
0
data/dialog-14-13-01.tsv
Normal file
|
0
data/dialog-14-15-01.tsv
Normal file
0
data/dialog-14-15-01.tsv
Normal file
|
0
data/dialog-14-17-01.tsv
Normal file
0
data/dialog-14-17-01.tsv
Normal file
|
0
data/dialog-14-19-01.tsv
Normal file
0
data/dialog-14-19-01.tsv
Normal file
|
0
data/dialog-15-02-01.tsv
Normal file
0
data/dialog-15-02-01.tsv
Normal file
|
0
data/dialog-15-04-01.tsv
Normal file
0
data/dialog-15-04-01.tsv
Normal file
|
0
data/dialog-15-06-01.tsv
Normal file
0
data/dialog-15-06-01.tsv
Normal file
|
0
data/dialog-15-08-01.tsv
Normal file
0
data/dialog-15-08-01.tsv
Normal file
|
0
data/dialog-15-12-01.tsv
Normal file
0
data/dialog-15-12-01.tsv
Normal file
|
0
data/dialog-15-14-01.tsv
Normal file
0
data/dialog-15-14-01.tsv
Normal file
|
0
data/dialog-15-16-01.tsv
Normal file
0
data/dialog-15-16-01.tsv
Normal file
|
0
data/dialog-15-18-01.tsv
Normal file
0
data/dialog-15-18-01.tsv
Normal file
|
126
notebooks/03-04-czarnoksieznik-z-oz.ipynb
Normal file
126
notebooks/03-04-czarnoksieznik-z-oz.ipynb
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "885e01f8",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Eksperymenty typu „Czarnoksiężnik z Oz”\n",
|
||||||
|
"=======================================\n",
|
||||||
|
"\n",
|
||||||
|
"W eksperymencie typu „Czarnoksiężnik z Oz” rolę agenta dialogowego odgrywa operator,\n",
|
||||||
|
"który symuluje działanie systemu udzielając zamiast niego odpowiedzi w reakcji na komunikaty przekazywane przez użytkownika.\n",
|
||||||
|
"\n",
|
||||||
|
"Komunikacja odbywa się za pośrednictwem interfejsu użytkownika zbliżonego do docelowego interfejsu\n",
|
||||||
|
"agenta dialogowego.\n",
|
||||||
|
"\n",
|
||||||
|
"Użytkownik wchodząc w interakcje z czarnoksiężnikiem nie zdaje sobie sprawy z tego, że rozmawia z\n",
|
||||||
|
"człowiekiem a nie z maszyną.\n",
|
||||||
|
"\n",
|
||||||
|
"Instrukcje dla użytkowników\n",
|
||||||
|
"---------------------------\n",
|
||||||
|
"Na potrzeby eksperymentów typu „Czarnoksiężnik z Oz”\n",
|
||||||
|
"warto przygotować zestaw instrukcji opisujących zadania, jakie użytkownik może wykonać za\n",
|
||||||
|
"pośrednictwem rozwijanego systemu.\n",
|
||||||
|
"\n",
|
||||||
|
"Instrukcje takie wręcza się użytkownikom przed przystąpieniem do eksperymentu.\n",
|
||||||
|
"\n",
|
||||||
|
"### Przykład\n",
|
||||||
|
"Przyjrzyjmy się instrukcjom, które zostały przygotowane na potrzeby *Dialog State Tracking Challenge 2* (Henderson i in., 2014).\n",
|
||||||
|
"\n",
|
||||||
|
"Dane wykorzystane w tym konkursie pobierzemy z GitHuba https://github.com/matthen/dstc."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "47d5e497",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"!mkdir -p l03\n",
|
||||||
|
"%cd l03\n",
|
||||||
|
"!wget https://github.com/matthen/dstc/releases/download/v1/dstc2_test.tar.gz\n",
|
||||||
|
"!tar xzvf dstc2_test.tar.gz\n",
|
||||||
|
"%cd .."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "80e57282",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Wyświetlmy kilka przykładowych instrukcji."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "352cee76",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import json\n",
|
||||||
|
"\n",
|
||||||
|
"samples = ['voip-00d76b791d-20130327_005342',\n",
|
||||||
|
" 'voip-00d76b791d-20130327_012544',\n",
|
||||||
|
" 'voip-0f41c16f2f-20130402_004710']\n",
|
||||||
|
"\n",
|
||||||
|
"for sample in samples:\n",
|
||||||
|
" with open(f'l03/data/Mar13_S2A0/{sample}/label.json') as f:\n",
|
||||||
|
" print(json.load(f)['task-information']['goal']['text'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "57a6ca00",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zachęcam również do zapoznania się z opisem samego konkursu https://github.com/matthen/dstc/blob/master/handbook.pdf.\n",
|
||||||
|
"\n",
|
||||||
|
"Zadanie\n",
|
||||||
|
"-------\n",
|
||||||
|
"Korzystając z MS Teams przeprowadzić rozmowy, w których jedna z osób pełni rolę systemu (operatora eksperymentu) a druga użytkownika.\n",
|
||||||
|
"\n",
|
||||||
|
" - W pierwszej serii eksperymentów role użytkowników przyjmują osoby o nieparzystych numerach (kolumna `Lp` tabeli `operatorzy.pdf`).\n",
|
||||||
|
"\n",
|
||||||
|
" - W drugiej serii eksperymentów role użytkowników przyjmują osoby o parzystych numerach (kolumna `Lp` tabeli `operatorzy.pdf`).\n",
|
||||||
|
"\n",
|
||||||
|
"Każdy użytkownik powinien przeprowadzić przynajmniej jedną rozmowę z każdym operatorem.\n",
|
||||||
|
"\n",
|
||||||
|
"Operator eksperymentu zachowuje zapis rozmowy w katalogu `data` gałęzi master\n",
|
||||||
|
"repozytorium projektowego w pliku o nazwie `dialog-XX-YY-NN.tsv`, gdzie:\n",
|
||||||
|
"\n",
|
||||||
|
" - `XX` numer operatora\n",
|
||||||
|
"\n",
|
||||||
|
" - `YY` numer użytkownika\n",
|
||||||
|
"\n",
|
||||||
|
" - `NN` numer rozmowy (`01` dla pierwszej rozmowy miedzy `XX` i `YY`)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "e23b38d3",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zapisy rozmów proszę zachować w postaci plików o rozszerzeniu `tsv`.\n",
|
||||||
|
"Pierwsza kolumna pliku powinna zawierać oznaczenie roli interlokutora (ciąg znaków `system` lub `user`) druga jego wypowiedź.\n",
|
||||||
|
"\n",
|
||||||
|
"Czy przeprowadzone testy można uznać za realizację techniki \"Czarnoksiężnik z Oz\"?\n",
|
||||||
|
"\n",
|
||||||
|
"Literatura\n",
|
||||||
|
"----------\n",
|
||||||
|
" 1. Matthew Henderson, Blaise Thomson, Jason D. Williams, The Second Dialog State Tracking Challenge, SIGDIAL 2014, 263-272."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"jupytext": {
|
||||||
|
"cell_metadata_filter": "-all",
|
||||||
|
"main_language": "python",
|
||||||
|
"notebook_metadata_filter": "-all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
299
notebooks/05-struktura-dialogu.ipynb
Normal file
299
notebooks/05-struktura-dialogu.ipynb
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "5fb40545",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Struktura dialogu\n",
|
||||||
|
"=================\n",
|
||||||
|
"\n",
|
||||||
|
"Dialog można podzielić na *tury* będące naprzemiennymi wypowiedziami\n",
|
||||||
|
"poszczególnych uczestników konwersacji.\n",
|
||||||
|
"\n",
|
||||||
|
"<!-- TODO rysunek drawio (chmurki) -->\n",
|
||||||
|
"\n",
|
||||||
|
"### Akty mowy\n",
|
||||||
|
"Akcje podejmowane przez mówców za pomocą wypowiedzi nazywamy *aktami mowy*.\n",
|
||||||
|
"\n",
|
||||||
|
"#### Aspekty aktów mowy według Austina (za Zdunkiewicz 1993)\n",
|
||||||
|
"| Aspekt | Opis |\n",
|
||||||
|
"|-------------:|:-----------------------------------------------------------------------------------------------------------------------------|\n",
|
||||||
|
"| lokucyjny | dotyczy samego procesu tworzenia określonego wyrażenia (bez uwzględnienia kontekstu) |\n",
|
||||||
|
"| illokucyjny | dotyczy tego co mówca chce osiągnąć za pośrednictwem danej wypowiedzi (np. prośba, ostrzeżenie, obietnica, żądanie) |\n",
|
||||||
|
"| perlokucyjny | dotyczy ubocznych celów i rezeltatów osiągniętych za pośrednictwem danej wypowiedzi (np. zlekceważenie, obraza, rozbawienie) |\n",
|
||||||
|
"\n",
|
||||||
|
"#### Klasyfikacja aktów mowy według Searla (za Zdunkiewicz 1993)\n",
|
||||||
|
"\n",
|
||||||
|
"| Typ | Cel | Przykłady |\n",
|
||||||
|
"|--------------------------:|:------------------------------------------------------------|:------------------------|\n",
|
||||||
|
"| asercja (assertive) | przedstawienie sądu o stanie rzeczy | wątpienie |\n",
|
||||||
|
"| dyrektywa (directive) | wywieranie nacisku na odbiorcę | rozkaz, prośba |\n",
|
||||||
|
"| komisywa (commisive) | podjecie zobowiązania | obietnica, zobowiązanie |\n",
|
||||||
|
"| ekspresywa (expressive) | wyrażenie stanu emocjonalnego | gratulacje, kondolencje |\n",
|
||||||
|
"| deklaratywa (declarative) | wywołanie określonego stanu rzeczy w stosunkach społecznych | mianowanie |"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "58255cc1",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Akty dialogowe\n",
|
||||||
|
"\n",
|
||||||
|
"Budując system dialogowy zwykle przyjmuje się węższa i jednocześnie bardziej\n",
|
||||||
|
"szczegółową klasyfikację.\n",
|
||||||
|
"Tzw. *akty dialogowe* stanowią reprezentację znaczenia wypowiedzi użytkownika i/lub systemu.\n",
|
||||||
|
"\n",
|
||||||
|
"Przyjrzyjmy się teraz klasyfikacji aktów dialogowych, które Henderson i in. (2013), wzorując się na Youngu i in. (2010), przyjęli na potrzeby ewaluacji systemów rekomendujących restauracje."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "1a0618ce",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"!mkdir -p l04\n",
|
||||||
|
"%cd l04\n",
|
||||||
|
"!wget -c https://github.com/matthen/dstc/releases/download/v1/dstc2_test.tar.gz\n",
|
||||||
|
"!tar xzvf dstc2_test.tar.gz\n",
|
||||||
|
"%cd .."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2f2a21be",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"#### Akty użytkownika\n",
|
||||||
|
"\n",
|
||||||
|
"| Typ | Opis |\n",
|
||||||
|
"|---------:|:-----------------------------------|\n",
|
||||||
|
"| ack | potwierdzenie |\n",
|
||||||
|
"| affirm | zatwierdzenie |\n",
|
||||||
|
"| bye | zakończenie rozmowy |\n",
|
||||||
|
"| hello | przywitanie |\n",
|
||||||
|
"| help | prośba o pomoc (bez szczegółów) |\n",
|
||||||
|
"| negate | zaprzeczenie |\n",
|
||||||
|
"| null | akt niezrozumiały dla systemu |\n",
|
||||||
|
"| repeat | prośba o powtórzenie |\n",
|
||||||
|
"| reqalts | prośba o alternatywną rekomendację |\n",
|
||||||
|
"| reqmore | prośba o uszczegółowienie |\n",
|
||||||
|
"| restart | żądanie restartu |\n",
|
||||||
|
"| silence | cisza |\n",
|
||||||
|
"| thankyou | podziękowanie |\n",
|
||||||
|
"| confirm | potwierdzenie wartości slotu |\n",
|
||||||
|
"| deny | odrzucenie wartości slotu |\n",
|
||||||
|
"| inform | przekazanie wartości slotu |\n",
|
||||||
|
"| request | prośba o podanie wartości slotu |"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b6112a72",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zilustrujmy powyższe zestawienie przykładami bezpośrednio ze zbioru testowego konkursu *Dialog State Tracking Challenge 2*."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "95b948c5",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import glob\n",
|
||||||
|
"import json\n",
|
||||||
|
"import tabulate\n",
|
||||||
|
"import itertools\n",
|
||||||
|
"\n",
|
||||||
|
"def acts2desc(acts):\n",
|
||||||
|
" descs = []\n",
|
||||||
|
"\n",
|
||||||
|
" for intent, iacts in itertools.groupby(sorted(acts, key=lambda x: x['act']), key=lambda x: x['act']):\n",
|
||||||
|
" slots = ','.join(f'{slot[0]}={slot[1]}' if slot[0] != 'slot' else slot[1] for act in iacts for slot in act['slots'])\n",
|
||||||
|
" descs.append(f'{intent}({slots})')\n",
|
||||||
|
"\n",
|
||||||
|
" return '&'.join(descs) if descs else 'null()'\n",
|
||||||
|
"\n",
|
||||||
|
"examples = set()\n",
|
||||||
|
"\n",
|
||||||
|
"for path in sorted(glob.glob('l04/data/**/label.json', recursive=True)):\n",
|
||||||
|
" if len(examples) > 30:\n",
|
||||||
|
" break\n",
|
||||||
|
"\n",
|
||||||
|
" with open(path) as f:\n",
|
||||||
|
" for turn in json.load(f)['turns']:\n",
|
||||||
|
" examples.add((acts2desc(turn['semantics']['json']), turn['transcription']))\n",
|
||||||
|
" # examples.add(((turn['semantics']['cam']), turn['transcription']))\n",
|
||||||
|
"\n",
|
||||||
|
"tabulate.tabulate(examples, tablefmt='html', headers=['act', 'utterance'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "4d9bd69f",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Powyższe przykłady pokazują, że tury nie zawsze są pełnymi zdaniami. Komunikacja przy użyciu mowy\n",
|
||||||
|
"ma spontaniczny charakter, stąd w toku konwersacji mogą pojawić się poprawki, wtręty czy żądania\n",
|
||||||
|
"restartu.\n",
|
||||||
|
"\n",
|
||||||
|
"#### Akty systemu\n",
|
||||||
|
"\n",
|
||||||
|
"| Typ | Opis |\n",
|
||||||
|
"|----------------------------:|:--------------------------------------------------------|\n",
|
||||||
|
"| affirm | potwierdzenie |\n",
|
||||||
|
"| bye | zakończenie rozmowy |\n",
|
||||||
|
"| canthear | „nic nie słyszę” |\n",
|
||||||
|
"| confirm-domain | prośba o potwierdzenie dziedziny |\n",
|
||||||
|
"| negate | zaprzeczenie |\n",
|
||||||
|
"| repeat | prośba o powtórzenie |\n",
|
||||||
|
"| reqmore | sprawdzenie czy użytkownik chce dodatkowych informacji |\n",
|
||||||
|
"| welcomemsg | przywitanie |\n",
|
||||||
|
"| canthelp | „nie mogę pomóc” |\n",
|
||||||
|
"| canthelp.missing_slot_value | „potrzebuję poznać wartość slotu, żeby pomóc” |\n",
|
||||||
|
"| expl-conf | potwierdzenie (wprost), że slot ma daną wartość |\n",
|
||||||
|
"| impl-conf | potwierdzenie (nie wprost), że slot ma daną wartość |\n",
|
||||||
|
"| inform | poinformowanie użytkownika, o przyjętej wartości slotu |\n",
|
||||||
|
"| offer | rekomendacja (restauracji) |\n",
|
||||||
|
"| request | pytanie użytkownika o wartość slotu |\n",
|
||||||
|
"| select | prośba o dokonanie wyboru spośród przedstawionych opcji |\n",
|
||||||
|
"\n",
|
||||||
|
"Przyjrzyjmy się również przykładom aktów systemowych."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "c12c43b9",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import glob\n",
|
||||||
|
"import json\n",
|
||||||
|
"import tabulate\n",
|
||||||
|
"\n",
|
||||||
|
"examples = set()\n",
|
||||||
|
"\n",
|
||||||
|
"for path in sorted(glob.glob('l04/data/**/log.json', recursive=True)):\n",
|
||||||
|
" if len(examples) > 30:\n",
|
||||||
|
" break\n",
|
||||||
|
"\n",
|
||||||
|
" with open(path) as f:\n",
|
||||||
|
" for turn in json.load(f)['turns']:\n",
|
||||||
|
" output = turn['output']\n",
|
||||||
|
" examples.add((acts2desc(output['dialog-acts']), output['transcript']))\n",
|
||||||
|
"\n",
|
||||||
|
"tabulate.tabulate(examples, tablefmt='html', headers=['act', 'utterance'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2d8d9f4a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Jak widać w powyższym ujęciu akty dialogowe takie jak `inform`, `request` czy `expl-conf` mogą\n",
|
||||||
|
"przyjmować pewne parametry.\n",
|
||||||
|
"\n",
|
||||||
|
"### Ramy\n",
|
||||||
|
"Strukturą danych powszechnie wykorzystywaną w systemach dialogowych do reprezentacji wiedzy\n",
|
||||||
|
"jest *rama* (ang. *frame*).\n",
|
||||||
|
"Ramy są wykorzystywane zarówno do reprezentowania poszczególnych aktów mowy jak i do\n",
|
||||||
|
"modelowania bieżącego stanu dialogu oraz celów użytkownika.\n",
|
||||||
|
"Rama ma nazwę oraz pewną liczbę *slotów*. Każdy slot ma określoną nazwę oraz wartość.\n",
|
||||||
|
"\n",
|
||||||
|
"Ramy przedstawione poniżej stanowią reprezentacje aktów dialogowych."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "61cebc74",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import json\n",
|
||||||
|
"\n",
|
||||||
|
"samples = ['voip-00d76b791d-20130327_005342',\n",
|
||||||
|
" 'voip-00d76b791d-20130327_012544',\n",
|
||||||
|
" 'voip-0f41c16f2f-20130402_004710']\n",
|
||||||
|
"\n",
|
||||||
|
"for sample in samples:\n",
|
||||||
|
" with open(f'l04/data/Mar13_S2A0/{sample}/label.json') as f:\n",
|
||||||
|
" print(json.dumps(json.load(f)['turns'][3]['semantics']['json'], indent=2))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "60012ed2",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zadanie\n",
|
||||||
|
"-------\n",
|
||||||
|
"Opisać wypowiedzi użytkownika i odpowiedzi systemu zgromadzone w Państwa korpusie eksperymentalnym (tj. plikach `*.tsv` w katalogu `data`) aktami dialogowymi."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "07d5cb8f",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Uwagi\n",
|
||||||
|
"\n",
|
||||||
|
" - Akty reprezentujące znaczenie poszczególnych wypowiedzi należy umieszczać w trzeciej kolumnie plików `*.tsv`.\n",
|
||||||
|
"\n",
|
||||||
|
" - Do zapisu aktów proszę stosować notację wykorzystywaną w przykładach (`inform(phone=01223 244277)&offer(name=the lucky star)`).\n",
|
||||||
|
"\n",
|
||||||
|
" - Klasyfikacja aktów dialogowych przedstawiona przez Hendersona i in. (2013) może stanowić dobry punkt wyjścia, ale nie trzeba się jej kurczowo trzymać."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "8eabbfee",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Przykładowe narzędzia do oznaczania tekstu\n",
|
||||||
|
"------------------------------------------\n",
|
||||||
|
"\n",
|
||||||
|
" - [brat](http://brat.nlplab.org/)\n",
|
||||||
|
"\n",
|
||||||
|
" - [doccano](https://github.com/doccano/doccano)\n",
|
||||||
|
"\n",
|
||||||
|
" - [WebAnno](https://webanno.github.io/webanno/)\n",
|
||||||
|
"\n",
|
||||||
|
" - [LabelStudio](https://labelstud.io/)\n",
|
||||||
|
"\n",
|
||||||
|
" - Microsoft Excel, Office 365 itp.\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b2e21e26",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Literatura\n",
|
||||||
|
"----------\n",
|
||||||
|
" 1. Austin, John Langshaw, How to Do Things with Words, Oxford, 1962.\n",
|
||||||
|
"\n",
|
||||||
|
" 2. John Searle, Speech Acts, Cambridge University Press, 1969, ISBN 0-521-09626-X.\n",
|
||||||
|
"\n",
|
||||||
|
" 3. Dorota Zdunkiewicz, Akty mowy, Współczesny język polski, Wrocław, 1993, pp. 259-270.\n",
|
||||||
|
"\n",
|
||||||
|
" 4. Matthew Henderson, Blaise Thomson, Jason D. Williams, The Second Dialog State Tracking Challenge, SIGDIAL 2014, 263-272."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"jupytext": {
|
||||||
|
"cell_metadata_filter": "-all",
|
||||||
|
"main_language": "python",
|
||||||
|
"notebook_metadata_filter": "-all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
99
notebooks/06-architektura-systemu-dialogowego.ipynb
Normal file
99
notebooks/06-architektura-systemu-dialogowego.ipynb
Normal file
File diff suppressed because one or more lines are too long
217
notebooks/07-parsing-semantyczny-gramatyki.ipynb
Normal file
217
notebooks/07-parsing-semantyczny-gramatyki.ipynb
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "82a52d23",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Parsing semantyczny z wykorzystaniem gramatyk\n",
|
||||||
|
"=============================================\n",
|
||||||
|
"\n",
|
||||||
|
"Wartości slotów możemy wydobywać z wypowiedzi użytkownika korzystając z takich technik, jak:\n",
|
||||||
|
"\n",
|
||||||
|
" - wyszukiwanie słów kluczowych w tekście,\n",
|
||||||
|
"\n",
|
||||||
|
" - dopasowywanie wzorców zbudowanych przy użyciu wyrażeń regularnych,\n",
|
||||||
|
"\n",
|
||||||
|
" - parsery regułowe (temat dzisiejszych zajęć),\n",
|
||||||
|
"\n",
|
||||||
|
" - uczenie maszynowe (temat kolejnych zajęć)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "4e864fb4",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Przykłady parserów regułowych\n",
|
||||||
|
"-----------------------------\n",
|
||||||
|
"\n",
|
||||||
|
" - [Phoenix](http://wiki.speech.cs.cmu.edu/olympus/index.php/Phoenix_Server) — parser gramatyk\n",
|
||||||
|
" bezkontekstowych whodzący w skład systemu dialogowego [Olympus](http://wiki.speech.cs.cmu.edu/olympus/index.php/Olympus)\n",
|
||||||
|
"\n",
|
||||||
|
" - Parsery [DCG](https://www.swi-prolog.org/pldoc/man?section=DCG) (Definite Clause Grammars) języka [Prolog](https://www.swi-prolog.org/)\n",
|
||||||
|
"\n",
|
||||||
|
" - [JSpeech Grammar Format](https://www.w3.org/TR/jsgf/) (JSGF)\n",
|
||||||
|
"\n",
|
||||||
|
"Przykład\n",
|
||||||
|
"--------\n",
|
||||||
|
"Zapiszmy w JSGF gramatykę semantyczną dla aktu dialogowego reprezentującego zamiar rezerwacji\n",
|
||||||
|
"stolika w restauracji."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "4c6b17fc",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"%%writefile book.jsgf\n",
|
||||||
|
"#JSGF V1.0 UTF-8 pl;\n",
|
||||||
|
"\n",
|
||||||
|
"grammar book;\n",
|
||||||
|
"\n",
|
||||||
|
"public <rezerwuj> = chciałbym zarezerwować stolik <dzien_rezerwacji> <godzina_rezerwacji> <liczba_osob> ;\n",
|
||||||
|
"\n",
|
||||||
|
"<dzien_rezerwacji> = na <dzien> {day};\n",
|
||||||
|
"\n",
|
||||||
|
"<dzien> = dzisiaj | jutro | poniedziałek | wtorek | środę | czwartek | piątek | sobotę | niedzielę;\n",
|
||||||
|
"\n",
|
||||||
|
"<godzina_rezerwacji> = na [godzinę] <godzina_z_minutami> {hour};\n",
|
||||||
|
"\n",
|
||||||
|
"<godzina_z_minutami> = <godzina> [<minuty>];\n",
|
||||||
|
"\n",
|
||||||
|
"<godzina> = dziewiątą | dziesiątą | jedenastą | dwunastą;\n",
|
||||||
|
"\n",
|
||||||
|
"<minuty> = pietnaście | trzydzieści;\n",
|
||||||
|
"\n",
|
||||||
|
"<liczba_osob> = (na | dla) <liczba> {size} osób;\n",
|
||||||
|
"\n",
|
||||||
|
"<liczba> = dwie | dwóch | trzy | trzech | cztery | czterech | pięć | pieciu;\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "7442f5b9",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Parser akceptujący powyższą gramatykę utworzymy korzystając z biblioteki [pyjsgf](https://github.com/Danesprite/pyjsgf)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "927f7cac",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import jsgf\n",
|
||||||
|
"\n",
|
||||||
|
"book_grammar = jsgf.parse_grammar_file('book.jsgf')\n",
|
||||||
|
"book_grammar"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "7fbf718f",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Wykorzystajmy gramatykę `book.jsgf` do analizy następującej wypowiedzi"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "fe70432a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"utterance = 'chciałbym zarezerwować stolik na jutro na godzinę dwunastą trzydzieści na pięć osób'\n",
|
||||||
|
"matched = book_grammar.find_matching_rules(utterance)\n",
|
||||||
|
"matched"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "4dd1ac3d",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Reprezentację znaczenia można wydobyć ze sparsowanej wypowiedzi na wiele sposobów. My do\n",
|
||||||
|
"wydobywania slotów wykorzystamy mechanizm tagów JSGF a za nazwę aktu dialogowego przyjmiemy nazwę\n",
|
||||||
|
"gramatyki. Wzorując się na [DSTC2](https://github.com/matthen/dstc) wynikową ramę zapiszemy korzystając ze słownika o polach `act` i `slots`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "2b2bd6b7",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def get_dialog_act(rule):\n",
|
||||||
|
" slots = []\n",
|
||||||
|
" get_slots(rule.expansion, slots)\n",
|
||||||
|
" return {'act': rule.grammar.name, 'slots': slots}\n",
|
||||||
|
"\n",
|
||||||
|
"def get_slots(expansion, slots):\n",
|
||||||
|
" if expansion.tag != '':\n",
|
||||||
|
" slots.append((expansion.tag, expansion.current_match))\n",
|
||||||
|
" return\n",
|
||||||
|
"\n",
|
||||||
|
" for child in expansion.children:\n",
|
||||||
|
" get_slots(child, slots)\n",
|
||||||
|
"\n",
|
||||||
|
" if not expansion.children and isinstance(expansion, jsgf.NamedRuleRef):\n",
|
||||||
|
" get_slots(expansion.referenced_rule.expansion, slots)\n",
|
||||||
|
"\n",
|
||||||
|
"get_dialog_act(matched[0])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2fca2fc3",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Łącząc powyższe funkcje możemy zbudować prosty moduł NLU."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "87a917a7",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def nlu(utterance):\n",
|
||||||
|
" matched = book_grammar.find_matching_rules(utterance)\n",
|
||||||
|
"\n",
|
||||||
|
" if matched:\n",
|
||||||
|
" return get_dialog_act(matched[0])\n",
|
||||||
|
" else:\n",
|
||||||
|
" return {'act': 'null', 'slots': []}\n",
|
||||||
|
"\n",
|
||||||
|
"nlu('chciałbym zarezerwować stolik na jutro na godzinę dziesiątą dla trzech osób')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "9e801dde",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Problemy\n",
|
||||||
|
"--------\n",
|
||||||
|
"\n",
|
||||||
|
" - Co z normalizacją wyrażeń liczbowych takich, jak godziny, daty czy numery telefonów?\n",
|
||||||
|
"\n",
|
||||||
|
" - Co w przypadku gdy więcej niż jedna reguła zostanie dopasowana?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "c8289023",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zadanie\n",
|
||||||
|
"-------\n",
|
||||||
|
"Zaimplementować analizator języka naturalnego (NLU) na potrzeby realizowanego agenta dialogowego.\n",
|
||||||
|
"\n",
|
||||||
|
"Moduł powinien być zbudowany z wykorzystaniem parsingu regułowego i/lub technik uczenia maszynowego.\n",
|
||||||
|
"\n",
|
||||||
|
"Przygotować skrypt `evaluate.py` wyznaczający *dokładność* (ang. accuracy) analizatora względem zgromadzonego korpusu eksperymentalnego,\n",
|
||||||
|
"tj. stosunek liczby wypowiedzi użytkownika, w których akty dialogowe zostały rozpoznane prawidłowo do liczby wszystkich wypowiedzi użytkownika w korpusie.\n",
|
||||||
|
"\n",
|
||||||
|
"Analizator języka naturalnego umieścić w gałęzi `master` repozytorium projektowego. Skrypt `evaluate.py` umieścić w katalogu głównym tej gałęzi."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"jupytext": {
|
||||||
|
"cell_metadata_filter": "-all",
|
||||||
|
"main_language": "python",
|
||||||
|
"notebook_metadata_filter": "-all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
450
notebooks/08-parsing-semantyczny-uczenie.ipynb
Normal file
450
notebooks/08-parsing-semantyczny-uczenie.ipynb
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "68bc3d74",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Parsing semantyczny z wykorzystaniem technik uczenia maszynowego\n",
|
||||||
|
"================================================================\n",
|
||||||
|
"\n",
|
||||||
|
"Wprowadzenie\n",
|
||||||
|
"------------\n",
|
||||||
|
"Problem wykrywania slotów i ich wartości w wypowiedziach użytkownika można sformułować jako zadanie\n",
|
||||||
|
"polegające na przewidywaniu dla poszczególnych słów etykiet wskazujących na to czy i do jakiego\n",
|
||||||
|
"slotu dane słowo należy.\n",
|
||||||
|
"\n",
|
||||||
|
"<pre>chciałbym zarezerwować stolik na jutro<b>/day</b> na godzinę dwunastą<b>/hour</b> czterdzieści<b>/hour</b> pięć<b>/hour</b> na pięć<b>/size</b> osób</pre>\n",
|
||||||
|
"\n",
|
||||||
|
"Granice slotów oznacza się korzystając z wybranego schematu etykietowania.\n",
|
||||||
|
"\n",
|
||||||
|
"### Schemat IOB\n",
|
||||||
|
"\n",
|
||||||
|
"| Prefix | Znaczenie |\n",
|
||||||
|
"|:------:|:---------------------------|\n",
|
||||||
|
"| I | wnętrze slotu (inside) |\n",
|
||||||
|
"| O | poza slotem (outside) |\n",
|
||||||
|
"| B | początek slotu (beginning) |\n",
|
||||||
|
"\n",
|
||||||
|
"<pre>chciałbym zarezerwować stolik na jutro<b>/B-day</b> na godzinę dwunastą<b>/B-hour</b> czterdzieści<b>/I-hour</b> pięć<b>/I-hour</b> na pięć<b>/B-size</b> osób</pre>\n",
|
||||||
|
"\n",
|
||||||
|
"### Schemat IOBES\n",
|
||||||
|
"\n",
|
||||||
|
"| Prefix | Znaczenie |\n",
|
||||||
|
"|:------:|:---------------------------|\n",
|
||||||
|
"| I | wnętrze slotu (inside) |\n",
|
||||||
|
"| O | poza slotem (outside) |\n",
|
||||||
|
"| B | początek slotu (beginning) |\n",
|
||||||
|
"| E | koniec slotu (ending) |\n",
|
||||||
|
"| S | pojedyncze słowo (single) |\n",
|
||||||
|
"\n",
|
||||||
|
"<pre>chciałbym zarezerwować stolik na jutro<b>/S-day</b> na godzinę dwunastą<b>/B-hour</b> czterdzieści<b>/I-hour</b> pięć<b>/E-hour</b> na pięć<b>/S-size</b> osób</pre>\n",
|
||||||
|
"\n",
|
||||||
|
"Jeżeli dla tak sformułowanego zadania przygotujemy zbiór danych\n",
|
||||||
|
"złożony z wypowiedzi użytkownika z oznaczonymi slotami (tzw. *zbiór uczący*),\n",
|
||||||
|
"to możemy zastosować techniki (nadzorowanego) uczenia maszynowego w celu zbudowania modelu\n",
|
||||||
|
"annotującego wypowiedzi użytkownika etykietami slotów.\n",
|
||||||
|
"\n",
|
||||||
|
"Do zbudowania takiego modelu można wykorzystać między innymi:\n",
|
||||||
|
"\n",
|
||||||
|
" 1. warunkowe pola losowe (Lafferty i in.; 2001),\n",
|
||||||
|
"\n",
|
||||||
|
" 2. rekurencyjne sieci neuronowe, np. sieci LSTM (Hochreiter i Schmidhuber; 1997),\n",
|
||||||
|
"\n",
|
||||||
|
" 3. transformery (Vaswani i in., 2017).\n",
|
||||||
|
"\n",
|
||||||
|
"Przykład\n",
|
||||||
|
"--------\n",
|
||||||
|
"Skorzystamy ze zbioru danych przygotowanego przez Schustera (2019)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "8cca8cd1",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"!mkdir -p l07\n",
|
||||||
|
"%cd l07\n",
|
||||||
|
"!curl -L -C - https://fb.me/multilingual_task_oriented_data -o data.zip\n",
|
||||||
|
"!unzip data.zip\n",
|
||||||
|
"%cd .."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "56d91f6c",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zbiór ten gromadzi wypowiedzi w trzech językach opisane slotami dla dwunastu ram należących do trzech dziedzin `Alarm`, `Reminder` oraz `Weather`. Dane wczytamy korzystając z biblioteki [conllu](https://pypi.org/project/conllu/)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "18b9a032",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from conllu import parse_incr\n",
|
||||||
|
"fields = ['id', 'form', 'frame', 'slot']\n",
|
||||||
|
"\n",
|
||||||
|
"def nolabel2o(line, i):\n",
|
||||||
|
" return 'O' if line[i] == 'NoLabel' else line[i]\n",
|
||||||
|
"\n",
|
||||||
|
"with open('l07/en/train-en.conllu') as trainfile:\n",
|
||||||
|
" trainset = list(parse_incr(trainfile, fields=fields, field_parsers={'slot': nolabel2o}))\n",
|
||||||
|
"with open('l07/en/test-en.conllu') as testfile:\n",
|
||||||
|
" testset = list(parse_incr(testfile, fields=fields, field_parsers={'slot': nolabel2o}))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "7477593e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zobaczmy kilka przykładowych wypowiedzi z tego zbioru."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "b2799ad2",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from tabulate import tabulate\n",
|
||||||
|
"tabulate(trainset[0], tablefmt='html')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "ba2c2706",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"tabulate(trainset[1000], tablefmt='html')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "b5c9db18",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"tabulate(trainset[2000], tablefmt='html')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "0f35074d",
|
||||||
|
"metadata": {
|
||||||
|
"lines_to_next_cell": 0
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Na potrzeby prezentacji procesu uczenia w jupyterowym notatniku zawęzimy zbiór danych do początkowych przykładów."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "f735ca85",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"trainset = trainset[:300]\n",
|
||||||
|
"testset = testset[:300]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "66284486",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Budując model skorzystamy z architektury opartej o rekurencyjne sieci neuronowe\n",
|
||||||
|
"zaimplementowanej w bibliotece [flair](https://github.com/flairNLP/flair) (Akbik i in. 2018)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "f3e30f81",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from flair.data import Corpus, Sentence, Token\n",
|
||||||
|
"from flair.datasets import FlairDatapointDataset\n",
|
||||||
|
"from flair.embeddings import StackedEmbeddings\n",
|
||||||
|
"from flair.embeddings import WordEmbeddings\n",
|
||||||
|
"from flair.embeddings import CharacterEmbeddings\n",
|
||||||
|
"from flair.embeddings import FlairEmbeddings\n",
|
||||||
|
"from flair.models import SequenceTagger\n",
|
||||||
|
"from flair.trainers import ModelTrainer\n",
|
||||||
|
"\n",
|
||||||
|
"# determinizacja obliczeń\n",
|
||||||
|
"import random\n",
|
||||||
|
"import torch\n",
|
||||||
|
"random.seed(42)\n",
|
||||||
|
"torch.manual_seed(42)\n",
|
||||||
|
"\n",
|
||||||
|
"if torch.cuda.is_available():\n",
|
||||||
|
" torch.cuda.manual_seed(0)\n",
|
||||||
|
" torch.cuda.manual_seed_all(0)\n",
|
||||||
|
" torch.backends.cudnn.enabled = False\n",
|
||||||
|
" torch.backends.cudnn.benchmark = False\n",
|
||||||
|
" torch.backends.cudnn.deterministic = True"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "c1a33987",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Dane skonwertujemy do formatu wykorzystywanego przez `flair`, korzystając z następującej funkcji."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "f3c47593",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def conllu2flair(sentences, label=None):\n",
|
||||||
|
" fsentences = []\n",
|
||||||
|
"\n",
|
||||||
|
" for sentence in sentences:\n",
|
||||||
|
" fsentence = Sentence(' '.join(token['form'] for token in sentence), use_tokenizer=False)\n",
|
||||||
|
" start_idx = None\n",
|
||||||
|
" end_idx = None\n",
|
||||||
|
" tag = None\n",
|
||||||
|
"\n",
|
||||||
|
" if label:\n",
|
||||||
|
" for idx, (token, ftoken) in enumerate(zip(sentence, fsentence)):\n",
|
||||||
|
" if token[label].startswith('B-'):\n",
|
||||||
|
" start_idx = idx\n",
|
||||||
|
" end_idx = idx\n",
|
||||||
|
" tag = token[label][2:]\n",
|
||||||
|
" elif token[label].startswith('I-'):\n",
|
||||||
|
" end_idx = idx\n",
|
||||||
|
" elif token[label] == 'O':\n",
|
||||||
|
" if start_idx is not None:\n",
|
||||||
|
" fsentence[start_idx:end_idx+1].add_label(label, tag)\n",
|
||||||
|
" start_idx = None\n",
|
||||||
|
" end_idx = None\n",
|
||||||
|
" tag = None\n",
|
||||||
|
"\n",
|
||||||
|
" if start_idx is not None:\n",
|
||||||
|
" fsentence[start_idx:end_idx+1].add_label(label, tag)\n",
|
||||||
|
"\n",
|
||||||
|
" fsentences.append(fsentence)\n",
|
||||||
|
"\n",
|
||||||
|
" return FlairDatapointDataset(fsentences)\n",
|
||||||
|
"\n",
|
||||||
|
"corpus = Corpus(train=conllu2flair(trainset, 'slot'), test=conllu2flair(testset, 'slot'))\n",
|
||||||
|
"print(corpus)\n",
|
||||||
|
"tag_dictionary = corpus.make_label_dictionary(label_type='slot')\n",
|
||||||
|
"print(tag_dictionary)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "0ed59fb2",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Nasz model będzie wykorzystywał wektorowe reprezentacje słów (zob. [Word Embeddings](https://github.com/flairNLP/flair/blob/master/resources/docs/TUTORIAL_EMBEDDINGS_OVERVIEW.md))."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "408cf961",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"embedding_types = [\n",
|
||||||
|
" WordEmbeddings('en'),\n",
|
||||||
|
" FlairEmbeddings('en-forward'),\n",
|
||||||
|
" FlairEmbeddings('en-backward'),\n",
|
||||||
|
" CharacterEmbeddings(),\n",
|
||||||
|
"]\n",
|
||||||
|
"\n",
|
||||||
|
"embeddings = StackedEmbeddings(embeddings=embedding_types)\n",
|
||||||
|
"tagger = SequenceTagger(hidden_size=256, embeddings=embeddings,\n",
|
||||||
|
" tag_dictionary=tag_dictionary,\n",
|
||||||
|
" tag_type='slot', use_crf=True)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "ab634218",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Zobaczmy jak wygląda architektura sieci neuronowej, która będzie odpowiedzialna za przewidywanie\n",
|
||||||
|
"slotów w wypowiedziach."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "04d0bbf3",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"print(tagger)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "8e0da880",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Wykonamy dziesięć iteracji (epok) uczenia a wynikowy model zapiszemy w katalogu `slot-model`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "0fd2b573",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"trainer = ModelTrainer(tagger, corpus)\n",
|
||||||
|
"trainer.train('slot-model',\n",
|
||||||
|
" learning_rate=0.1,\n",
|
||||||
|
" mini_batch_size=32,\n",
|
||||||
|
" max_epochs=10,\n",
|
||||||
|
" train_with_dev=False)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "bcd0c303",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Jakość wyuczonego modelu możemy ocenić, korzystając z zaraportowanych powyżej metryk, tj.:\n",
|
||||||
|
"\n",
|
||||||
|
" - *tp (true positives)*\n",
|
||||||
|
"\n",
|
||||||
|
" > liczba słów oznaczonych w zbiorze testowym etykietą $e$, które model oznaczył tą etykietą\n",
|
||||||
|
"\n",
|
||||||
|
" - *fp (false positives)*\n",
|
||||||
|
"\n",
|
||||||
|
" > liczba słów nieoznaczonych w zbiorze testowym etykietą $e$, które model oznaczył tą etykietą\n",
|
||||||
|
"\n",
|
||||||
|
" - *fn (false negatives)*\n",
|
||||||
|
"\n",
|
||||||
|
" > liczba słów oznaczonych w zbiorze testowym etykietą $e$, którym model nie nadał etykiety $e$\n",
|
||||||
|
"\n",
|
||||||
|
" - *precision*\n",
|
||||||
|
"\n",
|
||||||
|
" > $$\\frac{tp}{tp + fp}$$\n",
|
||||||
|
"\n",
|
||||||
|
" - *recall*\n",
|
||||||
|
"\n",
|
||||||
|
" > $$\\frac{tp}{tp + fn}$$\n",
|
||||||
|
"\n",
|
||||||
|
" - $F_1$\n",
|
||||||
|
"\n",
|
||||||
|
" > $$\\frac{2 \\cdot precision \\cdot recall}{precision + recall}$$\n",
|
||||||
|
"\n",
|
||||||
|
" - *micro* $F_1$\n",
|
||||||
|
"\n",
|
||||||
|
" > $F_1$ w którym $tp$, $fp$ i $fn$ są liczone łącznie dla wszystkich etykiet, tj. $tp = \\sum_{e}{{tp}_e}$, $fn = \\sum_{e}{{fn}_e}$, $fp = \\sum_{e}{{fp}_e}$\n",
|
||||||
|
"\n",
|
||||||
|
" - *macro* $F_1$\n",
|
||||||
|
"\n",
|
||||||
|
" > średnia arytmetyczna z $F_1$ obliczonych dla poszczególnych etykiet z osobna.\n",
|
||||||
|
"\n",
|
||||||
|
"Wyuczony model możemy wczytać z pliku korzystając z metody `load`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "d12596c1",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"model = SequenceTagger.load('slot-model/final-model.pt')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a97dd603",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Wczytany model możemy wykorzystać do przewidywania slotów w wypowiedziach użytkownika, korzystając\n",
|
||||||
|
"z przedstawionej poniżej funkcji `predict`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "87c310cf",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def predict(model, sentence):\n",
|
||||||
|
" csentence = [{'form': word, 'slot': 'O'} for word in sentence]\n",
|
||||||
|
" fsentence = conllu2flair([csentence])[0]\n",
|
||||||
|
" model.predict(fsentence)\n",
|
||||||
|
"\n",
|
||||||
|
" for span in fsentence.get_spans('slot'):\n",
|
||||||
|
" tag = span.get_label('slot').value\n",
|
||||||
|
" csentence[span.tokens[0].idx - 1]['slot'] = f'B-{tag}'\n",
|
||||||
|
"\n",
|
||||||
|
" for token in span.tokens[1:]:\n",
|
||||||
|
" csentence[token.idx - 1]['slot'] = f'I-{tag}'\n",
|
||||||
|
"\n",
|
||||||
|
" return csentence\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "97043331",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"tabulate(predict(model, 'set alarm for 20 minutes'.split()), tablefmt='html')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "29856a8a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"tabulate(predict(model, 'change my 3 pm alarm to the next day'.split()), tablefmt='html')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "21b00302",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Literatura\n",
|
||||||
|
"----------\n",
|
||||||
|
" 1. Sebastian Schuster, Sonal Gupta, Rushin Shah, Mike Lewis, Cross-lingual Transfer Learning for Multilingual Task Oriented Dialog. NAACL-HLT (1) 2019, pp. 3795-3805\n",
|
||||||
|
" 2. John D. Lafferty, Andrew McCallum, and Fernando C. N. Pereira. 2001. Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data. In Proceedings of the Eighteenth International Conference on Machine Learning (ICML '01). Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 282–289, https://repository.upenn.edu/cgi/viewcontent.cgi?article=1162&context=cis_papers\n",
|
||||||
|
" 3. Sepp Hochreiter and Jürgen Schmidhuber. 1997. Long Short-Term Memory. Neural Comput. 9, 8 (November 15, 1997), 1735–1780, https://doi.org/10.1162/neco.1997.9.8.1735\n",
|
||||||
|
" 4. Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin, Attention is All you Need, NIPS 2017, pp. 5998-6008, https://arxiv.org/abs/1706.03762\n",
|
||||||
|
" 5. Alan Akbik, Duncan Blythe, Roland Vollgraf, Contextual String Embeddings for Sequence Labeling, Proceedings of the 27th International Conference on Computational Linguistics, pp. 1638–1649, https://www.aclweb.org/anthology/C18-1139.pdf\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"jupytext": {
|
||||||
|
"cell_metadata_filter": "-all",
|
||||||
|
"main_language": "python",
|
||||||
|
"notebook_metadata_filter": "-all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
201
notebooks/12-ujednoznacznianie.ipynb
Normal file
201
notebooks/12-ujednoznacznianie.ipynb
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2c89fac1",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Ujednoznacznianie wypowiedzi użytkownika\n",
|
||||||
|
"========================================\n",
|
||||||
|
"\n",
|
||||||
|
"Problem\n",
|
||||||
|
"-------\n",
|
||||||
|
"W systemie dialogowym ukierunkowanym na wypełnianie wielu zadań jednocześnie polecenia użytkownika mogą być niejednoznacznie. Przykładowo wypowiedź\n",
|
||||||
|
"\n",
|
||||||
|
"> please book it for me\n",
|
||||||
|
"\n",
|
||||||
|
"może dotyczyć zarówno rezerwacji pokoju w hotelu jak i biletu na pociąg.\n",
|
||||||
|
"\n",
|
||||||
|
"System, w którym moduł NLU jest zbudowany z wykorzystaniem gramatyk semantycznych może zwrócić\n",
|
||||||
|
"więcej niż jedną ramę reprezentującą znaczenie wypowiedzi. Która rama powinna zostać uznana za\n",
|
||||||
|
"prawidłową?\n",
|
||||||
|
"\n",
|
||||||
|
"System, w którym moduł NLU jest zbudowany przy użyciu modelu sekwencyjnego może zwrócić jedną,\n",
|
||||||
|
"arbitralnie wybraną ramę. Co wtedy?\n",
|
||||||
|
"\n",
|
||||||
|
"Ujednoznacznianie z wykorzystaniem reguł\n",
|
||||||
|
"----------------------------------------\n",
|
||||||
|
"\n",
|
||||||
|
"Do ujednoznaczniania wypowiedzi użytkownika można wykorzystać monitor stanu dialogu oraz taktykę\n",
|
||||||
|
"prowadzenia dialogu. Możemy m.in.:\n",
|
||||||
|
"\n",
|
||||||
|
" 1. Dopasować niejednoznaczną wypowiedź do wszystkich dziedzin licząc na to, że w toku dialogu\n",
|
||||||
|
" niejednoznaczność zostanie rozstrzygnięta (to\n",
|
||||||
|
" rozwiązanie zostało przyjęte w monitorze `SimpleRuleDST` przedstawionym na zajęciach ósmych).\n",
|
||||||
|
"\n",
|
||||||
|
" 2. Dopasować niejednoznaczną wypowiedź wyłącznie do tej dziedziny, dla której stan dialogu zawiera\n",
|
||||||
|
" wypełnione sloty.\n",
|
||||||
|
"\n",
|
||||||
|
" 3. Sprawdzić czy wypowiedź użytkownika stanowi odpowiedź na pytanie uprzednio zadane przez system\n",
|
||||||
|
" (pole `request_state` w monitorze `SimpleRuleDST`).\n",
|
||||||
|
"\n",
|
||||||
|
" 4. Wykorzystać taktykę prowadzenia dialogu do zadania pytania, które rozstrzygnie\n",
|
||||||
|
" niejednoznaczność."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "4c43c939",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Ujednoznacznianie z wykorzystaniem uczenia maszynowego\n",
|
||||||
|
"------------------------------------------------------\n",
|
||||||
|
"\n",
|
||||||
|
"W procesie uczenia modelu NLU można wykorzystać historię dialogu jako kontekst (zbiór dodatkowych\n",
|
||||||
|
"cech) warunkujących wynik uczenia.\n",
|
||||||
|
"Takie podejście zostało zastosowane w modelu [jointBERT](https://github.com/thu-coai/ConvLab-2/blob/master/convlab2/nlu/jointBERT/jointBERT.py), w którym kontekst składa się z trzech (sklejonych ze sobą) tur dialogu poprzedzających bieżącą wypowiedź.\n",
|
||||||
|
"\n",
|
||||||
|
"Porównajmy skuteczność modelu bezkontekstowego ze skutecznością modelu uwzględniającego kontekst.\n",
|
||||||
|
"Do oceny jakości wykorzystamy zbiór danych [MultiWOZ](https://github.com/budzianowski/multiwoz) (Budzianowski i in., 2018)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "dc543a04",
|
||||||
|
"metadata": {
|
||||||
|
"lines_to_next_cell": 0
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from convlab2.nlu.jointBERT.multiwoz import BERTNLU\n",
|
||||||
|
"from convlab2.util.dataloader.module_dataloader import MultiTurnNLUDataloader\n",
|
||||||
|
"from convlab2.util.dataloader.dataset_dataloader import MultiWOZDataloader\n",
|
||||||
|
"\n",
|
||||||
|
"dataloader = MultiTurnNLUDataloader(dataset_dataloader=MultiWOZDataloader())\n",
|
||||||
|
"data = dataloader.load_data(data_key='test', role='sys')['test']"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "18cee3d4",
|
||||||
|
"metadata": {
|
||||||
|
"lines_to_next_cell": 0
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"data['utterance'][:3]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "eafcffe8",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"data['dialog_act'][:3]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "10607b8d",
|
||||||
|
"metadata": {
|
||||||
|
"lines_to_next_cell": 0
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Precision, recall oraz F1 obu modeli zmierzymy korzystając z funkcji `evaluate`."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "0c9b943c",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from convlab2.nlu.evaluate import calculateF1\n",
|
||||||
|
"from tqdm.notebook import tqdm\n",
|
||||||
|
"\n",
|
||||||
|
"def evaluate(model, data):\n",
|
||||||
|
" results = []\n",
|
||||||
|
"\n",
|
||||||
|
" for utt, ctx, acts in tqdm(zip(data['utterance'], data['context'], data['dialog_act']), total=len(data['utterance'])):\n",
|
||||||
|
" predicted = model.predict(utterance=utt, context=ctx)\n",
|
||||||
|
" results.append({'predict': predicted, 'golden': acts})\n",
|
||||||
|
"\n",
|
||||||
|
" precision, recall, fscore = calculateF1(results)\n",
|
||||||
|
" print(f'Precision: {precision:.4f} Recall: {recall:.4f} F1: {fscore:.4f}')\n",
|
||||||
|
" return precision, recall, fscore"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "db8227a6",
|
||||||
|
"metadata": {
|
||||||
|
"lines_to_next_cell": 0
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Zmierzmy skuteczność modelu bezkontekstowego."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "7c29b75f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"noctx_model = BERTNLU(mode='all',\n",
|
||||||
|
" config_file='multiwoz_all.json',\n",
|
||||||
|
" model_file='https://convlab.blob.core.windows.net/convlab-2/bert_multiwoz_all.zip')\n",
|
||||||
|
"\n",
|
||||||
|
"noctx_results = evaluate(noctx_model, data)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "f82fb6fc",
|
||||||
|
"metadata": {
|
||||||
|
"lines_to_next_cell": 0
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Zmierzmy skutecznosć modelu uwzględniającego kontekst."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "d3d7773f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"ctx_model = BERTNLU(mode='all',\n",
|
||||||
|
" config_file='multiwoz_all_context.json',\n",
|
||||||
|
" model_file='https://convlab.blob.core.windows.net/convlab-2/bert_multiwoz_all_context.zip')\n",
|
||||||
|
"\n",
|
||||||
|
"ctx_results = evaluate(ctx_model, data)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "621c5295",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Literatura\n",
|
||||||
|
"----------\n",
|
||||||
|
" 1. Pawel Budzianowski, Tsung-Hsien Wen, Bo-Hsiang Tseng, Iñigo Casanueva, Stefan Ultes, Osman Ramadan, Milica Gasic, MultiWOZ - A Large-Scale Multi-Domain Wizard-of-Oz Dataset for Task-Oriented Dialogue Modelling. EMNLP 2018, pp. 5016-5026"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"jupytext": {
|
||||||
|
"cell_metadata_filter": "-all",
|
||||||
|
"main_language": "python",
|
||||||
|
"notebook_metadata_filter": "-all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
75
utils/script.py
Normal file
75
utils/script.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
def remove_empty_lines(text):
|
||||||
|
lines = text.split('\n')
|
||||||
|
|
||||||
|
non_empty_lines = []
|
||||||
|
for line in lines:
|
||||||
|
if line.strip():
|
||||||
|
non_empty_lines.append(line)
|
||||||
|
|
||||||
|
return '\n'.join(non_empty_lines)
|
||||||
|
|
||||||
|
|
||||||
|
def join_lines(text):
|
||||||
|
lines = text.split("\n")
|
||||||
|
joined_lines = [lines[0]]
|
||||||
|
|
||||||
|
for line in lines[1:]:
|
||||||
|
if line.startswith("["):
|
||||||
|
joined_lines.append(line)
|
||||||
|
else:
|
||||||
|
joined_lines[-1] += " " + line
|
||||||
|
|
||||||
|
return "\n".join(joined_lines)
|
||||||
|
|
||||||
|
|
||||||
|
def process_text(text, nazwisko_user, nazwisko_system):
|
||||||
|
lines = text.split('\n')
|
||||||
|
result = []
|
||||||
|
for line in lines:
|
||||||
|
if nazwisko_system in line:
|
||||||
|
result.append("system " + line.split(nazwisko_system, 1)[1].strip())
|
||||||
|
elif nazwisko_user in line:
|
||||||
|
result.append("user " + line.split(nazwisko_user, 1)[1].strip())
|
||||||
|
else:
|
||||||
|
result.append(line)
|
||||||
|
return '\n'.join(result)
|
||||||
|
|
||||||
|
|
||||||
|
def read_tsv(file_path):
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as tsv_file:
|
||||||
|
content = tsv_file.read()
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def write_tsv(file_path, content):
|
||||||
|
with open(file_path, 'w', encoding='utf-8') as tsv_file:
|
||||||
|
tsv_file.write(content)
|
||||||
|
|
||||||
|
|
||||||
|
def replace_first_space_with_tab(text):
|
||||||
|
lines = text.split("\n")
|
||||||
|
new_lines = []
|
||||||
|
for line in lines:
|
||||||
|
first_space_index = line.find(" ")
|
||||||
|
if first_space_index != -1:
|
||||||
|
new_line = line[:first_space_index] + "\t" + line[first_space_index + 1:]
|
||||||
|
new_lines.append(new_line)
|
||||||
|
else:
|
||||||
|
new_lines.append(line)
|
||||||
|
return "\n".join(new_lines)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# wypelnic przed uruchomieniem
|
||||||
|
nazwisko_user = ""
|
||||||
|
nazwisko_system = ""
|
||||||
|
numer_user = ""
|
||||||
|
numer_system = ""
|
||||||
|
file_path = f"J:\PycharmProjects\systemy_dialogowe\data\dialog-{numer_system}-{numer_user}-01.tsv"
|
||||||
|
|
||||||
|
text = read_tsv(file_path)
|
||||||
|
text = remove_empty_lines(text)
|
||||||
|
text = join_lines(text)
|
||||||
|
text = process_text(text, nazwisko_user, nazwisko_system)
|
||||||
|
text = replace_first_space_with_tab(text)
|
||||||
|
write_tsv(file_path, text)
|
Loading…
Reference in New Issue
Block a user