A blog.hu a legnagyobb magyar nyelvű blog platform. Ha valakinek sikerül kikerülni a címlapra a szolgáltatónál szinte biztosan jó olvasottságot tud elérni a bejegyzése számára. Viszont a blogmotornak megvannak a maga hiányosságai. Ezek egyike a matematikai kifejezések támogatásának hiánya. Ebben a bejegyzésben megnézünk egy egyszerű módszert arra, hogy ne kelljen ezeket képként beszúrni.
In medias rex, a dolgok közepébe vágva: Létezik egy olyan nyelv, a Markdown. Ezt, ezt fogjuk használni a probléma megoldására.
Egy kis bevezetés annak, aki még nem hallott erről a nyelvről: A Markdown olyan egyszerű szintaxisú szövegszerkesztésre használt nyelv, amit kifejezetten arra dolgoztak ki, hogy növeljék a produktivitást. A lényeg: soha sem kell felemelnünk a kezünket a billentyűzetről, lényegében minden egyes szövegszerkesztési feladatot elvégezhetünk gépelés közben. Online publikáció írásakor a Markdown napjainkban az egyik legnépszerűbb megoldás. Több szerkesztő elérhető az interneten Markdown szövegek szedésére. Én most ezek közül a μr² megoldását fogom használni.
Térjünk a lényegre és nézzünk egy példát.
Ez egy görög betű a szövegben: . Ez pedig egy matematikai kifejezés blokkban:
Ami Markdownban egyszerű LaTeX bevitelt jelent $$ jelek között:
Ez egy görög betű a szövegben:$$\sigma$$.
Ez pedig egy matematikai kifejezés blokkban:
$$
P_{\omega}=\hbar\omega\,\frac{1+R}{1-v^2}\int\limits_{-1}^{1}dx\,(x-v)|x-v|
$$
Ha megírtuk Markdown-ban a bejegyzésünket, akkor a következő módon tudjuk importálni a blog.hu-ba:
Először nyissuk meg a μr² szerkesztő oldalsó menüjét, a jobb felső sarokban lévő ikonra kattintva. Valami ilyesmit fogunk látni:
Majd állítsuk HTML-re az előnézetet, az oldalsó menü HTML pontjára kattintva. Ekkor a szerkesztő bal oldalán a bejegyzésünk nyers HTML kódját fogjuk látni. Ezt el is menthetjük, de ha nem túl hosszú, akkor csak jelöljük ki és másoljuk be egy blog.hu bejegyzés HTML részébe:
Készen is vagyunk.
Matematikai képletek mellett a Markdownt több olyan dologra is tudjuk használni ami talán egy kicsit nehézkes a blog.hu-ban. Mire gondolok? Például lábjegyzet[1], formázott táblázat vagy irodalomjegyzék. Akit érdekelnek a részletek vessen egy pillantást a μr² felhasználói kézikönyvére.
Az előző részben átnéztük, a Neurális Hálózat részeit és a lejátszási szakaszt. Most folytassuk a Hibaszámítással és a Visszajátszással!
Hibaszámítás
Az előző részben, a lejátszás végén kaptunk egy előrejelzést a bemeneti adatok alapján. A konkrét példánk esetében ez így alakult:
Mivel felügyelettel végrehajtott tanulást végzünk ismerjük a bemeneti adatok tényleges eredményét. Semmi akadálya tehát, hogy összevessük ezt az eredményt az MNH előrejelzésével. Nem meglepő, hogy a kettő különbsége lesz az előrejelzés hibája. Több módon számíthatjuk ezt az értéket, az egyetlen megkötés, hogy részekben deriválható legyen. A legegyszerűbb, és amit itt mi is alkalmazunk, a négyzetes hiba:
Ahol:
E — a Hiba
y — a valós eredmény
Számítsuk is ki a korábbi példán, legyen mondjuk a tényleges eredmény:
Ennek megfelelően a Hiba:
y = np.array([0,1])
e = 0.5*(y-o)**2
print("Teljes hiba: ", sum(e))
Aminek az eredménye:
Ezzel a lépéssel készek is vagyunk. Most már csak tanulnunk kell a tévedésből, ez lesz a Visszajátszás.
Visszajátszás
Ebben a lépésben frissítjük a Hálózat beállításait annak megfelelően, hogy mekkora részben járultak hozzá az előző lépésben számított Hibához. Ezt a frissítést most visszafelé haladva hajtjuk végre a rendszeren. Vagyis az adatáramlás így alakul:
Hogy miért visszafelé tesszük ezt? Ennek számítástechnikai oka van, amit majd lentebb bemutatok.
De mit is frissítünk konkrétan? Ha valaki odafigyelt, akkor nyilvánvaló a számára, hogy az MNH-nak csupán egyetlen része nem fixen meghatározott: a súlyok. A visszajátszás során ezeket állítjuk. Ugye, így szabályozzuk, hogy az előző rétegben az egyes tulajdonságoknak mekkora szerepük legyen az adott neuron kimeneti értékében.
Most nézzük magát a konkrét számítást! Ez egy minimalizációs probléma: azt szeretnénk, hogy a Hiba minél kisebb legyen. És a Hiba ott a legkisebb, ahol a deriváltja nulla. Legalábbis elméletileg. A gyakorlatban lehetségesek olyan lokális minimumok, amelyek kielégítik ezt a feltételt, és mégsem a legjobb megoldások. Amint azt a nevük is mutatja, csak lokálisan a legjobbak. Ezt mindig tartsuk az észben! A MNH csupán azt garantálja, hogy a lokális minimumot megtaláljuk, de azt nem, hogy ez valóban a legjobb megoldás a lehetséges megoldások végtelenjében.
A kimeneti réteg súlyainak hibája
Térjünk vissza a számításra! Az első lépésben azt nézzük meg, hogy a Kimeneti réteg egyes súlyainak mekkora szerepük volt a Hibában. Ezt az értéket fogjuk gradiensnek nevezni. Hogy ezt kiszámoljuk, deriválnunk kell a Hibát az egyes súlyokra. Nézzünk egy konkrét példát, a súlyt:
Vegyük észre, hogy a csak egyetlen egy hibához, a hibájához járul hozzá. Az teljesen független tőle. Ugye, a négyzetes hibában nem szerepel a , tehát ez a parciális deriválás nem lesz egy lépésben elvégezhető művelet. A láncszabályt használva vissza kell fejtenünk az egyenletet a keresett súlyig. Először is írjuk fel a Hibát, úgy, hogy lássuk a keresett elemet:
Most már látjuk a v súlyokat. Úgyhogy felírhatjuk a parciális deriváltak sorát. Először deriváljuk a -t az -hez tartozó hibából:
Lépjünk egyel visszább, most az -ból a -t. Ez egy kicsit trükkösebb, mivel a ReLU nem deriválható egy az egyben, csak két részben: külön eset ha kisebb, mint 0 és külön eset, ha nagyobb.
És a következőben már meg is érkeztünk a -hoz. Vegyük észre, hogy itt a deriváltnál szintén két lehetőség van: 1 ha az eltolásra deriválunk, és 1 ha bármelyik másra:
A fentieknek megfelelően a Hiba -ra számolt részderiváltja:
Ami behelyettesítve:
Ez azt fejezi ki, hogy mekkora részben felelős a a Hibáért. Mivel csökkenteni akarjuk a hibát, ezért az így kapott eredményt ki kell vonnunk a jelenleg beállított súlyból, hogy a következő alkalommal jobb eredményt kapjunk. Ennek megfelelően a frissített súly így alakul:
Ahol:
— a tanulási ráta. Erre most nem térek ki, maradjunk annyiban, hogy gradient descent tanulást alkalmazunk.
Gondolom, már mindenki rájött, hogy a lejátszáshoz hasonlóan, ezt se kell egyesével számolni a neuronokra. Rétegenként is elvégezhetjük egyszerű lineáris algebrával:
Most már csak frissíteni kell ezzel az értékkel a kimeneti réteg súlyait az elözöeknek megfelelően. De mielőtt ez megtennénk számoljuk ki a Rejtett réteg súlyainak gradienseit. Ajánlott előszőr minden gradienst kiszámolni és csak utána frissíteni az összes súlyt. Miért? Mindjárt kiderül.
A Rejtett réteg súlyainak hibája
Az alapvető eljárás ugyanaz lesz itt is mint a Kimeneti réteg esetében, azzal az eltéréssel, hogy itt még visszább kell fejteni a láncszabály segítségével. Ami még megbonyolítja az életünket, az az, hogy a Rejtett rétegben nem csak 1 irányból érkezik az adat, hanem a Kimeneti rétegben lévő minden neurontól. Nézzük például a súlyt:
A fenti ábrán pirossal jelöltem, honnan származnak az információk, amelyeket ennek a súlynak a frissítésére használunk. Egyértelmű a különbség a Kimeneti réteghez képest. Ott a neuronokra csak egy irányból érkezett információ, ezzel szemben a Rejtett rétegben az előző rétegben lévő minden neuron befolyásolja, hogy milyen módon frissítjük a súlyt. Ennek megfelelően a -nak megfelelő parciális derivált a következő lesz:
Ahol:
— a Rejtett réteg 1. neuronjának kimenete
Vegyük észre, hogy menyire hasonlít ez a Kimeneti réteg egyenletére. Számítása is hasonló lesz, csak az első részderivált okozhat némi problémát. Ez a rész arra válaszol, hogy összességében mekkora hibát generált ez a súly a következő rétegen. Vagyis:
Hogyan valósítsuk meg ezt a gyakorlati életben? Úgy, hogy a Visszajátszás során minden előző rétegben kiszámoljuk, ezt az értéket, és csak ezt passzoljuk vissza az előző rétegnek. Ez a magyarázata annak, amiért nem frissítjük a súlyokat egyből, amint kiszámoljuk a hibájukat. Ha így tennénk az összeadás elemei megváltoznának.
Az összeadásban szereplő elemeket meg így általánosíthatjuk:
A konkrét számtani példánál maradva az eredmény pedig a következő:
A Súlyok frissítése
Most már, hogy ismerjük az össze súly hibáját, nyugodtan frissíthetjük őket:
eta = 0.002
v = v-eta*v_gradient[:,1:]
v0 = (v0.T - eta*v_gradient[:,0]).T
w = w-eta*w_gradient[:,1:]
w0 = (w0.T - eta*w_gradient[:,0]).T
Aminek megfelelően az új súlyok a következők lesznek:
Befejezés
Ezzel készen is vagyunk. Átnéztük a MNH alapvető lépéseit és elemeit. Napjainkban már persze egy rakás szoftver könyvtár elérhető MNH megvalósítására, és általában azokat használjuk a gyakorlati életben. Viszont, ha anélkül használunk valamit, hogy valóban értenénk a működését, fennáll a veszélye annak, hogy az „mágiává” válik. Sokszor mint valami Delphoi orákulumot kezelik a Neurális Hálózatokat. Ami sajnos magával hozza a rossz felhasználásokat is. Ez a lehetőség maga is megérne egy újabb bejegyzést, de nem részletezem, hanem végszó gyanánt álljon itt két fontos megjegyzés:
Minden MNH annyit ér, amennyit az adat, amivel tanítjuk.
Csak a lokális legjobb válasz megtalálása garantált.
Napjaink igen felkapott elnevezéseinek egyike minden bizonnyal a Mesterséges Neurális Hálózat (MNH), avagy Artificial Neural Networks (ANN). Ami jórészt annak köszönhető, hogy e technológiának a mindennapi életben való alkalmazásai az emberek egy jelentős részét lenyűgözi. Az MNH az alapja sok arcfelismerő, képfeldolgozó megoldásnak, a Google-fordítónak vagy a Facebook-hirdetés optimalizációjának, hogy csak néhányat említsek. Mai posztomban a legegyszerűbb MNH-t, az un. Feedforward-típust törekszem egy kicsit részletesében bemutatni.
In medias res, kezdjük a neurális hálózat részeivel! Ehhez rajzoltam egy diagramot:
Elsőre talán bonyolultnak látszik, de valójában nagyon egyszerű. Ha jól megnézzük a fenti ábrát, láthatjuk, hogy csupán két fajta objektumból épül fel:
a körök — az úgynevezett neuronok. Ezek végzik a számítást.
a nyilak — a neuronok közötti kapcsolatokat jelölik. A fenti ábrán minden neuron kapcsolódik minden neuronhoz a következő rétegben. Ezt az elrendezést „teljesen csatolt” rendszernek nevezzük. (Van olyan eset is, amikor ez nem így van. Ilyenkor „részlegesen csatolt” a rendszer, de a mi példánk nem ilyen.)
Az alapelemek nem véletlenszerűen helyezkednek el a térben, hanem rétegekbe rendezve. Három rétegtípusról beszélhetünk:
Bemeneti réteg — gondolom, senkit nem lepek meg, ha azt mondom, hogy a megfigyelt adatok itt érkeznek a hálózatba. Ebből a rétegből jobbára csak egy van (a kivételekkel most nem foglalkozunk). A rétegben elhelyezkedő neuronok mind egy-egy tulajdonságot, megfigyelési dimenziót jelölnek.
Rejtett réteg — a számítások helye. Ennek a rétegnek a célja modellezni a bemeneti rétegben feltüntetett tulajdonságok kapcsolatát. (A fenti példában egy rejtett réteg van, de voltaképpen akármennyi követheti egymást, akár elhagyhatjuk is ezt a réteget.).
Kimeneti réteg — beszédes neve szerint ez az utolsó réteg, az MNH eredményének helye.
Most nézzük a többi kifejezést az ábrán:
xn — az n tulajdonság megfigyelt értéke
w0m — a rejtett réteg neuronjára jellemző eltolás
wnm — a bemeneti és a rejtett réteg közötti kapcsolatokhoz rendelt súlyok. Az indexek a rétegeknek megfelelő neuronokat jelölik. Pl: w12 a bementi réteg 1. neuronját köti össze a rejtett réteg 2. neuronjával.
fr — a rejtett réteg aktivációs függvénye. Erről később lesz szó. Most csak azt vegyük észre, hogy a réteg összes neuronján megegyezik.
zm — az aktivációs függvény – az előző réteg kimenetéből és a súlyokból számolt – bemenete.
v0p — a kimeneti réteg neuronjára jellemző eltolás.
vmp — a rejtett és a kimeneti réteg közötti kapcsolatok súlyai. Az indexelés ugyanazon az elven működik, mint a wnm -nél.
fk — a kimeneti réteg aktivációs függvénye, hasonlóan a rejtett réteghez, a rétegen belül minden neuronon ugyanaz.
up — a kimeneti réteg aktivációs függvényének bemenete.
op — a hálózat végső eredménye.
Most, hogy ismerjük a MNH részeit, nézzük, hogyan mozog az adat a rendszeren belül. Ehhez idézzük fel, hogy minden felügyelettel végrehajtott tanulás lényegében három részből áll:
Alkalmazzuk a már meglévő ismereteinket egy megfigyelésen, azaz az eddigi ismereteink alapján kiszámoljuk, hogy mi lehet a megfigyelés eredménye.
Összevetjük az előző lépésben kiszámított eredményt a tényleges eredménnyel. Ha a kettő nem egyezik meg, akkor kalkuláljuk az eltérés mennyiségét és irányát. Lényegében Loss kalkulációt végzünk.
Korrigáljuk az ismereteinket, annak megfelelően, hogy mekkora és milyen az előző pontban kiszámított hiba.
A Feedforward-típusú MNH első lépését nevezzük Lejátszásnak (Forward propagation), a másodikat a Hibaszámításnak, míg az utolsót a Visszajátszásnak (Back propagation). Gondolom, senkit se lepek meg, ha elárulom, hogy a lejátszás során az adatok a Bemeneti réteg felől a Kimeneti réteg felé haladnak. Az első ábrám ezt a lépést szemlélteti. Ezzel szemben a Visszajátszás során az ellenkező irányba haladunk:
Most, hogy ismerjük a hálózat alapvető felépítését, nézzük meg, mi a konkrét kivitelezése az egyes lépéseknek.
Lejátszás — Előrejelzés
Mint fentebb említettem, az összes számítás a neuronokban történik. De mit is csinál egy neuron? Lényegében hipersíkokat állít elő. Magát a konkrét számítást, amit végez, így lehetne megjeleníteni:
A fenti ábra a j rejtett rétegbeli neuron működését szemlélteti, de minden, nem a Bemeneti rétegben elhelyezkedő neuron ugyanígy működik. Első lépésben összeadja a bemeneti adatok súlyozott értekét. Ez lesz a zj . Vegyük észre, hogy van egy bemeneti érték, ami mindig 1, ez az eltolás. Vagyis:
Majd ezen a zj-én alkalmazza a fr aktivációs függvényt. És ezzel kész is van. A függvény kimeneti értéke már megy is a neuron kimenetére. Miért kell az aktivációs függvény? Azért használjuk, hogy a lineárisan nem elválasztható feladatokat is meg tudjunk oldani.
Hogy ne csak elméletben legyünk képesek megoldani ezt a feladatot, számszerűsítsük a fenti modellt, valahogy így:
Mivel elég kusza lett volna, ha minden számot feltűntetek a fenti ábrán, csak néhány értéket ábrázoltam. A teljes kezdeti állapot legyen a következő:
Nézzük az első neuront a Rejtett rétegben. Ennek a z1 értéke az (1) alapján:
Aki egy kicsit járatos a lineáris algebrában, az már biztosan rájött, hogy nem kell minden neuront külön-külön kiszámítanunk, hanem a számítást rétegenként egyszerre elvégezhetjük:
import numpy as np
# megfigyelés x = np.array([.05, .1])
# rejtet réteg súlyai w = np.array([[.25,.35],[.55, .65],[.85, .95]])
A Rejtett réteget be is fejeztük. Most ismételjük meg ugyanezeket a lépéseket a Kimeneti rétegben. A lépések ugyanezek, az egyetlen különbség, hogy az aktivációs függvény ReLU lesz:
Ne is húzzuk az időt, nézzük mi a Kimeneti réteg eredménye:
class ReLU():
def run(self, x):
return np.maximum(0,x)
def derivate(self, x):
x[x0] = 1
return x
# kimeneti réteg súlyai
v = np.array([[0.3,0.4,0.5],[0.7,0.8,0.9]])
# kimeneti rétek eltolása v0 = np.array([[.2],[.6]])
# kimeneti réteg u = (np.concatenate((v0, v), axis=1))@np.insert(o_r,0,1,axis=0) f_k = ReLU() o = f_k.run(u)
Aminek az eredményei:
Mind a két szám pozitív, így nem meglepő módon a ReLU aktivációs függvény nem változtat rajtuk:
Végére is értünk a Lejátszási szakasznak.
A következő lépésben meg kell néznünk, hogy mekkora hibát követtünk el, és a beállításokat ennek megfelelően kell frissítenünk. Ezt fogjuk a következő blogbejegyzésben megtárgyalni.
a.k.a Miért megszámolható a Racionális számok halmaza és miért nem a Valósoké?Valószínűleg a lustaságom az oka annak, hogy reggel azon gondolkodtam: miért duplázzuk meg a valószínűségszámítást azzal, hogy ugyanazt a számítást felírjuk külön diszkrét és külön folytonos esetre.
Bevezetés
Az diszkrét és folytonos esetek közötti egyetlen különbség az, hogy a diszkrét esetben Összegzést a folytonos esetben Integrált használunk. Nézzük például a valószínűségi Tömegfüggvényt[1] és a Sűrűségfüggvényt[2]. Mind a kettő ugyanazt mutatja: mekkora a valószínűsége, hogy x értéket figyeljük meg a populációból.[3] Nézzünk egy példát:
Mint tudjuk a teljes valószínűség a Sűrűségfüggvény alatti terület:
A Tömegfüggvény esetén pedig:
Ez eddig egyszerű, de mi van akkor, ha sokkal de sokkal több pontunk van a Tömegfüggvényben? Pl:
És mi van ha mondjuk végtelen sok pont? Az elég folytonosnak látszik nem? Nekem erről ez jutott eszembe:
Na mi ez? Igen-igen. A Darboux felső integrál számítás szemléltetése. A határozatlan integrálás célját általában úgy szokták bevezetni, hogy: “az görbék alatti területek kiszámítására való”. Majd következik a fenti ábra.
Ebből a hozzám hasonló egyszerű lelkek azt gondolják, hogy az integrál lényegeben egyfajta Összegzés: Van egy rakás végtelenül kicsi szélességű oszlopunk és összeadjuk a területüket. De milyen kicsi az a végtelenül kicsi oszlop szélesség? Leibniz és Newton nemes egyszerűséggel nem foglalkoztak ezzel a kérdéssel, amiért sok kritikát kaptak később. Viszont mi megtesszük, nem mintha sokkal okosabbak lennék, hanem mert mások már elvégezték a munkát számunkra és mindig könnyű más tollaival ékeskedni. Tehát mi legyen ez a végtelenül kicsi szám? Ha mondjuk az mondom hogy legyen a legkisebb pozitív Racionális szám? Vagy inkább a legkisebb pozitív Valós szám? Mi az pont amikor azt mondjuk ez még diszkrét, (tehát összegezzük), de az már folytonos (tehát integráljuk).
Maga a definíciója a diszkrétnek megadja a választ erre a kérdésre. Diszkrét az ami megszámolható, a folytonos pedig nem. A folytonosság pedig alapfeltétele az integrálásnak. És ezzel elérkeztünk ahhoz, amiről lényegében írni szeretnék. Miért megszámolható a Racionális számok halmaza és miért nem a Valósoké?
Miért megszámolhatóak a Racionális számok?
Van egy számhalmaz, ami definíciója szerint megszámolható, ez a Természetes számok halmaza (jele az N). Ezt nekem úgy tanították az általános iskolában, hogy a pozitív egész számok halmaza.[5] Ezek a számok a 0, 1, 2, 3, 4 … számok, és a dolgok számosságát jelentik. Ha erre emlékszünk, akkor már egy nem nagy logikai ugrással tudjuk, hogy valami csakis akkor megszámolható, ha egy az egyben le lehet vetíteni[6] a Természetes számok halmazára.
Vagyis ha a Racionális számok (jele a Q) megszámolhatóak, akkor ez a vetítés lehetséges. De nincs itt valami ellentmondás? A Természetes számok a racionális számok alhalmaza nem?
Legalább mintha így tanítanák: minden N benne van az Egész számok halmazában (jele a Z), és minden Z benne van a Racionális számok halmazában. Logikus. De ha ez igaz akkor, nem kellene a Q halmaznak nagyobbnak lennie mint az N halmazé?
Nem. Ezt pedig először egy bizonyos Georg Ferdinand Ludwig Philipp Cantor nevű német matematikus ismerte fel. Neki köszönhetjük a megszámolható és megszámlálhatatlan halmazok megkülönböztetését.
A trükk ott van, hogy minden megszámolható ami sorba rendezhető. ??? Igen, itt bizony a természetes számok egy eltérő értelmezésével állunk szemben. Az N halmaz elemeit két oldalról közelíthetjük meg:
egyrészt tekinthetjük mint: 0,1,2,3… — Ezeket nevezzük Kardinális számnak, és matematikába való bevezetésüket szintén Cantor-nak köszönhetjük. Értelmük lényegében megegyezik az elemszámával, vagyis a “Mennyi?” kérdésre válaszolunk vele. Például az {a, b, c, d, e} halmaznak 5 a kardinális száma, mivel 5 eleme van.
másrészt mint: első, második etc. — A második értelmezést nevezzük Rendszámnak[7], és a “Melyik?” kérdésre válaszolunk velük.
A Racionális számok pedig sorba rendezhetők. Mégpedig az alábbi módon:
Ez nagyon érdekes. Ez azt bizonyítja, hogy ugyanannyi Természetes számunk van mint ahány Racionális számunk. Mennyi? Végtelen! De ez a két végtelen egyenlő.
Minden végtelen egyenlő, de a Valós számok végtelenje egyenlőbb
De akkor miért nem megszámolhatóak a Valós számok? Az is végtelen számú nem? Igen! De ez a végtelen nagyobb mint az előző. Ezt pedig a Átlós eljárással lehet könnyen bizonyítani:
Úgy néz ki Cantor lendületben volt a Racionális számok megszámolása után és úgy gondolta akkor megnézi hány darab Valós szám van. Mint kiderült ez nem megszámolható. Ehhez először azt bizonyította, hogy 0 és 1 között megszámolhatatlan sok van. A bizonyítás első lépésében felírunk egy rakás racionális számot egymás után. Pl. nulladik legyen a 0,236436775676…, az első mondjuk 0,098473294543… és így tovább. Tegyük fel, hogy rengeteg időnk van és felírjuk az összes (végtelen mennyiségű) lehetséges Racionális számot. Ezután vegyük a felírt számok átlóját, a fenti képen pirossal jelöltem ezt. Ez átlón szereplő számjegyek egy számot adnak nekünk. A fenti példában: 0,293233992132… Ebből a számból készíthetünk egy új számot, méghozzá úgy, hogy az minden számjegyét kicseréljük egy számra ami nem egyezik vele, és 0-val vagy 9-el.[8] Például az első kettes helyébe írjunk 7-et (bármit írhatunk kivéve 2, 0 és 9), a második 9 helyébe mondjuk 4-et. A lényeg csak, hogy ne egyezzen. Mit tudunk az így kapott számról (a példában 0,746894310875…)? Nem egyezik a nulladik számmal, mivel az első tizedesnél eltér tőle. Nem egyezik az első számmal, mivel a második tizedesnél eltérnek … Vagyis nem egyezik egyik számmal se a listán. És mit jelent ez, ha felírtuk mind a végtelen mennyiségű Racionális számot? Pontosan! Ez a szám nagyobb mint az a Természetes számok végtelenje.
Csodálatos! Egyrészt kiderült, hogy a végtelenek nagysága nem egyforma, másrészt, hogy több Valós szám van mint Természetes. A második következménye pedig, hogy a Valós számok halmaza nem megszámolható, tehát nem diszkrét. A csodálatos dolog, hogy két egymáshoz végtelenül közel lévő Racionális szám között is végtelen számú Valós szám van. Ez a folytonosság.
Röviden ez az oka annak, hogy mindent kétszer mondunk el a valószínűségszámításban…
Nem egyenlő végtelenség
a.k.a. miért nem integrálunk mindent?
Lássuk be: lusta vagyok. Ennek egyik következménye, hogy néha olyan dolgokon gondolkodom amin jó dolgos emberek nem. Valószínűleg ez az oka, hogy reggel azon gondolkodtam miért duplázzuk meg lényegében a valószínűségszámítást azzal, hogy ugyanazt a számítást felírjuk külön diszkrét és külön folytonos esetre.
Tudom-tudom. A Sűrűségfüggvénynél nincs a pont értéknek valószínűsége, és a terület fejezi ki az adott valószínűséget, míg a Tömegfüggvénynél van. De ez a különbség a számítás módjából következik. Most pont erről van szó. Miért használjuk az egyik vagy másik számítási módot. ↩︎