Címkearchívumok: teszt

A Turing-teszt: mire jó és mire nem?

Gondolkodhatnak-e a számítógépek? És ha igen, hogyan lehet ezt bizonyítani? Ezeket a kérdéseket tette fel Alan Turing a számítástechnika és a számítógépek történetének egyik, talán a legnagyobb alakja. A megállási probléma felvetésével, és annak bizonyításával, hogy a probléma eldönthetetlen, az elméleti számítástechnikában és a matematikai logikában is maradandót alkotott. Ugyanakkor a számítástechnikát a gyakorlatban is hasznosította, hozzájárulva egy olyan gép megépítéséhez, ami hatékonyan tudott titkosított üzeneteket visszafejteni.

A számítástechnika lendületes fejlődésbe kezdett, úgy tűnt, semmi sem állhat annak útjában, hogy a mesterséges intelligencia még a 20. században megszülethessen. Turing valószínűleg komolyan hitt ebben, hiszen már arról kezdett gondolkodni, hogy ha lesz mesterséges intelligencia, hogyan tudjuk majd eldönteni, hogy versenyképes-e az emberi gondolkodással, vagyis azt a kérdést tette fel, hogyan dönthetjük majd el, hogy egy gép valóban gondolkodik-e.

A teszt valójában egyszerű, viszont igen mély filozófiai kérdéseket vet fel. Két szobában van egy gép és egy ember, nem láthatják egymást, csak üzeneteket cserélhetnek. Az ember feladata, hogy a kérdéseivel „letapogassa” a másik oldalt, és eldöntse, hogy a másik szobában ember van, vagy gép. Ha a tesztelő úgy dönt, hogy a beszélgetőtársa ember, és kiderül, hogy valójában egy géppel kommunikált, akkor a gép átment a Turing-teszten, el kell ismernünk, hogy gondolkodik.

Első nekifutásra rendben lévőnek tűnik minden, mégis azonnal érkeztek ellenvetések, a legismertebb és legkeményebb ellenérvelés John Searle „kínai szoba” ötlete. A részleteket most nem elemezzük, nagyon gazdag irodalma van ennek.

Hogy akkor miért is írok erről a tesztről? Láttam az „Ex Machina” című filmet, és ezen gondolkodva jöttem rá néhány alapvető problémára a Turing-teszttel kapcsolatban. Anélkül, hogy túlságosan sokat árulnék el a filmről (ami amúgy nagyon tetszett), elég, ha annyit tudunk, hogy a filmben egy Turing-teszt zajlik, egy kicsit módosított változatban. Sajnos ez a módosított helyzet a Turing-teszt lényegét is megváltoztatja, hiszen a tesztelő tudja, hogy robot a partnere, ráadásul a robot igen vonzó női testben „él”, amit a tervezője ráadásul a tesztelő ízlése szerint készített el. A tesztelő heves érzelmeket táplál a tesztelendő fél iránt, ezzel a teszt lényege valójában sérül.

A tesztelő végül úgy dönt, hogy a robot átment a Turing-teszten, de ezt inkább az érzelmeire alapozza, mint a kérdésire érkezett válaszokra. Valójában több történik, a robot megtéveszti, átveri a tesztelőjét, ezzel tényleg úgy néz ki, hogy valóban képes emberi gondolkodásra, hiszen képes előre tervezni, befolyásolni egy embert, sőt még arra is képes, hogy megtévessze.

Fogadjuk el tehát, annak ellenére, hogy bár maga a Turing-teszt, amit a filmben elvégeztek, nem felel meg az eredeti követelményeknek, de a robot mégis elfogadhatóan, bizonyítottan emberként viselkedett, ebben az értelemben átment a Turing-teszten.

Na de mit jelent ez valójában? Mit jelent az, ha egy mesterséges intelligencia átmegy a Turing-teszten?

Azt semmi esetre sem, hogy tudata, én-tudata lenne. Azt sem jelenti, hogy valódi érzelmei lennének. Nem bizonyítottuk, hogy a robot tud a saját létezéséről, tehát nem bizonyítottuk, hogy ez a robot egyenértékű egy emberrel. Lehet, hogy egyenértékű, de lehet, hogy nem az, és nekem meggyőződésem, hogy sem bizonyítani, sem cáfolni nem tudjuk ezt, és soha nem is fogjuk tudni teljes bizonyossággal.

Amit igazolni tud a Turing-teszt, az az intelligencia jelenléte, és most intelligencián probléma megoldást értünk. Intelligens gépeket építhetünk, hiszen ennek egy módja az, ha összegyűjtünk minden eddigi kérdést, és választ, amit emberek valaha feltettek, minden problémát és megoldást, amit csak össze tudunk gyűjteni (a megvalósíthatóságról most elvi értelemben beszélünk, a gyakorlatban ez nyilván igen nehéz feladat lenne). Ehhez még hozzá teszünk egy gépi tanulást lehetővé tevő algoritmust, genetikai algoritmusokat, és amit még lehet, és ezzel létrehozható egy olyan gép, ami az emberek nagy részét már meggyőzné egy Turing-teszten. Emellett meg kell még említenünk azt a problémát is, hogy még egy ember is elbukhat a Turing-teszten, ha az elmeműködése korlátozott (műtét, betegség, alkoholos, vagy kábítószeres befolyásoltság, alvásmegvonás, ….) Ebben az esetben egy ember egy másik embert is minősíthet robotnak!

De ami az igazán lényeges, egy ilyen, minden lehetséges kérdés és válasz birtokában lévő gép, bár átmehet a Turing-teszten, semmiképpen nem minősülhet embernek.

És most érkeztünk el a tényleges és lényeges mondandónkhoz: semmilyen kísérlettel nem dönthető el, hogy egy másik létező egyenértékű egy emberrel, vagy sem. És ezen nem is érdemes fáradozni, erre törekedni körülbelül olyan, mintha az örökmozgó építésével próbálkoznánk, vagy a bizonyítás ellenére mégis megpróbálnánk megoldani a megállási problémát, vagy ellenpéldát találni a nagy Fermat-tételre, esetleg a görögök három, körzővel és vonalzóval megoldhatatlan problémáján törnénk a fejünket, vagy a Goldbach-sejtés, vagy az ikerprím-sejtés bizonyításával próbálkoznánk. Bár ez utóbbi kettő még talán bizonyítható, de most nagyon úgy néz ki, hogy olyan problémák, amik a Gödel-tétel alapján igazak, de sem nem cáfolhatók, sem nem bizonyíthatók.

El kell fogadnunk, hogy vannak az emberi elme számára megoldhatatlan problémák. Nem csak gyakorlati, hanem elvi okok miatt is.

Honnan tudhatjuk, hogy egy másik ember egyenértékű velünk? Hogy van-e én-tudata, vannak-e érzelmei, érzései? Hogy intelligens-e, ahhoz elegendő a Turing-teszt, vagy a szokásos intelligencia tesztek. Ezek mérhetik, hogy mennyire képes problémák megoldására. De attól, hogy valaki/valami intelligens, még nem biztos, hogy ember.

Emberek esetében el kell fogadnunk a hasonlósági elvet: minden ember ugyanúgy fogan, fejlődik, születik, felnő, majd meghal. Ugyanazokból az anyagokból vagyunk, DNS alapú az öröklődési rendszerünk, sejtekből állunk, minden sejtünkben a mitokondrium az „erőmű”, az agyunk is ugyanolyan (nagy léptékben) felépítésű, az idegrendszerünk ugyanúgy működik, hasonló helyzetekben hasonlóan reagálunk. Mivel én magamról tudom, hogy van tudatom, én-tudatom, érzek fájdalmat, örömöt és még annyi minden mást, ha sót teszek e nyelvemre, sós ízt érzek, ha piros dolgot látok, a piros érzete jelenik meg az agyamban. A hasonlóság alapján fel kell tételeznem, hogy a többi ember ugyanilyen. Van tudata, érzései, érzelmei, de azt már nem tudhatom, hogy a sós íz, vagy a piros szín ugyanazt az érzetet kelti-e benne, mint amilyen érzetek bennem keletkeznek.

Ami a lényeg: egy másik emberről a hasonlósági elv alapján elfogadhatom, hogy egyenértékű velem, bár szigorúan véve ezt sem bizonyítani, sem cáfolni nem tudom.

Az állatokkal kapcsolatban már nehezebb dolgunk van. A hasonlósági elv részben velük szemben is használható, de azt, hogy van-e tudatuk, nem tudjuk eldönteni. Valójában még abban sem lehetünk biztosak, hogy fájdalmat éreznek-e. Készíthető olyan gép, ami különböző külső hatásokra ugyanúgy reagál, mint egy állat, ha megszúrjuk, hangot ad ki, és visszahúzódik. Érzi vajon a fájdalmat? Kétlem. Az állatok éreznek fájdalmat? A hasonlósági elv alapján a válasz: igen. Hasonló a testfelépítésük, az öröklődési rendszerük, az idegrendszerük, ez elég ahhoz, hogy kijelenthessük, vannak érzeteik. Hogy érzelmeik vannak-e, az már a bizonyíthatatlan kategória, ehhez a hasonlósági elv már kevés.

A növények és az élettelen dolgok esetében a hasonlósági elv már nem használható. Mégis, vannak, akik abban hisznek, hogy még az élettelen tárgyaknak is van valamilyen „lelke”, „személyisége”, bizonyos értelemben én is hajlok ez irányban elfogadónak lenni, de ez már színtiszta hit, és nem tudomány.

A következő szint a földön kívüli értelmes élet. Mivel eddig ilyennel még nem találkoztunk, csak annyit állapíthatunk meg, hogy ha használható a hasonlósági elv, akkor könnyebb a dolgunk, de ha lényegesen különbözni fognak tőlünk, akkor ugyanaz a helyzet, mint a gépi intelligenciával kapcsolatban.

És most érkeztünk el a gépi értelemhez. Azt már beláttuk, hogy intelligensek lehetnek, azzal kapcsolatban viszont kétségeink vannak, hogy az ember-ekvivalencia megállapítható-e.

Most pedig nézzük a gondolatmenet legfontosabb részét, be fogjuk látni, hogy nem tudjuk sehogyan sem bebizonyítani, hogy egy másik lény érez-e, vannak-e érzelmei, van-e én-tudata. A probléma lényege a külső-belső, objektív-szubjektív ellentétpárokon keresztül ragadható meg. Én belülről látom magam, szubjektív érzéseim, érzelmeim vannak. Ha fáj a fogam, belül érzem, ha piros színt látok, én érzem a piros szín érzetét, soha senki más nem fogja tudni, milyen az, ha nekem fáj a fogam, milyen az, ha én látom a piros színt.

Ahhoz, hogy megtudjam, egy másik entitás ugyanazt érzi-e mint én, bele kell tudnom helyezni magam az ő helyébe, még pontosabban, a tudatomat bele kell tennem az ő tudata helyére. Ezzel mit is érek el? Ugyanazt fogom érezni az ő agyában, az ő testében, mint amit a saját agyamban, testemben éreztem. Bizonyítottam ezzel bármit is? Nem!

Úgy kellene belehelyezkednem a tudatába, hogy egyszerre legyek ő és én. Hogy esélyem legyen az érzéseink összehasonlítására. De ezzel sem csináltam semmit, az, hogy érzem az ő érzéseit, és érzem a magam érzéseit, és ezeket összehasonlítom, még mindig nem tudom, milyen „ő”-nek lenni. Miért? Azért mert még mindig a saját énemmel érzem az ő érzéseit is! Nem azt érzem, amit ő érez, hanem azt, amit én érzek, az ő érzéseit észlelve. Egyszerre kellene saját magam és valaki más lenni, és ez lehetetlen.

Még egyszerűbb kérdésekre sem tudunk válaszolni: kinek fáj a feje jobban? Belevezethetünk érzékelőket a két ember fájdalomközpontjába, és megmérhetjük a fájdalomingerek szintjét. De ugyanolyan szintű fájdalominger ugyanolyan fájdalmat vált-e ki a két ember tudatában? Nem tudhatjuk. Azért, mert nem tudjuk, hogy valójában hol tudatosulnak az érzetek. Hol van a tudatunk? Lokalizálható-e, vagy egy holisztikus az egész agyunkban, az egész testünkben, sőt esetleg azon kívül is jelenlévő jelenség?

Az agykutatás, az ideg-tudományok nagyon nagy fejlődésen mentek keresztül, de nem szabad azt hinnünk, hogy minden kérdésre választ adhatnak. A tudat valódi természete, hogy mit érez a többi ember, élőlény, esetleg élettelen tárgy, hogy lehet-e tudata egy gépnek, ezek a megválaszolhatatlan kérdések közé tartoznak. És nem azért mert buták vagyunk, ezekhez a kérdésekhez sosem leszünk elég okosak, mint ahogy örökmozgót sem tudunk építeni, és a megállási problémát sem fogjuk tudni soha megoldani.

Jobb ezeket a korlátokat elfogadni, és olyasmiken dolgozni, amiknek a megvalósítását nem teszi eleve lehetetlenné a Természet.

Tara Winstead fotója a Pexels oldaláról

A software tesztelés problémái

Mindig is bosszant, amikor akár egy operációs rendszerben, akár egy felhasználói programban bukkanok rá valamilyen hibára. Minél ostobább egy hiba, annál inkább tűnik érthetetlennek, hogy a mai korszerű programfejlesztő eszközökkel hogyan maradhatnak ilyen hibák egy termékben.

Talán mégsem annyira fejlett a programírás elmélete és gyakorlata, mint amennyire hinni szeretnénk ebben? Talán a kapkodás, a pénzhajhászás magyarázza a primitív hibák jelenlétét? Vagy valami egészen másról van szó?

Elkezdtem ezen gondolkodni, és elképzelni egy olyan tesztelő rendszert, amivel ki lehetne szűrni minden programozási és rendszer hibát. És arra jöttem rá, hogy ilyen rendszer nem készíthető, legalábbis ami a tesztek egyik fajtáját, a “black-box” (fekete-doboz, vagy külső) tesztelést illeti.

Ez olyan tesztelési technika, amikor a tesztelő nem rendelkezik a forrásprogrammal, csak a végleges termék van a kezében. Erről kell megállapítania, hogy hibátlan-e vagy sem. Mondjuk, hogy a kezében van a specifikáció, sorban ellenőrzi az abban foglalt elvárásokat, ha mindegyiket sorra vette, és nem talált a futtatás során hibát, akkor ugye hibátlannak tekinthető a vizsgált termék. Egyáltalán nem. A specifikáció ugyanis nem biztos, hogy tartalmazza a különleges eseteket is. Elfogy a hely a lemezen, elfogy a memória, megszakad a hálózati kapcsolat, a felhasználó olyan adatokat ad a programnak, amit a specifikáció szerint nem adhatna, de a felhasználó már csak ilyen, szándékosan, vagy véletlenül olyan feltételek közé viheti a programot, amire a specifikáció készítői nem gondoltak.

De még ha rendelkezünk is egy teljes specifikációval, amely minden határesetre és különleges helyzetre tartalmaz viselkedési leírást, akkor sem teljesíthetjük tökéletesen a tesztelési feladatunkat.

Ennek belátásához nézzünk meg egy nagyon egyszerű esetet, kapunk valahonnan egy max() függvényt (mondjuk egy DLL-ben), ami két egészet vár, és visszaadja a kettő közül a nagyobbikat. Le tudjuk-e úgy tesztelni black-box módszerrel ezt a függvényt, hogy kijelenthessük, a függvény 100%-osan hibamentes és minden körülmények között vissza fogja adni a két kapott egész érték közül a nagyobbat?

Írjunk egy tesztprogramot, tegyük bele a max(1, 2) és a max(2 ,1) hívást, mindkét esetben 2-t kell, hogy kapjunk eredményül. A biztonság kedvéért hívjuk meg a függvényt max(2, 2) módon is, ekkor is 2-t kell, hogy kapjunk. Készen vagyunk vajon a teszteléssel? A kód 100%-osan hibamentes?

Elvileg igen. A gyakorlatban számolnunk kell a rosszindulatú kódoló esetével, ez egy olyan programozó, aki szándékosan hibát rejt el a kódban, ezt ráadásul nagyon fondorlatos módokon tudja megtenni. Az elvileg 100%-osan hibamentes kódunk tehát valójában rengeteg hibát rejthet magában.

Mert mi van, ha a kódban van egy részlet, ami a kapott argumentumoktól függően működik, és ha valamelyik argumentum mondjuk 1 000 000, akkor nem a nagyobb, hanem a kisebb argumentumot adja vissza. Ezt csak úgy tudjuk tesztelni és a hibát detektálni, ha 1 000 000-ig mindenféle kombinációban meghívjuk a max() függvényt. És mivel nem tudhatjuk, hogy hol van a hiba elrejtve, ki kell próbálnunk nemcsak 1 000 000-ig, hanem a gépen ábrázolható maximális nagyságú egész számig minden hívás kombinációt.

Ez a teszt már tovább fog tartani, mint a legelső, lefuttatjuk, nem találunk hibát. Vajon 100%-osan hibátlannak nyilváníthatjuk most a függvényt?

Nem, még nem. A programozónk lehet még ennél is rosszindulatúbb, és elrejthet dátumhoz és időponthoz kötött hibát is. Ennek megtalálásához az összes elképzelhető dátumra és időpontra be kell állítanunk a gépünk óráját, és meg kell ismételnünk az összes lehetséges egész szám kombinációra a tesztet, hiszen a programozó a dátum-, és az argumentum vizsgálatot össze is kapcsolhatta úgy, hogy a függvény elképzelhető, hogy csak az elkövetkező ötven év egyetlen bizonyos másodpercében egyetlen kombinációra fog hibás választ adni, a többi esetben hibátlan lesz. De elég egyetlen hiba ahhoz, hogy a kódot ne tekinthessük tökéletesen hibamentesnek.

Azt hiszem, már látjuk a reménytelen jövőt. A rosszindulatú kódolónk az argumentumok és a rendszeridő mellé odaveheti a program méretét, az összes-, és a szabad memória méretét, azt, hogy egy bizonyos regiszterben páros-, vagy páratlan szám van-e éppen, letárolhatja, hogy hányszor hívták már meg, és ettől függően működik jól, vagy rosszul. Gyakorlatilag végtelenek a lehetőségek, emiatt pedig teljesen esélytelen, hogy emberi idő alatt végezzünk.

Persze mondhatjuk, hogy ezek a példák eléggé abszurd rosszindulatot tételeznek fel a kódolónk részéről, de mi most nem azt vizsgáltuk, hogy mennyire életszerű ez az elképzelés, hanem annak szerettünk volna utánajárni, hogy elvileg lehetséges-e a tökéletes black-box tesztelés.

Én az eddig elmondottak alapján bizonyítottnak látom, hogy külső eszközökkel nem állapítható meg egy programról, vagy kódról, hogy az hibátlan-e vagy sem. Még százalékos becslést sem tudunk mondani, hiszen nem tudjuk, hogy egy-egy felderített hibára hány felderítetlen jut.

Ezzel nem szeretném még véletlenül sem azt a látszatot kelteni, hogy felmentést érdemelnek mindazok, akik hibás kódot adnak ki a kezükből. Szó sincs erről. Egyszerűen tény, hogy a black-box tesztelés nem adhat nekünk teljes biztonságot.

Hogy akkor hol keressük a teljes biztonságot? Elsősorban a saját magunk számára készített saját kódunkban bízhatunk meg, hiszen arról tudjuk, hogy nem egy rosszindulatú kódoló írta, és nem abból a célból, hogy kárt okozzon vele. Másrészt fokozottan megbízhatunk azokban a nyílt forrású kódokban, amiket elvileg sokan ellenőrizhetnek, így kiderülhet, ha esetleg rosszindulatú kód van benne. Bár attól, hogy valami nyílt forrású, még nem biztos, hogy ellenőrzött. Elvileg minden nyílt forrású kód mellé kapnunk kellene egy ellenőrzési listát arról, hogy ki, mikor, milyen részeket, és milyen mélységig elemezte a kódot. Mondanom sem kell, ilyen manapság nem létezik, és elképzelni is nehéz hány ember-év kellene egy-egy nyílt forrású program ellenőrzési listájának elkészítéséhez. És ez a lista, csak az első módosításig lenne megbízható, utána felül kellene vizsgálni minden egyes módosítás után.

Mivel láttuk, hogy a black-box tesztelés milyen határok között megbízható, nézzük meg, hogy vajon javíthatunk-e a megbízhatóságán. Ehhez a “black-box”-ot valamennyire ki kell nyitnunk, azaz bele kell néznünk a kódba is. Ehhez nyomkövetőt, visszafordítót, vagy automatikus elemző programot használhatunk. Így már némileg több esélyünk van arra, hogy rátaláljunk egy-egy furcsa konstansra, vagy feltételes ugró utasításra, ami rosszindulatú kódra utalhat. Ez például egy max() függvény esetében még működhet is, de hát egy max() függvényt mi magunk is megírhatunk ahelyett, hogy a rengeteg időt az elemzésére fordítanánk. Csakhogy a kódok legtöbbször sokkal-sokkal bonyolultabbak a példánkban szereplő max() függvénynél. Egy nagyobb programban nyomkövetéssel, vagy visszafejtéssel rátalálni valamilyen rejtett kódra anélkül, hogy a teljes program működését megértenénk, nagyon nagy feladat.

Úgy néz ki tehát, hogy a “nyitott black-box” technikával, vagy akár a nyílt forrású kód elemzésével sem fogunk tudni eljutni a 100%-os bizonyosságig.

Hogy más eszközökkel juthatunk-e ennél messzebbre, arra példaként a legjobb, ha a víruskeresőket vizsgáljuk meg egy kicsit közelebbről, vajon ők milyen szintre jutottak a rosszindulatú kódok automatikus felderítésében. Sajnos azt mondhatjuk, nagyon sok a bizonytalanság. Amikor egy amúgy népszerű, széles körben használt, megvásárolt kereső heurisztikus elemzését kell kikapcsolni, mert olyan programokat töröl le, amik nélkül nem tudunk dolgozni (nem egyet saját magunk írtunk), akkor úgy tűnik, az elemzés vagy olyan kódot is gyanúsnak talál, ami nem az, vagy pedig túl engedékeny és elnéző, ezzel a valóban vírusos kódot is veszélytelennek mutatja.

Talán az automatikus kódelemzéstől 100%-os teljesítményt várni ugyanolyan lehetetlen elvárás, mint olyan program megírásában bízni, amely bármely másik programról megmondja, hogy végtelen ciklusba kerül-e, vagy megáll majd valamikor. Erről már tudjuk, hogy lehetetlen. Talán a kártékony kód és a programhibák automatikus elemzéssel történő 100%-os detektálása is ugyanilyen lehetetlen feladat. Erre persze nem tudok bizonyítással szolgálni.

Itt lenne az ideje annak, hogy valaki elkészítsen egy, Hilbert 23 pontos listájához (ami a matematika megoldandó problémáit sorolta fel) hasonló listát a nyitott, még megoldandó számítástechnikai problémákról, ezen a listán szerepelhetne a kérdés: “Lehetséges-e programhelyesség bizonyító programot írni, ha nem, akkor miért nem?”. Talán már látjuk is a választ a kérdésre, valószínűleg a megállási probléma megoldhatatlansága a kulcs itt is.

Tudom, hogy ha elkészülne egy ilyen program, akkor először ennek a helyességéről kellene meggyőződni, és talán ez az az ok, ami miatt soha nem fog elkészülni ez a program sem…

Nyíregyháza, 2018. szeptember 27 – 2019. április 7.