Biologia
computaziona le
A.A. 2010-2011 semestre II
UNIVERSITÀ
DEGLI STUDI DI MILANO
Docente: Giorgio Valentini Istruttore: Matteo Re
p
8 Hidden Markov Models
C.d.l. Biotecnologie Industriali e Ambientali
Obiettivi
• Programmazione dinamica in PERL (2)
• Implementazione di un algoritmo che utilizzi tecniche di programmazione dinamica ed un modello generativo
• Hash di hash
• Hash di array
• Biologia computazionale
• Decoding di una sequenza di osservazioni dato un HMM
• Implementazione algoritmo VITERBI
• Addestramento di un HMM a partire da una collezione di
sequenze biologiche a stati noti
Linee guida
• Il livello di complessità di questa esercitazione è alto
• Cercate di risolvere il problema dopo averlo suddiviso in sottoproblemi
• Indipendentemente dal fatto che lo script Perl funzioni o meno l’esercizio NON verrà valutato se, insieme allo script, non verrà inviato anche lo pseudocodice.
• Modalità di svolgimento dell’esercitazione:
• Scaricare dal sito web del corso il file HMM_exampleVIT_ls.pl
• Questo script è incompleto
• La posizione delle parti da aggiungere è evidenziata da questo commento:
########### description # FILL IN ##################
description: descrizione dell’operazione da svolgere
• Una differenza importante tra le esercitazioni precedenti e questa è che,
dopo aver reso utilizzabile lo script dell’algoritmo di Viterbi, dovrete
scrivere senza nessun template, degli script Perl che vi permettano di
stimare i parametri dell’HMM da inserire in HMM_example_VIT_ls.pl per
effettuare il decoding di una sequenza proteica. I file contenenti le
collezioni di sequenze sono reperibili sul sito del corso.
Permette di identificare:
La sequenza di stati che, con probabilità massima, ha prodotto l’intera sequenza di osservazioni (ma non ci dice nulla rispetto alla probabilità di essere in un certo stato ad una determinata posizione nella sequenza).
E’ basato su:
tecniche di programmazione dinamica.
DECODING (VITERBI):
Input:
3 1 5 1 1 4 6 6 6 6 6 2 4 (osservazioni)
HMM
+
VITERBI: algoritmo
Input: x = x
1……x
L+ HMM Inizializzazione:
V
0(0) = 1 (0 è una prima posizione fittizia) V
k(0) = 0, per ogni k > 0
Iterazione:
V
j(i) = e
j(x
i) max
ka
kjV
k(i – 1) Ptr
j(i) = argmax
ka
kjV
k(i – 1)
Terminazione:
P(x, *) = max
kV
k(L) Traceback:
L* = argmax
kV
k(L)
i-1* = Ptr
i(i)
E’ di fondamentale importanza progettare bene la parte dell’algo- ritmo che realizza l’iterazione ! Lo stato finale è determinato dallo stato a valore massimo
dell’ultimo step di iterazione.
Realizzazione algoritmo VITERBI
1) Acquisizione sequenza di osservazioni 2) Definizione parametri del modello HMM 3) Inizializzazione Viterbi
4) Iterazione Viterbi
5) Determinazione ultimo stato
6) Traceback (costruzione sequenza di stati)
7) Stampa output: sequenza stati
Realizzazione algoritmo VITERBI
• Inizializzazione Viterbi
# Initialization:
my %v = ( 'F' => [0], 'L' => [-0.51] );
NB: hash di arrays .
Una variabile dichiarata in questo modo è un normale hash ma i suoi valori sono arrays (come potete
indovinare dalle parentesi quadre) . I valori inseriti si trovano in POSIZIONE 0 (primo elemento) degli array. I valori possono essere aggiunti così:
$v{chiave_hash}->[indice_array] = valore ;
Realizzazione algoritmo VITERBI
• Inizializzazione Viterbi
# Initialization:
my %v = ( 'F' => [0], 'L' => [-0.51] );
St. 3 1 5 1 1 6 6 6
FF 0.64 LF -1.61 FL -2.30 LL 0.59
F
L
Obs.
0
-0.51
V_F 0 V_L -0.51
p_F p_L
Assumiamo uguali le probabilità Iniziali di transire in stato F o L.
F = E_f(0) + 0 + 0 = 0
L = F_l(0) + 0 + 0 = -0.51 Questo passaggio corrisponde
alla prima colonna nella
Matrice di progr. dinamica.
Realizzazione algoritmo VITERBI
• Definizione della procedura di iterazione
Per ogni stato k, e per una posizione fissata i nella seq.,
V k (i) = max {1… i-1} P[x 1 …x i-1 , 1 , …, i-1 , x i , i = k]
Massimizzazione probabilità seq.
di stati da pos. 1 a pos. i-1
Osservazioni da posizione 1
a posizione i-1
Seq. Stati da posizione 1 a posizione i-1
Emissione osservazione in pos. i
Assumendo di essere in stato k
prob. di essere in stato k alla posizione i
V l (i+1) = e l (x i+1 ) max k a kl V k (i)
emissione transizione Viterbi stato k posizione i Pos. i
Pos. i+1
ITERAZIONE
Realizzazione algoritmo VITERBI
• Definizione della procedura di iterazione
V l (i+1) = e l (x i+1 ) max k a kl V k (i)
emissione transizione Viterbi stato k posizione i
F F F
L L L
1
3 5
0.64 FF 0.64
-2.12
Emissione_F(5) = 0 transizione
max
V F (i+1) = 0 + 0.64 + 0.64 = 1.28
Realizzazione algoritmo VITERBI
• Definizione della procedura di iterazione
V l (i+1) = e l (x i+1 ) max k a kl V k (i)
emissione transizione Viterbi stato k posizione i
F F F
L L L
1
3 5
0.64 FF 0.64
-2.12
Emissione_F(5) = 0 transizione
max
Questo calcolo va eseguito, per ogni coppia di simboli (i, i-1), per ogni possibile transizione.
HMM 1°
ordine
Realizzazione algoritmo VITERBI
• Definizione della procedura di iterazione
V l (i+1) = e l (x i+1 ) max k a kl V k (i)
emissione transizione Viterbi stato k posizione i
F F F
L L L
1
3 5
0.64 FF 0.64
-2.12
Emissione_F(5) = 0 transizione
max
Questo calcolo va eseguito, per ogni coppia di simboli (i, i-1), per ogni possibile transizione.
HMM 1°
ordine
VITERBI: iterazione
my $idx = 1;
foreach my $tmp_obs (@obs_list) { my $max_state = '';
my $max_state_v = 0;
foreach my $state2 qw(F L) {
my ($max_v, $max_prev_state, $max_path) = (-1,'X','XX');
foreach my $state1 qw(F L) { my $tmp_trans = $state1.$state2;
####### FILL IN #### VITERBI ITERATION STEP ######
# my $tmp_v =
if(
$tmp_v > $max_v
) {$max_v = $tmp_v;
$max_prev_state = $state1;
$max_path = $state1.$state2;
} }
$path{$idx}->{$state2} = $max_prev_state;
$v{$state2}->[$idx] = $max_v;
}
$idx += 1;
}
V l (i+1) = e l (x i+1 ) max k a kl V k (i)
Per ogni simbolo (colonna)
Per ogni transizione
(doppio foreach)
VITERBI: iterazione
foreach my $state2 qw(F L) {
my ($max_v, $max_prev_state, $max_path) = (-1,'X','XX');
foreach my $state1 qw(F L) {
my $tmp_trans = $state1.$state2;
####### FILL IN # # my $tmp_v =
if( $tmp_v > $max_v ) {
$max_v = $tmp_v;
$max_prev_state = $state1;
$max_path = $state1.$state2;
} }
$path{$idx}->{$state2} = $max_prev_state;
$v{$state2}->[$idx] = $max_v;
}
F F F
L
0.64
-2.12
Scelta miglior percorso “locale”
state2 state1
symbol idx
(seq. cycle)
NB: Salvataggio variabili VITERBI
per lo step successivo ? (if)
VITERBI: iterazione
my $idx = 1;
foreach my $tmp_obs (@obs_list) { my $max_state = '';
my $max_state_v = 0;
foreach my $state2 qw(F L) {
my ($max_v, $max_prev_state, $max_path) = (-1,'X','XX');
foreach my $state1 qw(F L) { my $tmp_trans = $state1.$state2;
####### FILL IN #### VITERBI ITERATION STEP ######
# my $tmp_v =
if(
$tmp_v > $max_v
) {$max_v = $tmp_v;
$max_prev_state = $state1;
$max_path = $state1.$state2;
} }
$path{$idx}->{$state2} = $max_prev_state;
$v{$state2}->[$idx] = $max_v;
}
$idx += 1;
}
Complessità temporale = K * K * L = K 2 L
Lunghezza seq. : L
N° stati : K
N° stati : K
VITERBI: determinaz.
stato finale
## Determine the last state ##
my $last_state = 'X';
if( $v{'F'}->[$idx-1] > $v{'L'}->[$idx-1] ){
$last_state = 'F';
}else{
$last_state = 'L';
}
print "Final state: $last_state (v= $v{$last_state}-
>[$idx-1])\n";
Controllo valori ultima colonna Valore > determina stato finale
Stampa stato finale “vincente” e relativo
valore VITERBI
VITERBI: Traceback
## Traceback ##
my @state_seq = ();
for(my $i=$idx-1;$i>0;$i--) {
my $prev_state = $path{$i}->{$last_state};
push(@state_seq,$prev_state);
$last_state = $prev_state;
}
St. 3 1 5 1 1 6 6 6
F
L
0
-0.51
0.64 -2.12
-2.81 -0.43
1.28 -2.12
-2.81 -0.43
1.92 -1.96
-1.53 -0.27
2.56 -1.88
-0.89 -0.19
3.20 -1.80
-0.25 -0.11
3.84 -1.72
2.00 1.58
4.48 0.39
2.64 3.69
6
5.12 2.08
3.28 5.38 TRANSIZIONE:
Qui $prev_state
di L diventa F !!!
VITERBI: Traceback
## Traceback ##
my @state_seq = ();
for(my $i=$idx-1;$i>0;$i--) {
my $prev_state = $path{$i}->{$last_state};
push(@state_seq,$prev_state);
$last_state = $prev_state;
}
Si parte da $last_state dell’ultima colonna Ma questo viene ripetutamente sostituito dal valore del puntatore della colonna
precedente.
$last_state (ultima col.)
Array stati prodotto da
Traceback (ordine inverso)
necessario reverse …
VITERBI: Traceback
## Traceback ##
my @state_seq = ();
for(my $i=$idx-1;$i>0;$i--) {
my $prev_state = $path{$i}->{$last_state};
push(@state_seq,$prev_state);
$last_state = $prev_state;
}
## Print most probable path ##
print "\n[Output]\n";
print join("",@obs_list),"\n";
print join("",reverse @state_seq),"\n";
OUTPUT VITERBI: sequenza di stati che ha prodotto
l’intera serie di osservazioni con probabilità maggiore.
VITERBI: Output aggiuntivo
my $jseq = join(" \t", @obs_list);
print "\tB\t$jseq\n";
my $arrayref = $v{"F"};
my @Vf = @{ $arrayref };
my $Fvit=join("\t", @Vf);
print "F\t$Fvit\n";
$arrayref = $v{"L"};
my @Vl = @{ $arrayref };
my $Lvit=join("\t", @Vl);
print "L\t$Lvit\n\n";
STAMPA MATRICE VITERBI
Estrazione arrays
da hash di array
VITERBI: Output aggiuntivo
my $rHoH = \%path;
my $curpos=0;
for my $k1 ( sort {$a <=> $b} (keys %$rHoH) ) { print "Step: $k1 \tEmission: $obs_list[$curpos]\n";
for my $k2 ( keys %{$rHoH->{ $k1 }} ) { print "\tmax path to $k2 : $rHoH->{ $k1 }{ $k2 }\t";
if($k2 ne $rHoH->{ $k1 }{ $k2 }){
print "*\n";
}else{
print "\n";
} }
$curpos++;
print "\n";
}