O bocie, który rozmawia

2011-09-17 22:55

Sporo szumu zrobiła ostatnio informacja o tym, że pewien chatterbot (program udający rozmowę tekstową i/lub głosową) z sukcesem przebrnął przez test Turinga. Przebiła się ona nawet do mediów ogólnych, co zwykle oznacza jedną z dwóch rzeczy: albo wydarzenie jest naprawdę ważne, albo wybitnie wyolbrzymione.
Niestety, w tym przypadku mamy do czynienia raczej z tym drugim wariantem.

Dla porządku warto oczywiście przypomnieć, o co tu właściwie chodzi. Test Turinga był zaproponowany w pierwszej połowie zeszłego stulecia jako jedna z możliwości odpowiedzi na pytanie o to, czy komputery mogą “myśleć”. Ogólna idea jest tu bardzo prosta: jeśli maszyna będzie dla postronnego rozmówcy nieodróżnialna od człowieka, wtedy przechodzi test pozytywnie. Szczegóły dotyczą rzecz jasna dokładnego sposobu przeprowadzenia testu: medium komunikacji (np. konsoli tekstowej), dozwolonego czasu odpowiedzi, a przede wszystkim sposobu oceny – co obejmuje chociażby ilość sędziów i metodę ustalania werdyktu.
W przypadku Cleverbota mówimy o rezultacie trochę lepszym niż rzut monetą (ale statystycznie istotnym): 59.3% rozmówców uznało, że mają do czynienia z człowiekiem. W tym samym scenariuszu faktyczni ludzie uzyskiwali wynik… 63.3%. Najwyraźniej komputery są już całkiem blisko, by być lepsze od ludzi w… udawaniu ludzi :)

Czy jednak wynika z tego faktu cokolwiek znaczącego? Nawet jeśli uznamy, że rzeczywiście mamy tu do czynienia z pierwszym sukcesem w teście Turinga (bo diabeł jak zwykle tkwi w szczegółach), to nie wydaje mi się, aby wydarzenie to było czymś więcej niż tylko historycznym symbolem. Mamy tu oczywiście do czynienia ze sztuczną inteligencją (AI), lecz jest ona podobnej klasy co programy do rozpoznawania obrazu i dźwięku, algorytmy szachowe czy systemy automatycznego wnioskowania w stylu 20Q. W każdym z tych przypadków chodzi o wykonywanie określonego zadania, które zazwyczaj lepiej wychodzi ludziom niż komputerom. Sposób zaatakowania problemu jest też zawsze taki sam i polega na rzuceniu na front odpowiednio dużej mocy obliczeniowej, opcjonalnie wspartej pokaźnym zbiorem danych.

Tak też robi Cleverbot, będący w gruncie rzeczy silnikiem do przeszukiwania bazy wiedzy w odpowiedzi na zapytania pisane w określonym języku (w tym przypadku angielskim). Został stworzony w konkretnym celu i okazał się być w swojej domenie wystarczająco dobry, by zacząć konkurować z ludźmi. Dokładnie tak, jak kiedyś Deep Blue – który przynajmniej nie twierdził, że jest jednorożcem ;]

Tags: , ,
Author: Xion, posted under Computer Science & IT, Events » 4 comments

Ujemna wartość bezwzględna?…

2011-09-13 22:31

Każdemu absolwentowi szkoły podstawowej (mam nadzieję, że wciąż podstawowej…) powinna być znana poniższa funkcja:

\displaystyle |x| =  \begin{cases}   x & \text{dla } x \ge 0 \\   -x & \text{dla } x < 0 \end{cases}

Tak, jest to zwyczajna wartość bezwzględna, znana również jako moduł liczby. Jej formalna definicja gwarantuje, że |x| \ge 0 dla każdego x \in \mathbb{R}. Innymi słowy, wartość bezwzględna nigdy nie może być ujemna. Nic więc dziwnego, że używamy jej chętnie w tych właśnie sytuacjach, gdy interesuje nas tylko dodatnia połowa osi liczb. Oto bardzo prosty przykład:

  1. private Random random = new Random();
  2. private int identifier = -1; // niezainicjowany
  3.  
  4. private void generateIdentifier() {
  5.     identifier = Math.abs(random.nextInt());
  6. }
  7.  
  8. public boolean isInitialized() {
  9.     return identifier >= 0;
  10. }

Mamy tu elementarną sztuczkę, polegającą na początkowym przypisaniu polu identifier wartości spoza zwykłej dziedziny (-1), co oznaczać ma brak identyfikatora. Możemy tak zrobić, bo dzięki wartości bezwzględnej (funkcji Math.abs) generowane losowe identyfikatory będą zawsze dodatnie.

Albo raczej prawie zawsze

Tags: , ,
Author: Xion, posted under Programming » 1 comment

Eksperyment z losowymi ciągami

2011-09-06 20:51

Zdarzyło się dzisiaj, że musiałem zaimplementować rozwiązanie wyjątkowo klasycznego problemu. Siląc się matematyczny formalizm, mógłbym go zdefiniować następująco:

  • Mamy dany zbiór A=\{a_1, \ldots, a_n\} dowolnych elementów a_i oraz liczbę naturalną k \in N.
  • Szukamy ciągu S=<s_1 , \ldots, s_k> k elementów s_i \in A.

Krótko mówiąc, chodzi o trywialną wariację z powtórzeniami. Ambitne to zadanie jest w sumie nawet mniej skomplikowane niż częste ćwiczenie dla początkujących pt. losowanie Lotto, więc po chwili wyprodukowałem coś podobnego do kodu poniżej:

  1. import random
  2.  
  3. def k_permutation(elems, k=None):
  4.     k = k or len(elems)
  5.     res = []
  6.     while k > len(res):
  7.         next = elems[random.randrange(0, len(elems)]
  8.         res.append(next)
  9.     return res

I na tym pewnie historia by się zakończyła, gdybym nie przypomniał sobie, że Python domyślnie potrafi obsługiwać naprawdę duże liczby. (Może nie aż tak duże jak te tutaj, ale jednak dość spore ;]). Obserwacja ta daje się bowiem połączyć z inną: taką, iż ciąg elementów z pewnego zbioru jest równoważny liczbie w systemie o podstawie równej mocy tego zbioru. Taka liczba jest oczywiście bardzo duża w prawie każdym praktycznym przypadku, lecz to nie umniejsza w niczym prawdziwości stwierdzenia. Jest ono zresztą z powodzeniem wykorzystywane w systemach kryptograficznych w rodzaju RSA.

Postanowiłem więc i ja z niego skorzystać. Przynajmniej teoretycznie fakt ten powinien dawać lepsze rezultaty, zamieniając k losowań na tylko jedno – tak jak poniżej:

  1. def k_permutations_bignum(elems, k=None):
  2.     k = k or len(elems)
  3.     max_seq_num = len(elems) ** k
  4.     seq_num = random.randrange(0, max_seq_num) # (zob. 3. komentarz)
  5.     res = []
  6.     while seq_num > 0:
  7.         seq_num, next = divmod(seq_num, len(elems))
  8.         res.append(elems[next])
  9.     return res

Doświadczenie z kolei uczyłoby, że bezpośrednie aplikowanie dziwnych matematycznych koncepcji do programowania rzadko miewa dobre skutki ;) Jak więc jest w tym przypadku?…

Tags: , , , ,
Author: Xion, posted under Math, Programming » 4 comments

Proste formaty tekstowe

2011-09-02 23:02

Wprawdzie dobry kod znaczy więcej niż tysiąc słów, ale czasami kawałek dokumentacji jest po prostu nieodzowny. Osobiście uważam, że w tym względzie liczy się prostota i zaprzęganie do pracy takich formatów jak .doc czy nawet .pdf jest niemal zawsze grubą przesadą. Jest o wiele łatwiej, jeśli dokument daje się edytować zwyczajnym edytorem tekstowym.

Ale nawet wśród czysto tekstowych formatów występuje całkiem spora różnorodność. Mamy chociażby kilka opartych na XML-u – takich jak DocBook – że nie wspominając o nieśmiertelnym \tau\epsilon\chi-u. Te i im podobne są językami znacznikowymi (markup languages) i poza sporymi możliwościami mają jedną wadę: są rozwlekłe. Stosunek “sygnału do szumu” nie jest w nich specjalnie wysoki, przez co w swojej surowej formie są one trudniejsze w czytaniu – a więc i w edycji.

Tej w wady są w dużym stopniu pozbawione formaty w stylu wiki, przypominające trochę różne spontaniczne pomysły na formatowanie czystego tekstu spacjami, myślnikami i gwiazdkami. Czasami nie mają one często zaawansowanych możliwości pozwalających na przykład na wstawianie tabel, ale w zakresie oferowanej funkcjonalności są zaskakująco często wystarczające. Z pewnością wystarczają chociażby do postów na forach czy ticketów w systemach do śledzenia błędów.

Jest tylko pewien szkopuł: jest ich mnóstwo. Poza kilkoma wariantami składni wiki, mamy też takie wynalazki jak Markdown albo reStructuredText. W sumie jednak stanowią one tylko część tych co bardziej znanych. Sytuacja przypomina tu trochę pewien szczególny komiks z xkcd. Skutkiem tego jest często konieczność sprawdzania, jakiej to składni używa akurat ta konkretna strona, na której piszemy post lub komentarz, jeśli tylko nie robimy tego regularnie.

Na szczęście przyswojenie sobie nowej składni tego rodzaju nie jest przeraźliwie wyczerpującym wysiłkiem umysłowym ;-) Niekiedy sprawę upraszcza też fakt wspierania przez dany serwis więcej niż jednego standardu – tak robi na przykład GitHub. I dlatego nawet istnienie kilkunastu podobnych formatów nie wydaje się być jakimś szczególnie wielkim problemem.
Porównajmy to chociażby z hipotetyczną sytuacją, gdy w użyciu jest kilka formatów podobnie rozbudowanych i skomplikowanych co XML… Brr :)

Tags: , ,
Author: Xion, posted under Applications, Programming » Comments Off on Proste formaty tekstowe

Podaj bloga

2011-08-31 20:29

Podobno dzisiaj – czyli 31 sierpnia – obchodzimy międzynarodowy BlogDay. Piszę ‘podobno’, bo oficjalna strona tej inicjatywy pamięta jeszcze zeszły rok, ale chociażby ruch na Twitterze sugeruje, że nie jest to zupełnie zapomniane wydarzenie. A skoro tak, to pozwolę sobie również je zauważyć :)

Jego celebracja w założeniu polega na napisaniu notki, w której polecamy swoim czytelnikom pięć innych blogów – na przykład takich, które regularnie czytujemy. Nic prostszego, prawda? Wystarczy przecież spojrzeć na listę w swoim czytniku RSS – i już…
Cóż, niezupełnie – a przynajmniej nie w moim przypadku. Chociaż bowiem lista nie jest pusta, to nie wydaje mi się, żebym mógł się nią jakoś specjalnie chwalić. Widnieją na niej głównie klasyki, które powinny być wszystkim znane – takie jak Coding Horror czy Joel on Software – lub wyspecjalizowane blogi poświęcone wąskiemu tematowi – jak blog Nicka Johnsona o Google App Engine. Nie widzę specjalnego sensu w szczegółowym opisywaniu któregokolwiek z nich. Mógłbym co najwyżej wspomnieć o rzadko aktualizowanych perełkach w stylu Linux Hater’s czy Hyperbole and a Half, ale wolałbym nie obdarzać was zbyt wielką liczbą narzędzi wspomagających prokrastynację ;)

Dlatego też postanowiłem odwrócić “tradycję” Dnia Blogowania i poprosić czytelników o polecenie innych blogów podobnych do niniejszego – lub nawet zupełnie odmiennych, o ile tylko zachowamy ustalone proporcje (4 do 1). Przy odrobinie szczęścia długość powstałej w ten sposób listy interesujących blogów powinna o wiele rzędów wielkości przekroczyć 5 :)

Tags:
Author: Xion, posted under Internet, Programming » 6 comments

Prezentacja nt. programowania UI w Androidzie

2011-08-29 21:16

W sobotę wziąłem udział w pierwszej konferencji Appspirina – wydarzeniu poświęconemu tworzeniu aplikacji mobilnych. Ta pierwsza edycja była współorganizowana przez polski GTUG i tematycznie była związana z platformą Android, więc przypadkowo w całości pokrywała się z moimi zainteresowaniami ;)
Cieszę się więc, że mogłem tam wystąpić, prezentując wykład na temat niektórych co bardziej zaawansowanych aspektów programowania interfejsu użytkownika w Androidzie. Omówiłem tam nieco rzadziej spotykane przypadki użycia takich typowych narzędzi jak zasoby (resources), układy kontrolek (layouts) czy też różne sposoby powiadamiania użytkownika o istotnych i mniej istotnych zdarzeniach.

Na facebookowej stronie inicjatywy powinno się już pojawić kilka zdjęć, a wkrótce powinien też zostać udostępniony film z każdego z (trzech) wykładów. Póki co zamieszczam dla potomności slajdy ze swojej własnej prezentacji :)

File: Zaawansowane programowanie UI na platformie Android [PL]  Zaawansowane programowanie UI na platformie Android [PL] (762.0 KiB, 13,136 downloads)

Tags: , , , ,
Author: Xion, posted under Events, Programming » 4 comments

Sprzątanie śmieci nie zapobiega wyciekom

2011-08-26 20:14

Mogę się mylić, ale wydaje mi się, że potoczne wyobrażenia na temat odśmiecaczy pamięci (garbage collectiors) obejmują przekonanie, iż zapobiegają one każdemu problemowi właściwemu dla ręcznego zarządzaniu pamięcią. Jasne, wprowadzają przy tym swoje własne – jak choćby nieustalony czas życia obiektów – ale przynajmniej zapewniają nam, że nigdy nie “stracimy” zaalokowanego kawałka pamięci… Krótko mówiąc, garbage collectory podobno chronią nas całkowicie przed zjawiskiem wycieku pamięci.

Wiadomo, że nie jest to do końca prawdą. Wspominałem o tym chociażby w swoim artykule opisującym implementację w C++ odśmiecacza opartego o zliczanie referencji. Taki mechanizm nie potrafi posprzątać obiektów powiązanych zależnościami cyklicznymi (A \rightarrow B \rightarrow A). Jest tak dlatego, gdyż podbijają one wzajemnie swoje liczniki referencji i żaden z nich nie może w ten sposób osiągnąć zera. Nawet więc jeśli taki cykl nie jest dostępny z żadnego widocznego miejsca w programie, jego wewnętrzne odwołania będą utrzymywać go przy życiu.
To jednak dość znany przypadek, który występuje tylko w stosunkowo najprostszym mechanizmie odśmiecania. Bardziej wyrafinowane rozwiązania w rodzaju mark & sweep nie mają tej wady. Tam każda struktura odłączona od reszty programu będzie nieosiągalna dla algorytmu odśmiecacza i zostanie uprzątnięta. Z założenia eliminuje to więc wszystkie przypadki, które przy ręcznym zarządzaniu pamięcią kwalifikowałyby się jako jej wyciek.

Ale to jeszcze nie oznacza, że jakiekolwiek wycieki pamięci nie mają prawda się tu zdarzyć. Przeciwnie, są one jak najbardziej możliwe – i to ze zgoła przeciwnych powodów niż przy zarządzaniu wymagającym ręcznego zwalniania obiektów.

Tags: ,
Author: Xion, posted under Programming » 7 comments
 


© 2021 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.