Augmentacja danych w przetwarzaniu języka naturalnego

06.12.2024 | Przemysław Solecki

Z artykułu dowiesz się

  • Czym jest augmentacja danych i dlaczego warto ją stosować w analizie tekstu
  • Poznasz szerokie spectrum technik augmentacji tekstu od najprostszych opartych o podstawowe przekształcenia tekstu do zaawansowanych metod bazujących na GenAI
  • Zrozumiesz zalety i ograniczenia poszczególnych metod generowania przypadków uczących
  • Zapoznasz się z przykładowymi implementacjami opisywanych metod

Wstęp

Analiza tekstu wymaga ogromnych ilości danych. Bogactwo słownictwa, ilość możliwych rozwiązań składniowych, neologizmy, błędy – w rezultacie możliwości wyrażania tej samej treści na różne sposoby są praktycznie nieograniczone. Z drugiej strony modele posiadają miliony parametrów, dzięki którym są w stanie zrozumieć język naturalny. To, co jest ich zaletą, staje się jednak wadą, gdy nie jesteśmy w stanie dostarczyć wystarczająco bogatego zbioru treningowego. Na zbyt małym i jednorodnym zbiorze modele językowe bardzo szybko się przeuczają, a wręcz uczą się zbioru na pamięć! W konsekwencji nie potrafią prawidłowo zidentyfikować wzorców występujących w zbiorze uczącym, a następnie uogólnić je na zbiór testowy na satysfakcjonującym poziomie.

Przygotowanie danych tekstowych wraz z etykietami do zadań klasyfikacji, wyszukiwania, generowania podsumowań czy Q&A wymaga dużych nakładów czasu. Co więcej, ponieważ jest to proces wyjątkowo żmudny, manualne przygotowanie przez człowieka tysięcy przykładów często prowadzi do spadku ich jakości. Przyjrzyjmy się, w jaki sposób możemy zautomatyzować ten proces.

Czym jest augmentacja danych

Augmentacja danych to dosłownie proces ich „powiększania”. Jest to technika polegająca na dostarczeniu do zbioru treningowego wygenerowanych, syntetycznych przypadków w celu redukcji zjawiska przetrenowania modelu oraz zwiększenia jego umiejętności uogólniania [1]. Temat ten jest doskonale rozpoznany w obszarze Computer Vision, gdzie wzbogacenie treningowego zbioru obrazów następuje poprzez proste, mechanicznie przekształcenia, takie jak: obracanie, zmiana kadrowania, kolorystyki czy zanieczyszczanie losowym szumem, co najczęściej znacząco poprawia możliwości generalizacji.

W porównaniu z obrazami tekst wydaje się zdecydowanie trudniejszy w obróbce i wymaga znacznie większej ostrożności. Głównym problemem jest możliwość niekontrolowanej zmiany znaczenia generowanych dokumentów i w konsekwencji pogorszenia jakości zbioru. Tekst musi zachować sens i strukturę gramatyczną jak najbardziej zbliżoną do oryginału, aby można go było wykorzystać w analizie opartej na znaczeniu dokumentu, a nie tylko na zawartości słów [2].

Augmentacja danych pozwala przezwyciężyć ograniczenia tkwiące w danych – zwiększyć liczbę przypadków, wprowadzić większą różnorodność, uwzględnić zanieczyszczenia i przez to pozytywnie wpłynąć na zdolności predykcyjne modelu [6]. W tym miejscu warto jednak zwrócić uwagę na poważne zastrzeżenia – techniki te w znacznym stopniu opierają się na jakimś modelu lub regułach. Zadaniem naszego modelu jest uczenie się rzeczywistych wzorców, a nie tych „wygenerowanych” – w rezultacie ocena skuteczności powinna opierać się na realnych, a nie syntetycznych przykładach. Należy pamiętać, że augmentacja powinna być prowadzona wyłącznie na zbiorze treningowym, a model należy walidować tylko przy pomocy realnych przykładów, które nie były podstawą tworzenia syntetycznych danych. Ponadto augmentacja powinna być traktowana jako wsparcie i co najwyżej jeden z etapów procesu przygotowania danych, a nie go zastąpić. Ludzka kontrola nad całym procesem jest w tym przypadku niezbędna.

Generowanie szumu

Najbardziej podstawowe techniki augmentacji tekstu to wprowadzanie szumu, np. przez mechaniczną podmianę losowych słów w dokumentach [2, 3, 5]. Przeanalizujmy je na przykładzie zapytania: Nie wiem jak złożyć wniosek o dopłatę do fotowoltaiki. Gdzie mogę uzyskać informację na ten temat?

  • Losowe usuwanie słów (random deletion) - jak nazwa wskazuje, polega na wybraniu zadanej liczby słów w tekście i usunięciu ich:

    Nie wiem jak złożyć wniosek o do fotowoltaiki. Gdzie mogę uzyskać informację na ten temat?
  • Losowa zamiana słów (random swap) - wybieramy losowo pary słów w tekście, które następnie zamieniamy miejscami:

    Nie wiem jak złożyć wniosek o uzyskać do fotowoltaiki. Gdzie mogę dopłatę informację na ten temat?

Czy to ma sens? Otóż ma! Techniki te nie tyle generują nowe próbki, co raczej wprowadzają szum do istniejących przykładów i przez to wpływają na odporność modelu na zanieczyszczenia. Docelowe rozwiązanie powinno być odporne na błędy, braki wyrazów, czy nieprawidłowy szyk zdania, których występowanie w języku naturalnym jest raczej regułą niż wyjątkiem. Zaletą tego podejścia jest jego prostota i skuteczność.

Gdy myślimy o augmentacji tekstu, intuicyjnie przychodzą nam na myśl synonimy. Ich wykorzystanie nie zmienia znacząco sensu wypowiedzi, a model może poszerzyć zasób obsługiwanego słownictwa. W tej samej rodzinie mieszczą się 2 kolejne techniki:

  • Losowe wstawianie słów (random insertion) - metoda polega na tym, że wybieramy dowolne słowo i wstawiamy do tekstu w losowym miejscu jego synonim:

Nie wiem dostać jak złożyć wniosek o dopłatę do fotowoltaiki. Gdzie mogę uzyskać informację na ten temat?

  • Zastępowanie synonimami (synonym replacement) - w tym przypadku zastępujemy losowe słowo jego synonimem:

Nie wiem jak złożyć wniosek o dofinansowanie do fotowoltaiki. Gdzie mogę dostać informację na ten temat?


​​​​​​​Jak przekonują autorzy Easy Data Augmentation w artykule opisującym to rozwiązanie [3], zdroworozsądkowe podejście do mechanizmów opartych o synonimy i dodawanie szumu do tekstu jest kluczowe dla ich skuteczności. Przeprowadzone przez nich testy wskazują, że nie powinno się przekształcać więcej niż 10-20% słów. W przeciwnym wypadku możemy wygenerować przykłady zbyt odległe semantycznie od oryginałów i w konsekwencji zanieczyścić zbiór danych, zamiast go wzbogacić. Kolejnym parametrem analizy jest liczba dodatkowych przykładów. Dla małych zbiorów danych większa liczba wygenerowanych przykładów poprawiała jakość modelu, natomiast dla dużych zbiorów augmentacja nie przynosiła znaczących efektów. Stosowane z umiarem podejście daje zaskakująco dobre rezultaty i nie wymaga dużych zasobów [3].

Podczas wzbogacania zbioru treningowego o nowe przykłady warto skorzystać z gotowych rozwiązań open source. Przykładem może być stworzona w Pythonie biblioteka TextAttack. Poza wspomnianymi technikami posiada ona także inne możliwości – od losowego zamieniania liter, przekształcenia bazujące na regułach oraz wykorzystanie modeli językowych i słowników do wyszukiwania synonimów, aż po własne funkcje tworzone przez użytkownika. Możliwe jest również stosowanie kilku funkcji wybieranych w sposób losowy. Zainteresowanych odsyłam do dokumentacji projektu [4].

Przyjrzyjmy się przykładowej implementacji opisanych zmian w bibliotece TextAttack.

from textattack.augmentation import EasyDataAugmenter

sample = "The newest function in the application does not work. The application hangs up always if I want to use it"

augmenter = EasyDataAugmenter(pct_words_to_swap=0.2, transformations_per_example=1)

augmenter.augment(sample)

>>> [ The newest part in the application does not solve. The application cling up always if I wish to use it]

Generowanie synonimów w oparciu o słowniki

Najważniejszym pytaniem w tym kontekście jest źródło pozyskania synonimów na potrzeby augmentacji danych. Ogólnie rzecz ujmując, techniki poszukiwania wyrazów o podobnym znaczeniu możemy podzielić na dwa rodzaje [2, 5]:

  • Modyfikacje oparte na słowniku,
  • Modyfikacje bazujące na reprezentacjach wektorowych.

Do zaimplementowania podejścia opartego o słownik wykorzystać można WordNet [8], tj. słownik semantyczny obsługiwany m.in. przez Natural Language Tool Kit (NLTK) – klasyczną bibliotekę do analizy tekstu. Jako polski wordnet powstała w szczególności Słowosieć [9] będąca zbiorem powiązanych ze sobą semantycznie i hierarchicznie słów i wyrażeń języka polskiego. Ponieważ jest to biblioteka dość hermetyczna, warto przed jej użyciem zapoznać się z dokumentacją na stronie projektu. Jej słownik dostępny jest także publicznie na stronie repozytorium [11]. W poniższym przykładzie, zaimplementowanym w Pythonie, wykorzystałem bibliotekę plwordnet [12]:

import plwordnet
plwn = plwordnet.load('./plwordnet_3_0/plwordnet-3.0.xml')


Po zaimportowaniu biblioteki i załadowaniu pobranego z repozytorium słownika można rozpocząć poszukiwanie synonimów. Ponieważ słowa, dla których poszukujemy wyrazów bliskoznacznych, mogą mieć rozmaite znaczenia, implementacja uwzględnia dwie pętle:

  • Pętla pierwsza: dla wszystkich znaczeń danego słowa
  • Pętla druga: dla każdej relacji, wybierz tylko te, które są różne od analizowanego słowa
relations = plwn.find('wypłata')
synonyms = []
for relation in relations:
    synonyms.extend([x.name for x in relation.synset.lexical_units
                    if x.name != relation.name])
synonyms
>>> ['płaca', 'pensja', 'uposażenie', 'pobory', 'pierwszy']


Jeżeli chcemy dotrzeć do konkretnego znaczenia naszego słowa i jego synonimów wystarczy je wyszukać w następujący sposób:

relations = plwn.find('wypłata.2')

Innym źródłem synonimów, przeznaczonym dla otwartych pakietów biurowych, może być słownik przygotowany przez autorów projektu Dobrysłownik.pl. Jego wykorzystanie jest wyjątkowo proste. Ze strony projektu można pobrać gotowy plik tekstowy, udostępniany na licencji GPL, zawierający zestawienia słów i ich synonimów [10]. Poniżej krótki przykład kodu w języku Python z jego użyciem.

W pierwszym kroku wczytujemy słownik z podanej ścieżki. Dla ułatwienia przetwarzania wczytujemy go od razu jako listę linii:

path_to_dictionary = "./thesaurus/thesaurus.txt-latest"
with open(path_to_dictionary, 'r', encoding='utf8') as file:
    lines = file.readlines()


W kolejnym kroku, po kilku podstawowych zabiegach czyszczących, przekształcamy listę na słownik, gdzie pierwsze słowo jest kluczem, a lista wyrazów bliskoznacznych wartością. Następnie odpytujemy gotowy słownik i w odpowiedzi otrzymujemy listę synonimów.

lines = [line.rstrip() for line in lines if not line.startswith("#")]
lines = [line.split(";") for line in lines]
synonyms = {line[0]: line[1:] for line in lines}
synonyms['pensja']
>>> ['zapłata', 'pobory', 'wynagrodzenie', 'stawka', 'gaża', 'zarobek', 'płaca']


Warto dodać, że nie wszystkie słowa występujące jako synonimy pojawiają się również jako klucze w słowniku. W tym miejscu pominę jednak rozwinięcie algorytmu.
Niestety poważnym problemem w przypadku języka polskiego jest odmiana wyrazów. Ponieważ słowniki, co zrozumiałe, bazują na formach podstawowych, konieczne jest odpowiednie przygotowanie tekstu, co komplikuje podejście bazujące na otwartym słowniku synonimów. Pracując na dokumentach w języku angielskim mamy praktycznie gotowe rozwiązania, które możemy oprzeć na bibliotekach typu TextAttack albo na NLTK + WordNet. Warto więc rozważyć uwzględnienie maszynowego tłumaczenia tekstu w naszym rozwiązaniu. Sporą zaletą takiego rozwiązania jest wykorzystanie reguł językowych – technika oparta o synonimy faktycznie wzbogaca przykłady, a nie tylko generuje szum. Wykorzystajmy ponownie TextAttack do implementacji synonimami.

from textattack.augmentation import WordNetAugmenter

sample = "The newest function in the application does not work. The application hangs up always if I want to use it"

word_net_augmenter = WordNetAugmenter(pct_words_to_swap=0.2)
word_net_augmenter.augment(sample)
>>> ['The newest subprogram in the application does not shape. The application attend up forever if I want to use it']

Augmentacja kontekstowa

Ważnym elementem, który powinniśmy uwzględnić, jest kontekst podmienianego słowa, dlatego też pomocnym rozwiązaniem mogą okazać się modele językowe. Modele typu BERT czy RoBERTa uczą się prognozować słowa (w zasadzie tokeny) na podstawie kontekstu. Każdy token posiada w tym modelu swoją wektorową reprezentację, która dodatkowo może się zmieniać w zależności od otaczających go sekwencji. Tę natywną właściwość możemy wykorzystać na potrzeby generowania nowych próbek uczących na podstawie już istniejących przykładów [2, 6].

Jak modele uczą się rozumieć tekst? Trening odbywa się techniką nazywaną Masked Language Modeling (MLM). Tekst jest dzielony na tokeny, a następnie część z nich jest zakrywana. Zadaniem modelu jest nauczyć się prawidłowo prognozować losowo zakryte tokeny na podstawie kontekstu, czyli pozostałej, widocznej części sekwencji. Jest to zadanie skomplikowane, czasochłonne, wymaga sporych zasobów obliczeniowych i ogromnych ilości tekstu do przetworzenia. W rezultacie model, na podstawie zebranej w procesie uczenia wiedzy, przewiduje najbardziej prawdopodobne tokeny, które powinny znaleźć się na danym miejscu w tekście.

Przykładowo, w procesie uczenia nasze oryginalne zdanie...

Nie wiem jak złożyć wniosek o dopłatę do fotowoltaiki. Gdzie mogę uzyskać informację na ten temat?

​​​​​​​...może zostać przetworzone w następujący sposób:

Nie wiem jak złożyć <mask> o dopłatę do fotowoltaiki. Gdzie mogę uzyskać <mask> na ten temat?

Zadaniem modelu jest nauczyć się, że w takim kontekście pod maskami kryją się słowa „wniosek” i „informację”… lub przynajmniej coś, co po uzupełnieniu sprawi, że powyższy tekst będzie sensowny.

W celu wygenerowania prognoz skorzystamy z biblioteki transformers oraz obiektu pipeline, który pozwoli nam na efektywne wykonanie predykcji. Użyty model pochodzi z HuggingFace [15].

from transformers import pipeline
unmasker = pipeline(task='fill-mask', model="./FacebookAI/xlm-roberta-large", top_k=5)


Obiekt pipeline wymaga zdefiniowania zadania oraz wskazania modelu, za pomocą którego je wykonamy. Parametr top_k wskazuje, ile prognoz chcemy uzyskać.

text = """Nie wiem jak złożyć wniosek o dofinansowanie do fotowoltaiki. Gdzie mogę <mask> informację na ten temat?"""

unmasker(text)


Znacznik <mask> oznacza, że w tym miejscu model powinien wstawić przewidywane słowo. Znacznik może się różnić w zależności od wykorzystanego modelu, możemy również prognozować kilka zamaskowanych tokenów na raz.

Pipeline zwraca listę słowników z najbardziej dopasowanymi predykcjami. Najbardziej prawdopodobne propozycje to: znaleźć, uzyskać, zdobyć, sprawdzić i kupić. Słownik z wynikami jest duży, dlatego zamieściłem tylko prognozę dla zwycięskiej pozycji.



Score jest prawdopodobieństwem – model był więc mocno przekonany, wskazując słowo „znaleźć”. Dodatkowo otrzymujemy identyfikator tokenu oraz uzupełnioną sekwencję. Warto pamiętać o przefiltrowaniu listy propozycji na podstawie wartości „score”, ponieważ nierzadko wśród najlepszych propozycji znajdzie się sporo „wysoce nieprawdopodobnych”. Dość powiedzieć, że piąta propozycja na naszej liście miała prawdopodobieństwo na poziomie tylko 0,0006.

Maskując w ten sposób słowa i uzyskując ich zamienniki, możemy wygenerować wiele nowych przykładów uczących. Pamiętajmy jednak o kilku ograniczeniach tej techniki. Przede wszystkim, to co model podstawi do tekstu, jest tylko prawdopodobne, ale niekoniecznie musi być synonimem zakrytego słowa. Decyduje statystyka, a nie formalne reguły językowe, co jest wadą w stosunku do korpusu synonimów przygotowanego przez specjalistów. W dużym stopniu jesteśmy zależni do tego, na jakich danych uczył się model, od jego jakości i architektury. W przypadku specyficznych dokumentów, napisanych technicznym albo branżowym językiem, możemy nie uzyskać najlepszych rezultatów. Ważne jest też to, że tokeny to nie zawsze całe słowa. Jeżeli słowo składa się z kilku tokenów, to zakrywając je pojedynczą maską, sugerujemy modelowi błędnie, że zakryliśmy jeden token. Ten problem jest oczywiście do zaadresowania na poziomie tokenów, ale wymaga już większego doświadczenia w pracy z sieciami neuronowymi, modelami językowymi i transformerami.

Z drugiej strony, za tym rozwiązaniem przemawia jego prostota w porównaniu do metod opartych o słownik. Nie przejmujemy się odmianami słów i skomplikowanym przygotowaniem danych. Podstawowa implementacja jest prosta, a osoba doświadczona jest w stanie rozbudować to podejście – zaimplementować inne typy modeli, sterować wyjściowymi prawdopodobieństwami, wykorzystać model oparty o język branżowy lub napisać i wytrenować swój własny model do generowania syntetycznych dokumentów.

Translacja wsteczna

Innym podejściem do tematu jest wygenerowanie całych dokumentów, mających znaczenie jak najbardziej zbliżone do pierwotnych przykładów. Zadanie polega na przygotowaniu nowego dokumentu na podstawie dostarczonego przykładu – modyfikacji może podlegać zarówno słownictwo, jak i składnia, ale sens dokumentu powinien zostać zachowany.

Bardzo ciekawą strategią jest translacja wsteczna (back translation). Polega ona na maszynowym przetłumaczeniu dokumentu, a następnie przetłumaczeniu go z powrotem na język źródłowy. W efekcie składnia i słownictwo najprawdopodobniej się zmienią. Technika ta jest o tyle ciekawa, że może zostać oparta na ogólnych modelach językowych, bez konieczności ich dotrenowania [5, 6]. Przyjrzyjmy się implementacji dwóch modeli sequence to sequence na potrzeby translacji wstecznej. Najpierw definiujemy tokenizery oraz właściwe modele do wykonania tłumaczenia [13, 14]:

from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

pl2en_tokenizer = AutoTokenizer.from_pretrained("./sdadas/mt5-base-translator-pl-en")
pl2en_model = AutoModelForSeq2SeqLM.from_pretrained("./sdadas/mt5-base-translator-pl-en")
en2pl_tokenizer = AutoTokenizer.from_pretrained("./sdadas/mt5-base-translator-en-pl")
en2pl_model = AutoModelForSeq2SeqLM.from_pretrained("./sdadas/mt5-base-translator-en-pl")


W kolejny kroku definiujemy oryginalny tekst…

text_pl = """ W promocji mogą brać udział osoby poniżej 25 roku życia, które są klientami banku przez minimum rok i nie posiadają jeszcze rachunku oszczędnościowego."""


… który po tłumaczeniu na język angielski przestawia się w następujący sposób.

tokens = pl2en_tokenizer(text_pl, return_tensors='pt')
generated_ids = pl2en_model.generate(**tokens, max_new_tokens=512)
text_eng = pl2en_tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
text_eng
>>> 'The promotion can be taken by people under 25 years of age who have been customers of the bank for a minimum of one year and do not yet have a savings account.'


Czas na odwrotną translację. Kod w zasadzie jest identyczny, zmieniają się tylko modele, a wraz z nimi kierunek tłumaczenia:

tokens = en2pl_tokenizer(text_eng, return_tensors='pt')
generated_ids = en2pl_model.generate(**tokens, max_new_tokens=512)
new_text_pl = en2pl_tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
new_text_pl
>>> 'Promocję mogą podjąć osoby poniżej 25 roku życia, które są klientami banku przez co najmniej rok i nie mają jeszcze konta oszczędnościowego.'


W rezultacie otrzymaliśmy zbliżony, ale jednak odmienny tekst. Cel został osiągnięty – otrzymaliśmy nowy dokument o zawartości zgodnej z oryginałem, ale wyrażonej w odmienny sposób. Podobieństwo może być skutkiem tego, że modele są autorstwa tej samej osoby i prawdopodobnie były trenowane na tych samych danych (ale w odwrotnym kierunku pl → eng vs. eng → pl). Zaleca się, żeby na różnych etapach tłumaczenia wykorzystywać modele przygotowane przez różne zespoły. Oparcie modeli o odmienne architektury i zbiory uczące pomoże zwiększyć kreatywność naszego rozwiązania. Kolejnym pomysłem, mającym na celu zwiększenie odmienności nowego tekstu od oryginału, mogłoby być wykorzystanie omawianych wcześniej technik generowania synonimów i za ich pomocą przekształcanie tekstu anglojęzycznego przed wykonaniem wstecznej translacji. Ciekawą możliwością jest również szeregowe tłumaczenie tekstu na różne języki przed powrotem do języka macierzystego. W efekcie miksowania różnych technik jesteśmy w stanie uzyskać coraz bardziej zróżnicowane przykłady. Ryzykiem związanym z tą techniką jest natomiast jakość i adekwatność wykorzystanych słowników do naszego przypadku.

Generowanie z przykładów

Zamiast korzystać z technik wstecznego tłumaczenia, możemy zaimplementować model, który wprost będzie generował dla nas przykłady uczące poprzez parafrazowanie przypadków, tworzenie podsumowań lub dodawanie pytań do dokumentów na potrzeby systemów Q&A. W wykorzystywanym już w tym tekście repozytorium Hugging Face znajdziemy wiele modeli realizujących zadania text-generation, które bazują na instrukcjach lub text-to-text-generation, które realizują określone zadanie na podstawie dostarczonego tekstu (np. tłumaczenie). Warto na bieżąco śledzić zmiany i nowości w repozytorium modeli [16].

W tym miejscu skupimy się na największych obecnie dostępnych publicznie modelach językowych. Modele takie jak GPT, Gemini, LLaMA, czy polski Bielik są niewątpliwym przełomem w zadaniach związanych z generowaniem tekstu. W odpowiedzi na odpowiednio skonstruowane zapytanie są w stanie wygenerować dla nas zróżnicowane i jednocześnie złożone treści. Modelami sterujemy przy pomocy instrukcji (promptów), które formułujemy w języku naturalnym. Zaletą tego typu rozwiązań jest efektywna integracja z innymi usługami do analizy danych jak przykładowo Big Query dla GCP [7] oraz możliwości wykorzystanie API w komunikacji z użytkownikiem.

Modele tej klasy, dostarczane przez dostawców, można wykorzystać na różne sposoby. Na początek przyjrzyjmy się prostej implementacji algorytmu, który zastępuje synonimami słowa w podanym tekście. Warto zauważyć, że Gemini od razu odmienia wstawiane synonimy, co jest dużym ułatwieniem w stosunku do implementacji opisywanych wcześniej metod low-code.

PROMPT: You will receive a short text. Your task is to replace 3 words from the given text with their synonyms, keeping the overall meaning and sentiment as close as possible to the original text. Here you have a text: {user-input}. Return only transformed text without explanations.

Prawdziwą moc duże modele językowe pokazują jednak wówczas, gdy chcemy wykorzystać je jako zaawansowane generatory. Przy pomocy Gemini możemy zażądać wygenerowania całych dokumentów na podstawie dostarczonego wzorca. Poprośmy więc model Gemini o wygenerowanie 3 nowych przykładów, o takim samym znaczeniu, na podstawie dostarczonego przez nas fikcyjnego zgłoszenia klienta. To, jak będą one dokładne i co będą zawierać, zależy wyłącznie od nas. Pozwólmy AI zmieniać szyk zdań i stosować język nieformalny – ważne jednak, aby znaczenie i sentyment wygenerowanych przykładów zostały zachowane.

PROMPT: You need to simulate real customer feedback on the basis of the given text. Prepare a list of 3 different versions of the text. You can change the order of sentences or omit some of them but the general meaning and sentiment should stay the same as in original text. Here you have the text: {user-input}. Answer in Polish. Try to be informal. Return only a numbered list of your proposals.

Kolejnym możliwym zastosowaniem jest trening modeli na potrzeby rozwiązań opartych o pytania i odpowiedzi, wyszukiwanie semantyczne, a nawet systemy oparte o RAG. Ważne jest wówczas, by podczas procesu uczenia model rozpoznał wzorce pojawiające się w pytaniach, które mają prowadzić do określonych odpowiedzi. Celem kolejnego ćwiczenia jest więc wygenerowanie pytań, na które odpowiedź znajduje się w podanym tekście.

PROMPT: You will receive a summary of the document. Prepare 5 short, different questions about the summary. The answer on your questions should be in the given text. Here you have the summary: {user-input}. All your options should be in Polish. Return only your proposals of questions as a numbered list.

Podejście oparte o modele generatywne, zwłaszcza o duże modele językowe ma ogromny potencjał i szerokie możliwości zastosowania do augmentacji danych na potrzeby innych modeli. Eksperymenty z generowaniem danych treningowych dla modeli językowych przy pomocy ChatGPT wykazały lepszą jakość finalnego modelu do klasyfikacji tekstu, w porównaniu z innymi metodami augmentacji danych. Co więcej, w trudnych i wąskich dziedzinach model trenowany na wzbogaconych danych potrafił uzyskiwać nawet lepsze wyniki niż ChatGPT instruowany technikami few-shot learning [6].

Rezultaty są obiecujące, jednak rozwiązanie ma też swoje ograniczenia. Od strony organizacyjnej wymaga korzystania z płatnych rozwiązań (ChatGPT, Gemini). Należy również pamiętać o zasadach ochrony danych (zwłaszcza danych osobowych i danych wrażliwych) oraz ogólnych zasadach korzystania z GenAI w organizacji. Wykorzystanie tego typu rozwiązań może podlegać restrykcjom związanym z łączeniem się firmy ze światem zewnętrznym, etyką, prywatnością i poufnością przekazywanych danych. Automatyzacja połączenia z API czata wymaga pewnych umiejętności developerskich. Dodajmy też, że jeżeli nasz przypadek biznesowy opiera się na specyficznych dokumentach, przykłady wygenerowane przez AI mogą nie być wystarczające.

Podsumowanie

W powyższym artykule przedstawiłem szeroki zakres technik, które możemy wykorzystać w przypadku potrzeby wzbogacenia zbiorów treningowych o syntetycznie wygenerowane przypadki. Nie jest to lista wyczerpująca, ale są one dostępne w przywołanej literatura, zwłaszcza w [4, 6]. Przed implementacją warto zastanowić się, które spośród nich odpowiadają naszym potrzebom i możliwościom wdrożenia. Dają one duże możliwości rozszerzenia zbioru danych treningowych i w rezultacie zwiększenia skuteczności naszych modeli językowych, jednak należy jeszcze raz podkreślić, że augmentacja nie zastąpi procesu przygotowania danych, a jedynie stanowi jego element.

Bibliografia

  1. Data Augmentation (https://en.wikipedia.org/wiki/Data_augmentation)
  2. Text augmentation techniques in NLP (https://www.geeksforgeeks.org/text-augmentation-techniques-in-nlp/)
  3. Jason Wei, Kai Zou, EDA: Easy Data Augmentation Techniques for Boosting Performance on Text Classification Tasks (https://arxiv.org/abs/1901.11196)
  4. TextAttack Documentation (https://textattack.readthedocs.io/en/master/)
  5. Bohan Li, Yutai Hou, Wanxiang Che, Data augmentation approaches in natural language processing: A survey (https://www.sciencedirect.com/science/article/pii/S2666651022000080)
  6. Haixing Dai i inni, AugGPT: Leveraging ChatGPT for Text Data Augmentation, (https://arxiv.org/abs/2302.13007)
  7. Karl Weinmeister, How to Augment Text Data with Gemini through BigQuery DataFrames (https://medium.com/google-cloud/how-to-augment-text-data-with-gemini-through-bigquery-dataframes-347bc6378413)