HTML

Az élet kódjai

Csináld maga. Senki nem csinálja meg helyetted.

Friss topikok

Mitózis detektálás idősoros képeken

2017.05.08. 00:23 Travis.CG

A csoportunkban igen intenzív mikroszkópos munka folyik. A szekvenálás, amit elemzek, csak egy része a kísérleteknek. A másik része a szövetek vagy sejtek időbeli változásának nyomon követése mikroszkópos képeken.

A legtöbb munkát a kutatók meg tudják oldani maguk is, de néha elkél nekik a segítség. Csak röviden említem, hogy sejtosztódásnál az utódsejtek nem azokos arányban osztódnak tovább. Az egyik utód sejt nem fog tovább osztódni. Ez biztosítja, hogy a szövet képes legyen fenntartani egy állandó állapotot. Ha viszont felborul ez az egyensúly, - márpedig ráknál pont ez történik - akkor a szövet burjánzásnak indul.

Az egyik projekt tehát, hogy figyelik, hogyan, miként változik a sejtosztódás. Ezt úgy csinálják, hogy egy ember ül a képernyő elött, nézi a képeket és klikkel. Úgyhogy egy csoport megbeszélésen a kutató nekünk szegezte a kérdést, tudunk-e valami módszert, amivel meggyorsíthatjuk a mitózis keresést.

Természetesen azt mondtam, hogy tudok. Az ötletem az volt, hogy betanítok egy neurális hálót, hogy ismerje fel a sejt osztódást.

Első lépésben szükségem volt egy tréning adatszettre. Mivel a munkatársam már végigszenvedte ezt, örömmel megosztotta velem az eredményt. Sajnos elég volt rá egy rövid pillantást vetni, hogy kiderüljön, nekem ez nem lesz jó. Maga a mitózis elég szépen felismerhető. Az egyik képen még egy sejt van, a következőn pedig kettő (sőt, néhány kivételes alkalommal három!). A kapott adatban viszont munkatársam néha a mitózis elejét jelölte be, néha a végét. Néha az egyik utód sejtet jelölte meg, mint pozíciót, náha a szülő sejtet. Ezek különböző kombinációiból állt az adat.

A másik dolog, ami miatt ez nem volt megfelelő tréning adatnak, az a negatív adatok hiánya. A hatékony tanításhoz nem csak azt kell beadni a neurális hálónak, mi a tényleges mitózis, hanem azt is, mi az, ami biztosan nem az.

Ezt rendbe kellett szedni. Először írtam egy elég primitív programot, amivel a kurzor billetyűkkel a képkockák között tudtam váltani, jobb egérgombbal pozitív adatot, ballal a negatív adatot definiálhattam. Kis kör jelölte, amit a kollégám azonotított. Esc-re kilépett, mint egy demo :-) Ezzel elég gyorsan újra definiálhattam az adatokat.

A második lépés a neurális háló tanítása volt. Először is a mikroszkópos képeket be kellett olvasni:

vector<Mat> frames;
imreadmulti("pic.tif", frames);

Létre kellett hozni a mátrixokat. Összesen négy mátrixra volt szükségem. Kettő a tréning adatnak, kettő a teszt adatnak. OpenCV-ben egy mátrix az értékeket tartalmazza, amivel tanítjuk a neurális hálónkat, egy pedig az eredményt, amit kapni szeretnénk. A teszt adat pontosan ugyan ilyen felépítésű lesz, de azzal más terveim voltak.

Mit fognak tartalmazni a mátrixok? Először is, a pixelek intenzitását. A vizsgált kép 40x40-es, ami nem tűnik nagynak, de 1600 pixelt tartalmaz. Ez még csak egy kép. Ha a mitózis előtti állapotot is bele akarjuk rakni, az újabb 1600 pixel lesz. Ha van 600 adatsorunk, a mátrix 3200x600 méretű lesz (vagy 600x3200, ízlés kérdése, az OpenCV mindkettőt elfogadja).

Az eredmény az én esetemben egy oszlop volt, 600 sorral (minden tréning adathoz egy). Az érték pedig -1, ha nem történt mitózis, 1, ha történt. A neten sok példaprogram a 0-1 számokat használja. Én úgy tapasztaltam, a -1 - 1 jobb eredményt ad.

Mat train_data(600, 3200, CV_32FC1);
Mat train_label(600, 1, CV_32FC1);

Ezeket a mátrixokat feltöltöttem adattal. A teszt adatszettet ugyan így készítettem elő. Kellett még néhány paraméter, például meddig tanuljon az algoritmus, mikor álljon le.

TermCriteria termCrit = TermCriteria(
        TermCriteria::Type::MAX_ITER,
        500,
        0.0001
        );

Ez azt jelenti, hogy max 500 ciklus fog lefutni vagy akkor áll meg, ha az újabb adatsor tanulásával az eredmény csak picit változik. Ezt a két értéket nyugodtan lehet változtatni. Javaslat: amíg a program a hibakeresés, tesztelés fázsban van, érdemes a ezeket az értékeket használni, mert a program gyorsan le fog futni. De amint készen vagyunk és a háló hatékonyságát nézzük, az 500-t akár 10 millióra is emelhetjük, a másik paraméter meg még alacsonyabb lehet.

Mat layers = Mat(4, 1, CV_16U);
layers.row(0) = Scalar(3200);
layers.row(1) = Scalar(800);
layers.row(2) = Scalar(800);
layers.row(3) = Scalar(1);

Ez lesz a hálózatunk topológiája. 3200 bemeneti neuron, két rejtett réteg egyenként 800 neuronnal, majd 1 kimeneti réteg. Igazából nincs arra egzakt szabály, mennyi köztes réteg legyen és azok mennyi neuront tartalmazzanak. Ami szabály van, azok sokkal több matematikai tudást igényelnek, mint ami nekem van. A próba-szerencse módszer sokkal célravezetőbb volt.

Ptr<TrainData> td = TrainData::create(train_data, SampleTypes::ROW_SAMPLE, train_label);

Itt csak összepárosítottam az adatot és az elvárt eredményt, valamint megmondtam a rendszernek, hogyan értelmezze a mátrixokat. Jelen esetben soronként.

Ptr<ANN_MLP> mlp = ANN_MLP::create();
mlp->setTrainMethod(ANN_MLP::TrainingMethods::BACKPROP, 0.1, 0.1);
mlp->setTermCriteria(termCrit);
mlp->setLayerSizes(layers);
mlp->setActivationFunction(ANN_MLP::ActivationFunctions::SIGMOID_SYM, 1, 1);
mlp->train(td);

Végül összeállítottam a neurális hálót és betanítottam. Ezen a ponton pár dolgot kiemelnék. A setActivationFunction-t érdemes a setLayerSizes után meghívni, különben értelmezhetetlen lesz az eredmény. Ha a setActivationFunction-t SIGMOID_SYM-re állítjuk, az utána lévő két paramétert is állítsuk be, mert alapértelmezetten 0-k és szintén furcsa, nehezen felderíthető hibát okoznak. (Egy teljes hétvégém erre ment rá, hogy rájöjjek.)

Kész a tanítás, mennyire jó a rendszer? Most volt szükségem a teszt adatszettre.

Mat response;
mlp->predict(test_data, response);

A response változó pont olyan dimenziójú, mint a train_label. Csupán össze kell hasonlítani a test_data-hoz tartozó eredménnyel és máris megtudjuk. Ne várjunk teljes hasonlóságot! Én -1 és 1-t adtam meg, de e két érték között bármilyen értéket kaphatunk, attól függően, a rendszer mennyire "biztos" az eredményben. Ha egynél nagyobb vagy -1-nél kisebb számot kapunk, valószínűleg a neurális hálónk nem tanult jól. Adjunk neki több adatot, ha tudunk, vagy játszunk a paraméterekkel.

Nekem sokáig nem adott rendes eredményt a program. Már ott tartottam, hogy előadást tartok a módszerről, de a program még mindig nem működött. (Prediktálás után nan-t kaptam. nan=not a number) Végül az előadás után egy héttel jöttem rá, hogy a tréning adat teljesen rossz. Egy nagyon amatőr kasztolási hibát ejtettem, amitől csupa szeméttel tanítottam a hálót. Természetes, hogy hülyeséget adott vissza.

A poszt írásának pillanatában 72%-os hatékonysággal működik, amivel nem fogok gépi tanulás versenyeket nyerni, de arra jó lesz, hogy lerövidítse a klikkelések számát.

Szólj hozzá!

Címkék: opencv machine learning

A bejegyzés trackback címe:

https://cybernetic.blog.hu/api/trackback/id/tr7912486585

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása