Dane oryginału

Original edition copyright © 2019 by Manning Publications Co. All rights reserved. Title of English-language original: Natural Language Processing in Action: Understanding, Analyzing, and Generating Text with Python by Hobson Lane, Cole Howard, Hannes Hapke, ISBN 978-1-61729-463-1. Polish-language edition © 2021 by Polish Scientific Publishers PWN Wydawnictwo Naukowe PWN Spółka Akcyjna. All Rights reserved.

Posłowie do wydania polskiego

dr Łukasz Kobyliński, Ryszard Tuora

Przekład Małgorzata Dąbkowska-Kowalik, Wojciech Fenrich, Witold Sikorski

na zlecenie WITKOM Witold Sikorski

Projekt okładki polskiego wydania INT-MEDIA Dawid Mazur na podstawie oryginału

Wydawca Wioleta Szczygielska-Dybciak

Redaktor prowadzący Jolanta Kowalczuk

Redaktor Izabela Mika

Koordynator produkcji Anna Bączkowska

Skład wersji elektronicznej na zlecenie Wydawnictwo Naukowe PWN Michał Latusek

Konsultacja merytoryczna

dr Łukasz Kobyliński, Ryszard Tuora

Zastrzeżonych nazw firm i produktów użyto w książce wyłącznie w celu identyfikacji.

Copyright © for the Polish edition by Wydawnictwo Naukowe PWN SA

Warszawa 2021

ISBN 978-83-01-21721-1

eBook został przygotowany na podstawie wydania papierowego z 2021r. (Wydanie I)

Warszawa 2021

Wydawnictwo Naukowe PWN SA

02-460 Warszawa, ul. Gottlieba Daimlera 2

tel. 22 69 54 321, faks 22 69 54 288

infolinia 801 33 33 88

e-mail: pwn@pwn.com.pl, reklama@pwn.pl

www.pwn.pl

Bezpłatny fragment

wprowadzenie

wstęp

podziękowania

o książce

o autorach

o ilustracji na okładce

Część 1. Mówiące maszyny

1. Pakiety myśli (przegląd NLP)

1.1. Język naturalny a język programowania

1.2. Magia

1.2.1. Maszyny prowadzące konwersację

1.2.2. Matematyka

1.3. Zastosowania praktyczne

1.4. Język widziany „oczyma” komputera

1.4.1. Język zamków

1.4.2. Wyrażenia regularne

1.4.3. Prosty chatbot

1.4.4. Inny sposób

1.5. Krótkie spojrzenie na hiperprzestrzeń

1.6. Kolejność słów i gramatyka

1.7. Potok języka naturalnego chatbota

1.8. Szczegóły przetwarzania

1.9. IQ języka naturalnego

2. Zbuduj swój słownik (tokenizacja słów)

2.1. Wyzwania (wprowadzenie do stemmingu)

2.2. Tworzenie swojego słownika za pomocą tokenizatora

2.2.1. Iloczyn skalarny

2.2.2. Pomiar nakładania się wektorów BoW

2.2.3. Poprawianie tokenów

Jak działają wyrażenia regularne

Poprawione wyrażenia regularne do podziału słów

Formy skrócone

2.2.4. Rozszerzenie słownika za pomocą n-gramów

N-gramy

Stop listy

2.2.5. Normalizacja słownika

Ujednolicanie wielkości liter

Stemming

Lematyzacja

Przypadki użycia

2.3. Wydźwięk

2.3.1. VADER – analizator wydźwięku oparty na regułach

2.3.2. Naiwny klasyfikator bayesowski

3. Matematyka na słowach (wektory TD-IDF)

3.1. Wektor BoW

3.2. Wektoryzacja

3.2.1. Przestrzenie wektorowe

3.3. Prawo Zipfa

3.4. Modelowanie tematyczne

3.4.1. Powrót Zipfa

3.4.2. Ranking trafności

3.4.3. Narzędzia

3.4.4. Inne możliwości

3.4.5. Okapi BM25

3.4.6. Co dalej

4. Odnajdowanie znaczenia w licznikach słów (analiza semantyczna)

4.1. Od liczników słów do wyników dla tematów

4.1.1. Wektory TF-IDF i lematyzacja

4.1.2. Wektory tematyczne

4.1.3. Eksperyment myślowy

4.1.4. Algorytm do oceny tematów

„Kuzyni” LSA

4.1.5. Klasyfikator LDA

Inny „kuzyn”

4.2. Analiza utajonych własności semantycznych (LSA)

4.2.1. Wasz eksperyment myślowy staje się prawdziwy

Gra w Mad libs

4.3. Rozkład według wartości osobliwej

4.3.1. U – lewostronne wektory osobliwe

4.3.2. S – wartości osobliwe

4.3.3. V T – prawostronne wektory osobliwe

4.3.4. Orientacja macierzy SVD

4.3.5. Obcinanie tematów

4.4. Analiza głównych składowych

4.4.1. PCA dla wektorów 3D

4.4.2. Przestańmy szaleć i wróćmy do NLP

4.4.3. Stosowanie PCA do semantycznej analizy komunikatów SMS

4.4.4. Używanie obciętego SVD do analizy semantycznej komunikatu SMS

4.4.5. Jak dobrze działa LSA przy klasyfikacji spamu

Rozszerzenia LSA i SVD

4.5. Ukryta alokacja Dirichleta (LDiA)

4.5.1. Idea LDiA

4.5.2. Model tematyczny LDiA dla komunikatów SMS

4.5.3. LDiA + LDA = klasyfikator spamu

4.5.4. Uczciwsze porównanie: 32 tematy LDiA

4.6. Odległość i podobieństwo

4.7. Sterowanie za pomocą informacji zwrotnej

4.7.1. Liniowa analiza dyskryminacyjna

4.8. Moc wektorów tematycznych

4.8.1. Wyszukiwanie semantyczne

4.8.2. Ulepszenia

Część 2. Głębsze uczenie się (sieci neuronowe)

5. Sieci neuronowe krok po kroku (perceptrony i propagacja wsteczna)

5.1. Sieci neuronowe – lista składników

5.1.1. Perceptron

5.1.2. Perceptron numeryczny

5.1.3. Zboczenie z drogi spowodowane odchyleniem

Neuron w Pythonie

Klasa tkwi w sesji

Uczenie się logiki to czysta frajda

Następny krok

Koniec drugiej zimy sztucznej inteligencji

Propagacja wsteczna

Zróżniczkujmy wszystko

5.1.4. Poszusujmy – powierzchnia błędu

5.1.5. Z wyciągu prosto na stok

5.1.6. Udoskonalmy to nieco

5.1.7. Keras: sieci neuronowe w Pythonie

5.1.8. Wprzód i w głąb

5.1.9. Normalizacja: stylowe wejście

6. Wnioskowanie przy użyciu wektorów słów (Word2vec)

6.1. Zapytania semantyczne i analogie

6.1.1. Pytania o analogię

6.2. Wektory słów

6.2.1. Wnioskowanie zorientowane wektorowo

Jeszcze więcej powodów, by korzystać z wektorów słów

6.2.2. Jak obliczać reprezentacje Word2vec

Podejście skip-gram

Czym jest softmax?

W jaki sposób sieć uczy się reprezentacji wektorowej?

Odnajdywanie wektorów słów za pomocą algebry liniowej

Podejście z ciągłym BoW

Skip-gram a CBoW. Kiedy korzystać z którego podejścia?

Triki obliczeniowe Word2vec

Częste bigramy

Podpróbkowanie często występujących tokenów

Próbkowanie negatywne

6.2.3. Jak korzystać z modułu gensim.word2vec

6.2.4. Jak wygenerować własne reprezentacje wektorów słów

Kroki przetwarzania wstępnego

Szkolenie dziedzinowego modelu Word2vec

6.2.5. Word2vec a GloVe (Global Vectors)

6.2.6. fastText

Jak korzystać z gotowych modeli fastText

6.2.7. Word2vec a LSA

6.2.8. Wizualizacja związków między słowami

6.2.9. Nienaturalne słowa

6.2.10. Doc2vec i podobieństwo dokumentów

Jak wyuczyć wektory dokumentów

7. Kolejność słów i konwolucyjne sieci neuronowe (CNN)

7.1. Uczenie się znaczenia

7.2. Zestaw narzędzi

7.3. Konwolucyjne sieci neuronowe

7.3.1. Elementy składowe

7.3.2. Długość kroku

7.3.3. Budowa filtra

7.3.4. Uzupełnianie

Potok konwolucyjny

7.3.5. Uczenie

7.4. Zaiste, wąskie okna

7.4.1. Implementacja w Kerasie: przygotowanie danych

7.4.2. Architektura konwolucyjnej sieci neuronowej

7.4.3. Warstwa łącząca (pooling)

7.4.4. Dropout

7.4.5. Wisienka na torcie

Optymalizacja

Dopasowanie (fit)

7.4.6. Czas zabrać się za naukę (trening)

7.4.7. Użycie modelu w potoku

7.4.8. Gdzie pójdziecie dalej?

8. Zapętlone (rekurencyjne) sieci neuronowe (RNN)

8.1. Zapamiętywanie za pomocą sieci rekurencyjnych

8.1.1. Propagacja wsteczna przez czas

Tl;Dr – Krótka rekapitulacja

8.1.2. Kiedy i co aktualizować?

Czy jednak obchodzi was to, co wyszło z wcześniejszych kroków?

8.1.3. Rekapitulacja

8.1.4. Zawsze jest jakiś haczyk

8.1.5. Rekurencyjne sieci neuronowe z Kerasem

8.2. Składanie w całość

8.3. Nauczmy się czegoś o przeszłości

8.4. Hiperparametry

8.5. Przewidywanie

8.5.1. Stanowość

8.5.2. Ulica dwukierunkowa

8.5.3. Co to takiego?

9. Lepsza pamięć dzięki sieciom LSTM

9.1. LSTM

9.1.1. Propagacja wsteczna przez czas

W praktyce

9.1.2. Próba ognia

9.1.3. Brudne dane

9.1.4. Powrót do brudnych danych

9.1.5. Słowa są trudne. Litery są prostsze

9.1.6. Kolej na rozmowę

9.1.7. Zwrot ku klarownej mowie

9.1.8. Jak mówić i co mówić

9.1.9. Inne rodzaje pamięci

9.1.10. Idąc głębiej

10. Modele ciąg-ciąg i uwaga (attention)

10.1. Architektura koder-dekoder

10.1.1. Dekodowanie myśli

10.1.2. Wygląda znajomo?

10.1.3. Konwersacja ciąg-ciąg

10.1.4. Powtórzenie LSTM

10.2. Składanie potoku ciąg-ciąg

10.2.1. Przygotowanie naszego zbioru danych do szkolenia ciąg-ciąg

10.2.2. Model ciąg-ciąg w Kerasie

10.2.3. Koder ciągów

10.2.4. Dekoder myśli

10.2.5. Składanie sieci ciąg-ciąg

10.3. Szkolenie sieci ciąg-ciąg

10.3.1. Generowanie ciągów wyjściowych

10.4. Budowanie chatbota przy użyciu sieci ciąg-ciąg

10.4.1. Przygotowanie korpusu do szkolenia

10.4.2. Budowanie słownika znaków

10.4.3. Generowanie zbiorów treningowych zakodowanych metodą 1 z n

10.4.4. Uczenie chatbota ciąg-ciąg

10.4.5. Składanie modelu do generowania ciągów

10.4.6. Przewidywanie ciągu

10.4.7. Generowanie odpowiedzi

10.4.8. Rozmowa z waszym chatbotem

10.5. Ulepszenia

10.5.1. Redukcja złożoności treningu za pomocą sortowania danych (bucketing)

10.5.2. Uwaga (attention)

10.6. W świecie rzeczywistym

Część 3. Przejście do rzeczywistości (prawdziwe problemy NLP)

11. Ekstrakcja informacji (rozpoznawanie jednostek nazewniczych i odpowiadanie na pytania)

11.1. Jednostki nazewnicze i relacje

11.1.1. Baza wiedzy

11.1.2. Ekstrakcja informacji

11.2. Regularne wzorce

11.2.1. Wyrażenia regularne

11.2.2. Ekstrakcja informacji jako ekstrakcja cech z wykorzystaniem uczenia się maszyn

11.3. Informacje warte wyodrębnienia

11.3.1. Ekstrakcja lokalizacji GPS

11.3.2. Ekstrakcja dat

11.4. Ekstrakcja relacji

11.4.1. Znakowanie częściami mowy

11.4.2. Normalizacja jednostek nazewniczych

11.4.3. Normalizacja i ekstrakcja relacji

11.4.4. Wzorce słów

11.4.5. Segmentacja

Segmentacja na zdania

11.4.6. Dlaczego split('.!?') nie będzie działać?

11.4.7. Segmentacja na zdania za pomocą wyrażeń regularnych

11.5. W prawdziwym świecie

12. Pogaduszki (silniki dialogowe)

12.1. Umiejętności językowe

12.1.1. Nowoczesne podejścia

Systemy dialogowe odpowiadające na pytania

Wirtualni asystenci

Chatboty konwersacyjne

Chatboty marketingowe

Zarządzanie społecznością

Obsługa klienta

Terapia

12.1.2. Podejście hybrydowe

12.2. Podejście polegające na dopasowaniu do wzorców

12.2.1. Chatbot oparty na dopasowaniu do wzorca i AIML

AIML 1.0

Interpreter AIML w Pythonie

12.2.2. Sieciowe spojrzenie na dopasowanie do wzorców

12.3. Oparcie na wiedzy

12.4. Wyszukiwanie

12.4.1. Problem kontekstu

12.4.2. Przykładowy chatbot oparty na wyszukiwaniu danych

12.4.3. Chatbot oparty na wyszukiwaniu

12.5. Modele generatywne

12.5.1. Czat na temat NLPIA

12.5.2. Zalety i wady każdego podejścia

12.6. Napęd na cztery koła

12.6.1. Will osiąga sukces

Instalowanie Willa

Hello WILL

12.7. Proces projektowania

12.8. Sztuczki

12.8.1. Zadawanie pytań z przewidywalnymi odpowiedziami

12.8.2. Bycie zabawnym

12.8.3. Gdy wszystko inne zawiedzie, trzeba wyszukać

12.8.4. Bycie popularnym

12.8.5. Być łącznikiem

12.8.6. Stawanie się emocjonalnym

12.9. W świecie rzeczywistym

13. Skalowanie (optymalizacja, zrównoleglanie i przetwarzanie wsadowe)

13.1. Zbyt wiele dobrego (danych)

13.2. Optymalizowanie algorytmów NLP

13.2.1. Indeksowanie

13.2.2. Zaawansowane indeksowanie

13.2.3. Zaawansowane indeksowanie za pomocą Annoy

13.2.4. Po co w ogóle stosować indeksy przybliżone?

13.2.5. Obejście indeksowania: dyskretyzacja

13.3. Algorytmy ze stałą pamięcią RAM

13.3.1. Gensim

13.3.2. Obliczenia graficzne

13.4. Zrównoleglanie waszych obliczeń NLP

13.4.1. Trenowanie modeli NLP na procesorach graficznych (GPU)

13.4.2. Wynajem a kupno

13.4.3. Opcje wynajmu GPU

13.4.4. Jednostki przetwarzania tensorowego

13.5. Zmniejszanie zużycia pamięci podczas trenowania modeli

13.6. Uzyskiwanie wglądu w model za pomocą TensorBoard

13.6.1. Jak wizualizować zanurzenia słów

dodatek A. Nasze narzędzia NLP

dodatek B. Swawolny Python i wyrażenia regularne

dodatek C. Wektory i macierze (podstawy algebry liniowej)

dodatek D. Narzędzia i techniki uczenia się maszyn

dodatek E. Ustawianie własnego AWS GPU

dodatek F. Mieszanie wrażliwe na lokalizację (LSH)

źródła

słownik

posłowie do wydania polskiego

przypisy

wprowadzenie

Po raz pierwszy spotkałem Hannesa w roku 2006, gdy zaczęliśmy studia podyplomowe na tym samym wydziale. Stał się szybko znany ze swojej pracy związanej z wykorzystaniem połączenia uczenia się maszyn z elektrotechniką, a w szczególności ze względu na duże zaangażowanie w pozytywne przyjęcie tego na świecie. Podczas całej jego kariery zaangażowanie to kierowało każdą firmą, w której pracował, i każdym projektem, z którym miał styczność, a to dzięki podążaniu za wewnętrznym kompasem powiązanym z firmą Hobson and Cole, która dzieliła z nim pasję do projektów o silnym, pozytywnym wpływie.

Gdy miałem napisać to wprowadzenie, właśnie ta pasja do zastosowania uczenia się maszyn była tym, co mnie ostatecznie przekonało. Moja osobista podróż po badaniach nad uczeniem się maszyn była także kierowana przez silne pragnienie, aby mieć pozytywny wpływ na świat. Moja ścieżka doprowadziła mnie od tworzenia algorytmów do modelowania danych ekologicznych z różną rozdzielczością, do modelowania rozmieszczenia gatunków w celu optymalizacji ich ochrony i badań. Od tego czasu byłem zdecydowany kontynuować pracę w obszarach, w których mogę poprawić życie i oczekiwania.

Wielka władza niesie ze sobą wielką odpowiedzialność

Wolter?

Niezależnie od tego, czy przypiszemy te słowa Wolterowi czy wujkowi Benowi, są one dziś bardzo prawdziwe, choć w dzisiejszych czasach ujmujemy to nieco inaczej, mówiąc „Wielki dostęp do danych niesie ze sobą wielką odpowiedzialność”. Ufamy firmom posiadającym nasze dane w nadziei, że zostaną one wykorzystane do poprawy naszego życia. Pozwalamy na skanowanie naszych e-maili, aby pomóc nam w tworzeniu listów poprawnych gramatycznie, fragmenty naszego codziennego życia w mediach społecznościowych są analizowane i używane do wstawiania reklam do naszych informacji. Nasze telefony i domy odpowiadają na nasze słowa, czasem nawet zanim cokolwiek do nich powiemy. Nawet nasze preferencje dotyczące wiadomości są monitowane, aby nasze zainteresowania, opinie i wiara nie były pogwałcone. Co znajduje się w sercu tych technologii?

Odpowiedzią jest przetwarzanie języka naturalnego. W tej książce poznacie zarówno teorię, jak i umiejętności praktyczne potrzebne, aby wyjść poza proste zrozumienie wewnętrznego działania tych systemów i zacząć tworzenie własnych algorytmów lub modeli. Podstawowe koncepcje informatyki są bezboleśnie przekładane na solidne podstawy podejścia i praktyki, których należy przestrzegać. Zabierając czytelników w prostą i dobrze opisaną podróż przez podstawowe metodologie przetwarzania języka naturalnego, autorzy zaczynają od wypróbowanych metod, jak TF-IDF, zanim przejdą do płytkiego, ale głębokiego (tak, to mój żart) zanurzenia się w sieci neuronowe dla NLP.

Język jest podstawą, na której zbudowaliśmy nasze wspólne poczucie człowieczeństwa. Przekazujemy sobie nie tylko fakty, ale i emocje. Poprzez język nabywamy wiedzę spoza obszaru naszych rzeczywistych doświadczeń i budujemy zrozumienie poprzez dzielenie się tymi doświadczeniami. Mamy możliwość rozwijania solidnego zrozumienia, a nie tylko mechanizmów NLP, a także możliwość tworzenia wpływowych systemów, które pewnego dnia mogą zrozumieć ludzkość poprzez nasz język. Technika NLP ma wielki potencjał do niewłaściwego użycia, lecz ma również potencjał dla dobra. Przez dzielenie się swoją wiedzą za pośrednictwem tej książki autorzy mają nadzieję na wskazanie nam jaśniejszej przyszłości.

Dr. Arwen Griffioen

Starszy analityk danych

RESEARCH ZENDESK

wstęp

Około roku 2013 przetwarzanie języka naturalnego i chatboty zaczęły dominować w naszym życiu. Na początku Google Search było rodzajem indeksu, narzędziem, które wymagało niewielkich umiejętności, aby znaleźć to, czego szukacie. Ale wkrótce stało się mądrzejsze i zaczęło akceptować coraz więcej wyszukiwań w języku naturalnym. Uzupełnianie tekstów w smartfonach stało się wyrafinowane. Środkowa propozycja była często dokładnie tym, czego szukaliście[1].

Pod koniec roku 2014 współpracowałem z Thunderem Shiviahem w projekcie Hack Oregon, aby uzyskać dane badań języka naturalnego na temat finansowania kampanii. Próbowaliśmy znaleźć powiązania między darczyńcami polityków. Wydawało się, że politycy ukrywali tożsamość swoich darczyńców za pomocą zaciemniającego języka w swoich zeznaniach na temat finansowania kampanii. Ciekawe nie było to, że mogliśmy zastosować proste techniki przetwarzania języka naturalnego do wykrycia tych powiązań. Tym, co mnie najbardziej zaskoczyło, był fakt, że Thunder często odpowiadał na moje chaotyczne emaile konkretnie i szybko, kilka sekund po naciśnięciu przeze mnie klawisza wyślij. Używał narzędzia Smart Reply, „asystenta” w skrzynce odbiorczej Gmaila, który tworzy odpowiedzi szybciej niż możemy przeczytać otrzymany email.

Pogrzebałem w tym, aby poznać sztuczki stosowane w tej magii. Im więcej się dowiadywałem, tym większe wrażenie robiły na mnie wykonywalne i zrozumiałe osiągnięcia przetwarzania języka naturalnego. I niemal każdy projekt w zakresie uczenia się maszyn, który podejmowałem, obejmował przetwarzanie języka naturalnego.

Zapewne wynikało to z tego, że lubię słowa i jestem zafascynowany ich rolą w ludzkiej inteligencji. Potrafiłem spędzać całe godziny, debatując z Johnem Kowalskim, moim szefem od teorii informacji w Sharp Labs, nad tym, czy słowa w ogóle mają jakieś znaczenie. Gdy nabrałem pewności siebie i dowiadywałem się coraz więcej od moich mentorów i mentorek, wydało mi się, że potrafię sam zbudować coś nowego i magicznego.

Jedną ze sztuczek, której się nauczyłem, było iterowanie zbioru dokumentów i zliczanie, jak często pojawiały się słowa „Wojna” i „Głód”, a po nich słowa jak „Gry” lub „III”. Jeśli dokonamy tego na dużym zestawie tekstów, możemy dość dobrze odgadnąć poprawne słowo w ciągu słów, frazie lub w zdaniu. Klasyczne podejście do przetwarzania języka jest dla mnie dość intuicyjne.

Profesorowie i szefowie nazywają to łańcuchami Markowa, ale dla mnie jest to po prostu tabela prawdopodobieństw. To tylko lista wystąpień każdego ze słów na podstawie słowa poprzedniego. Profesorowie nazywają to rozkładem warunkowym, prawdopodobieństwem słów uwarunkowanym słowem poprzednim. Mechanizm korekty pisowni zbudowany przez Petera Norviga dla Google pokazał, jak dobrze skaluje się to podejście i jak niewiele kodu w Pythonie wymaga[2]. Potrzebujemy tylko dużo tekstu w języku naturalnym. Byłem bardzo podekscytowany możliwościami, jakie to daje na ogromnych darmowych zbiorach tekstów jak Wikipedia czy Projekt Gutenberga[3].

Potem usłyszałem o analizie utajonych własności semantycznych (LSA, latent semantic analysis). Wydało mi się, że jest to tylko szczególny sposób opisu niektórych działań z zakresu algebry liniowej, czego uczyłem się w szkole. Jeśli będziemy śledzić wszystkie słowa, które występują razem, możemy wykorzystać algebrę liniową do pogrupowania tych słów w „tematy”. LSA może skompresować znaczenie całego zdania lub nawet długiego dokumentu do postaci jednego wektora. Gdy używałem wyszukiwarki, wydawało mi się, że LSA ma niezwykłą zdolność do zwracania dokładnie tych dokumentów, których szukałem. Dobre wyszukiwarki robią tak nawet wtedy, gdy nie potrafię określić słów, które mogą być w tych dokumentach!

Potem gensim wypuścił implementację wektoryzacji słów Word2vec w Pythonie, sprawiając, że semantyczna matematyka stała się możliwa na pojedynczych słowach. Okazało się, że jeśli podzieliło się dokument na mniejsze kawałki, to wyszukana matematyka tej sieci neuronowej była analogiczna do starej techniki LSA. To otworzyło mi oczy. Dało mi nadzieję, że ja potrafię dokonać czegoś na tym polu. Od lat myślałem o hierarchicznych wektorach – jak książki składające się z rozdziałów podzielonych na akapity złożone ze zdań, fraz i słów zapisanych w znakach. Tomas Mikolov, twórca Word2vec, uważał, że dominującą semantykę tekstu można znaleźć w powiązaniu pomiędzy dwiema warstwami hierarchii, między słowami a frazami złożonymi z 10 słów. Przez dziesięciolecia badacze NLP uważali, że słowa mają komponenty takie jak grzeczność i zabarwienie emocjonalne. I te oceny wydźwięku, komponenty, można było dodawać lub odejmować, aby połączyć znaczenia wielu słów. Ale Mikolov odkrył sposób tworzenia tych wektorów bez ich ręcznego projektowania, a nawet bez definiowania, jakie powinny być to komponenty[4]. To sprawiło, że NLP stało się przyjemnością!

Mniej więcej w tym samym czasie Thunder przedstawił mnie swojej mentorce, Cole. A potem inni przedstawili mnie Hannes. Nasza trójka zaczęła prowadzić na polu NLP politykę „dziel i rządź”. Byłem zaintrygowany możliwością budowania chatbotów, które brzmiałyby inteligentnie. Cole i Hannes były zainspirowane pełnymi mocy czarnymi skrzynkami sieci neuronowych. Wkrótce zaczęły otwierać czarne skrzynki, zaglądając do wnętrza i opisując mi, co tam znalazły. Cole wykorzystała to do tworzenia chatbotów wspomagających mnie w mojej podróży przez NLP.

Za każdym razem, gdy zagłębialiśmy się w niezwykłe nowe podejścia do NLP, wydawało się, że jest to coś, co potrafię zrozumieć i wykorzystać. I wyglądało na to, że w Pythonie jest implementacja niemal każdej pojawiającej się nowej techniki. Dane i wytrenowane wstępnie modele, które były nam potrzebne, znajdowały się w tych pakietach Pythona. „Jest do tego pakiet” stało się refrenem powtarzanym w niedzielne popołudnia we Floyd’s Coffee Shop, gdzie spotykałem się z Cole i Hannes na burzy mózgów z przyjaciółmi lub grając w Go i w grę „środkowego przycisku”. Robiliśmy też szybki postęp dzięki prowadzeniu rozmów i wykładów na zajęciach i w zespołach Hack Oregon.

W latach 2015 i 2016 sprawy przyjęły poważniejszy obrót. Gdy Tay[5] firmy Microsoft i inne boty zaczęły wpadać w amok, stało się jasne, że boty języka naturalnego wpływają na społeczeństwo. W roku 2016 byłem zajęty testowaniem bota, który zasysał tweety, próbując przewidzieć wyniki wyborów. W tym samym czasie zaczęły pojawiać się wiadomości o wpływie botów Twittera na wybory prezydenckie w USA. W 2015 dowiedziałem się o systemie używanym do przewidywania trendów ekonomicznych i uruchamiania dużych transakcji finansowych wyłącznie na podstawie „opinii” algorytmów o tekstach w języku naturalnym[6]. Te algorytmy wpływające na gospodarkę i zmieniające społeczeństwo spowodowały powstanie dodatniego sprzężenia zwrotnego. „Przetrwanie najsilniejszego” dla tych algorytmów wydaje się faworyzować algorytmy, które generują najwięcej zysków. A zyski te często powstają kosztem strukturalnych podstaw demokracji. Maszyny wpływają na ludzi, a my ludzie wyszkoliliśmy je w wykorzystaniu języka naturalnego, tak aby ten wpływ zwiększyć. Oczywiście maszyny te były pod kontrolą myślących i samoświadomych ludzi, ale gdy zdamy sobie sprawę, że ludzie ci są pod wpływem botów, nasz umysł zaczyna się dziwić. Czy te boty mogłyby spowodować niekontrolowaną reakcję łańcuchową wciąż wzmacniającej się informacji zwrotnej? Zapewne warunki początkowe tych botów mogły mieć duży wpływ na to, czy ta reakcja łańcuchowa sprzyja wartościom i dążeniom ludzi, czy jest dla nich niekorzystna.

Gdy Brian Sawyer z Manning Publishing zadzwonił do mnie, od razu wiedziałem, o czym chcę napisać i kogo chciałbym mieć do pomocy. Tempo rozwoju algorytmów NLP i agregacja danych w języku naturalnym nadal rosły, a ja, Cole i Hannes staraliśmy się dotrzymać kroku.

Dostęp do nieustrukturyzowanych[7] danych w języku naturalnym dotyczących polityki i ekonomii pomógł NLP stać się ważnym narzędziem w przyborniku każdego szefa kampanii lub finansów. Na nerwy działa świadomość, że niektóre z artykułów, które kierują tymi przewidywaniami, są napisane przez inne boty. Boty te często nie zdają sobie wzajemnie sprawy ze swego istnienia. Boty te dosłownie rozmawiają ze sobą i próbują sobą wzajemnie manipulować, podczas gdy zdrowie ludzi i społeczeństwa schodzi na drugi plan. Po prostu łapiemy się na przejażdżkę.

Jeden z przykładów takiej pętli botów rozmawiających z botami został pokazany w 2015 roku przez startup Banjo[8]. Dzięki monitorowaniu Twittera NLP stosowane przez Banjo mogło przewidzieć wydarzenia warte odnotowania od 30 minut do godziny, zanim wiadomość ta została przekazana przez reporterów Reutera lub CNN. Wiele tweetów zostało wykorzystanych do śledzenia tych zdarzeń, które niemal na pewno będą faworyzowane i przekazane dalej do kilku innych botów z intencją „przyciągnięcia uwagi” bota NLP Banjo. A tweety, które były faworyzowane przez boty i monitorowane przez Banjo, były nadzorowane, promowane lub mierzone nie tylko zgodnie z algorytmami uczenia się maszyn kierowanymi przez analityków. Wiele z tych tweetów było napisanych w całości przez mechanizmy NLP[9].

Coraz więcej treści związanych z rozrywką, reklamami i raportami finansowymi może być generowanych bez jakiegokolwiek udziału człowieka. Boty NLP tworzą całe scenariusze filmowe[10]. Wideo i światy wirtualne zawierają boty, które prowadzą z nami konwersację, czasami dotyczącą samych botów i sztucznej inteligencji. Ta „gra w grze” stanie się jeszcze bardziej „meta” w miarę jak filmy o grach wideo, a potem boty w świecie rzeczywistym będą pisać recenzje, aby pomóc nam podjąć decyzję, które filmy oglądać. Przypisywanie autorstwa stanie się trudniejsze, gdyż przetwarzanie języka naturalnego (NLP) może uczyć się imitować i generować tekst w podanym stylu[11].

NLP wpływa na społeczeństwo w mniej bezpośredni sposób. Umożliwia skuteczne pozyskiwanie informacji (wyszukiwanie), a stanowiąc dobry filtr lub narzędzie promowania niektórych stron, wpływa na wykorzystywane przez nas informacje. Wyszukiwanie to pierwsze komercyjne zastosowanie NLP zakończone powodzeniem. Coraz szybszy rozwój algorytmów NLP z kolei miał wpływ na poprawę samych technik wyszukiwania. Pomagamy wam przyczynić się do tego pozytywnego cyklu powiększającej się zbiorowej siły mózgu, pokazując niektóre techniki indeksowania i przewidywania będące podstawą wyszukiwania internetowego. Pokazujemy wam, jak indeksować tę książkę, tak aby mózg miał czas na myślenie na wyższym poziomie, pozwalając maszynom na zajęcie się zapamiętywaniem terminologii, faktów i fragmentów kodu w Pythonie. Zapewne będziecie mogli sami wpływać na kulturę waszą i waszych przyjaciół za pomocą własnych narzędzi wyszukiwania w języku naturalnym.

Rozwój systemów NLP zbudował crescendo przepływu informacji i obliczeń przez ludzkie mózgi i pomiędzy nimi. Teraz wystarczy wpisać tylko kilka znaków w pasku wyszukiwania i często otrzymamy dokładnie ten kawałek informacji, którego potrzebujemy do realizacji naszych zadań, jak np. pisanie oprogramowania do podręcznika na temat NLP. Kilka pierwszych opcji autouzupełniania jest często zadziwiająco odpowiednich, tak że wydaje nam się, jakby to człowiek asystował w naszym wyszukiwaniu. Oczywiście my, jako autorzy, używaliśmy podczas pisania tego podręcznika różnych wyszukiwarek. W niektórych przypadkach te wyniki wyszukiwania obejmowały posty i artykuły społeczne nadzorowane lub pisane przez boty, które z kolei inspirowały wiele z objaśnień i aplikacji NLP podanych na kolejnych stronach.

Co jest siłą napędową postępów w NLP:

■ Docenienie na nowo stale rozszerzającej się sieci danych nieustrukturyzowanych?

■ Zwiększenie mocy przetwarzania nadążające za pomysłami uczonych?

■ Efektywność interakcji z maszyną w naszym własnym języku?

Chodzi o wszystko powyżej i wiele innych elementów. Możemy zapytać dowolną wyszukiwarkę: „Dlaczego przetwarzanie języka naturalnego jest teraz takie ważne?”[12] i znaleźć w Wikipedii artykuł pełen dobrych powodów[13].

Są też głębsze powody. Jednym z nich jest przyspieszający pościg za ogólną sztuczną inteligencją (artificial general intelligence, AGI)[14], czyli inaczej głęboką (Deep) AI. Ludzka inteligencja jest możliwa tylko dlatego, że potrafimy zbierać myśli w odrębne pakiety znaczeń, które przechowujemy (pamiętamy) i skutecznie się nimi dzielimy. Umożliwia to nam rozciągnięcie naszej inteligencji w czasie i przestrzeni oraz łączenie naszych umysłów w celu utworzenia zbiorowej inteligencji.

Jednym z pomysłów w The Stuff of Thoughts Stevena Pinkera jest to, że w istocie myślimy w języku naturalnym[15]. Nie bez powodu nazywa się to „dialogiem wewnętrznym”. Facebook, Google i Elon Musk opierają się na fakcie, że słowa będą domyślnym protokołem komunikacji dla myśli. Zainwestowali w projekty, które próbują przetłumaczyć myśl, fale mózgowe i sygnały elektryczne na słowa[16]. Ponadto hipoteza Sapira–Whorfa mówi, że słowa wpływają na sposób, w jaki myślimy[17]. A język naturalny jest medium komunikacyjnym kultury i zbiorowej świadomości.

Tak więc, jeśli jest to odpowiednie dla ludzkich mózgów, to chcielibyśmy emulować, czyli symulować ludzką myśl w maszynie, a wtedy przetwarzanie języka naturalnego zapewne stanie się kluczowe. Ponadto możemy mieć ciekawe wskazówki dotyczące inteligencji ukrytej w strukturach danych i zagnieżdżonych połączeniach między słowami, które poznamy dzięki tej książce. W końcu mamy używać tych struktur, a sieci połączeń sprawiają, że nieożywiony system może przetrawić, przechować, uzyskać i wygenerować język naturalny w sposób, który wygląda na ludzki.

I jest jeszcze jeden, nawet ważniejszy powód, dla którego możecie chcieć nauczyć się, jak zaprogramować system, który dobrze wykorzystuje język naturalny… może zdołacie ocalić świat. Mam nadzieję, że obserwowaliście poniższą dyskusję między wpływowymi politykami o Problemie kontroli nad AI i wyzwaniem, którym jest utworzenie „przyjaznej AI”[18]. Nick Bostroma[19], Caluma Chace[20], Elon Musk[21] i wielu innych wierzy, że przyszłość ludzkości leży w naszych możliwościach rozwinięcia przyjaznych maszyn. A język naturalny będzie w przewidywalnej przyszłości ważnym powiązaniem między ludźmi i maszynami.

Nawet gdy będziemy mogli „myśleć” razem z maszynami, myśli te będą zapewne ukształtowane w naszych mózgach w naturalne słowa i języki. Podział na język naturalny i maszynowy zostanie zamazany tak jak zanika podział między człowiekiem a maszyną. W istocie podział ten zaczął się zacierać w roku 1984. To rok manifestu Cyborga (Cyborg Manifesto)[22], który sprawił, że dystopijne przewidywania George’a Orwella stały się bardziej prawdopodobne i łatwiejsze dla nas do zaakceptowania[23],[24].

Mam nadzieję, że fraza „ocalić świat” nie pozostawiła was w niedowierzaniu. Podczas czytania tej książki pokazujemy, jak zbudować i połączyć kilka płatów „mózgu” chatbota. Gdy to zrobicie, zauważycie, że bardzo małe wtrącenia w społecznościowe pętle sprzężenia zwrotnego między ludźmi i maszynami mogą mieć rozległy wpływ zarówno na ludzi, jak i na maszyny. Podobnie jak machnięcie skrzydła motyla w Chinach niewielka korekta na dalekim miejscu po przecinku w parametrze „samolubności” naszego chatbota może spowodować pełną chaosu burzę antagonistycznego zachowania chatbota i konflikty[25]. I zauważycie też, jak nowy rodzaj altruistycznych systemów szybko zbierze lojalne grupy zwolenników, którzy pomogą zdławić chaos spowodowany przez krótkowzroczne boty – boty, które realizują „funkcje celu” ukierunkowane na finansowy zysk swoich właścicieli. Prospołeczne, współpracujące chatboty mogą mieć ogromny wpływ na świat z powodu sieciowego efektu zachowań prospołecznych[26].

Oto jak i dlaczego autorzy tej książki się spotkali. Pomocna społeczność pojawiła się dzięki otwartej, uczciwej i prospołecznej komunikacji przez Internet za pomocą języka, co przyszło nam w sposób naturalny. Używamy kolektywnej inteligencji, która pomaga nam w zbudowaniu i wspieraniu innych częściowo inteligentnych aktorów (maszyn). Mamy nadzieję, że nasze słowa pozostawią ślad w waszych umysłach i będą się rozprzestrzeniać[27] jak memy w świecie chatbotów, zarażając innych pasją tworzenia prospołecznych systemów NLP. Mamy też nadzieję, że superinteligencja, która ostatecznie się pojawi, będzie napędzana, nawet w niewielkim stopniu, etosem prospołecznym.

podziękowania

Przygotowanie tej książki i oprogramowania, aby ją ożywić, nie byłoby możliwe bez wspomagającej sieci utalentowanych deweloperów, mentorów i przyjaciół. Współpracownicy ci pochodzą z dynamicznej społeczności Portland wspieranej przez organizacje, takie jak PDX Python, Hack Oregon, Hack University, Civic U, PDX Data Science, Hopester, PyDX, PyLadies i Total Good.

Uznanie dla Zachary’ego Kenta, który zaprojektował, zbudował i utrzymywał openchat (bot PyConOpen Spaces Twitter), i Rileya Rustada, który tworzył prototyp jego systemu danych w miarę powstawania tej książki i zwiększania się naszych umiejętności. Santi Adavani zaimplementował rozpoznawanie nazwanych jednostek, wykorzystując bibliotekę Stanford CoreNLP, opracował podręczniki do SVD i PCA oraz wspierał nas w dostępie do schematu jego RocketML, platformy HPC do trenowania modelu opisu wideo w czasie rzeczywistym przeznaczonego dla niewidomych. Eric Miller przenaczył nieco zasobów Squishy Media do uruchomienia zdolności wizualizacyjnych Hobsona w NLP. Eric Larson i Aleck Landgraf w swoim startupie dali Hobsonowi i Hannes swobodę eksperymentowania z uczeniem się maszyn i NLP.

Anna Ossowski pomogła zaprojektować bota PyCon Open Spaces Twitter, a potem pilnowała go w początkowych fazach uczenia, aby pomóc mu odpowiedzialnie tweetować. Chcik Wells był współzałożycielem Total Good, opracował sprytne i zabawne testy IQ dla chatbotów i stale wspierał nas swoim doświadczeniem deweloperskim. Eksperci NLP, jak Kyle Gorman, hojnie dzieli się z nami swoim czasem, wiedzą o NLP, kodem i cennymi zbiorami danych. Catherine Nikolovski podzieliła się z nami swoją społecznością i zasobami Hack Oregon i Civic U. Chris Gian wniósł pomysły ze swojego projektu NLP do przykładów zawartych w tej książce i odważnie został instruktorem w klasie Civic U Machine Learning, gdy nauczyciel wypisał się w połowie drogi. Jesteś jak Sky Walker. Rachel Kelly dała nam dostęp do swoich prac i wsparcie potrzebne we wczesnych opracowywania materiałów. Thunder Shiviah zapewniał stałą inspirację, niestrudzenie ucząc i przejawiając nieograniczony entuzjazm do uczenia się maszyn i do życia.

Molly Murphy i Natasha Pettit z Hopester są odpowiedzialne za pokazanie nam celu, inspirującą koncepcję prospołecznego chatbota. Jeremy Robin i personel Talentpair dostarczyli nam cennych informacji zwrotnych na temat oprogramowania inżynierskiego i pomogli nam wprowadzić w życie niektóre koncepcje podane w tej książce. Dan Fellin pomógł rozpocząć naszą przygodę z NLP dzięki pomocy dydaktycznej z podręcznika PyCon 2016 oraz zajęć na Hack University dotyczących problemów z Twitterem. Alex Rosengarten, Enrico Casini, Rigoberto Macedo, Charlina Hung i Ashwin Kanan z Aira „umobilnili” pojęcia chatbota za pomocą skutecznego, niezawodnego i łatwego w utrzymaniu silnika dialogowego i mikrousługi. Podziękowania dla Elli i Wesley’a Mintonów za to, że byli królikami doświadczalnymi, eksperymentując z naszymi zwariowanymi pomysłami chatbotowymi, podczas nauki pisania pierwszych programów w Pythonie. Suman Kanuganti i Maria MacMullin mieli wizję, znajdując „Do More Foundation”, aby wizualny intepretator Airy był dostępny finansowo dla studentów. Dziękuję też Claytonowi Lewisowi za zaangażowanie mnie w swoje badania nad poznawczym asystentem, gdy ja mogłem wnieść do jego pracowni w Coleman Institute tylko entuzjazm i nędzny kod.

Część pracy omawianej w tej książce została sfinansowana przez grant 1722399 z National Science Foundation (NSF) dla Aira Tech Corp. Wszelkie opinie, ustalenia i rekomendacje zawarte w tej książce pochodzą od autorów i nie muszą odzwierciedlać poglądów organizacji i osób, które zostały tu wymienione.

Na koniec chcieliśmy podziękować wszystkim z Manning Publications za ich ciężką pracę, a także dr. Arwenowi Griffieoenowi za napisanie wprowadzenia, dr. Davidowi Cadamuro za opinię techniczną oraz wszystkim naszym recenzentom, których uwagi i pomoc poprawiły tę książkę, znacznie zwiększając naszą kolektywną inteligencję. Są to: Chung-Yao Chuang, Fradj Zayen, Geoff Barto, Jared Duncan, Mark Miller, Parthasarathy Mandayam, Roger Meli, Shobha Iyer, Simona Russo, Srdjan Santic, Tommaso Teofili, Tony Mullen, Vladimir Kuptsov, William E. Wheeler i Yogesh Kulkarni.

Jestem dozgonnie wdzięczny moim rodzicom za to, że napełniają mnie zachwytem nad słowami i matematyką. Dziękuję Larissie Lane, najbardziej nieustraszonej poszukiwaczce przygód, jaką znam – jestem na zawsze twoim dłużnikiem za pomoc w osiągnięciu dwóch życiowych marzeń, żeglowania po świecie i napisania książki. Wobec Arzu Karaery mam dług za jej dobroć i cierpliwość, gdy pomagała mi pozbierać w całość moje złamane serce, utwierdzając mnie w mojej wierze w ludzkość i sprawiając, że ta książka zachowała swoje pełne nadziei przesłanie.

Hobson Lane

Jestem winien podziękowania mojej partnerce Whitney, która bezgranicznie wspierała mnie stale w tym przedsięwzięciu. Dziękuję ci za rady i uwagi. Chciałbym też podziękować rodzinie, zwłaszcza moim rodzicom, którzy zachęcali mnie, aby iść w świat i go odkrywać. Bez nich cała ta praca nie byłaby możliwa. Wszystkie moje przygody życiowe nie byłyby też możliwe bez tych dzielnych kobiet i mężczyzn zmieniających świat w listopadową noc 1989 roku. Dziękuję za waszą odwagę.

Hannes Max Hapke

Chciałbym podziękować moje żonie Dawn. Jej nadludzka cierpliwość i zrozumienie są prawdziwą inspiracją. I mojej matce za wolność eksperymentowania i zachętę, aby zawsze się uczyć.

Cole Howard

o książce

Przetwarzanie języka naturalnego w akcji to praktyczny przewodnik po przetwarzaniu i generowaniu tekstu w języku naturalnym w realnym świecie. W książce tej dajemy wam wszystkie narzędzia i techniki potrzebne do zbudowania backendowych systemów NLP do obsługi wirtualnego asystenta (chatbota/agenta dialogowego), filtra spamu, moderatora forum, systemu do analizy wydźwięku, generatora baz wiedzy, analizatora tekstów języka naturalnego i każdego innego zastosowania NLP, jakie możecie sobie wyobrazić.

Książka ta jest skierowana do deweloperów Pythona, od średnio zaawansowanych do zaawansowanych. Dla czytelników, którzy już umieją projektować i tworzyć złożone systemy, książka także będzie przydatna, gdyż daje wiele przykładów dobrych praktyk oraz wgląd w możliwości najnowszych algorytmów NLP. Wiedza na temat programowania obiektowego w Pythonie będzie przydatna do budowy lepszych systemów, ale nie jest wymagana przy nauce z tej książki.

W przypadku specjalnych tematów podajemy odpowiednią ilość materiału pomocniczego i cytujemy zasoby (tekstowe i online) dla tych, którzy chcą szczegółowo się z nimi zapoznać.

Plan działania

Osoby nieznające Pythona i przetwarzania języka naturalnego powinny najpierw przeczytać część 1, a potem dowolne rozdziały z części 3, które związane są z ich zainteresowaniami lub wyzwaniami w pracy. Jeśli chcecie przyśpieszyć zdobywanie nowych możliwości NLP, na które pozwala deep learning, będziecie chcieli przeczytać po kolei część 2. Buduje ona zrozumienie sieci neuronowych, przyrostowo zwiększając złożoność i możliwości sieci neuronowych.

Gdy znajdziecie rozdział lub część z fragmentem programu, który możecie „uruchomić w głowie”, powinniście wykonać go na swoim komputerze. A jeśli jakieś przykłady wyglądają, jakby można je było zastosować w swoich dokumentach, powinniście wstawić ten tekst do CSV lub do pliku tekstowego (jeden dokument w wierszu) w katalogu nlpia/src/nlpia/data/. Wtedy możecie użyć funkcji nlpia.data.loaders.get_data() do uzyskania tych danych i wykonania przykładów na swoich danych.

O książce

Rozdziały z części 1 dotyczą logistyki pracy z językiem naturalnym i przekształcania go w liczby, które można wyszukiwać i obliczać. To „tworzenie bloków i chwytanie” słów daje nagrodę w postaci zadziwiająco użytecznych aplikacji, jak wyszukiwanie informacji i analiza wydźwięku. Gdy już dobrze opanujecie podstawy, okaże się, że już przy użyciu prostej arytmetyki wykonywanej w pętli można rozwiązać niektóre dość skomplikowane problemy, jak filtrowanie spamu. Filtry spamu, które zbudujecie w rozdziałach od 2 do 4, są tym, co ocaliło globalny system e-mailowy przed anarchią i stagnacją. Dowiecie się, jak tworzyć filtry spamu o dokładności ponad 90% za pomocą technologii z ery lat dziewięćdziesiątych – obliczając jedynie liczbę słów i proste średnie tych liczb.

Cała ta matematyka dotycząca słów może wydawać się uciążliwa, ale w istocie to dość dobra zabawa. Bardzo szybko będziecie budować algorytmy, które będą mogły podejmować decyzje dotyczące języka naturalnego tak samo dobrze lub lepiej niż my sami (a na pewno dużo szybciej). Może to być pierwszy raz w waszym życiu, gdy będziecie mieli perspektywę, aby ocenić w pełni sposób, w jaki słowa odzwierciedlają i wzmacniają wasze myślenie. Spojrzenie na słowa i myśli przez perspektywę wielowymiarowej przestrzeni wektorowej pozostawi nasz mózg w ruchu w rekurencyjnych pętlach samo-odkrywania.

Tempo nauki może osiągnąć najwyższy punkt w połowie książki. Rdzeniem książki w części 2 jest poznawanie skomplikowanej sieci obliczeń i komunikacji z sieciami neuronowymi. Sieciowy efekt małych jednostek logicznych w interakcji z siecią „myślenia” dał maszynom moc rozwiązywania problemów, którymi w przeszłości zajmowali się tylko ludzie, obejmując takie elementy jak pytania o analogie, streszczanie tekstu i tłumaczenia między językami naturalnymi.

W miarę nauki poznacie wektory słów, ale bez obaw, o wiele więcej. Będziecie w stanie dokonać wizualizacji słów, dokumentów i zdań w chmurze powiązanych pojęć, rozciągającej się znacznie poza trzy wymiary, które jesteśmy gotowi ogarnąć. Zaczniecie myśleć o dokumentach i słowach jak o postaciach w grze Dungeons and Dragons, z miriadą losowo wybranych charakterystyk i zdolności, które wyewoluowały i urosły z biegiem czasu, lecz tylko w naszych głowach.

Docenienie tego wielotematycznego świata słów i ich znaczenia stanie się podstawą do coup-de-grace z części 3, gdzie nauczycie się, jak budować maszyny, które prowadzą konwersację i odpowiadają na pytania tak samo dobrze jak ludzie.

O kodzie

Książka zawiera wiele przykładów kodu źródłowego zarówno w ponumerowanych listingach, jak i w wierszach normalnego tekstu. W obu przypadkach kod jest zapisany czcionką o stałej szerokości (jak ta) i oddzielony od reszty tekstu. Czasami kod jest także pogrubiony, aby podkreślić zmiany w stosunku do poprzednich kroków w rozdziale, jak w przypadku dodania nowej funkcji w istniejącym wierszu kodu.

W wielu przypadkach oryginalny kod źródłowy został przeformatowany. Przełamaliśmy wiersze i dodaliśmy wcięcia, aby dostosować do dostępnej szerokości kolumny. W rzadkich przypadkach nawet to nie wystarczyło i listingi zawierają znaczniki kontynuacji kodu (→). Ponadto w przypadkach, gdy kod jest opisany w tekście, komentarze z kodu źródłowego zostały usunięte z listingów. Wielu listingom towarzyszą adnotacje kodu, aby uwypuklić ważne pojęcia.

Kod źródłowy wszystkich listingów z tej książki jest dostępny do pobrania z witryny wydawnictwa Manning pod adresem https://www.manning.com/books/natural-language-processingin-action oraz na GitHub pod adresem https://github.com/totalgood/nlpia.

Forum dyskusyjne liveBook

Zakupienie tej książki obejmuje bezpłatny dostęp do prywatnego forum sieciowego prowadzonego przez Manning Publications, gdzie możecie komentować książkę, zadawać pytania techniczne i otrzymać pomoc od autorów i innych użytkowników. Aby mieć dostęp do forum, trzeba wejść na stronę https://livebook.manning.com/#!/book/natural-languageprocessing-in-action/discussion. Więcej o forum Manninga i obowiązujących tam zasadach można się dowiedzieć na stronie https://livebook.manning.com/#!/discussion.

Manning zobowiązuje się zapewnić czytelnikom forum, na którym może mieć miejsce sensowny dialog między czytelnikami oraz między czytelnikami a autorami. Nie jest to zobowiązanie do konkretnego stopnia zaangażowania ze strony autorów, których udział w forum jest dobrowolny (i bezpłatny). Sugerujemy, aby zadawać autorom trudne pytania, co przyciągnie ich uwagę! Forum i archiwa zawierające wcześniejsze dyskusje są dostępne na witrynie wydawcy od chwili wydrukowania tej książki.

o autorach

HOBSON LANE ma 20 lat doświadczenia w tworzeniu systemów autonomicznych, które podejmują ważne decyzje w imieniu ludzi. W firmie Talentpair Hobson uczył maszyny czytać i rozumieć informacje o karierze z mniejszym uwarunkowaniem niż większość rekruterów. W firmie Aira pomagał w budowie ich pierwszego chatbota do interpretacji świata wizualnego dla osób niewidzących. Hobson pasjonuje się sztuczną inteligencją otwartą i prospołeczną. Aktywnie uczestniczy w projektach open source takich jak Keras, scikit-learn, PyBrain, PUGNLP i ChatterBot. Obecnie prowadzi badania w projektach otwartej nauki i edukacji dla Total Good obejmujących tworzenie asystenta poznawczego open source. Opublikował artykuły i miał wykłady na konferencjach AIAA, PyCon, PAIS i IEEE. Uzyskał też kilka patentów w dziedzinie robotyki i automatyzacji.

HANNES MAX HAPKE jest inżynierem elektrykiem, który zmienił się w inżyniera uczenia się maszyn. Zafascynowały go sieci neuronowe, gdy był w liceum, gdzie analizował sposoby tworzenia sieci neuronowych z mikrokontrolerów. Na studiach stosował koncepcje sieci neuronowych do efektywnego sterowania elektrowniami wykorzystującymi energię odnawialną. Hannes uwielbia automatyzować tworzenie oprogramowania oraz potoki wykorzystujące uczenie się maszyn. Jest współautorem modeli uczenia głębokiego i potoków stosowanych w rekrutacji, energetyce i ochronie zdrowia. Hannes mówił o uczeniu się maszyn na różnych konferencjach, w tym na OSCON, Open Source Bridge i Hack University.

COLE HOWARD to inżynier z dziedziny uczenia się maszyn, praktyk NLP i pisarz. Będąc całe życie łowcą wzorców, znalazł swój prawdziwy dom w świecie sztucznych sieci neuronowych. Opracował wielkoskalowe silniki rekomendacji dla e-handlu i nowoczesne wysokowymiarowe sieci neuronowe dla systemów inteligentnych maszyn (sieci neuronowe wykorzystujące głębokie uczenie się), które uzyskują wyniki na najwyższym poziomie w konkursach Kaggle. Miał prezentacje na temat konwolucyjnych i rekurencyjnych sieci neuronowych oraz ich roli w przetwarzaniu języka naturalnego na konferencji Open Source Bridge i na Hack University.

o ilustracji na okładce

Obraz na okładce książki ma podpis „Kobieta z Kranjska Gora w Słowenii”. Ilustracja pochodzi z nowego przedruku Balthasara Hacqueta Images and Descriptions of Southwestern and Eastern Wends, Illyrians, and Slavs, opublikowanego przez Ethnographic Museum w Splicie w Chorwacji w 2008 roku. Hacquet (1739–1815) był austriackim lekarzem i uczonym, który spędził wiele lat, badając botanikę, geologię i etnografię Alp Julijskich, łańcucha górskiego, który rozciąga się od północnowschodnich Włoch do Słowenii, a ich nazwa pochodzi od Juliusza Cezara. Ręcznie wykonane ilustracje towarzyszą wielu pracom naukowym i książkom opublikowanym przez Hacqueta.

Bogata różnorodność rysunków w publikacjach Hacqueta żywo mówi o niepowtarzalności i indywidualności wschodnich regionów alpejskich sprzed jedynie 200 lat. Były to czasy, w których sposób ubioru dwóch wiosek odległych od siebie o kilka kilometrów identyfikowało jednoznacznie ludzi pochodzących z jednej lub drugiej, a ludzie należący do klasy społecznej lub zawodu mogli być rozpoznani przez swój strój. Od tego czasu sposób ubierania się zmienił, a ówczesna różnorodność regionu zanikła. Teraz często odróżnić mieszkańca jednego kontynentu od drugiego, a mieszkańców malowniczych miast i wiosek Alp słoweńskich trudno odróżnić od mieszkańców innych części Słowenii lub reszty Europy. W wydawnictwie Manning cenimy inwencję, inicjatywę i radość biznesu komputerowego za pomocą okładek opartych na bogatej różnorodności życia w regionach dwa wieki temu, przywracanych do życia przez obrazy z jego kolekcji.

Część 1

Mówiące maszyny

W części 1 rozpoczynacie przygodę z przetwarzaniem języka naturalnego (NLP) od wprowadzenia w niektóre rzeczywiste zastosowania.

W rozdziale 1 zaczniecie szybko myśleć o tym, w jaki sposób można w swoim życiu wykorzystać maszyny, które przetwarzającą teksty. I mam nadzieję, że poczujecie magię – siłę maszyn, które mogą czerpać informacje ze słów z dokumentu w języku naturalnym. Słowa są podstawą każdego języka, niezależnie od tego, czy są to słowa kluczowe w języku programowania, czy słowa języka naturalnego, które poznaliśmy w dzieciństwie.

W rozdziale 2 dajemy wam narzędzia potrzebne, aby nauczyć maszyny, jak wyodrębniać słowa z dokumentów. To większe zadanie niż można by sądzić, a my pokazujemy tu wszystkie sztuczki. Dowiecie się, jak automatycznie grupować słowa języka naturalnego w grupy słów o podobnym znaczeniu bez konieczności ręcznego tworzenia listy synonimów.

W rozdziale 3 liczymy te słowa i składamy je w wektory, które reprezentują znaczenie dokumentu. Można użyć tych wektorów do reprezentowania znaczenia całego dokumentu niezależnie od tego, czy jest to tweet złożony ze 140 znaków, czy 500-stronicowa powieść.

W rozdziale 4 poznacie kilka sprawdzonych sztuczek matematycznych służących do kompresji wektorów w znacznie bardziej użyteczne wektory tematyczne.

Pod koniec części 1 będziecie mieć narzędzia do wielu ciekawych zastosowań NLP – od wyszukiwania semantycznego do chatbotów.

1

Pakiety myśli (przegląd NLP)

Tematyka rozdziału

■ Czym jest przetwarzanie języka naturalnego (NLP)?

■ Dlaczego NLP jest trudne i dopiero ostatnio się rozpowszechniło?

■ Kiedy kolejność słów i gramatyka są ważne, a kiedy można je zignorować?

■ Jak chatbot łączy wiele narzędzi NLP?

■ Jak używać wyrażeń regularnych do utworzenia początku malutkiego chatbota?

Właśnie rozpoczynacie pasjonującą przygodę z przetwarzaniem języka naturalnego. Najpierw pokażemy, czym jest NLP i wszystko, co możemy z tym zrobić. To pozwoli wam ruszyć i pomoże pomyśleć o sposobach wykorzystania NLP w swoim życiu, zarówno w pracy, jak i w domu.

Potem zagłębiamy się w szczegóły, jak przetwarzać niewielki fragment angielskiego tekstu za pomocą języka programowania jak Python, co pomoże po kolei zbudować własny zestaw narzędzi NLP. W tym rozdziale napiszecie pierwszy program, który potrafi czytać i pisać zdania po angielsku. Ten fragment programu w Pythonie będzie pierwszym, którego użyjecie, aby nauczyć się sztuczek potrzebnych do utworzenia silnika dialogowego w języku angielskim – chatbota.

1.1. Język naturalny a język programowania

Języki naturalne różnią się od komputerowych języków programowania. Nie są przeznaczone do przełożenia na skończony zbiór działań matematycznych, tak jak języki programowania. Języki naturalne są tym, co pozwala ludziom na dzielenie się ze sobą informacjami. Nie używamy języków programowania, aby opowiedzieć innym o swoim dniu lub podać wskazówki do sklepu spożywczego. Program komputerowy napisany w języku programowania mówi maszynie dokładnie, co ma robić. Ale nie ma kompilatorów ani interpreterów języków naturalnych, takich jak angielski czy francuski.

DEFINICJA Przetwarzanie języka naturalnego to dziedzina badań w informatyce i sztucznej inteligencji (AI) związana z przetwarzaniem języków naturalnych, takich jak angielski lub mandaryński. Przetwarzanie to obejmuje ogólnie tłumaczenie języka naturalnego na dane (liczby), które komputer może wykorzystać, aby uczyć się świata. A to zrozumienie świata czasami jest używane do generowania tekstu w języku naturalnym, który odzwierciedla to zrozumienie.

Niemniej jednak rozdział ten pokazuje, jak maszyna może przetwarzać język naturalny, Możecie nawet myśleć o tym jak o interpreterze języka naturalnego, podobnie jak o interpreterze Pythona. Gdy napisany przez was program komputerowy przetwarza język naturalny, potrafi działać na jego zdaniach, a nawet na nie odpowiadać. Ale te działania i odpowiedzi nie są precyzyjnie zdefiniowane, co pozostawia wam więcej swobody przy tworzeniu potoku przetwarzania (pipeline) języka naturalnego.

DEFINICJA System przetwarzania języka naturalnego jest często nazywany potokiem, gdyż zwykle obejmuje kilka etapów przetwarzania, w których język programowania wpływa z jednego końca, a przetworzone wyniki wypływają z drugiego.

Wkrótce będzie umieć pisać oprogramowanie, które wykonuje ciekawe, nieprzewidywalne, rzeczy, jak prowadzenie konwersacji, która sprawia, że maszyna wydaje się bardziej ludzka. Może to się z początku wydawać nieco magiczne, jak każda zaawansowana technika. Ale odsłonimy kurtynę, abyście mogli przeanalizować kulisy i wkrótce odkryć wszystkie rekwizyty i narzędzia potrzebne, aby samodzielnie robić te magiczne sztuczki.

Wszystko jest łatwe, gdy już znamy odpowiedź.

Dave Magee

1.2. Magia

Co takiego magicznego jest w tym, że maszyna może czytać i pisać w języku naturalnym? Maszyny przetwarzają języki od czasu wynalezienia komputerów. Jednak te „sformalizowane” języki – jak wczesne języki Ada, COBOL i Fortran – zostały zaprojektowane, aby mogły być interpretowane (lub kompilowane) w jeden poprawny sposób. Dziś Wikipedia wymienia ponad 700 języków programowania. Natomiast Ethnologue [28] zidentyfikował 10 razy więcej języków naturalnych, którymi mówią ludzie na całym świecie. Indeks Google’a obejmujący dokumenty w językach naturalnych ma ponad 100 milionów gigabajtów[29]. A tu chodzi tylko o indeks. I nie jest on pełny. Rozmiar treści w językach naturalnych dostępnych obecnie online musi przekraczać 100 miliardów gigabajtów[30]. Ale ta ogromna ilość tekstów w językach naturalnych nie jest jedynym powodem, dla którego ważne jest tworzenie oprogramowania, które może je przetwarzać.

Ciekawe, że proces ten jest trudny. Maszyny z możliwością przetwarzania czegoś naturalnego nie są naturalne. Przypomina to budowanie struktury, która potrafi zrobić coś użytecznego z rysunkami architektonicznymi. Gdy oprogramowanie może przetwarzać języki, które nie są przeznaczone dla maszyn, wygląda to na magię – coś, co uważaliśmy dotąd za wyłączną zdolność ludzi.

Słowo „naturalny” w wyrażeniu „język naturalny” używane jest w takim samym sensie jak w wyrażeniu „świat naturalny”. Naturalne rzeczy wokół nas, które wyewoluowały, różnią się od mechanicznych, sztucznych rzeczy zaprojektowanych i zbudowanych przez ludzi. Zdolność do zaprojektowania i zbudowania oprogramowania, które może czytać i przetwarzać język, jak to, co teraz czytacie – język o tworzeniu oprogramowania, które może przetwarzać język naturalny … cóż, bardzo meta, bardzo magiczne.

Aby było wam łatwiej, skupimy się na jednym języku naturalnym, na angielskim. Ale techniki poznane w tej książce możecie wykorzystać do stworzenia oprogramowania, które będzie przetwarzać dowolny język, nawet język, którego nie rozumiecie albo musi zostać odszyfrowany przez archeologów i lingwistów. I pokażemy wam, jak pisać oprogramowanie do przetwarzania i generowania tego języka, wykorzystując tylko jeden język programowania, Python.

Python został zaprojektowany od podstaw tak, by był językiem czytelnym. Pokazuje on też wiele „bebechów” sposobu, w jaki jest przetwarzany. Obie te cechy sprawiają, że stanowi naturalny wybór do nauki przetwarzania języka naturalnego. Jest to świetny język do tworzenia łatwych do utrzymania potoków produkcyjnych dla algorytmów NLP w środowisku firmowym, z wieloma osobami tworzącymi jedną bazę kodu. Gdzie tylko jest to możliwe, używamy Pythona nawet w miejsce „języka uniwersalnego” matematyki i symboli matematycznych[31], a jest zaprojektowany tak, że jest bardzo czytelny dla takich programistów jak wy.

1.2.1. Maszyny prowadzące konwersację

Języki naturalne nie mogą zostać bezpośrednio przetłumaczone na dokładny zbiór działań matematycznych, ale zawierają informacje i instrukcje, które można z nich wyodrębnić. Te fragmenty informacji i instrukcji można zapisać, indeksować, przeszukiwać lub wykonać na nich natychmiastowe działania. Jednym z tych działań może być wygenerowanie ciągu słów w odpowiedzi na instrukcję. Jest to funkcja „agenta dialogowego”, czyli budowanego przez was chatbota.

Skupiamy się w całości na dokumentach i komunikatach w języku angielskim, nie na zdaniach mówionych. Omijamy konwersję mówionych stwierdzeń na tekst – rozpoznawanie mowy, czyli przekształcanie mowy na tekst (Speech To Text, STT). Ignorujemy także generowanie mowy, czyli przekształcanie tekstu na mowę, przekształcanie tekstu z powrotem na brzmiące po ludzku wypowiedzi. Jednak wciąż można wykorzystać to, czego się nauczycie, do stworzenia interfejsu głosowego lub wirtualnego asystenta jak Siri lub Alexa, gdyż biblioteki mowa-na-tekst i tekst-na-mowę są powszechnie dostępne. Istnieją aplikacje rozpoznawania mowy wysokiej jakości wraz z API generującymi dla mobilnych systemów operacyjnych, Android i iOS. Są też pakiety Pythona do osiągnięcia podobnej funkcjonalności na laptopie lub serwerze.

Systemy rozpoznawania mowy

Zbudowanie niestandardowego systemu rozpoznawania lub generowania mowy to przedsięwzięcie wymagające oddzielnej książki poświęconej tej tematyce. Pozostawiamy to jako „ćwiczenie dla czytelników”. Wymaga to dużej ilości etykietowanych danych wysokiej jakości, nagrań głosu oznaczonych ich fonetyczną wymową i transkrypcji naturalnego języka powiązanego z plikami dźwiękowymi. Niektóre algorytmy poznane w tej książce mogą w tym pomóc, ale większość algorytmów rozpoznawania i generowania jest inna.

1.2.2. Matematyka

Przetwarzanie języka naturalnego do wydobycia użytecznych informacji może być trudne. Wymaga żmudnego przetwarzania danych statystycznych, ale do tego są maszyny. I podobnie jak w przypadku wielu innych problemów technicznych rozwiązywanie jest znacznie łatwiejsze, jeśli znacie odpowiedź. Maszyny nadal nie potrafią wykonać najbardziej praktycznych zadań NLP, jak konwersacja i zrozumienie tekstu czytanego, tak dokładnie i niezawodnie, jak robią to ludzie. Dlatego możecie dopracowywać algorytmy poznane w tej książce, aby lepiej wykonywały zadania NLP.

Poznawane techniki są jednak dostatecznie silne, aby tworzyć maszyny, które potrafią prześcignąć ludzi w dokładności i szybkości niektórych zaskakująco subtelnych zadań. Na przykład, nie zgadlibyście, że rozpoznanie sarkazmu w pojedynczym komunikacie Twittera można zrobić z większą dokładnością za pomocą maszyny, niż zrobi to człowiek[32]. Nie martwmy się, gdyż ludzie nadał lepiej rozpoznają humor i sarkazm w prowadzonym dialogu dzięki naszej zdolności do przechowywania informacji na temat kontekstu stwierdzenia. Ale maszyny są coraz lepsze w rozumieniu informacji kontekstowej. A ta książka pomoże włączyć kontekst (meta-dane) do waszego potoku NLP, gdy będziecie chcieli poprawić jakość istniejących metod przetwarzania języka naturalnego.

Gdy z języka naturalnego wyodrębniacie ustrukturyzowane dane liczbowe, wektory, korzystacie ze wszystkich narzędzi matematyki i uczenia się maszyn. Używamy tych samych sztuczek algebry liniowej, jak projekcja obiektów 3D na dwuwymiarowy ekran komputera, coś co komputery i kreślarze robili na długo przed pojawieniem się przetwarzania języka naturalnego. Te przełomowe pomysły otworzyły świat analizy „semantycznej”, umożliwiając komputerom interpretację i przechowywanie „znaczenia” zdań zamiast zliczania słów lub znaków. Analiza semantyczna wraz ze statystyką mogą pomóc w rozwiązaniu problemu niejednoznaczności języka naturalnego – faktu, że słowa i wyrażanie mają często różne znaczenia i interpretacje.

Tak więc wyodrębnianie informacji nie przypomina budowy kompilatora języka programowania (na szczęście dla was). Najbardziej obiecujące techniki omijają ścisłe reguły regularnej gramatyki (szablony) i języki formalne[33]. Możecie opierać się na powiązaniach statystycznych między słowami, zamiast na głębokim systemie reguł logicznych[34]. Wyobraźcie sobie, że mielibyście zdefiniować reguły gramatyki i pisowni angielskiej w zagnieżdżonym drzewie instrukcji if (jeśli) … then (to). Czy moglibyście zapisać dostatecznie dużo reguł, aby poradzić sobie ze wszystkimi możliwymi sposobami, w jakie słowa, litery i znaki przestankowe mogą złożyć się w zdanie? Czy choć zaczniecie definiować semantykę, znaczenie zdań w języku angielskim? Jeśli nawet udałoby się to dla pewnego rodzaju zdań, wyobraźcie sobie jak ograniczone i powierzchowne byłoby takie oprogramowanie. Nieprzewidziana pisownia lub znaki przestankowe naruszyłyby lub zaciemniły wasz algorytm.

Języki naturalne zawierają dodatkowe wyzwanie „dekodowania”, które jest jeszcze trudniejsze do rozwiązania. Mówiący i piszący w językach naturalnych zakładają, że przetwarzanie przeprowadza człowiek (słuchając lub czytając), a nie maszyna. A zatem, jeśli mówię „good morning”, zakładam, że macie wiedzę o tym, czym jest ranek i że po ranku jest południe, popołudnie i wieczór, a potem noc. I musicie wiedzieć, że chodzi tu o pory dnia, a także ogólne pojęcie przedziału czasu. Zakłada się, że interpretator będzie wiedział, że „miłego ranka” można użyć jako powitania, które wcale nie zawiera informacji o samym ranku. Odzwierciedla raczej stan umysłu mówiącego i gotowość do rozmowy z innymi.

Ta teoria umysłu dotycząca ludzkiego modułu do rozumienia języka okazuje się bardzo silnym założeniem. Pozwala nam powiedzieć wiele za pomocą niewielu słów, jeśli założymy, że „moduł” ma dostęp do powszechnej życiowej wiedzy o świecie (wiedzy zdroworozsądkowej). Ten stopień zrozumienia jest nadal nieosiągalny dla maszyn. Nie ma żadnej implementacji takiej „teorii umysłu”, którą można znaleźć w potoku NLP. Jednak w dalszych rozdziałach pokażemy wam techniki, które pomagają maszynom w budowaniu ontologii lub baz wiedzy powszechnej, aby na podstawie tej wiedzy pomóc im w interpretowaniu zdań.

1.3. Zastosowania praktyczne

Przetwarzanie języka naturalnego jest wszędzie. Jest tak powszechne, że niektóre przykłady z tabeli 1.1 mogą was zaskoczyć.

Tabela 1.1. Kategorie zastosowań NLP

Wyszukiwanie

Internet

dokumenty

autouzupełnianie

Edycja

pisownia

gramatyka

styl

Dialog

chatbot

asystent

harmonogramowanie

Pisanie

indeks

konkordancje

spis treści

Email

filtr spamu

klasyfikacja

priorytetyzacja

Eksploracja tekstu

streszczanie

ekstrakcja wiedzy

diagnozy medyczne

Prawo

wnioskowanie prawne

szukanie precedensów

klasy fikacja wezwań

Wiadomości

wykrywanie zdarzeń

sprawdzanie faktów

tworzenie nagłówków

Przypisywanie

wykrywanie plagiatów

literatura kryminalistyczna

porady stylistyczne

Analiza wydźwięku

monitoring morale społeczności

przegląd recenzji produktu

dbanie o klienta

Przewidywanie zachowania

finanse

przewidywanie wyników wyborów

marketing

Kreatywne pisanie

scenariusze filmowe

poezja

teksty piosenek

Wyszukiwarka może zapewnić nam bardziej znaczące wyniki, jeśli indeksuje strony internetowe lub archiwa dokumentów w sposób, który bierze pod uwagę znaczenie tekstu w języku naturalnym. Autouzupełnianie wykorzystuje NLP do dopowiedzenia waszej myśli i jest popularne w wyszukiwarkach i klawiaturach telefonów komórkowych. Wiele procesorów tekstu, wtyczek przeglądarek i edytorów tekstu ma korektę pisowni, sprawdzanie gramatyki, konkordancery, a ostatnio porady stylistyczne. Niektóre silniki dialogowe (chatboty) używają języka naturalnego, aby znaleźć odpowiedź na komunikat od partnera konwersacji.

Potoki NLP, które generują (komponują) tekst, mogą być używane nie tylko do tworzenia krótkich odpowiedzi w chatbotach i wirtualnych asystentach, ale także do złożenia znacznie dłuższych fragmentów tekstu. Associated Press używa „dziennikarzy-robotów” NLP do pisania artykułów z wiadomościami finansowymi i reportaży z wydarzeń sportowych[35]. Boty mogą tworzyć prognozy pogody, które brzmią podobnie do tego, co powie wasza lokalna pogodynka zapewne dlatego, że meteorolodzy (ludzie) używają procesorów tekstu z funkcjami NLP do pisania szkiców.

Filtry spamu NLP we wczesnych programach pocztowych pomagały poczcie elektronicznej na początku lat dziewięćdziesiątych przejmować kanały komunikacji telefonicznej i faksowej. I filtry spamu utrzymały swoje miejsce w zabawie w kotka i myszkę między filtrami spamu a generatorami e-mailowego spamu, ale przegrywają w innych środowiskach, takich jak sieci społecznościowe. Szacuje się, że 20% tweetów dotyczących wyborów prezydenckich w USA w 2016 roku było tworzonych przez chatboty[36]. Te boty wzmacniają punkt widzenia ich właścicieli i twórców. A „władcami marionetek” mogą być obce rządy lub wielkie korporacje posiadające zasoby i motywacje, aby wpływać na opinie społeczeństwa.

Systemy NLP mogą generować coś więcej niż tylko krótkie posty w sieciach społecznościowych. NLP można wykorzystać do tworzenia długich recenzji filmów lub ocen produktów na Amazonie i w innych miejscach. Wiele opinii jest tworem autonomicznych potoków NLP, które nigdy nie postawiły stopy w kinie ani nie nabyły produktu, który oceniają.

Chatboty działają na Slack, IRC, a nawet na witrynach usług klienckich – w miejscach, gdzie muszą się mierzyć z niejednoznacznymi poleceniami lub pytaniami. A chatboty w połączeniu z systemami rozpoznawania i generowania mowy mogą obsługiwać nawet długą konwersację bez zaplanowanego z góry celu ani określonej „funkcji celu” jak rezerwowanie miejsca w lokalnej restauracji[37]. Systemy NLP mogą odbierać telefony w firmach, które chcą mieć coś lepszego niż drzewo wyboru telefonicznego lub nie chcą płacić ludziom, aby pomagali ich klientom.

UWAGA Podczas pokazu systemu Duplex w Google IO inżynierowie i menedżerowie pominęli zagadnienia dotyczące etyki uczenia chatbotów do oszukiwania ludzi. Wszyscy ignorujemy ten dylemat, gdy radośnie wchodzimy w interakcję z chatbotami na Twitterze i na innych anonimowych sieciach społecznościowych, gdzie boty nie piszą o swoim rodowodzie. W przypadku botów, które przekonująco nas oszukują, pojawia się problem kontroli AI[38], a ostrzegawcze przewidywania Yuvala Harari „Homo Deus”[39] mogą nadejść wcześniej, niż myślimy.

Istnieją systemy NLP, które działają jak „recepcjoniści” emaili dla biznesu lub jako asystenci dla menedżerów. Asystenci ci mogą planować spotkania i zapisywać szczegóły podsumowujące w elektronicznych Rolodex lub CRM (systemie zarządzania relacjami z klientami), wchodząc z innymi w interakcję przez email w imieniu swojego szefa. Firmy powierzają swoje marki i twarze systemom NLP, pozwalając botom, aby prowadziły kampanie marketingowe i wysyłały komunikaty. A niektórzy niedoświadczeni śmiałkowie piszący podręczniki NLP pozwalają, aby boty pisały kilka zdań w ich książce. Więcej na ten temat piszemy dalej.

1.4. Język widziany „oczyma” komputera

Gdy piszecie „Good morning Rosa” („Dzień dobry Różo”), komputer widzi tylko „010001110110111101101111 …”. Jak możecie zaprogramować chatbota, aby inteligentnie odpowiedział na ten ciąg binarny? Czy zagnieżdżone drzewo warunków (instrukcji if… else…) może sprawdzić wszystkie te bity i działać na nich indywidualnie? Byłoby to odpowiednikiem napisania specjalnego rodzaju programu nazywanego automatem skończonym (finite state machine, FSM). Taki automat, który działając wypuszcza ciąg nowych symboli, jak funkcja str.translate w Pythonie, jest nazywany transduktorem skończonym (finite state transducer, FST). Zapewne zbudowaliście już FSM, nawet o tym nie wiedząc. Czy pisaliście kiedyś wyrażenia regularne? Jest to rodzaj FSM używanych przez nas w kolejnym punkcie, aby pokazać jedno z możliwych podejść do NLP: podejście oparte na wzorcach.

Co będzie, jeśli zdecydujecie się przeszukiwać pamięć (bazę danych) w poszukiwaniu takiego samego ciągu bitów, znaków lub słów i wykorzystać jedną z odpowiedzi, której inni ludzie i autorzy użyli dla tego zdania w przeszłości? Ale wyobraźcie sobie, że znajdzie się tam literówka lub jakaś odmiana zdania. Nasz bot zacznie wariować. A bity nie są ciągłe i nie przebaczają – albo pasują, albo nie. Nie ma oczywistego sposobu na znalezienia podobieństwa między dwoma potokami bitów, który bierze pod uwagę ich znaczenie. Te bity dla „dobry” będą tak samo podobne jak te dla „zły!” lub dla „okey”.

Zobaczmy jednak, jak to podejście będzie działać, zanim pokażemy wam lepsze sposoby. Zbudujmy małe wyrażenie regularne rozpoznające powitania jak „Good morning Rosa” i odpowiednio na nie odpowiadające – nasz pierwszy malutki chatbot!

1.4.1. Język zamków

O dziwo prosty zamek kombinatoryczny stanowi prosty mechanizm przetwarzania języka. Jeśli więc macie zacięcie do mechaniki, ten punkt będzie pouczający. Ale jeśli nie musicie stosować analogii mechanicznych, aby zrozumieć algorytmy i sposób działania wyrażeń regularnych, to możecie ten punkt pominąć.

Po przeczytaniu tego punktu nigdy nie pomyślicie o zamku cyfrowym do roweru w taki sam sposób. Zamek cyfrowy z pewnością nie potrafi czytać ani rozumieć podręczników zamkniętych w szkolnej szafce, ale potrafi zrozumieć język zamków. Może zrozumieć, gdy „mówimy” mu „hasło” – kombinację cyfr. Kombinacja do kłódki to dowolny ciąg symboli, który jest zgodny z „gramatyką” (wzorcem) języka zamka. Co ważniejsze, kłódka może stwierdzić, czy „zdanie” zamka pasuje do istotnego zdania, które jest jedyną poprawną „odpowiedzią”: aby zwolnić blokadę trzymającą wygiętą zawleczkę, abyście mogli dostać się do swojej szafki.

Język zamka (wyrażenia regularne) jest szczególnie prosty. Ale nie jest na tyle prosty, abyśmy nie mogli użyć go w chatbocie. Możemy go użyć, aby rozpoznać kluczową frazę lub polecenie umożliwienia wykonania określonego działania lub zachowania.

Na przykład chcielibyśmy, aby nasz chatbot rozpoznawał pozdrowienia jak „Hello Rosa” i odpowiednio na nie reagował. Ten rodzaj języka, jak język zamków, jest językiem formalnym, gdyż ma ścisłe reguły dotyczące sposobu, w jaki akceptowalne zdanie musi zostać złożone i zinterpretowane. Jeśli kiedykolwiek pisaliście równanie matematyczne lub zakodowaliście wyrażenie w języku programowania, pisaliście zdanie w sformalizowanym języku.

Języki sformalizowane są podzbiorem języków naturalnych. Wiele zdań w języku naturalnym można dopasować lub wygenerować za pomocą formalnej gramatyki języka, takiej jak wyrażenia regularne. Dlatego zboczyliśmy do mechanicznego, „przekręcanego”[40] języka zamków.

1.4.2. Wyrażenia regularne

Wyrażenia regularne to specjalny rodzaj (klasa) formalnej gramatyki języka określanej jako gramatyka regularna. Gramatyki regularne są przewidywalne, można udowodnić ich zachowanie, ale są na tyle elastyczne, że mogą zasilić najbardziej wyrafinowane silniki dialogowe i chatboty znajdujące się na rynku. Alexa Amazona i Now Google’a są przede wszystkim oparte na wzorcach, które opierają się na gramatykach regularnych. Głębokie, złożone reguły gramatyki regularnej można często wyrazić za pomocą jednego wiersza kodu określanego jako wyrażenie regularne. Istnieją skuteczne schematy chatbotów w Pythonie, jak Will, które opierają się wyłącznie na tego rodzaju języku w celu wytworzenia użytecznego i ciekawego zachowania. Echo Amazona, Home Google’a i podobni do nich złożeni i użyteczni asystenci używają tego rodzaju języka do zakodowania zasad większości ich interakcji z użytkownikiem.

UWAGA Wyrażenia regularne zaimplementowane w aplikacjach Pythona i POSIX-a (Uniksa), jak grep, nie są prawdziwymi gramatykami regularnymi. Mają funkcje języka i logiki, jak podgląd w przód i wstecz, które umożliwiają wykonanie skoków i rekurencji, które nie są dozwolone w gramatyce regularnej. W wyniku tego wyrażenia regularne nie mają udowodnionego stopu. Mogą czasami „paść” lub działać w nieskończoność[41].

Być może mówicie sobie: „Słyszeliśmy o wyrażenia regularnych. Korzystamy z grep. Ale to dotyczy tylko wyszukiwania!”. I macie rację. Wyrażenia regularne, które potrafią znaleźć dopasowanie w obrębie tekstu, są też świetne przy prowadzeniu dialogów. Niektóre chatboty, jak Will, używają polecenia „search” do znajdowania w zdaniu użytkownika ciągów znaków, na które umieją odpowiedzieć. Te rozpoznane ciągi wyzwalają następnie odpowiedź w postaci odpowiedniego skryptu pasującego do tego konkretnego wyrażenia regularnego. I to samo wyrażenie regularne może być też wykorzystane do wyciągnięcia użytecznej części informacji z tego zdania. Chatbot może dodać ten kawałek informacji do swojej bazy wiedzy o użytkowniku lub o świecie, który użytkownik opisuje.

Maszynę, która przetwarza ten rodzaj języka, można traktować jako obiekt formalnej matematyki noszący nazwę automatu skończonego lub deterministycznego automatu skończonego (deterministic finite automaton, DFA). W książce wciąż powracają automaty skończone (FSM). Dlatego warto dobrze pojąć, do czego są one używane, bez przekopywania się przez ich teorię i całą matematykę. Dla osób, które nie mogą się oprzeć próbie zrozumienia czegoś więcej o tych narzędziach informatyki, na rysunku 1.1 jest pokazane miejsce FSM w zagnieżdżonym świecie automatów (botów). A pokazana dalej uwaga wyjaśnia pewne szczegóły formalne dotyczące sformalizowanych języków.

Rysunek 1.1. Rodzaje automatów

Formalne matematyczne objaśnienie języków sformalizowanych

Kyle Gorman tak opisuje języki programowania:

■ Większość z nich, jeśli nie wszystkie, pochodzą z klasy języków bezkontekstowych.

■ Języki bezkontekstowe są analizowane składniowo za pomocą bezkontekstowych gramatyk, które zapewniają wydajną analizę.

■ Języki regularne są także wydajnie analizowane składniowo i są powszechnie używane w przetwarzaniu dopasowywania łańcuchów.

■ Aplikacje związane z dopasowywaniem łańcuchów rzadko wymagają bezkontekstowej mocy ekspresyjnej.

■ Istnieje wiele klas języków sformalizowanych. Przytaczamy tu kilka z nich (z malejącą złożonością)a:

– wyliczane rekurencyjnie,

– kontekstowe,

– bezkontekstowe,

– regularne.

Języki naturalne mają następujące cechy:

■ nie są regularneb,

■ nie są bezkontekstowec,

■ nie mogą być zdefiniowane za pomocą jakiejkolwiek formalnej gramatykid.

a Patrz artykuł w Wikipedii „Chomsky hierarchy” (https://en.wikipedia.org/wiki/Chomsky_hierarchy).

b Shuly Wintner „English is not a regular language” (http://cs.haifa.ac.il/~shuly/teaching/08/nlp/complexity.pdf#page=20).

c Shuly Wintner „Is English context-free?” (http://cs.haifa.ac.il/~shuly/teaching/08/nlp/complexity.pdf#page=24).

d Patrz podrozdział 1.11, „Formal and Natural Languages”, w książce How to Think Like a Computer Scientist: Interactive Edition (https://runestone.academy/runestone/books/published/thinkcspy/GeneralIntro/FormalandNaturalLanguages.html).

1.4.3. Prosty chatbot

Zbudujmy szybki i prosty chatbot. Nie będzie miał dużych zdolności i będzie wymagał wiele myślenia na temat języka angielskiego. Będziecie musieli też zakodować na stałe wyrażenia regularne, tak aby pasowały do sposobu, w jaki ludzie próbują coś powiedzieć. Ale nie martwcie się, jeśli wyda wam się, że sami nie doszlibyście do takiego kodu w Pythonie. Nie trzeba próbować myśleć o różnych sposobach, na jakie ludzie mogą coś powiedzieć, jak robimy to w tym przykładzie. Nie będziecie nawet pisać wyrażeń regularnych (regeksów), aby zbudować wypasionego chatbota. Pokażemy, jak zbudować własny chatbot w dalszych rozdziałach bez kodowania czegokolwiek na stałe. Nowoczesny chatbot może uczyć się, czytając (przetwarzając) zestaw tekstów po angielsku. Pokażemy w dalszych rozdziałach, jak to robić.

Ten chatbot dopasowujący do wzorców jest przykładem chatbota będącego pod ścisłą kontrolą. Tego typu chatboty były powszechne, zanim opracowano nowoczesne techniki uczenia się chatbotów. Pokazana tu odmiana podejścia związanego z dopasowywaniem do wzorców jest używana w takich chatbotach jak Alexa Amazona i w innych wirtualnych asystentach.

Na razie utwórzmy FSM, wyrażenie regularne, które może mówić językiem zamków cyfrowych (językiem regularnym). Możemy zaprogramować je tak, aby rozumiał zdania w języku z blokadą, jak „01-02-03”. Lepiej będzie, jeśli zrozumie pozdrowienia w rodzaju „open sesame” (sezamie otwórz się) lub „hello Rosa” (cześć Rosa). Istotną cechą prospołecznego chatbota jest zdolność do odpowiedzi na pozdrowienie. W liceum nauczyciele często upominali mnie, że jestem niegrzeczny, ignorując tego rodzaju pozdrowienia, gdy śpieszyłem się na lekcje. Z pewnością nie chcemy, aby tak postępował nasz życzliwy chatbot.

W protokole komunikowania się maszyn zdefiniowalibyśmy prostą zasadę uzgadniania z sygnałem potwierdzenia (ACK) po każdym komunikacie przekazywanym tam i z powrotem między dwiema maszynami. Ale nasze maszyny będą prowadzić interakcję z ludźmi, którzy mówią takie zdania jak „Good morning, Rosa”. Nie chcemy wysyłania kolejnych cyknięć, sygnałów dźwiękowych ani komunikatów ACK, jak podczas synchronizacji modemu lub połączenia http na początku konwersacji, lub sesji przeglądarki internetowej. Zamiast tego użyjemy wyrażenia regularnego, aby rozpoznać kilka popularnych pozdrowień używanych przez ludzi na początku konwersacji:

>>> import re

W Pythonie mamy dwa „oficjalne” pakiety dla wyrażeń regularnych. Używamy tu pakietu re tylko dlatego, że jest on zainstalowany we wszystkich wersjach Pythona. Pakiet regex dostarczany jest z późniejszymi wersjami języka i ma znacznie większe możliwości, co zobaczycie w rozdziale 2.

>>> r = "(hi|hello|hey)[ ]*([a-z]*)"

Znak „|” oznacza „OR” (LUB), a symbole „\*”, że poprzedzające je znaki mogą pojawić się 0 lub więcej razy i nadal pasować do wzorca. Tak więc nasz regex będzie dopuszczał pozdrowienia zaczynające się od „hi”, „hello” lub „hey”, po których nastąpi dowolna liczba znaków spacji, a potem dowolna liczba liter.

>>> re.match(r, 'Hello Rosa', flags=re.IGNORECASE)

Ignorowanie wielkości liter w tekście jest często stosowane, aby wyrażenie regularne było prostsze.

<_sre.SRE_Match object; span=(0, 10), match='Hello Rosa'>

>>> re.match(r, "hi ho, hi ho, it's off to work ...", flags=re.IGNORECASE)

<_sre.SRE_Match object; span=(0, 5), match='hi ho'>

>>> re.match(r, "hey, what's up", flags=re.IGNORECASE)

<_sre.SRE_Match object; span=(0, 3), match='hey>

W wyrażeniach regularnych możecie w nawiasach kwadratowych oznaczyć klasę znaków. Możecie też użyć kreski (-), aby wskazać zakres znaków bez konieczności wpisywania ich wszystkich pojedynczo. Tak więc wyrażenie regularne postaci "[a–z]" będzie pasować do każdej małej litery, od „a” do „z”. Gwiazdka (*) po klasie znaków oznacza, że wyrażenie regularne będzie pasować do dowolnie długiego ciągu znaków, jeśli tylko znaki będą należeć do tej samej klasy znaków.

Przekształćmy nasze wyrażenie regularne w postać bardziej szczegółową, aby spróbować uzyskać zgodność z większą liczbą pozdrowień:

>>> r = r"[^a-z]*([y]o|[h']?ello|ok|hey|(good[ ])?(morn[gin']{0,3}|"\

...     r"afternoon|even[gin']{0,3}))[\s,;:]{1,3}([a-z]{1,20})"

>>> re_greeting = re.compile(r, flags=re.IGNORECASE)

Możecie tak skompilować wyrażenie regularne, abyście nie musieli podawać konkretnych opcji (flag) przy każdym ich użyciu.

>>> re_greeting.match('Hello Rosa')

<_sre.SRE_Match object; span=(0, 10), match='Hello Rosa'>

>>> re_greeting.match('Hello Rosa').groups() 

('Hello', None, None, 'Rosa')

>>> re_greeting.match("Good morning Rosa")

<_sre.SRE_Match object; span=(0, 17), match="Good morning Rosa">

>>> re_greeting.match("Good Manning Rosa")

Zauważcie, że to wyrażenie regularne nie może rozpoznać (match) słów z literówkami (nie będzie zgodności).

>>> re_greeting.match('Good evening Rosa Parks').groups()

Nasz chatbot może podzielić różne części pozdrowienia na grupy, ale nie będzie świadomy nazwiska Rosy, gdyż nie mamy wzorca dopasowania dla liter po imieniu.

('Good evening', 'Good ', 'evening', 'Rosa')

>>> re_greeting.match("Good Morn'n Rosa")

<_sre.SRE_Match object; span=(0, 16), match="Good Morn'n Rosa">

>>> re_greeting.match("yo Rosa")

<_sre.SRE_Match object; span=(0, 7), match='yo Rosa'>

WSKAZÓWKA Litera „r” przed cudzysłowem określa łańcuch czystotekstowy (raw string), a nie wyrażenie regularne. W Pythonie łańcuch czystotekstowy pozwala na wysłanie odwrotnych ukośników bezpośrednio do kompilatora wyrażenia regularnego, bez konieczności stosowania podwójnego odwrotnego ukośnika („\\”) przed specjalnymi znakami wyrażeń regularnych, jak spacje („\\ ”) i nawiasy klamrowe („\\{ \\}”)).

W pierwszym wierszu kodu zawarto wiele treści – wyrażenie regularne. Wykonuje ono swoje zadanie dla zaskakująco dużego zakresu pozdrowień. Ale nie uwzględni literówki „Manning”, co jest jednym z powodów trudności w przetwarzania języka naturalnego (NLP). W uczeniu się maszyn i testach diagnostycznych w medycynie określa się to jako błąd klasyfikacji fałszywie ujemny. Niestety wyrażenie będzie też pasować do niektórych zdań, których ludzie raczej nie wypowiedzą – przypadek fałszywie dodatni, który też nie jest dobry. Występowanie błędów fałszywie ujemnych i fałszywie dodatnich oznacza, że nasze wyrażenie regularne jest zarówno zbyt liberalne, jak i zbyt ścisłe. Błędy te mogą sprawić, że nasz bot będzie zbyt nudny i mechaniczny. Musielibyśmy włożyć znacznie większą pracę, aby udoskonalić nasze frazy, tak aby dopasowania bardziej przypominały konwersację ludzi.

Ta uciążliwa praca zapewne i tak nie zakończyłaby się powodzeniem uwzględniającym cały slang i błędy literowe ludzi. Na szczęście ręczne tworzenie wyrażeń regularnych nie jest jedynym sposobem szkolenia chatbota. Więcej na ten temat będzie dalej (to pozostała część książki). Więc używamy tego tylko wtedy, gdy chcemy mieć precyzyjną kontrolę nad zachowaniem chatbota, jak podczas wnioskowania poleceń dla asystenta głosowego w waszym telefonie komórkowym.

Przejdźmy jednak dalej i ukończmy naszego chatbota za pomocą sztuczki, dodając generator tekstu. Wszak chatbot musi coś mówić. Używamy narzędzia formatowania łańcucha w Pythonie, aby utworzyć „szablon” odpowiedzi naszego chatbota:

>>> my_names = set(['rosa', 'rose', 'chatty', 'chatbot', 'bot',

...     'chatterbot'])

>>> curt_names = set(['hal', 'you', 'u'])

>>> greeter_name = ''

Nie wiemy jeszcze, kto rozmawia z botem, i w tym miejscu się tym nie przejmujemy.

>>> match = re_greeting.match(input())

...

>>> if match:

...     at_name = match.groups()[-1]

...       if at_name in curt_names:

...           print("Good one.")

...       elif at_name.lower() in my_names:

...           print("Hi {}, How are you?".format(greeter_name))

Jeśli więc uruchomicie ten niewielki skrypt i porozmawiacie z naszym botem za pomocą frazy jak „Hello Rosa”, odpowie, pytając, jak minął dzień. Jeśli, zwracając się do chatbota, użyjemy nieco mniej grzecznego tekstu, zareaguje gorzej, ale nie będzie oburzony, próbując zachęcić do grzeczności[42]. Jeśli podacie imię kogoś, kto może monitorować konwersację na forum lub linii towarzyskiej, bot będzie siedział cicho i pozwoli wam i osobie, do której się zwracacie, na rozmowę. Oczywiście nie ma nikogo, kto by śledził naszą linię wejściową input(), ale jeśli byłaby to funkcja bardziej rozbudowanego chatbota, mielibyście do czynienia z tego rodzaju sytuacjami.

Z uwagi na ograniczenia zasobów komputerowych pionierzy badań nad NLP musieli korzystać z mocy obliczeniowej ludzkiego mózgu, aby zaprojektować i dostroić złożone reguły logiczne do wyciągnięcia informacji z łańcucha w języku naturalnym. Jest to określane jako regułowe podejście do NLP lub podejście oparte na wzorcach. Wzorce nie muszą być tylko wzorcami w postaci ciągu znaków, jak nasze wyrażenia regularne. NLP często obejmuje wzorce złożone z ciągów słów lub części mowy lub z innych wzorców „wyższego rzędu”. Podstawowe elementy składowe NLP jak stemmery (elementy identyfikujące rdzeń) i tokenizatory (komponenty dzielące ciągły tekst na segmenty – tokeny), a także zaawansowane kompleksowe silniki dialogowe (chatboty), jak ELIZA, zostały zbudowane w ten sposób, za pomocą wyrażeń regularnych i dopasowywania do wzorców. Sztuka podejścia polegającego na dopasowywaniu do wzorców w NLP wnosi eleganckie wzorce, które przechwytują tylko to, czego chcecie, bez zbyt wielu wierszy kodu wyrażeń regularnych.

KLASYCZNA OBLICZENIOWA TEORIA UMYSŁU To klasyczne podejście dopasowywania do wzorców w NLP jest oparte na obliczeniowej teorii umysłu (computational theory of mind, CTM). CTM zakłada, że NLP przypominające ludzi można uzyskać za pomocą skończonego zbioru reguł logicznych, które są kolejno przetwarzane[43]. Postępy w neuronauce i NLP doprowadziły na przełomie wieków do opracowania „koneksjonistycznej” teorii umysłu, która pozwala na potoki oparte na równoległym przetwarzaniu języka naturalnego, podobnie jak robi się to w sieciach neuronowych[44],[45].

Więcej na temat podejść opartych na wzorcach – jak stemmer Portera i tokenizator Treebank – dowiecie się w rozdziale 2. Ale w kolejnych rozdziałach wykorzystujemy nowoczesne zasoby obliczeniowe, a także nasze większe zbiory danych, aby skrócić te pracochłonne ręczne programowanie i ulepszanie.

Osoby, które nie znają wyrażeń regularnych i chciałyby dowiedzieć się o nich więcej, mogą znaleźć w dodatku B dokumentację online dotyczącą wyrażeń regularnych w Pythonie. Ale nie musicie tego wszystkiego w tym momencie rozumieć. Będziemy dostarczać wam przykłady wyrażeń regularnych w miarę wykorzystywania ich jako części składowych naszego potoku NLP. Nie martwcie się więc, jeśli wyglądają one nieco bełkotliwie. Ludzkie mózgi są dość dobre w uogólnieniach na podstawie zbioru przykładów i jestem pewien, że przed końcem książki wszystko stanie się jasne. A okazuje się, że w taki sam sposób mogą się uczyć maszyny.

1.4.4. Inny sposób

Czy jest podejście oparte na statystyce lub metodzie uczenia się maszyn, które mogłoby działać zamiast podejścia opartego na wzorcach? Czy gdybyśmy mieli dość danych, moglibyśmy zrobić coś innego? Co by było, gdybyśmy mieli ogromną bazę danych zawierającą całe sesje dialogowe między ludźmi, stwierdzenia i odpowiedzi dla tysięcy, a nawet milionów konwersacji? Jednym ze sposobów zbudowania chatbota byłoby wyszukanie w takiej bazie danych identycznego łańcucha znaków, jakiego użył użytkownik chatbota, „mówiąc” do niego. Czy nie można by użyć jednej z odpowiedzi na to stwierdzenie spośród tych, których w przeszłości użyli ludzie?

Ale wyobraźmy sobie, jak jedna literówka lub odmiana stwierdzenia mogłaby wywrócić naszego bota. Bit i ciąg znaków są dyskretne. Albo pasują do wzorca, albo nie. Zamiast tego chcielibyśmy, aby nasz bot potrafił ocenić różnicę w znaczeniu między ciągami znaków.

Gdy używamy dopasowania znak-po-znaku jako miary odległości między frazami w języku naturalnym, często wynik jest błędny. Frazy o podobnym znaczeniu, jak „good” i „okay” mogą często składać się z różnych ciągów znaków. I ciągi o całkiem różnym znaczeniu, jak „bad” i „bar”, mogą być zbyt do siebie zbliżone, jeśli miary są opracowane tak, aby mierzyć odległości ciągów liczbowych. Miary, takie jak odległości wektorowe Jaccarda, Levensteina i Euklidesa, mogą czasami dodawać dość „rozmycia”, aby zapobiec potykaniu się chatbota na niewielkich błędach pisowni lub literówkach. Ale miary te zawodzą, gdy chcemy uchwycić związek między dwoma różniącymi się ciągami znaków. I czasem zbliżają do siebie niewielkie różnice w pisowni, które nie muszą być literówkami, jak w przypadku „bad” i „bar”.

Miary odległości opracowane dla ciągów liczbowych i wektorów są użyteczne w niewielu aplikacjach NLP, takich jak korektory pisowni i rozpoznawanie nazw własnych. Dlatego używamy ich, gdy ma to sens. Ale w aplikacjach NLP, gdzie jesteśmy bardziej zainteresowani znaczeniem języków naturalnych, a nie pisownią, istnieją lepsze metody. Korzystamy z wektorowych reprezentacji słów i tekstów języka naturalnego oraz pewnych miar odległości dla wektorów w tych aplikacjach NLP. Pokazujemy każde podejście po kolei, w miarę omawiania tych różnych reprezentacji wektorowych i rodzajów aplikacji, do których są one stosowane.

Nie zostaniemy długo w tym mylącym binarnym świecie logiki, ale wyobraźmy sobie, że jesteśmy słynnym kryptoanalitykiem z czasów II wojny światowej, Mavisem Bateyem, pracującym w Bletchley Park, i właśnie otrzymaliśmy binarny komunikat w alfabecie Morsa, przechwycony z łączności między dwoma niemieckimi oficerami. Może on zawierać klucz do wygrania wojny. Od czego zaczniemy? Pierwszym krokiem naszej analizy będzie jakieś opracowanie statystyczne ciągu bitów, aby zobaczyć, czy możemy znaleźć wzorce. Możemy użyć najpierw tabeli alfabetu Morsa (lub w naszym przypadku tabeli ASCII), aby przypisać litery do każdej grupy bitów. Potem, jeśli znaki dają nam bełkot, jak to ma miejsce w kryptografii z czasów II wojny światowej, możemy zacząć zliczać je, szukając krótkich sekwencji w słowniku wszystkich słów, które widzieliśmy wcześniej, wstawiając znaczek obok każdej pojawiającej się pozycji. Możemy także zaznaczyć coś w innym rejestrze, aby pokazać, w którym komunikacie słowo się pojawiło, tworząc encyklopedyczny indeks wszystkich dokumentów, które wcześniej czytaliśmy. Ten zbiór dokumentów nazywany jest korpusem, a zbiór wykazanych w naszym indeksie słów lub zdań określamy jako leksykon.

Jeśli mamy szczęście i nie prowadzimy wojny, a nasze komunikaty nie są silnie zaszyfrowane, zobaczymy wzorce w tych licznikach niemieckich słów, odzwierciedlające liczbę słów angielskich użytych do przekazania podobnego typu komunikatów. W przeciwieństwie do kryptoanalityka próbującego odszyfrować przekazy niemieckie alfabetem Morsa wiemy, że symbole mają stałe znaczenie i nie są zmieniane przy każdym kliknięciu, aby wprowadzić nas w błąd. To uciążliwe zliczanie znaków i słów jest tym, co komputer może zrobić bez myślenia. I co zaskakujące, to niemal wystarcza do tego, aby wydawało się, że maszyny rozumieją nasz język. Może też być dopasowane dla tych statystycznych wektorów, które jest zbieżne z naszym ludzkim zrozumieniem tych fraz i słów. Gdy w dalszych rozdziałach pokażemy wam, jak nauczyć maszynę naszego języka za pomocą Word2Vec, może to wydać się magią, ale nią nie jest. To tylko matematyka i obliczenia.

Ale pomyślmy przez chwilę o tym, jakie informacje zostały zgubione przy naszych wysiłkach zliczania wszystkich słów w otrzymywanych komunikatach. Przypisujemy słowa do pojemników i zapisujemy je w bitowych wektorach jak sortowane monety lub żetony (oryg. tokeny), kierując różne rodzaje żetonów na jedną stronę lub na drugą w kaskadzie kolejnych decyzji, które przydzielają je do pojemników na dole. Nasz mechanizm sortujący musi brać pod uwagę setki tysięcy, jeśli nie miliony możliwych „wartości” żetonów, po jednym dla każdego możliwego słowa, którego mówca lub autor mógł użyć. Każda fraza lub zdanie, lub dokument, które wprowadzimy do naszego sortowania żetonów, wyjdzie na dole, gdzie mamy „wektor” z liczbą żetonów w każdej przegródce. Większość naszych liczników ma wartość zero, nawet w przypadku dużych dokumentów z rozbudowanym słownictwem. Ale nie utraciliśmy jeszcze żadnych słów. Co utraciliśmy? Czy jako ludzie możecie zrozumieć dokument, który zaprezentujemy wam w taki sposób, jako zliczenie każdego słowa, które może wystąpić w języku, bez żadnej kolejności ani ułożenia powiązanego z tymi słowami? Wątpię. Ale jeśli byłoby to krótkie zdanie lub tweet, potrafilibyście zapewne w większości przypadków przestawić słowa zgodnie z zamierzoną kolejnością i znaczeniem.

Oto jak nasz sortownik żetonów pasuje do potoku NLP w miejscu, gdzie kończy działanie narzędzie segmentacyjne (patrz tokenizator w rozdziale 2). Włączyliśmy do naszego szkicu mechanicznego sortownika filtr stoplisty, jak i filtr „rzadkich” słów[46]. Łańcuchy przepływają od góry, a wektory BoW (od ang. bag-of-words – dosł. worek słów, reprezentacje tekstu ignorujące kolejność słów) tworzone są od góry profilu, tworząc „stosy” żetonów u dołu.

Okazuje się, że maszyny mogą w ten sposób dość dobrze obsłużyć wektor BoW i zebrać większość zawartych tam informacji nawet z umiarkowanie długich dokumentów. Każdy dokument po posortowaniu i zliczeniu segmentów może być przedstawiony jako wektor, ciąg liczb całkowitych dla każdego słowa lub segmentu w dokumencie. Surowy przykład możecie zobaczyć na rysunku 1.2, a potem w rozdziale 2 pokażemy więcej użytecznych struktur danych dla wektorów BoW.

Rysunek 1.2. Miejsce sortowania tokenów

To nasz pierwszy model przestrzeni wektorowej języka. Te pojemniki i liczby w nich zawarte są reprezentowane dla każdego słowa jako długie wektory zawierające wiele zer i kilka jedynek lub dwójek rozrzuconych tam, gdzie wystąpiło słowo dla tego pojemnika. Zbiór różnych sposobów, na które mogą zostać połączone słowa, aby stworzyć te wektory, nosi nazwę przestrzeni wektorowej. Związki między wektorami w tej przestrzeni są tym, co składa się na nasz model, który jest próbą przewidywania kombinacji tych słów występujących w kolekcji różnych ciągów słów (zazwyczaj zdań lub dokumentów). W Pythonie możemy przedstawiać te rzadkie (w większości puste) wektory (listy liczb) jako słowniki. Counter w Pythonie to specjalny rodzaj słownika, który wkłada obiekty (w tym łańcuchy) do pojemników i zlicza je dokładnie tak, jak chcemy:

>>> from collections import Counter

>>> Counter("Guten Morgen Rosa".split())

Counter({'Guten': 1, 'Rosa': 1, 'morgen': 1})

>>> Counter("Good morning, Rosa!".split())

Counter({'Good': 1, 'Rosa!': 1, 'morning,': 1})

Możecie zapewne wyobrazić sobie sposoby czyszczenia tych słów. Robimy to w następnym rozdziale. Ale możecie też pomyśleć sobie, że te rzadkie, wielowymiarowe wektory (wiele pojemników, po jednym na każde możliwe słowo) nie są zbyt użyteczne w przetwarzaniu języka. Ale są wystarczająco dobre dla niektórych narzędzi powodujących zmianę w całych branżach, jak filtry spamu, które omawiamy w rozdziale 3.

Możemy sobie wyobrazić podanie tej maszynie po jednym wszystkich dokumentów, wyrażeń, zdań, a nawet pojedynczych słów, na które możemy trafić. Zliczylibyśmy te żetony w każdej przegródce u dołu po przetworzeniu każdego z tych elementów i nazwalibyśmy tę ich reprezentację wektorową. Wszystkie możliwe wektory, które w ten sposób może utworzyć maszyna, nazywa się przestrzenią wektorową. A ten model dokumentów i stwierdzeń oraz słów nazywany jest modelem przestrzeni wektorowej. Pozwala on nam na używanie algebry liniowej do wykonywania operacji na tych wektorach i obliczania takich rzeczy, jak odległości i statystyki dotyczące stwierdzeń w języku naturalnym, co pomaga nam w rozwiązaniu o wiele szerszego zakresu problemów przy mniejszym zakresie programowania przez ludzi i mniejszą powierzchownością potoku NLP.

Statystyczne pytanie zadawane na temat ciągów wektorów BoW brzmi „Jaki ciąg słów najbardziej odpowiada wskazanemu wektorowi słów?”. Lub nawet lepiej, jeśli użytkownik wprowadza ciąg słów: „Który wektor BoW w naszej bazie danych jest najbliższy wektorowi BoW dostarczonemu przez użytkownika?”. Jest to zapytanie wyszukiwania. Słowa na wejściu są słowami, które moglibyśmy wpisać w polu wyszukiwania, a najbliższy wektor BoW odpowiada dokumentowi lub stronie internetowej, których szukacie. Zdolność do skutecznej odpowiedzi na te dwa pytania wystarczy, aby zbudować uczącego się chatbota, który będzie się stawał coraz lepszy, gdy będziemy mu podawać coraz więcej danych.

Zaczekajcie jednak chwilę, bo być może te wektory nie są podobne do czegokolwiek, nad czym pracowaliście do tej pory. Mają wyjątkowo wiele wymiarów. Możliwe, że mają miliony wymiarów dla trigramowego modelu słownictwa wyznaczonego z dużego korpusu. W rozdziale 3 omawiamy przekleństwo wymiarowości i kilka innych cech, które sprawiają, że trudno pracuje się z wektorami o bardzo wielu wymiarach.

1.5. Krótkie spojrzenie na hiperprzestrzeń

W rozdziale 3 pokażemy, jak skonsolidować słowa w mniejszej liczbie wymiarów wektora, aby pomóc w ograniczeniu przekleństwa wymiarowości i być może zmienić je w zaletę. Gdy rzutujemy te wektory na siebie, aby określić odległość między parami wektorów, uzyskamy rozsądne oszacowanie podobieństwa ich znaczenia, zamiast prostego statystycznego użycia słów. Ta miara odległości jest nazywana cosinusową metryką odległości. Omówimy ją w rozdziale 3, a potem pokażemy jej prawdziwą moc na wektorach tematów o zredukowanej wymiarowości w rozdziale 4. Możemy nawet rzutować (bardziej precyzyjnym terminem jest „zanurzyć”) te wektory na płaszczyznę 2D, aby „spojrzeć” na nie na wykresach i diagramach oraz ustalić, czy ludzki umysł może znaleźć wzorce. Możemy potem nauczyć komputer rozpoznawania tych wzorców i działania na nich na sposoby odzwierciedlające ukryte znaczenie słów tworzących te wektory.

Wyobraźcie sobie wszystkie możliwe tweety lub komunikaty, lub zdania pisane przez ludzi. Chociaż wiele razy się powtarzamy i tak istnieje wiele możliwości. A gdy te tokeny są traktowane jako oddzielne, różne wymiary, nie ma żadnego sensu mówić, że „Good morning Hobbs” ma jakieś wspólne znaczenie z „Guten Morgen, Hannes”. Musimy utworzyć jakiś model przestrzeni wektorowej komunikatów o zmniejszonych wymiarach, abyśmy mogli je oznaczyć za pomocą zbioru ciągłych (zmiennoprzecinkowych) wartości. Moglibyśmy ocenić komunikaty i słowa pod kątem cech takich jak temat i wydźwięk. Moglibyśmy zadać pytania:

■ Czy jest możliwe, że komunikat jest pytaniem?

■ Na ile dotyczy on osoby?

■ W jakim stopniu dotyczy on mnie?

■ W jakim stopniu ma on wydźwięk złości lub radości?

■ Czy jest to coś, co wymaga odpowiedzi?

Pomyślcie o wszystkich ocenach, które możemy przyznać zdaniom. Moglibyśmy uporządkować te oceny i „wyliczyć” je dla każdego zdania, aby skompilować „wektor” dla każdego z nich. Lista ocen lub wymiarów, które możecie nadać zbiorowi zdań, powinna być znacznie mniejsza niż liczba możliwych zdań. A zdania, które znaczą to samo, powinny mieć podobne wartości dla wszystkich naszych pytań.

Te wektory ocen stają się czymś, na co możemy zaprogramować reakcję maszyny. Możemy jeszcze bardziej uprościć i uogólnić wektory, zbijając ze sobą zdania (tworząc klastry). Sprawiając, że będą bliższe jednym wymiarom, a dalsze innym.

Ale jak komputer może przypisać wartości dla każdego z wymiarów tych wektorów? Cóż, upraszczamy pytania o wymiar naszego wektora do takich rzeczy jak: „Czy zawiera on słowo ‘good’?”, „Czy zawiera on słowo ‘morning’?” i tak dalej. Możecie zobaczyć, że możemy być w stanie dojść do około miliona pytań, których wynikiem są wartości liczbowe, które komputer może przypisać do frazy. Jest to pierwszy praktyczny model przestrzeni wektorowej, który jest nazywany bitowym wektorowym modelem języka lub sumą wektorów zakodowanych jako 1 z n (one-hot). Widać, dlaczego komputery dopiero teraz stają się dość silne, aby analizować język naturalny. Milionów wektorów o milionach wymiarów, które ludzie mogą wygenerować, po prostu „nie da się policzyć” na superkomputerach z lat 80., ale nie ma z tym problemu na zwykłym laptopie w XXI wieku. NLP stało się praktyką nie tylko z powodu czystej mocy i pojemności sprzętu. Przyrostowe algorytmy algebry liniowej o stałej złożoności pamięciowej to ostatni element układanki, który pozwolił maszynom na złamanie kodu języka naturalnego.

Istnieje jeszcze prostsza, ale znacznie większa reprezentacja, której można użyć w chatbocie. Co będzie, jeśli nasze wymiary wektora będą w pełni opisywały dokładną kolejność znaków. Obejmowałoby to odpowiedź na takie pytania, jak „Czy pierwszą literą jest A? Czy jest to B? … Czy drugą literą jest A?” i tak dalej. Ten wektor ma tę zaletę, że gromadzi on wszystkie informacje zawarte w oryginalnym tekście, w tym kolejność znaków i słów. Wyobraźmy sobie pianistę, który mógłby grać tylko po jednej nucie i miał do zagrania 52 lub więcej możliwych nut. Dla tego mechanicznego pianina języka naturalnego „nuty” to 26 małych i 26 wielkich liter plus znaki przestankowe, które pianola musi umieć „zagrać”. Rolka papieru nie musiałaby być szersza niż w prawdziwej pianoli, a liczba nut w niektórych długich piosenkach nie przekracza liczby znaków w niewielkim dokumencie. Ale ta reprezentacja w postaci ciągu znaków 1 z n jest użyteczna przede wszystkim do rejestrowania i ponownego odtwarzania dokładnego fragmentu, zamiast skomponowania czegoś nowego lub wydobycia sensu fragmentu. Nie możemy łatwo porównać papierowej rolki w pianoli dla jednej piosenki z tą dla innej. A reprezentacja ta jest dłuższa niż oryginalna reprezentacja dokumentu zakodowana w kodzie ASCII. Liczba możliwych reprezentacji dokumentów właśnie gwałtowanie wzrosła, aby zachować informacje o każdym ciągu znaków. Zachowaliśmy kolejność znaków i słów, ale rozszerzyliśmy wymiarowość naszego problemu NLP.

Te reprezentacje dokumentów nie łączą się dobrze w tym świece wektorów opartych na znakach. Rosyjski matematyk, Władimir Levenshtein, wymyślił błyskotliwe podejście do szybkiego wyszukiwania w tym świecie podobieństw między ciągami (łańcuchami znaków). Algorytm Leveshteina umożliwił utworzenie zaskakująco przyjemnych i użytecznych chatbotów z wykorzystaniem tylko tego uproszczonego, mechanicznego spojrzenia na język. Ale prawdziwa magia pojawiła się, gdy udało się dojść do tego, jak skompresować/zanurzyć te przestrzenie o większej liczbie wymiarów w przestrzeni o mniejszej liczbie wymiarów z rozmytymi wektorami znaczenia lub tematu. Zaglądamy za tę magiczną kurtynę w rozdziale 4, gdy mówimy o analizie utajonych własności semantycznych (LSA) i ukrytej alokacji Dirichleta – dwóch technikach tworzenia znacznie gęstszej i bardziej znaczącej wektorowej reprezentacji zdań i dokumentów.

1.6. Kolejność słów i gramatyka

Kolejność słów ma znaczenie. Reguły, które zarządzają kolejnością w ciągu słów (jak zdanie), są nazywane gramatyką języka. Jest to coś, co odrzucał we wcześniejszych przykładach nasz wektor BoW lub wektor słów. Na szczęście w większości krótkich fraz, a nawet w pełnych zdaniach, przybliżenie wektora słów działa dobre. Jeśli chcecie jedynie zakodować ogólny sens i wydźwięk krótkiego zdania, kolejność słów nie jest aż tak ważna. Popatrzcie na wszystkie permutacje w naszym przykładzie „Good morning, Rosa”:

>>> from itertools import permutations

>>> [" ".join(combo) for combo in\

... permutations("Good morning Rosa!".split(), 3)]

['Good morning Rosa!',

 'Good Rosa! morning',

 'morning Good Rosa!',

 'morning Rosa! Good',

 'Rosa! Good morning',

 'Rosa! morning Good']

Gdybyście spróbowali zinterpretować oddzielnie każdy z tych łańcuchów (bez patrzenia na pozostałe), doszlibyście zapewne do wniosku, że wszystkie one mają podobną intencję, czyli znaczenie. Moglibyście nawet zauważyć, że słowo „Good” jest pisane z wielkiej litery i umieścić je na początku tworzonej w umyśle frazy. Ale moglibyście też pomyśleć, że „Good Rosa” jest pewnego rodzaju nazwą własną, jak nazwa restauracji lub kwiaciarni. Nie mniej sprytny chatbot lub sprytna kobieta w latach czterdziestych XX wieku w Benchley Park odpowiedzieliby na każdą z tych sześciu permutacji za pomocą tego samego nieszkodliwego pozdrowienia „Good morning, my dear General”.

Wypróbujmy to teraz (w głowach) na znacznie dłuższej frazie, zdaniu logicznym, w którym kolejność słów ma duże znaczenie:

>>> s = """Find textbooks with titles containing 'NLP',

...     or 'natural' and 'language', or

...     'computational' and 'linguistics'."""

>>> len(set(s.split())) 

12

>>> import numpy as np

>>> np.arange(1, 12 + 1).prod() # factorial(12) = arange(1, 13).prod()

479001600

Liczba permutacji gwałtownie wzrosła z wartości factorial(3) == 6 w naszym prostym pozdrowieniu do factorial(12) == 479001600 w naszym dłuższym zdaniu! Jest jasne, że logika wynikająca z kolejności słów jest ważna dla każdej maszyny, która chciałaby poprawnie odpowiedzieć. Mimo że popularne pozdrowienia nie są zwykle przekręcane przy przetwarzaniu za pomocą wektora BoW, bardziej skomplikowane zdania mogą utracić większość swego znaczenia, gdy zostaną wrzucone do „worka”. Wektor BoW nie jest najlepszym sposobem, aby rozpocząć przetwarzanie zapytania w bazie danych, jak zapytanie języka naturalnego w powyższym przykładzie.

Niezależnie od tego, czy zdanie jest napisane w formalnym języku programowania jak SQL, czy w nieformalnym języku naturalnym jak angielski, kolejność słów i gramatyka są ważne, gdy zdanie ma przekazywać logiczne związki między rzeczami. Dlatego języki komputerowe polegają na rygorystycznej analizie gramatyki i składni. Na szczęście ostatnie postępy w analizatorach drzew składniowych języka naturalnego umożliwiły wyodrębnianie syntaktycznych i logicznych związków języka naturalnego z niezwykłą dokładnością (przekraczającą 90%)[47]. W kolejnych rozdziałach pokazujemy, jak korzystać z pakietów SyntaxNet (Parsey McParseface) i SpaCy do identyfikacji tych związków.

Podobnie jak w przykładzie z pozdrowieniem z Benchley Park, jeśli nawet logiczna interpretacja zdania nie opiera się na kolejności słów, czasami zwrócenie uwagi na kolejność słów może dać subtelne wskazówki znaczeniowe, które mogą ułatwić głębsze odpowiedzi. Te głębsze warstwy przetwarzania języka naturalnego są omawiane w kolejnym punkcie. A w rozdziale 2 pokażemy sztuczkę z włączeniem niektórych informacji przekazanych przez kolejność słów w naszą reprezentację wektora słów. Opiszemy też, jak ulepszyć surowy tokenizator użyty w poprzednich przykładach (str.split()), aby do dokładniej umieszczać słowa w pojemnikach, w bardziej odpowiednich przegródkach w wektorze słów, aby łańcuchy jak „good” i „Good” były przypisane do tego samego pojemnika, a oddzielne pojemniki były przypisane tokenom jak „rosa”, „Rosa”, ale nie „Rosa!”.

1.7. Potok języka naturalnego chatbota

Potok NLP wymagany, aby zbudować agenta dialogowego, czyli chatbota, jest podobny do potoku potrzebnego do zbudowania systemu odpowiadającego na pytania, opisanego w książce Taming text (Ingersol, Morton i Farris, 2013)[48]. Jednak niektóre algorytmy podane w pięciu blokach podsystemów mogą być dla was nowością. Pomożemy w ich implementacji w Pythonie, aby zrealizować różne zadania NLP niezbędne dla większości aplikacji, w tym dla chatbotów.

Chatbot wymaga czterech rodzajów przetwarzania, a także bazy danych do pamiętania poprzednich zdań i odpowiedzi. Każdy z czterech etapów przetwarzania może zawierać jeden lub więcej algorytmów działających równolegle lub sekwencyjnie (patrz rys. 1.3):

Rysunek 1.3. Potok przetwarzania chatbota (z rekurencją)

1 reprezentacja tekstu – ekstrakcja cech, strukturalnych danych liczbowych, z tekstu w języku naturalnym;

2 analiza – generowanie i łączenie cech za pomocą oceny tekstu ze względu na wydźwięk, gramatykę i semantykę;

3 generacja/synteza – skomponowanie możliwych odpowiedzi z wykorzystaniem wzorców, wyszukiwania i modeli języka;

4 wykonanie – planowanie zdań na podstawie historii i celów konwersacji i wybór kolejnej odpowiedzi.

Każdy z tych czterech etapów może być zaimplementowany za pomocą jednego lub więcej algorytmów podanych w odpowiednich ramkach schematu blokowego. Pokazujemy wam, jak użyć Pythona do uzyskania działania bliskiego współczesnym rozwiązaniom dla każdego etapu przetwarzania. Pokazujemy też kilka alternatywnych podejść do implementacji tych pięciu podsystemów.

Większość chatbotów będzie zawierać elementy wszystkich pięciu podsystemów (czterech etapów przetwarzania oraz bazę danych). Ale wiele aplikacji wymaga tylko prostych algorytmów w wielu z tych kroków. Niektóre chatboty lepiej sprawdzają się, odpowiadając na pytania dotyczące faktów, a inne są lepsze w generowaniu długich złożonych i przekonująco ludzkich odpowiedzi. Każda z tych zdolności wymaga innego podejścia. Pokazujemy wam techniki dla obu typów.

Ponadto deep learning i programowanie oparte na danych (uczenie się maszyn lub probabilistyczne modelowanie języka) gwałtownie zróżnicowały możliwe zastosowania NLP i chatbotów. To podejście oparte na danych pozwala na jeszcze większe zaawansowanie potoku NLP dzięki zapewnieniu mu coraz większej ilości danych z dziedziny, w której chcecie je zastosować. A gdy zostanie odkryte nowe podejście w uczeniu się maszyn, które jeszcze lepiej wykorzysta te dane, z bardziej wydajnym uogólnieniem modelu lub regularyzacją, możliwe będą duże postępy w zakresie możliwości.

Potok NLP dla chatbota pokazany na rysunku 1.3 zawiera wszystkie elementy składowe większości zastosowań NLP, które opisaliśmy na początku tego rozdziału. Podobnie jak w Taming Text dzielimy nasz potok na cztery główne podsystemy, czyli etapy. Ponadto jawnie pokazaliśmy bazę danych w celu rejestrowania danych potrzebnych w każdym z tych etapów i zapisania ich konfiguracji i danych treningowych. Może to umożliwić ponowne szkolenie z wykorzystaniem paczek zapisanych danych treningowych lub online dla każdego etapu, w miarę jak chatbot wchodzi w interakcję ze światem. Pokazaliśmy też w odpowiedziach naszego wygenerowanego tekstu „pętlę sprzężenia zwrotnego”, tak aby nasze odpowiedzi mogły być przetwarzane za pomocą tych samych algorytmów, które są używane do przetwarzania zdań użytkowników. „Oceny” lub cechy odpowiedzi mogą zostać następnie połączone w funkcji celu, aby obliczyć i wybrać najlepszą możliwą odpowiedź, zależnie od planu lub celu chatbota w dialogu. W książce tej skupiamy się na konfigurowaniu tego potoku NLP dla chatbota, ale możecie też dostrzec analogię do problemu znajdowania tekstu w NLP lub w „wyszukiwaniu”, zapewne najczęstszym zastosowaniu NLP. A nasz potok chatbota jest z pewnością odpowiedni dla aplikacji odpowiadających na pytania, które są podstawowym tematem Taming Text.

Zastosowanie tego potoku do prognoz finansowych lub analizy biznesowej może nie być zbyt oczywiste. Ale wyobraźcie sobie funkcje generowane przez analityczną część waszego potoku. Te funkcje waszej analizy, czyli generowanej funkcji, można zoptymalizować dla konkretnej prognozy finansowej lub biznesowej. W ten sposób mogą one wam pomóc włączyć dane języka naturalnego do potoku opartego na uczeniu się maszyn dla celów prognozowania. Mimo skupienia się na tworzeniu chatbota książka ta daje wam narzędzia potrzebne w szerokim zakresie zastosowań NLP, od wyszukiwania po prognozy finansowe.

Elementem przetwarzania z rysunku 1.3, który nie jest zwykle zaangażowany w systemy wyszukiwania, prognoz lub udzielania odpowiedzi, jest generowanie języka naturalnego. Dla chatbotów to podstawowa funkcja. Niemniej jednak krok generowania tekstu jest często włączany do zastosowań wyszukiwarki NLP i może nadać mu dużą przewagę względem konkurencji. Zdolność do konsolidowania lub streszczania wyników wyszukiwania to wiodąca funkcja w wielu popularnych wyszukiwarkach (DuckDuckGo, Bing i Google). I możecie sobie wyobrazić, jak cenna dla mechanizmu prognoz finansowych jest możliwość generowania zdań, tweetów lub całych artykułów na podstawie zdarzeń z dziedziny biznesu wykrywanych w strumieniach języka naturalnego pochodzących z mediów społecznościowych i wiadomości.

W następnym podrozdziale pokazujemy, jak warstwy takiego systemu mogą zostać połączone, tak aby utworzyć większe wyrafinowanie i możliwości w każdym etapie potoku NLP.

Przypisy

[1] Ponaciskajcie kilka razy na smartfonie środkowy przycisk propozycji (https://www.reddit.com/r/ftm/comments/2zkwrs/middle_button_game/), aby dowiedzieć się, jak Google przewiduje to, co chcemy powiedzieć. Zostało to po raz pierwszy przedstawione w roku 2013 na Reddit jako gra „SwiftKey game” (https://blog.swiftkey.com/swiftkey-game-winning-is/).

[2] Patrz strona internetowa Petera Norviga „How to write a spelling corrector” (http://www.norvig.com/spellcorrect.html).

[3] Kto docenia znaczenie swobodnego dostępu do książek w języku naturalnym, może być na bieżąco z międzynarodowymi staraniami o rozszerzenie praw autorskich znacznie poza określenie „wykorzystaj do”, zaglądając na strony: gutenberg.org (http://www.gutenberg.org) oraz gutenbergnews.org (http://www.gutenbergnews.org/20150208/copyrightterm-extensions-are-looming:)

[4] Oznacza to, że Word2Vec nie wymaga czasochłonnego i nieusuwalnie subiektywnego procesu wymyślania kolejnych zmiennych charakteryzujących słowa oraz przypisywania wartości tym zmiennym tak, by w sposób zrozumiały dla komputera reprezentować znaczenie tych słów (przyp. kons. meryt.).

[5] Wypuszczenie w marcu 2016 przez Microsoft chatbota Tay skończyło się dużym skandalem. Bot uczył się na bieżąco od rozmawiających z nim użytkowników, co łatwo wykorzystali trolle, by w ciągu godzin uczynić z Tay propagatorkę najbardziej prowokujących treści (przyp. kons. meryt.).

[6] Patrz strona internetowa Inc: „Why Banjo is the most important social media company you’ve never heard of” (https://www.inc.com/magazine/201504/will-bourne/banjo-the-gods-eye-view.html).

[7] Dane w języku naturalnym nie mają jawnej, zrozumiałej dla komputera struktury. Dopiero za pomocą narzędzi NLP można taką strukturę wydobyć, by komputery były w stanie je przetwarzać (przyp. kons. meryt).

[8] https://www.inc.com/magazine/201504/will-bourne/banjo-the-gods-eye-view.html.

[9] Raport finansowy złożony przez Tweetera w 2014 roku ujawnił, że ponad 8% tweetów utworzonych przez boty, a w roku 2015 DARPA ogłosiła konkurs (https://arxiv.org/ftp/arxiv/papers/1601/1601.05140.pdf) mający na celu wykryć je i zmniejszyć ich wpływ na społeczeństwo w USA.

[10] Podkast Five Thirty Eight (http://fivethirtyeight.com/features/some-like-it-bot/).

[11] NLP jest z powodzeniem używane, aby pomóc w badaniu charakterystyki ilościowej stylu szesnastowiecznych pisarzy takich jak Szekspir (https://pdfs.semanticscholar.org/3973/ff27eb173412ce532c8684b950f4cd9b0dc8.pdf).

[12] Zapytanie na temat NLP w Duck Duck Go (https://duckduckgo.com/?q=Why+is+natural+language+processing+so+important+right+now:).

[13] Patrz artykuł w Wikipedii „Natural language processing” (https://en.wikipedia.org/wiki/Natural_language_processingWikipedia/NLP).

[14] To znaczy inteligencją ogólnego zastosowania. Jak dotąd tworzyliśmy „sztuczną inteligencję” dedykowaną, zdolną (często bardziej od ludzi) do wykonywania konkretnych działań, np. planowania trasy podróży lub gry w szachy. Nie dysponujemy jednak systemem, który byłby w stanie wypełniać te wszystkie zadania w pojedynkę (przyp. kons. meryt.).

[15] Steven Pinker, The Stuff of Thought (https://en.wikipedia.org/wiki/The_Stuff_of_Thought).

[16] Patrz artykuł w magazynie Wired „We are entering the era of the brain machine interface” (https://backchannel.com/we-are-entering-the-era-of-the-brain-machine-interface-75a3a1a37fd3).

[17] Patrz artykuł w Wikipedii „Linguistic relativity” https://en.wikipedia.org/wiki/Linguistic _relativity).

[18] Patrz artykuł w Wikipedii: „AI Control Problem” ( https://en.wikipedia.org/wiki/AI_control_problem)

[19] Nick Bostrom, strona domowa (http://nickbostrom.com/).

[20] Calum Chace, Surviving AI (https://www.singularityweblog.com/calum-chace-on-surviving-ai/).

[21] Patrz artykuł E. Mack (2015), „Why Elon Musk spent $10 million to keep artificial intelligence friendly”, Forbes (http://www.forbes.com/sites/ericmack/2015/01/15/elon-musk-puts-down-10-million-to-fight-skynet/#17f7ee7b4bd0).

[22] D. Haraway, Cyborg Manifesto (https://en.wikipedia.org/wiki/A_Cyborg_Manifesto).

[23] Patrz artykuł w Wikipedii na temat 1984 George’a Orwella (https://en.wikipedia.org/wiki/Nineteen_Eighty-Four).

[24] Patrz artykuł w Wikipedii „1984” (https://en.wikipedia.org/wiki/1984).

[25] Podstawowym narzędziem chatbota jest naśladowanie ludzi, z którymi rozmawia. Więc uczestnicy dialogu mogą wykorzystywać ten wpływ, aby zrodzić w botach zarówno zachowania prospołeczne, jak i antyspołeczne. Patrz artykuł w Tech Republic, „Why Microsoft’s Tay AI bot went wrong” (http://www.techrepublic.com/article/why-microsofts-tay-ai-bot-went-wrong).

[26] Przykład autonomicznych maszyn „infekujących” ludzi przez swoje zamierzone zachowanie można znaleźć w badaniach nad wpływem, jaki autonomiczne samochody mogą mieć na ruch w godzinach szczytu (https://www.enotrans.org/wp-content/uploads/AV-paper.pdf). W niektórych badaniach zaledwie 1 taki samochód na 10 samochodów znajdujących się w pobliżu nas na autostradzie pomoże w moderowaniu ludzkich zachowań, zmniejszając korki i powodując bardziej płynny, bezpieczniejszy ruch.

[27] Książka Toby’ego Seragana, Programming Collective Intelligence, rozpoczęła w 2010 r. moją przygodę z uczeniem się maszyn (https://www.goodreads.com/book/show/1741472.Programming_Collective_Intelligence).

[28] Ethnologue to sieciowa publikacja, która zawiera statystyki dotyczące języków naturalnych.

[29] Patrz strona internetowa pod tytułem „Jak wyszukiwarka porządkuje informacje” (https://www.google.com/search/howsearchworks/crawling-indexing/).

[30] Można szacować, że liczba obecnych tekstów w języku naturalnym w sieci jest co najmniej 1000 razy większa niż indeks Google’a.

[31] Zapis matematyczny jest dwuznaczny. Patrz dział „Mathematical notation” w artykule w Wikipedii „Ambiguity” (https://en.wikipedia.org/wiki/Ambiguity#Mathematical_notation).

[32] Gonzalo-Ibanez i in. w swoim artykule opublikowanym w ATM doszli do wniosku, że wykształcony i przeszkolony człowiek nie może dorównać wydajności ich prostego algorytmu klasyfikacji w 69%. Wykrywacz sarkazmu (https://github.com/MathieuCliche/Sarcasm_detector) i aplikacja sieciowa przedstawiona przez Matthew Cliche w Cornell ((http://www.thesarcasmdetector.com/) uzyskuje podobną dokładność (ponad 70%).

[33] Przetwarzanie języka naturalnego ma wbrew pozorom długą historię. Pierwsze próby w pełni automatycznego tłumaczenia sięgają połowy lat 50. XX w. Jednak podejścia te były skupione wokół idei formalizacji języka, deterministycznych algorytmów i zbiorów reguł. Współczesna „rewolucja” w NLP wywodzi się od rozpowszechnienia technik uczenia się maszyn i pracy z dużymi zbiorami danych. Należy jednak pamiętać, że w niektórych problemach podejścia „starej szkoły” mogą okazać się bardziej efektywne (przyp. kons. meryt).

[34] Niektóre reguły gramatyki można implementować w abstrakcji informatycznej nazywanej automatem skończonym. Gramatykę regularną można implementować w wyrażeniach regularnych. Istnieją dwa pakiety Pythona do uruchamiania automatów skończonych dla wyrażeń regularnych. Są to: re, który jest wbudowany, i regex, który trzeba zainstalować, ale wkrótce może zastąpić re. Automaty skończone są to drzewa złożone z instrukcji if … then … else dla każdego elementu ciągu (znaku/słowa/n-gramu) lub działania, na które automat musi zareagować lub je wygenerować.

[35] „Roboty-dziennikarze” z AP piszą teraz własne historie: „AP’s 'robot journalists' are writing their own stories now”, The Verge, 29 stycznia, 2015 (http://www.theverge.com/2015/1/29/7939067/ap-journalism-automation-robots-financial-reporting).

[36] New York Times, 18 października 2016 (https://www.nytimes.com/2016/11/18/technology/automated-pro-trumpbots-overwhelmed-pro-clinton-messages-researchers-say.html) oraz MIT Technology Review, listopad 2016 (https://www.technologyreview.com/s/602817/how-the-bot-y-politic-influenced-this-election/).

[37] Google Blog z maja 2018 na temat ich systemu Duplex (https://ai.googleblog.com/2018/05/advances-in-semantictextual-similarity.html).

[38] Patrz artykuł w Wikipedii „AI control problem” (https://en.wikipedia.org/wiki/AI_control_problem).

[39] Blog WSJ z 10 marca 2017 (https://blogs.wsj.com/cio/2017/03/10/homo-deus-author-yuval-noah-harari-saysauthority-shifting-from-people-to-ai/).

[40] Jedna z sześciu zasad psychologii Cialdiniego zawartych w jego znanej książce Influence (http://changingminds.org/techniques/general/cialdini/click-whirr.htm).

[41] Giełda przestała działać na 30 minut 20 lipca 2016 r., gdy „padł” regex (http://stackstatus.net/post/147710624694/outage-postmortem-july-20-2016).

[42] Pomysł takiej rozbrajającej odpowiedzi został wprowadzony w pracy Viktora Frankla, Man’s Search for Meaning, jego logoteurapeutycznym (https://en.wikipedia.org/wiki/Logotherapy) podejściu do psychologii i wielu popularnych powieści, gdzie dziecięcy protagonista, jak Owen Meany, ma mądrość pozwalającą odpowiadać na obelgi w taki sposób.

[43] Stanford Encyclopedia of Philosophy, Computational Theory of Mind (https://plato.stanford.edu/entries/computational-mind/).

[44] Stanford Encyclopedia of Philosophy, Connectionism, https://plato.stanford.edu/entries/connectionism/.

[45] M.H. Christiansen i N. Chater (1999), „Connectionist Natural LanguageProcessing: The state of the art.”, Cognitive Science, 23(4): 417–437 (https://crl.ucsd.edu/~elman/Bulgaria/christiansen-chater-soa.pdf).

[46] W NLP często w trakcie przetwarzania dokumentu odrzuca się słowa bardzo rzadkie oraz bardzo częste (stopwords), które i tak pojawią się w każdym dokumencie (te ostatnie zbiera się w wykazie zwanym stoplistą (przyp. kons. meryt).

[47] Porównanie dokładności analizy składniowej SpaCy (93%), SyntaxNet (94%), Stanford’s CoreNLP (90%) i innych jest dostępne na witrynie https://spacy.io/docs/api/.

[48] G.S. Ingersoll, T.S. Morton i A.L. Farris (2013), Taming text (https://www.manning.com/books/taming-text).