Jak widać, moja teoretyczna regularność nie ma nic wspólnego z faktycznym stanem rzeczy i odstępy między notkami przypominają bardziej blogi bardziej znanych osób, które piszą coś dłuższego i mądrego raz na jakiś czas. Różnica jest zasadnicza – moje teksty nie są ani długie ani mądre, ale można powiedzieć, że jeden punkt już spełniłem.
Za silnik, a tym samym trawę, zasadniczo się nie brałem – zbyt wiele atrakcji działo się na początku semestru i dzieje się teraz, nie tylko związanych z informatyką. Chociażby udało się przywrócić niektórym wspomnienia o grze Magic: the Gathering i co jakiś organizować “magicowe okienka” na uczelni, aby towarzysko sobie pograć. Tym niemniej największym wydarzeniem były wybory prac inżynierskich, w efekcie czego pod koniec marca następowały istne cuda w dobieraniu się zespołów (“Masz już zespół? Masz? NIE MASZ?! To chodź do nas, chodź, chodź, no choooooodź… Aha, temat Cię nie interesuje…”) czy atakowaniu promotorów/opiekunów/kogokolwiek w celu zdobycia interesującego tematu czy też zdobycia czegokolwiek z puli “jeszcze te mogę robić”.
Była też pewna pula tematów tworzonych w ramach Software Development Studio (SDS). SDS to idea, w której następuje pewna współpraca pomiędzy studentami różnych lat w celu zdobycia dodatkowych umiejętności. Mówiąc mniej enigmatycznie – dwaj studenci IV roku ze specjalności magisterskiej Software Engineering (specjalność inżynierii oprogramowania na Politechnice Poznańskiej jest w języku angielskim) mają za zadanie opiekować się i wspomóc wytwarzanie jednego z wybranych tematów inżynierskich, które z kolei są realizowane przez czterech studentów III roku (to my). Jeżeli doliczymy do tego promotora i dwóch opiekunów z dziekanatu, wychodzi na to, że jest aż 9 osób (tzw. Drużyna Pierścienia). Każdy na tym zyskuje – pracownicy uczelni ciekawy (mam nadzieję) projekt, który można gdzieś dalej pokazać (zwykle projekty w ramach SDS są ważne dla uczelni, wydziału czy instytutu), studenci IV roku doświadczenie w zarządzaniu projektem i grupką czasami energicznie reagujących osób, a my – tytuł inżyniera. Oczywiście, nie wszystkie projekty są takie, ale 7 grup akurat realizuje swoje inżynierki w ramach SDS. Fajna sprawa, gdyż można się sprawdzić w takim grupowym projekcie. No i sam temat też jest bardzo interesujący, choć na razie nie będę o nim mówił, gdyż nie wiem, czy mogę.
Po co ten wstęp? Po prostu chciałem się pochwalić. Przy okazji pozdrawiam wszystkie osoby zaangażowane w projekt i mam nadzieję, że będzie nam się dobrze pracowało.
W niniejszej notce chciałem co nieco powiedzieć o sposobach porównywania łańcuchów (czyli właśnie rzeczonych stringów z tytułu – być może ktoś wszedł z myślą o innych stringach, w sumie też bym tak zrobił). Ostatnio myślałem nad myśleniem o myśleniu o możliwości logicznego porównywania łańcuchów. Kontekst zadania jest taki – mamy dwa tytuły książek czy artykułów i chcemy zobaczyć na ile są sobie bliskie tematycznie. Pewnie wielu z Was słusznie powie tutaj “hej, ale tego nie można sprawdzić samymi łańcuchami”. Owszem, najlepiej by było, jakby uruchomiło się tutaj wiedzę dziedzinową chociażby w rodzaju słów kluczowych. Nie mówię – być może będzie to także wykorzystane, jednak wymagałoby dodatkowych mechanizmów, o których nie wiadomo, czy by się opłaciły.
Tym niemniej pozostańmy przy samych łańcuchach, gdyż z nich też można dużo wyciągnąć. Dlaczego? Weźmy chociażby tytuły publikacji o inżynierii oprogramowania. A konkretnie dwa przykłady publikacji pana profesora Jerzego Nawrockiego (pozdrawiam).
Patrząc na tytuły można już wysnuć całkiem sporo wniosków.
- Oba dotyczą programowania, a zatem – teoretycznie – informatyki
- W obu mamy do czynienia w pracą w parach, co w powiązaniu z programowaniem może znaczyć “programowanie w parach”
- Być może oba teksty dotyczą inżynierii oprogramowania
Wszystkie wnioski uczyniliśmy tylko i wyłącznie na podstawie tytułów, a zatem łańcuchów (ciągów znaków, rzeczonych stringów). Pora sprawdzić to doświadczalnie.
Przez ostatnie dwa dni miałem chęci (przede wszystkim chęci – jak sobie coś ubzduram, bo mnie ekscytuje, to nie ma siły, abym przestał o tym myśleć), aby stworzyć jakiś prosty algorytm porównujący dwa ciągi pod względem podobieństwa. Oczywistym podejściem, na które równie oczywiste jest to, iż na nie nie wpadłem, jest liczenie tzw. odległości, która mówi o tym ile potrzeba operacji, aby jeden ciąg zamienić w drugi. Jednak zapominanie o tak prostych sprawach ma również dobre strony – będzie więcej algorytmów na tym świecie. A przynajmniej na tym blogu. Algorytmów? Owszem – bowiem wpadłem na dwa sposoby mierzenia łańcuchów.
Algorytm porównywania łańcuchów
Operacja porównania ciągów (w obu ignorujemy białe znaki) polega na kolejnym wyszukiwaniu coraz większych podciągów ciągu pierwszego, a następnie szukaniu ich w ciągu drugim. W drugim etapie zamienia się łańcuchy ze sobą i ponownie przeszukuje w poszukiwaniu podciągów. Wynikiem każdego jest procent (a konkretnie wartość z przedziału [0, 1]) trafionych poszukiwań w stosunku do wszystkich, a wynik łączny to średnia z tych dwóch pomiarów.
Powyższy opis wygląda dosyć mętnie, ale udokumentowałem go przykładem, na który składają się słowa “hala” oraz “hola”.
| Łańcuch pierwszy (który dzielimy na podciągi i porównujemy z drugim) | Długość podciągu | Rozpatrywany podciąg | Wynik (czy dany podciąg występuje w ciągu drugim) | | hala | 1 | h | TAK | | hala | 1 | a | TAK | | hala | 1 | l | TAK | | hala | 1 | a | TAK | | hala | 2 | ha | NIE | | hala | 2 | al | NIE | | hala | 2 | la | TAK | | hala | 3 | hal | NIE | | hala | 3 | ala | NIE | | hala | 4 | hala | NIE | | | | | Trafione: 5/10 = 0,5 | | | | | | | hola | 1 | h | TAK | | hola | 1 | o | NIE | | hola | 1 | l | TAK | | hola | 1 | a | TAK | | hola | 2 | ho | NIE | | hola | 2 | ol | NIE | | hola | 2 | la | TAK | | hola | 3 | hol | NIE | | hola | 3 | ola | NIE | | hola | 4 | hola | NIE | | | | | Trafione: 4/10 = 0,4 | |
Wynik końcowy: (0,5 + 0,4) / 2 = 0,45
Jak widać, według tej miary podobieństwo między tymi dwoma wyrazami wynosi 45%, co nie jest zbyt fascynującym wynikiem. Zwłaszcza, że optycznie słowa “hala” i “hola” są do siebie bardzo podobne i choć mają inne znaczenie, to różnica jednej literki może wskazywać na to, że nastąpiła tutaj zwyczajna literówka. Jest tutaj zatem wiele możliwości poprawy – warto na przykład zauważyć, że jeżeli przykładowe słowa byłyby dłuższe i różniłyby się paroma literami, końcowy wynik byłby bliższy jedynce (gdzie 1 oznacza równość ciągów). Troszkę gorzej wygląda to w momencie, kiedy staramy porównać się dwa tytuły (autorstwa innego pana profesora Jerzego Nawrockiego) ze sobą:
1. Permian to Early Triassic magnetostratigraphy from the Central European Basin in Poland: Implications on regional and worldwide correlations
2. The Middle Triassic magnetostratigraphy from the Peri-Tethys basin in Poland
Jak widać, w dość długich tytułach mamy wspólne słowa (magnetostratigraphy czy Poland), aczkolwiek widać, iż zdania są dosyć różne. Rzeczywiście, algorytm podaje wynik porównania 0,203932 – cóż, mogłoby być gorzej. Jeżeli weźmiemy z kolei jeden z poprzednio podawanych tytułów z inżynierii oprogramowania i jeden z tych medycznych, to ich wynik będzie oscylował wokół 0,05-0,1. Tym niemniej, jeśli chcielibyśmy zaklasyfikować publikacje 1. i 2., to byłoby to trudne na podstawie wyniku 0,2. Cóż, trzeba będzie popracować.
Algorytm mapowania znaków
Operacja mapowania znaków polega na szukaniu kolejnych znaków z jednego ciągu w drugim, a następnie usuwaniu tego znaku w obu łańcuchach. Wynikiem jest jeden minus stosunek liter pozostałych (niedopasowanych) do długości jednego ciągu. Jeśli łańcuchy mają różną długość, krótszy jest dopełniany białymi znakami.
Tutaj także mamy przykład – zbadamy mapowanie słów “anarchia” i “arena”. Jak widać, ten drugi wyraz należy dopełnić trzema białymi znakami, aby oba ciągi miały równą długość.
| Łańcuch pierwszy | Łańcuch drugi | Rozpatrywany znak | Wynik (czy rozpatrywany znak występuje w łańcuchu drugim) | | anarchia | arena | a | TAK | | narchia | rena | n | TAK | | archia | rea | a | TAK | | rchia | re | r | TAK | | chia | e | c | NIE | | chia | e | h | NIE | | chia | e | i | NIE | | chia | e | a | NIE | |
Wynik końcowy: 1 – (4 / 8) = 1 - 0,5 = 0,5
Idea polega na tym, aby zobaczyć, ile liter (formalnie znaków) nie zostanie dopasowanych między dwoma łańcuchami (wliczając w to także spacje). Jak widać, tutaj są to: c, h, i oraz trzecie a, gdyż te litery nie występują w słowie “arena”.
To badanie wydaje mi się rozsądniejsze od poprzedniego, choćby dlatego, że podczas testów wyszły nieco “mądrzejsze” wyniki. Choćby dla publikacji medycznych podanych wcześniej wynik tego algorytmu to 0,55 – na tej podstawie istotnie można wnioskować, że oba teksty zostały napisane dla potrzeb jednej dziedziny nauki. Ten algorytm wymaga jeszcze więcej testów, ale wyniki są obiecujące – jest on także znacznie krótszy i mniej skomplikowany niż poprzedni algorytm.
Tym niemniej myślę, że stosując obie techniki można przygotować prosty klasyfikator dla tytułów czy nazwisk autorów.
Oczywiście, jak to ja, nie pomyślałem o tym, aby wcześniej sprawdzić w Internecie, czy ktoś nie wymyślił czegoś lepszego. Owszem, iż wymyślił, przygotował całą bibliotekę, oparł na wcześniej wspomnianej odległości i całej teorii przestrzeni metrycznych. I wyszło to dużo lepiej – istnieje biblioteka LingPipe, a konkretny tutorial znajduje się tutaj.
Jeżeli macie jakieś uwagi, komentarze, rady czy własne pomysły – jak najbardziej zapraszam do pisania pod notką.
Pozdrawiam i dziękuję - SceNtriC