3A
  • Portfolio Top
  • Categories
  • Tags
  • Archives

HMMをpythonで実装

(kerasy.ML.HMM.HMM)の使い方¶

自作のモジュール(kerasy.ML.HMM.HMM)を使って実装をします。

In [1]:
from kerasy.ML.HMM import HMM
In [2]:
model = HMM()
In [3]:
# 以下のようなパラメタファイルを読み込む。
! cat params.json
{
    "M": 4,
    "K": 4,
    "basetypes": ["a", "c", "g", "u"],
    "pi": [0.7, 0.1, 0.1, 0.1],
    "A": [[0.8, 0.1, 0.1, 0.0],
          [0.0, 0.8, 0.1, 0.1],
          [0.1, 0.0, 0.8, 0.1],
          [0.1, 0.0, 0.1, 0.8]],
    "phi": [[0.4,  0.1,  0.1,  0.4],
            [0.25, 0.25, 0.25, 0.25],
            [0.1,  0.4,  0.4,  0.1],
            [0.3,  0.2,  0.2,  0.3]]
}
In [4]:
model.load_params("params.json")
In [5]:
# インスタンスに読み込まれた各種パラメータ
model.params()
【Parameter】
=====================================
*initial state
          z(1)   z(2)   z(3)   z(4)  
         0.7000 0.1000 0.1000 0.1000 
-------------------------------------
*transition probability matrix
          [States after transition]  
          z(1)   z(2)   z(3)   z(4)  
  z(1)   0.8000 0.1000 0.1000 0.0000 
  z(2)   0.0000 0.8000 0.1000 0.1000 
  z(3)   0.1000 0.0000 0.8000 0.1000 
  z(4)   0.1000 0.0000 0.1000 0.8000 
-------------------------------------
*emission probability
          z(1)   z(2)   z(3)   z(4)  
       a 0.4000 0.2500 0.1000 0.3000 
       c 0.1000 0.2500 0.4000 0.2000 
       g 0.1000 0.2500 0.4000 0.2000 
       u 0.4000 0.2500 0.1000 0.3000 
In [6]:
# なお、この時以下のような辞書を同時に作成しています。
print(model.base2int)
print(model.int2base)
{'a': 0, 'c': 1, 'g': 2, 'u': 3}
{0: 'a', 1: 'c', 2: 'g', 3: 'u'}
In [7]:
# また、パラメータはnumpyの行列の形で読み込まれています。
print(type(model.pi))
print(type(model.A))
print(type(model.phi))
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>
<class 'numpy.ndarray'>
In [8]:
# 以下のようにすれば、学習したパラメタを同じ形式で出力することができます。
model.save_params("out.json")

Viterbi algorithm¶

HMMのViterbiアルゴリズムを実装して、尤もらしいサンプル配列の隠れ状態列を推定します。

In [9]:
from kerasy.utils.bio import alignStr, readMonoSeq, readMultiSeq

# ファイルの中身

cat seq1.fasta ``` sample-RNA gagaguccuauacaaacuccaaaacacugagaccauacaaguaaaaccagucgagaaaau agucaacagcacccccguugcguauccugcggagaaugccucgcuaucuguccucacgau uggucuaaccgcucggcucaggcgugugggccugaaauccgggcagcaaacuacgguaag uuuucgcguaucaaaaauacauugaugaauguucgcuauuagccgggucgacguuuugau ggugacuaggagcgaaagugauuuuuuugugagcggugucauagcaggggaucaucugag gugaacuauggacgggucagucgcccucauuggguuuguuacucagauacgugacacacg uaaggucgcacggcaguagugauccacgagaaucggcacucuuacgagcaagucuauagc gacguggcuugcuauuaagacaguaauggacucggacagcuaguacgcgacuaaucauuu ucgcacgccaucacacuuucaacccaggagcuuacaguguuccaggggccaggcuugggg cagccucuguggaagugcgagggcugcgcuaguguacauuagccgacccucagacgugaa auaaagagaugcugcugguugcacagugagcaacguucacucggcaacccgucggauacc ```
In [10]:
# ファイルの読み込み
seq1 = readMonoSeq('seq1.fasta')
print(f"Input Sequence:\n{alignStr(seq1[0])}")
Input Sequence:
gagaguccuauacaaacuccaaaacacugagaccauacaaguaaaaccagucgagaaaau
agucaacagcacccccguugcguauccugcggagaaugccucgcuaucuguccucacgau
uggucuaaccgcucggcucaggcgugugggccugaaauccgggcagcaaacuacgguaag
uuuucgcguaucaaaaauacauugaugaauguucgcuauuagccgggucgacguuuugau
ggugacuaggagcgaaagugauuuuuuugugagcggugucauagcaggggaucaucugag
gugaacuauggacgggucagucgcccucauuggguuuguuacucagauacgugacacacg
uaaggucgcacggcaguagugauccacgagaaucggcacucuuacgagcaagucuauagc
gacguggcuugcuauuaagacaguaauggacucggacagcuaguacgcgacuaaucauuu
ucgcacgccaucacacuuucaacccaggagcuuacaguguuccaggggccaggcuugggg
cagccucuguggaagugcgagggcugcgcuaguguacauuagccgacccucagacgugaa
auaaagagaugcugcugguugcacagugagcaacguucacucggcaacccgucggauacc
In [11]:
# この時、文字列をリストに格納しています。
print(type(seq1))
<class 'list'>
In [12]:
pred1 = model.predict(sequences=seq1, asai=True)
In [13]:
# 変数asaiは、隠れ状態がZero-based numberingかどうかを決めるものであり、特に意味はありません。(課題の形式に対応したものがasai=True.)
print(f"Hidden Indexes:\n{alignStr(pred1[0])}")
Hidden Indexes:
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
222222223333333333333333333333331111113333333334444444444444
444433331111111111111111111111111111111113333333333331111111
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
In [14]:
# もちろんパラメタの更新は行われていません。
model.params()
【Parameter】
=====================================
*initial state
          z(1)   z(2)   z(3)   z(4)  
         0.7000 0.1000 0.1000 0.1000 
-------------------------------------
*transition probability matrix
          [States after transition]  
          z(1)   z(2)   z(3)   z(4)  
  z(1)   0.8000 0.1000 0.1000 0.0000 
  z(2)   0.0000 0.8000 0.1000 0.1000 
  z(3)   0.1000 0.0000 0.8000 0.1000 
  z(4)   0.1000 0.0000 0.1000 0.8000 
-------------------------------------
*emission probability
          z(1)   z(2)   z(3)   z(4)  
       a 0.4000 0.2500 0.1000 0.3000 
       c 0.1000 0.2500 0.4000 0.2000 
       g 0.1000 0.2500 0.4000 0.2000 
       u 0.4000 0.2500 0.1000 0.3000 

Baum-Welch algorithm¶

HMMのBaum-Welchアルゴリズムを実装して、モデルを学習させてます。

In [15]:
model = HMM()
model.load_params("params2.json")
model.params() # 文字が "acgu"→"ACGT"に変わっただけです。
【Parameter】
=====================================
*initial state
          z(1)   z(2)   z(3)   z(4)  
         0.7000 0.1000 0.1000 0.1000 
-------------------------------------
*transition probability matrix
          [States after transition]  
          z(1)   z(2)   z(3)   z(4)  
  z(1)   0.8000 0.1000 0.1000 0.0000 
  z(2)   0.0000 0.8000 0.1000 0.1000 
  z(3)   0.1000 0.0000 0.8000 0.1000 
  z(4)   0.1000 0.0000 0.1000 0.8000 
-------------------------------------
*emission probability
          z(1)   z(2)   z(3)   z(4)  
       A 0.4000 0.2500 0.1000 0.3000 
       C 0.1000 0.2500 0.4000 0.2000 
       G 0.1000 0.2500 0.4000 0.2000 
       T 0.4000 0.2500 0.1000 0.3000 
cat seq2.txt ``` >Vitis_vinifera_chr14.trna15-AlaAGC (28776087-28776159) Ala (AGC) 73 bp Sc: 68.12 GGGGATGTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAGGTACGGGGATCGATA CCCCGCATCTCCA >Vitis_vinifera_chr13.trna5-ArgCCG (2691241-2691313) Arg (CCG) 73 bp Sc: 83.85 GATCGCATAGCGGAGTGGATATCGCGTTAGACTCCGAATCTAAAGGTCGTGGGTTCGAAT CCCACTGCGATCG >Vitis_vinifera_chr3.trna6-GlnCTG (5807449-5807520) Gln (CTG) 72 bp Sc: 71.93 GGTCCCATGGTCTAGTGGTCAGGACATTGGACTCTGAATCCAGTAACCCGAGTTCAAATC TCGGTGGGACCT >Vitis_vinifera_chr14.trna19-LeuAAG (25640120-25640040) Leu (AAG) 81 bp Sc: 62.71 GTGGAGATGGCCGAGTTGGTCTAAGGCGCCAGATTAAGGTTCTTGTCCGAAAGGGCGTGG GTTCAAATCCCACTCTCCACA >Vitis_vinifera_chr18.trna9-MetCAT (2896034-2896118) Met (CAT) 85 bp Sc: 60.66 GGGGTGGTGGCGCAGTTGGCTAGCGCGTAGGTCTCATAGCTTCCGAGTAATCCTGAGGTC GAGAGTTCGAGCCTCTCTCACCCCA >Vitis_vinifera_chr3.trna30-ProTGG (7498415-7498344) Pro (TGG) 72 bp Sc: 68.98 GGGCATTTGGTCTAGTGGTATGATTCTCGCTTTGGGTGCGAGAGGTCCCGAGTTCGATTC TCGGAATGACCC >Vitis_vinifera_chr5.trna13-GluTTC (21745120-21745048) Glu (TTC) 73 bp Sc: 36.67 AGTCCCATAGCCTAGTTGGTCGAGCACAAGGTTTTCAATCTTGTGGTCGTGGGTTCGAGC CCTATTGGTGGTT >Vitis_vinifera_chr5.trna3-TyrGTA (7422575-7422666) Tyr (GTA) 92 bp Sc: 33.68 CCGATCTTAACTCAATTGGTAGAGCAGAGGACCGTAGTGGGGTTGACCCAATAGATATCC TTAGGTCGTTAGTTTGAATCCAACAGGTCTAA >Vitis_vinifera_chr1.trna8-ValCAC (11396083-11396156) Val (CAC) 74 bp Sc: 66.86 GTCTAGGTGGTATAGTTGGTTATCACGCTAGTCTCACACACTAGAGGTCCCTAGTTCGAA CCCAGGCTCAGATA >Vitis_vinifera_chr14.trna2-SerTGA (4021381-4021462) Ser (TGA) 82 bp Sc: 80.82 GTCGATATGTCCGAGTGGTTAAGGAGACAGACTTGAAATCTGTTGGGCTTCGCCCGCGCA GGTTCGAACCCTGCTGTCGACG ```
In [16]:
seq2 = readMultiSeq('seq2.txt')
In [17]:
for i, seq in enumerate(seq2):
    print(f"No.{i:>02}\n{alignStr(seq, width=45)}")
No.00
GGGGATGTAGCTCAGATGGTAGAGCGCTCGCTTAGCATGCGAGAG
GTACGGGGATCGATACCCCGCATCTCCA
No.01
GATCGCATAGCGGAGTGGATATCGCGTTAGACTCCGAATCTAAAG
GTCGTGGGTTCGAATCCCACTGCGATCG
No.02
GGTCCCATGGTCTAGTGGTCAGGACATTGGACTCTGAATCCAGTA
ACCCGAGTTCAAATCTCGGTGGGACCT
No.03
GTGGAGATGGCCGAGTTGGTCTAAGGCGCCAGATTAAGGTTCTTG
TCCGAAAGGGCGTGGGTTCAAATCCCACTCTCCACA
No.04
GGGGTGGTGGCGCAGTTGGCTAGCGCGTAGGTCTCATAGCTTCCG
AGTAATCCTGAGGTCGAGAGTTCGAGCCTCTCTCACCCCA
No.05
GGGCATTTGGTCTAGTGGTATGATTCTCGCTTTGGGTGCGAGAGG
TCCCGAGTTCGATTCTCGGAATGACCC
No.06
AGTCCCATAGCCTAGTTGGTCGAGCACAAGGTTTTCAATCTTGTG
GTCGTGGGTTCGAGCCCTATTGGTGGTT
No.07
CCGATCTTAACTCAATTGGTAGAGCAGAGGACCGTAGTGGGGTTG
ACCCAATAGATATCCTTAGGTCGTTAGTTTGAATCCAACAGGTCT
AA
No.08
GTCTAGGTGGTATAGTTGGTTATCACGCTAGTCTCACACACTAGA
GGTCCCTAGTTCGAACCCAGGCTCAGATA
No.09
GTCGATATGTCCGAGTGGTTAAGGAGACAGACTTGAAATCTGTTG
GGCTTCGCCCGCGCAGGTTCGAACCCTGCTGTCGACG
In [18]:
# 学習させる。
model.fit(sequences=seq2, epochs=2000, verbose=False)
In [19]:
import matplotlib.pyplot as plt
In [20]:
def plotHistory(model):
    """ 学習の過程をプロットする関数 """
    plt.plot(model.history)
    plt.title(f"Mean Log Likelihood Transition (eoochs={model.epoch})")
    plt.xlabel("epochs")
    plt.ylabel("Mean Log Likelihood")
    plt.show()
In [21]:
plotHistory(model)
In [22]:
model.params()
【Parameter】
=====================================
*initial state
          z(1)   z(2)   z(3)   z(4)  
         0.1024 0.0000 0.8976 0.0000 
-------------------------------------
*transition probability matrix
          [States after transition]  
          z(1)   z(2)   z(3)   z(4)  
  z(1)   0.2819 0.7181 0.0000 0.0000 
  z(2)   0.0000 0.5670 0.0000 0.4330 
  z(3)   0.0521 0.0000 0.3415 0.6064 
  z(4)   0.5158 0.0000 0.0000 0.4842 
-------------------------------------
*emission probability
          z(1)   z(2)   z(3)   z(4)  
       A 0.3436 0.3099 0.1059 0.0055 
       C 0.2538 0.0592 0.0970 0.4297 
       G 0.4026 0.4418 0.7971 0.0345 
       T 0.0000 0.1891 0.0000 0.5304 

※ 隠れ状態ごとにかなり偏った遷移を行なう。また、遷移行列の対角成分がそこまで大きい値では無い。

→ 特定の構造が、ある程度の長さのゆとりを持って繰り返されていると予想される。

In [23]:
pred2 = model.predict(sequences=seq2, asai=True)
In [24]:
for i,pred in enumerate(pred2):
    print(f"No.{i:>02} Hidden Indexes:\n{alignStr(pred, width=45)}")
No.00 Hidden Indexes:
333334122244412241241222224412444124122412222
2411222224412224441241244441
No.01 Hidden Indexes:
334411241241222412241241124412244441224441222
2412412244412244412441122441
No.02 Hidden Indexes:
334441241244412412441222412412244441224441241
244412244412244441241222444
No.03 Hidden Indexes:
341222241244122441244412222244122441222444441
244122222241222244412244412444441241
No.04 Hidden Indexes:
333341241241122441244124112412244412412444441
2241244441222441222244412244444441244441
No.05 Hidden Indexes:
333412441244412412412224444124444122224122222
444412244412444441222412444
No.06 Hidden Indexes:
334441241244412441244122411222244444124444122
2412412244412244441241241244
No.07 Hidden Indexes:
341244441244412441241222412222241241241222441
244412412241244441224124412444122444124122444
12
No.08 Hidden Indexes:
344412241241222441244124112441244412411244122
22444441244412244412244412241
No.09 Hidden Indexes:
344124122444122412441222222412244412224441241
2244412444112412244412244441122441241

補足:上記プログラムにバグがないかの確認¶

Baum-Welchアルゴリズムが正しく実装できていたか、極端な配列を学習させることで確認します。

In [25]:
model = HMM()
model.load_params("params3.json")
model.params()
【Parameter】
==============================
*initial state
          z(1)   z(2)   z(3)  
         0.7000 0.1000 0.2000 
------------------------------
*transition probability matrix
         [States after transition]
          z(1)   z(2)   z(3)  
  z(1)   0.8000 0.1000 0.1000 
  z(2)   0.1000 0.8000 0.1000 
  z(3)   0.1000 0.1000 0.1000 
------------------------------
*emission probability
          z(1)   z(2)   z(3)  
       A 0.4000 0.2500 0.1000 
       C 0.1000 0.2500 0.4000 
       G 0.1000 0.2500 0.4000 
       T 0.4000 0.2500 0.1000 
In [26]:
seq_extreme = readMonoSeq('seq3.txt')
In [27]:
# かなり極端な配列の例で実装してみる。
print(f"Input Sequence:\n{alignStr(seq_extreme[0])}")
Input Sequence:
TCTTTTTCCTCCTCTCTCCTTTCCCTCTTTTCCCTTCTTCTCTCCCTTTTCCTTCTCTTC
TCTCTTTTCTTCCCCTTTTCCTTTTCTCCTCCCTCCCTTTCTTCCCTCCTTCCTCCCCCC
CTCCCCTTTCCTTCCTTTCTCCTTCTCCCCATATGGCCATTTACTTCAGCTGATAGACAC
CGAGTAACAACAATAAAGCGTTAGGTGGACGAATGCTCTACTCTGACCTCTAGCTTGTGG
GTTCGCGGCTTGCCGAACGCTGGCCTCTGCCCGTCGAACCAATAAATGTTTATCCAGGAC
ACCCCGTTCTTTGGTGATATCCCTCGCTCGAGTTATAGCATTGAAACCTCCATATCCGGC
GATAAGAGCTACGGACCGTATACTGGGCGCCGGTAATTGGTTGCACTCGCCCTCGGTCTT
TTTCTTTTTGGTTTAGCAGAGCAAGGCGTGGAAAAGGAGAGAGGGAGAAAAGGGAAAGGG
AAAAGAGGAGAAGAAAGAAAAAGGAAGGGGGGAAGAGGAGAGAAGGGAAGGGAAGGGGGA
GAAAGAGGGAAAGAGGAGAAAAAAGGAGGGGGAAGAAGGAAGGGGGAAAGGGGGGGAAAG

上の配列は、以下の構造を持っていることがわかります。

index type
1~150 pyrimidine base
151~450 both
451~600 purine base
In [28]:
model.fit(sequences=seq_extreme, epochs=100, verbose=False)
In [29]:
plotHistory(model)
In [30]:
model.params()
【Parameter】
==============================
*initial state
          z(1)   z(2)   z(3)  
         1.0000 0.0000 0.0000 
------------------------------
*transition probability matrix
         [States after transition]
          z(1)   z(2)   z(3)  
  z(1)   0.9933 0.0000 0.0067 
  z(2)   0.0000 1.0000 0.0000 
  z(3)   0.0000 0.0033 0.9967 
------------------------------
*emission probability
          z(1)   z(2)   z(3)  
       A 0.0000 0.4851 0.2199 
       C 0.5034 0.0000 0.2627 
       G 0.0000 0.5149 0.2415 
       T 0.4966 0.0000 0.2760 
In [31]:
pred_extreme = model.predict(sequences=seq_extreme)
In [32]:
print(f"Hidden Indexes:\n{alignStr(pred_extreme[0])}")
Hidden Indexes:
111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111333333333333333333333333333333
333333333333333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333333333333333
333333333333333333333333333332222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222

うまく傾向をつかんでいることから、学習アルゴリズムに大きな誤りはなさそうです。

In [ ]:
 

  • « 生物統計論 第1回
  • 生物物理学 第1回 »
hidden
Table of Contents
Published
Sep 27, 2019
Last Updated
Sep 27, 2019
Category
情報基礎実験(浅井)
Tags
  • 3A 127
  • 情報基礎実験(浅井) 13
Contact
Other contents
  • Home
  • Blog
  • Front-End
  • Kerasy
  • Python-Charmers
  • Translation-Gummy
    • 3A - Shuto's Notes
    • MIT
    • Powered by Pelican. Theme: Elegant