การตรวจจับจุดเปลี่ยนหลายจุดและการเลือกรุ่นเบย์เซียน

การเลือกรุ่นเบย์เซียน

นำเข้า

import numpy as np
import tensorflow.compat.v2 as tf
tf
.enable_v2_behavior()
import tensorflow_probability as tfp
from tensorflow_probability import distributions as tfd

from matplotlib import pylab as plt
%matplotlib inline
import scipy.stats

งาน: การตรวจจับจุดเปลี่ยนด้วยจุดเปลี่ยนหลายจุด

พิจารณางานการตรวจจับจุดเปลี่ยน: เหตุการณ์เกิดขึ้นในอัตราที่เปลี่ยนแปลงตามเวลา ขับเคลื่อนโดยการเปลี่ยนแปลงอย่างกะทันหันในสถานะ (ไม่ได้สังเกต) ของระบบบางระบบหรือกระบวนการสร้างข้อมูล

ตัวอย่างเช่น เราอาจสังเกตชุดของการนับดังต่อไปนี้:

true_rates = [40, 3, 20, 50]
true_durations
= [10, 20, 5, 35]

observed_counts
= tf.concat(
   
[tfd.Poisson(rate).sample(num_steps)
     
for (rate, num_steps) in zip(true_rates, true_durations)], axis=0)

plt
.plot(observed_counts)
[<matplotlib.lines.Line2D at 0x7f7589bdae10>]

png

สิ่งเหล่านี้อาจแสดงถึงจำนวนความล้มเหลวในดาต้าเซ็นเตอร์ จำนวนผู้เข้าชมหน้าเว็บ จำนวนแพ็กเก็ตบนลิงก์เครือข่าย ฯลฯ

โปรดทราบว่ายังไม่ชัดเจนว่าระบอบการปกครองของระบบที่แตกต่างกันมีมากเพียงใดจากการดูข้อมูล คุณบอกได้ไหมว่าจุดสวิตช์ทั้งสามจุดเกิดขึ้นที่ใด

จำนวนรัฐที่ทราบ

ก่อนอื่นเราจะพิจารณากรณี (อาจไม่สมจริง) ซึ่งทราบจำนวนสถานะที่ไม่ได้สังเกตมาก่อน ในที่นี้ เราจะถือว่าเรารู้ว่ามีสถานะแฝงอยู่สี่สถานะ

เราจำลองปัญหานี้เป็นสลับ (inhomogeneous) กระบวนการ Poisson: ที่จุดในแต่ละครั้งจำนวนของเหตุการณ์ที่เกิดขึ้นเป็น Poisson กระจายและอัตราของเหตุการณ์ที่เกิดขึ้นจะถูกกำหนดโดยไม่มีใครสังเกตสถานะของระบบ zt:

xtPoisson(λzt)

แฝงรัฐมีความไม่ต่อเนื่อง: zt{1,2,3,4}ดังนั้น λ=[λ1,λ2,λ3,λ4] เป็นเวกเตอร์ที่เรียบง่ายที่มีอัตรา Poisson แต่ละรัฐ การจำลองการวิวัฒนาการของรัฐในช่วงเวลาที่เราจะกำหนดง่ายการเปลี่ยนแปลงรูปแบบการ p(zt|zt1): ขอบอกว่าในแต่ละขั้นตอนเราอยู่ในสถานะที่ก่อนหน้านี้มีบางอย่างที่น่าจะเป็น pและมีความน่าจะเป็น 1p การเปลี่ยนแปลงที่เราไป รัฐต่าง ๆ อย่างสม่ำเสมอโดยสุ่ม สถานะเริ่มต้นยังถูกสุ่มเลือกอย่างสม่ำเสมอ ดังนั้นเราจึงมี:

z1Categorical({14,14,14,14})zt|zt1Categorical({pif zt=zt11p41otherwise})

สมมติฐานเหล่านี้สอดคล้องกับ รูปแบบมาร์คอฟที่ซ่อนอยู่ กับการปล่อย Poisson เราสามารถเข้ารหัสไว้ใน TFP ใช้ tfd.HiddenMarkovModel ขั้นแรก เรากำหนดเมทริกซ์การเปลี่ยนแปลงและชุดเครื่องแบบก่อนในสถานะเริ่มต้น:

num_states = 4
initial_state_logits
= tf.zeros([num_states]) # uniform distribution

daily_change_prob
= 0.05
transition_probs
= tf.fill([num_states, num_states],
                           daily_change_prob
/ (num_states - 1))
transition_probs
= tf.linalg.set_diag(transition_probs,
                                      tf
.fill([num_states],
                                             
1 - daily_change_prob))

print("Initial state logits:\n{}".format(initial_state_logits))
print("Transition matrix:\n{}".format(transition_probs))
Initial state logits:
[0. 0. 0. 0.]
Transition matrix:
[[0.95       0.01666667 0.01666667 0.01666667]
 [0.01666667 0.95       0.01666667 0.01666667]
 [0.01666667 0.01666667 0.95       0.01666667]
 [0.01666667 0.01666667 0.01666667 0.95      ]]

ต่อไปเราจะสร้าง tfd.HiddenMarkovModel กระจายใช้ตัวแปรสุวินัยเพื่อเป็นตัวแทนของอัตราที่เกี่ยวข้องกับแต่ละสถานะของระบบ เรากำหนดพารามิเตอร์อัตราในพื้นที่บันทึกเพื่อให้แน่ใจว่ามีค่าเป็นบวก

# Define variable to represent the unknown log rates.
trainable_log_rates
= tf.Variable(
  tf
.math.log(tf.reduce_mean(observed_counts)) +
  tf
.random.stateless_normal([num_states], seed=(42, 42)),
  name
='log_rates')

hmm
= tfd.HiddenMarkovModel(
  initial_distribution
=tfd.Categorical(
      logits
=initial_state_logits),
  transition_distribution
=tfd.Categorical(probs=transition_probs),
  observation_distribution
=tfd.Poisson(log_rate=trainable_log_rates),
  num_steps
=len(observed_counts))

สุดท้ายเรากำหนดความหนาแน่นบันทึกรูปแบบของทั้งหมดรวมทั้ง lognormal ไม่ค่อยให้ข้อมูลก่อนที่อัตราและเรียกใช้เพิ่มประสิทธิภาพการคำนวณ สูงสุด posteriori (MAP) พอดีกับข้อมูลนับสังเกต

rate_prior = tfd.LogNormal(5, 5)

def log_prob():
 
return (tf.reduce_sum(rate_prior.log_prob(tf.math.exp(trainable_log_rates))) +
         hmm
.log_prob(observed_counts))

losses
= tfp.math.minimize(
   
lambda: -log_prob(),
    optimizer
=tf.optimizers.Adam(learning_rate=0.1),
    num_steps
=100)
plt
.plot(losses)
plt
.ylabel('Negative log marginal likelihood')
Text(0, 0.5, 'Negative log marginal likelihood')

png

rates = tf.exp(trainable_log_rates)
print("Inferred rates: {}".format(rates))
print("True rates: {}".format(true_rates))
Inferred rates: [ 2.8302798 49.58499   41.928307  17.35112  ]
True rates: [40, 3, 20, 50]

มันได้ผล! โปรดทราบว่าสถานะแฝงในแบบจำลองนี้สามารถระบุได้จนถึงการเปลี่ยนแปลงเท่านั้น ดังนั้นอัตราที่เรากู้คืนจึงอยู่ในลำดับที่ต่างออกไป และมีสัญญาณรบกวนเล็กน้อย แต่โดยทั่วไปแล้วจะเข้ากันได้ดี

ฟื้นฟูวิถีของรัฐ

ตอนนี้เราได้เหมาะสมกับรูปแบบที่เราอาจต้องการที่จะสร้างรัฐซึ่งรูปแบบเชื่อว่าระบบได้ในแต่ละ timestep

นี้เป็นงานการอนุมานหลัง: ที่กำหนดนับสังเกต x1:T และพารามิเตอร์แบบ (อัตราค่าบริการ) λเราต้องการที่จะอนุมานลำดับของตัวแปรแฝงที่ไม่ต่อเนื่องตามการกระจายหลัง p(z1:T|x1:T,λ)ในโมเดล Markov ที่ซ่อนอยู่ เราสามารถคำนวณส่วนเพิ่มและคุณสมบัติอื่นๆ ของการกระจายนี้ได้อย่างมีประสิทธิภาพโดยใช้อัลกอริธึมการส่งข้อความมาตรฐาน โดยเฉพาะอย่างยิ่ง posterior_marginals วิธีการได้อย่างมีประสิทธิภาพจะคำนวณ (โดยใช้ อัลกอริทึมไปข้างหน้าย้อนกลับ ) ร่อแร่กระจาย p(Zt=zt|x1:T) เหนือรัฐไม่ต่อเนื่องแฝง Zt ในแต่ละ timestep t

# Runs forward-backward algorithm to compute marginal posteriors.
posterior_dists
= hmm.posterior_marginals(observed_counts)
posterior_probs
= posterior_dists.probs_parameter().numpy()

การพล็อตความน่าจะเป็นหลัง เรากู้คืน "คำอธิบาย" ของแบบจำลองของข้อมูล: แต่ละสถานะทำงาน ณ จุดใด

def plot_state_posterior(ax, state_posterior_probs, title):
  ln1
= ax.plot(state_posterior_probs, c='blue', lw=3, label='p(state | counts)')
  ax
.set_ylim(0., 1.1)
  ax
.set_ylabel('posterior probability')
  ax2
= ax.twinx()
  ln2
= ax2.plot(observed_counts, c='black', alpha=0.3, label='observed counts')
  ax2
.set_title(title)
  ax2
.set_xlabel("time")
  lns
= ln1+ln2
  labs
= [l.get_label() for l in lns]
  ax
.legend(lns, labs, loc=4)
  ax
.grid(True, color='white')
  ax2
.grid(False)

fig
= plt.figure(figsize=(10, 10))
plot_state_posterior
(fig.add_subplot(2, 2, 1),
                     posterior_probs
[:, 0],
                     title
="state 0 (rate {:.2f})".format(rates[0]))
plot_state_posterior
(fig.add_subplot(2, 2, 2),
                     posterior_probs
[:, 1],
                     title
="state 1 (rate {:.2f})".format(rates[1]))
plot_state_posterior
(fig.add_subplot(2, 2, 3),
                     posterior_probs
[:, 2],
                     title
="state 2 (rate {:.2f})".format(rates[2]))
plot_state_posterior
(fig.add_subplot(2, 2, 4),
                     posterior_probs
[:, 3],
                     title
="state 3 (rate {:.2f})".format(rates[3]))
plt
.tight_layout()

png

ในกรณี (อย่างง่าย) นี้ เราพบว่าแบบจำลองมักจะค่อนข้างมั่นใจ: ส่วนใหญ่ขั้นตอนจะกำหนดมวลความน่าจะเป็นทั้งหมดให้กับหนึ่งในสี่สถานะ โชคดีที่คำอธิบายดูสมเหตุสมผล!

นอกจากนี้เรายังสามารถเห็นภาพหลังนี้ในแง่ของอัตราที่เกี่ยวข้องกับรัฐแฝงไปได้มากที่สุดในแต่ละ timestep, ควบแน่นหลังน่าจะเป็นคำอธิบายเดียว:

most_probable_states = hmm.posterior_mode(observed_counts)
most_probable_rates
= tf.gather(rates, most_probable_states)
fig = plt.figure(figsize=(10, 4))
ax
= fig.add_subplot(1, 1, 1)
ax
.plot(most_probable_rates, c='green', lw=3, label='inferred rate')
ax
.plot(observed_counts, c='black', alpha=0.3, label='observed counts')
ax
.set_ylabel("latent rate")
ax
.set_xlabel("time")
ax
.set_title("Inferred latent rate over time")
ax
.legend(loc=4)
<matplotlib.legend.Legend at 0x7f75849e70f0>

png

ไม่ทราบจำนวนรัฐ

ในปัญหาจริง เราอาจไม่ทราบจำนวนสถานะ 'จริง' ในระบบที่เรากำลังสร้างแบบจำลอง สิ่งนี้อาจไม่ใช่ข้อกังวลเสมอไป: หากคุณไม่สนใจเกี่ยวกับข้อมูลระบุตัวตนของรัฐที่ไม่รู้จักเป็นพิเศษ คุณสามารถเรียกใช้แบบจำลองที่มีสถานะมากกว่าที่คุณรู้ว่าแบบจำลองนั้นต้องการ และเรียนรู้ (เช่น) สำเนาจำนวนมาก สำเนาของรัฐที่แท้จริง แต่สมมติว่าคุณสนใจเกี่ยวกับการอนุมานจำนวนสถานะแฝง 'จริง'

เราสามารถดูนี้เป็นกรณีของ เบส์เลือกรูปแบบ : เรามีชุดของรุ่นผู้สมัครแต่ละคนมีจำนวนแตกต่างกันของรัฐแฝงและเราต้องการที่จะเลือกหนึ่งที่มีแนวโน้มที่จะมีการสร้างข้อมูลที่สังเกต การทำเช่นนี้เราจะคำนวณความน่าจะเป็นชายขอบของข้อมูลในแต่ละรุ่น (เรายังสามารถเพิ่มก่อนในรูปแบบของตัวเอง แต่ที่จะไม่จำเป็นในการวิเคราะห์นี้นั้น มีดโกนคชกรรมสาธารณรัฐโคลัมเบีย จะเปิดออกจะเพียงพอที่จะเข้ารหัส ชอบรุ่นที่เรียบง่ายกว่า)

แต่น่าเสียดายที่โอกาสร่อแร่จริงซึ่งรวมทั้งรัฐไม่ต่อเนื่อง z1:T และ (เวกเตอร์) พารามิเตอร์อัตรา λ, p(x1:T)=p(x1:T,z1:T,λ)dzdλ, ไม่ซูฮกสำหรับรุ่นนี้ เพื่อความสะดวกของเราจะใกล้เคียงโดยใช้สิ่งที่เรียกว่า " เบส์เชิงประจักษ์ " หรือ "พิมพ์ครั้งที่สองสูงสุดน่าจะเป็น" คาด: แทนอย่างบูรณาการออกพารามิเตอร์ (ไม่ทราบ) อัตรา λ เกี่ยวข้องกับแต่ละสถานะของระบบเราจะเพิ่มประสิทธิภาพ มากกว่าค่าของพวกเขา:

p~(x1:T)=maxλp(x1:T,z1:T,λ)dz

การประมาณนี้อาจเกินจริง กล่าวคือ จะชอบโมเดลที่ซับซ้อนมากกว่าความเป็นไปได้ที่แท้จริง เราอาจจะพิจารณาประมาณซื่อสัตย์มากขึ้นเช่นการเพิ่มประสิทธิภาพการแปรผันขอบเขตล่างหรือใช้ Monte Carlo ประมาณการเช่น การสุ่มตัวอย่างสำคัญอบ ; สิ่งเหล่านี้ (น่าเศร้า) อยู่นอกเหนือขอบเขตของสมุดบันทึกนี้ (สำหรับข้อมูลเพิ่มเติมเกี่ยวคชกรรมเลือกรูปแบบและใกล้เคียง, บทที่ 7 ของยอดเยี่ยม เครื่องเรียนรู้: กน่าจะเป็นมุมมอง คือการอ้างอิงที่ดี.)

ในหลักการที่เราสามารถทำได้เปรียบเทียบรูปแบบนี้ได้ง่ายๆโดยการเพิ่มประสิทธิภาพ rerunning ข้างต้นหลายครั้งที่มีค่าที่แตกต่างของ num_states แต่ที่จะทำงานมาก ที่นี่เราจะแสดงวิธีการที่จะต้องพิจารณาหลายรูปแบบในแบบคู่ขนานโดยใช้ TFP ของ batch_shape กลไกสำหรับการ vectorization

เมทริกซ์การเปลี่ยนแปลงและสถานะเริ่มต้นก่อน: มากกว่าการสร้างคำอธิบายรูปแบบเดียวตอนนี้เราจะสร้างชุดของการฝึกอบรมการเปลี่ยนแปลงและ logits ก่อนที่หนึ่งสำหรับผู้สมัครแต่ละรุ่นได้ถึง max_num_states เพื่อให้ง่ายต่อการจัดชุด เราจะต้องตรวจสอบให้แน่ใจว่าการคำนวณทั้งหมดมี 'รูปร่าง' เหมือนกัน: สิ่งนี้จะต้องสอดคล้องกับขนาดของแบบจำลองที่ใหญ่ที่สุดที่เราจะพอดี ในการจัดการโมเดลขนาดเล็ก เราสามารถ 'ฝัง' คำอธิบายของโมเดลเหล่านั้นในมิติบนสุดของพื้นที่สถานะ โดยถือว่ามิติที่เหลือเป็นสถานะจำลองที่ไม่เคยใช้อย่างมีประสิทธิภาพ

max_num_states = 10

def build_latent_state(num_states, max_num_states, daily_change_prob=0.05):

 
# Give probability exp(-100) ~= 0 to states outside of the current model.
  active_states_mask
= tf.concat([tf.ones([num_states]),
                                  tf
.zeros([max_num_states - num_states])],
                                 axis
=0)
  initial_state_logits
= -100. * (1 - active_states_mask)

 
# Build a transition matrix that transitions only within the current
 
# `num_states` states.
  transition_probs
= tf.fill([num_states, num_states],
                             
0. if num_states == 1
                             
else daily_change_prob / (num_states - 1))  
  padded_transition_probs
= tf.eye(max_num_states) + tf.pad(
      tf
.linalg.set_diag(transition_probs,
                         tf
.fill([num_states], - daily_change_prob)),
      paddings
=[(0, max_num_states - num_states),
               
(0, max_num_states - num_states)])

 
return initial_state_logits, padded_transition_probs

# For each candidate model, build the initial state prior and transition matrix.
batch_initial_state_logits
= []
batch_transition_probs
= []
for num_states in range(1, max_num_states+1):
  initial_state_logits
, transition_probs = build_latent_state(
      num_states
=num_states,
      max_num_states
=max_num_states)
  batch_initial_state_logits
.append(initial_state_logits)
  batch_transition_probs
.append(transition_probs)

batch_initial_state_logits
= tf.stack(batch_initial_state_logits)
batch_transition_probs
= tf.stack(batch_transition_probs)
print("Shape of initial_state_logits: {}".format(batch_initial_state_logits.shape))
print("Shape of transition probs: {}".format(batch_transition_probs.shape))
print("Example initial state logits for num_states==3:\n{}".format(batch_initial_state_logits[2, :]))
print("Example transition_probs for num_states==3:\n{}".format(batch_transition_probs[2, :, :]))
Shape of initial_state_logits: (10, 10)
Shape of transition probs: (10, 10, 10)
Example initial state logits for num_states==3:
[  -0.   -0.   -0. -100. -100. -100. -100. -100. -100. -100.]
Example transition_probs for num_states==3:
[[0.95  0.025 0.025 0.    0.    0.    0.    0.    0.    0.   ]
 [0.025 0.95  0.025 0.    0.    0.    0.    0.    0.    0.   ]
 [0.025 0.025 0.95  0.    0.    0.    0.    0.    0.    0.   ]
 [0.    0.    0.    1.    0.    0.    0.    0.    0.    0.   ]
 [0.    0.    0.    0.    1.    0.    0.    0.    0.    0.   ]
 [0.    0.    0.    0.    0.    1.    0.    0.    0.    0.   ]
 [0.    0.    0.    0.    0.    0.    1.    0.    0.    0.   ]
 [0.    0.    0.    0.    0.    0.    0.    1.    0.    0.   ]
 [0.    0.    0.    0.    0.    0.    0.    0.    1.    0.   ]
 [0.    0.    0.    0.    0.    0.    0.    0.    0.    1.   ]]

ตอนนี้เราดำเนินการในทำนองเดียวกันกับข้างต้น ในครั้งนี้เราจะใช้มิติชุดพิเศษในการ trainable_rates แยกพอดีกับอัตราสำหรับแต่ละรุ่นภายใต้การพิจารณา

trainable_log_rates = tf.Variable(
    tf
.fill([batch_initial_state_logits.shape[0], max_num_states],
            tf
.math.log(tf.reduce_mean(observed_counts))) +
     tf
.random.stateless_normal([1, max_num_states], seed=(42, 42)),
     name
='log_rates')

hmm
= tfd.HiddenMarkovModel(
  initial_distribution
=tfd.Categorical(
      logits
=batch_initial_state_logits),
  transition_distribution
=tfd.Categorical(probs=batch_transition_probs),
  observation_distribution
=tfd.Poisson(log_rate=trainable_log_rates),
  num_steps
=len(observed_counts))
print("Defined HMM with batch shape: {}".format(hmm.batch_shape))
Defined HMM with batch shape: (10,)

ในการคำนวณบันทึกปัญหาทั้งหมด เราระมัดระวังที่จะรวมเฉพาะค่าก่อนหน้าสำหรับอัตราที่ใช้จริงโดยส่วนประกอบแต่ละรุ่น:

rate_prior = tfd.LogNormal(5, 5)

def log_prob():
  prior_lps
= rate_prior.log_prob(tf.math.exp(trainable_log_rates))
  prior_lp
= tf.stack(
     
[tf.reduce_sum(prior_lps[i, :i+1]) for i in range(max_num_states)])
 
return prior_lp + hmm.log_prob(observed_counts)

ตอนนี้เราเพิ่มประสิทธิภาพวัตถุประสงค์ชุดที่เราได้สร้างแบบจำลองที่เหมาะสมของผู้สมัครทั้งหมดพร้อมกัน:

losses = tfp.math.minimize(
   
lambda: -log_prob(),
    optimizer
=tf.optimizers.Adam(0.1),
    num_steps
=100)
plt
.plot(losses)
plt
.ylabel('Negative log marginal likelihood')
Text(0, 0.5, 'Negative log marginal likelihood')

png

num_states = np.arange(1, max_num_states+1)
plt
.plot(num_states, -losses[-1])
plt
.ylim([-400, -200])
plt
.ylabel("marginal likelihood $\\tilde{p}(x)$")
plt
.xlabel("number of latent states")
plt
.title("Model selection on latent states")
Text(0.5, 1.0, 'Model selection on latent states')

png

จากการตรวจสอบความน่าจะเป็น เราจะเห็นว่าความเป็นไปได้ส่วนเพิ่ม (โดยประมาณ) มีแนวโน้มที่จะชอบแบบจำลองสามสถานะ ดูเหมือนว่าจะค่อนข้างเป็นไปได้ -- โมเดล 'จริง' มีสี่สถานะ แต่จากการดูข้อมูลเพียงอย่างเดียว ยากที่จะแยกแยะคำอธิบายสามสถานะออก

นอกจากนี้เรายังสามารถแยกอัตราที่เหมาะสมสำหรับแต่ละรุ่นของผู้สมัคร:

rates = tf.exp(trainable_log_rates)
for i, learned_model_rates in enumerate(rates):
 
print("rates for {}-state model: {}".format(i+1, learned_model_rates[:i+1]))
rates for 1-state model: [32.968506]
rates for 2-state model: [ 5.789209 47.948917]
rates for 3-state model: [ 2.841977 48.057507 17.958897]
rates for 4-state model: [ 2.8302798 49.585037  41.928406  17.351114 ]
rates for 5-state model: [17.399694  77.83679   41.975216  49.62771    2.8256145]
rates for 6-state model: [41.63677   77.20768   49.570934  49.557076  17.630419   2.8713436]
rates for 7-state model: [41.711704  76.405945  49.581184  49.561283  17.451889   2.8722699
 17.43608  ]
rates for 8-state model: [41.771793 75.41323  49.568714 49.591846 17.2523   17.247969 17.231388
  2.830598]
rates for 9-state model: [41.83378   74.50916   49.619488  49.622494   2.8369408 17.254414
 17.21532    2.5904858 17.252514 ]
rates for 10-state model: [4.1886074e+01 7.3912338e+01 4.1940136e+01 4.9652588e+01 2.8485537e+00
 1.7433832e+01 6.7564294e-02 1.9590002e+00 1.7430998e+01 7.8838937e-02]

และพล็อตคำอธิบายที่แต่ละโมเดลจัดเตรียมไว้สำหรับข้อมูล:

most_probable_states = hmm.posterior_mode(observed_counts)
fig = plt.figure(figsize=(14, 12))
for i, learned_model_rates in enumerate(rates):
  ax
= fig.add_subplot(4, 3, i+1)
  ax
.plot(tf.gather(learned_model_rates, most_probable_states[i]), c='green', lw=3, label='inferred rate')
  ax
.plot(observed_counts, c='black', alpha=0.3, label='observed counts')
  ax
.set_ylabel("latent rate")
  ax
.set_xlabel("time")
  ax
.set_title("{}-state model".format(i+1))
  ax
.legend(loc=4)
plt
.tight_layout()

png

ง่ายที่จะเห็นว่าแบบจำลองสามสถานะแบบหนึ่ง สอง และ (แบบละเอียดมากขึ้น) ให้คำอธิบายที่ไม่เพียงพอได้อย่างไร ที่น่าสนใจคือ โมเดลทั้งหมดที่อยู่เหนือสถานะทั้งสี่ให้คำอธิบายเดียวกันโดยพื้นฐานแล้ว! อาจเป็นเพราะ 'ข้อมูล' ของเราค่อนข้างสะอาดและเหลือที่ว่างเล็กน้อยสำหรับคำอธิบายทางเลือก สำหรับข้อมูลในโลกแห่งความเป็นจริงที่ยุ่งเหยิง เราคาดหวังว่าโมเดลที่มีความจุสูงกว่าจะให้ข้อมูลที่พอดีกับข้อมูลมากขึ้นเรื่อยๆ โดยมีจุดแลกเปลี่ยนที่ความพอดีที่ปรับปรุงแล้วจะมีน้ำหนักเกินจากความซับซ้อนของแบบจำลอง

ส่วนขยาย

โมเดลในโน้ตบุ๊กนี้สามารถขยายได้โดยตรงในหลาย ๆ ด้าน ตัวอย่างเช่น:

  • อนุญาตให้สถานะแฝงมีความน่าจะเป็นต่างกัน (บางสถานะอาจพบได้บ่อยและหายาก)
  • อนุญาตให้มีการเปลี่ยนสถานะที่ไม่สม่ำเสมอระหว่างสถานะแฝง (เช่น เพื่อเรียนรู้ว่าการขัดข้องของเครื่องมักจะตามมาด้วยการรีบูตระบบ มักจะตามด้วยช่วงเวลาของประสิทธิภาพที่ดี เป็นต้น)
  • รุ่นที่ปล่อยก๊าซเรือนกระจกอื่น ๆ เช่น NegativeBinomial รูปแบบกระจายในข้อมูลการนับหรือการกระจายอย่างต่อเนื่องที่แตกต่างกันเช่น Normal สำหรับข้อมูลจริงมูลค่า