HTML

Az élet kódjai

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

Friss topikok

Lineáris modellek

2017.02.28. 02:24 Travis.CG

A lineáris regresszió az egyik legegyszerűbb gépi tanulás módszer. Tudat alatt mi is sokszor használjuk, ezért a mögötte álló logika könnyen elsajátítható. Az alapkoncepció ugyanis az, ha egy mennyiséget növelünk, egy másik érték is növekedni fog. Egy hétköznapi példával élve, ha a kutyánknak több kaját adunk vacsorára, a súlya is növekedni fog. Itt az étel mennyisége és a kutya súlya áll kapcsolatban.

Ha tovább gondoljuk a példát, akkor érezzük, azért csupán a vacsora mennyisége, habár befolyásolja a testtömeget, nem elég, hogy pontosan meghatározzuk kutyánk tömegét. Tegyük fel, hogy rossz gazdik vagyunk és megengedjük állatunknak, hogy a szemétben is kotorásszon a séták idején. Kedvencünk súlyát tehát a szemétből kihalászott finomságok és a vacsora együttesen jobban meghatározzák, mint a vacsora egymaga.

Modellünknek immár két függő változója van (szemét + vacsi) és egy független változója (testsúly). Természetesen összetettebb modellel is próbálkozhatunk (megivott víz mennyisége, szőr között megbúvó kullancsok száma, stb.), de intuitíve érezzük, a súly meghatározása nem lesz sokkal pontosabb.

Ha eldicsekszünk másoknak is modellünkkel és ők is kipróbálják saját kutyájukon, csalódni fognak. Hamar ki fog derülni, hogy bár nekünk jól működik, más kutyák testsúlyát valami miatt rosszul határozza meg. A modellünk ugyanis nem elég általános, a szomszéd kutyája jónevelt, csak suttyomban eszik a kukák mellől, egy másik ismerősünk rendszeresen fut a kutyával, aki emiatt nehezebben hízik, stb. Jó lenne, ha ezeket a nehezen mérhető különbségeket is megjósolná a modellünk. Ha ezeket az adatokat is bevonjuk a modell generálás folyamatába, mi fog ezután történni? Valamelyik kutya súlyát pontosabban megjósolja, másokét kevésbé pontosan.

Úgy is mondhatnánk, egy idealizált kutya paramétereit kapjuk meg. Egyes kutyák jobban hasonlítanak majd erre a nem létező kutyára, mások (köztük természetesen a sajátunk is), kevésbé. Azt, hogy mennyire hasonlítanak az egyes kutyák erre az elméleti állatra, a modell által megjósolt testsúly és a ténylegesen mért érték különbségéből lehet kiszámolni (egészen pontosan a különbségek négyzetösszegéből).

Lássuk mindezt a gyakorlatban, bioinformatikához is köthető adatokkal. Töltsük le a Drosophila variációkat és genom annotációt. Készítsünk egy táblázatot, ami a gének nevét, hosszát és a bennük található SNP-k számát tartalmazza. Erre a következő szkriptet használhatjuk:

#!/usr/bin/python

import sys
import gzip
import re

class Gene:
    def __init__(self, start, stop, name):
        self.start = start
        self.stop  = stop
        self.name  = name
        self.count = 0

def findGene(genes, pos, starti, stopi, vnum):
    if genes[starti].start < pos and genes[starti].stop > pos:
        genes[starti].count += vnum
    if genes[stopi].start < pos and genes[stopi].stop > pos:
        genes[stopi].count += vnum
    if stopi - starti < 2:
        return
    midi = starti + (stopi - starti) / 2
    if pos > genes[starti].start and pos < genes[midi].stop:
        return findGene(genes, pos, starti, midi, vnum)
    if pos > genes[midi].start and pos < genes[stopi].stop:
        return findGene(genes, pos, midi, stopi, vnum)
    return

geneidpatt = re.compile('Name=([^;]+);')

genes = dict()

gff = gzip.open(sys.argv[1])
for line in gff:
    if line.startswith('#'):
        continue
    fields = line.rstrip().split()
    chrx   = fields[0]
    ftype  = fields[2]
    start  = int(fields[3])
    stop   = int(fields[4])
    match  = geneidpatt.search(fields[8])
    if ftype != 'gene' or not match:
        continue
    genename = match.group(1)
    if chrx not in genes:
        genes[chrx] = list()
    actual = Gene(start, stop, genename)
    genes[chrx].append(actual)
gff.close()

for c in genes:
    genes[c] = sorted(genes[c], key = lambda x:x.start)

vcf = gzip.open(sys.argv[2])
for line in vcf:
    fields = line.rstrip().split()
    if line.startswith('#'):
        continue
    chrx = fields[0]
    pos  = int(fields[1])
    vnum = len(fields[4].split(','))
    findGene(genes[chrx], pos, 0, len(genes[chrx]) - 1, vnum)
vcf.close()

print "length\tsnps"
for chrx in genes:
    for entry in genes[chrx]:
        print "%s\t%d\t%d" % (entry.name, entry.stop - entry.start, entry.count)

Töltsük be R-be a táblázatot és nézzük meg a változóink eloszlását:

data <- read.table("genes.tsv")
hist(data$length)
hist(data$snps)

Ez bizony baj. Kicsit sem hasonlítanak a normál eloszlásra, márpedig ez feltétele a lineáris regresszió használatának. Szerencsére egy egyszerű transzformáció segítségével közel normál eloszlásúvá alakíthatjuk őket. Ezután viszont tartsuk észben, hogy az összefüggésünk nem a gén hossza és a variációk száma között fog fennállni, hanem a transzformált értékek között!

data$length <- log(data$length + 1)
data$snps <- log(data$snps + 1)

R-ben a modell alkotás egyszerű folyamat. Meg kell adni a független változót (snps), jön egy furcsa karakter '~', majd felsoroljuk a függő változókat (jelen esetben ez csak a length). Az összes többi feladatot az R megoldja helyettünk. Érdemes alaposan összeismerkedni a modellekkel (az R dokumentáció formula néven emlegeti), mert teljesen új dimenziókat nyit meg előttünk.

model <- lm(snps ~ length, data = data)

Mit tudunk kezdeni ezzel a modellel? Jósolhatunk. Mennyi SNP-t várunk egy 23926 hosszú génben? Csak jusson eszünkbe, hogy a modellünk logaritmikus skálán működik!

a <- log(23926)
b <- predict(model, data.frame(length = a))

A válasz 7.100061. Ami 1212 mutációt jelent. Ha most megnézzük a 23926 hosszú géneket, akkor azt látjuk, hogy az stnB gén 1407 SNP-t tartalmaz, míg az stnA egyetlen egyet sem. Itt el is kezdhetünk gondolkodni, hogy mindez mit is jelent, de az túlmutat jelen poszt témáján.

Aki további részleteket akar megtudni a lineáris modellekről, annak ajánlom ezt a könyvet. Annyira szájbarágós, hogy még én is megértettem matematikai előképzettség nélkül. A Courseran is több kurzus értinti a témát. (ez, ez és még ez is, csak azokat említve, amiket láttam is.)

Szólj hozzá!

Címkék: machine learning

A bejegyzés trackback címe:

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

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