<jupyter_start><jupyter_text>算法 10.2（观测序列概率的前向算法）- 使用p175，10.2.1 直接计算法- 测试数据1：测试数据：p177，例10.2（主要的测试数据）- 测试数据2：测试数据：p173，例10.1（盒子和球模型）（用来与直接和后向算法做对照可以相互印证，结果是否正确。另外，由于p177，例10.2中，a的状态的数量、b的状态的数量和观测序列的长度是对齐的，都是3，难以辨别对应的参数是否用对了，所以p173，例10.1没有对齐的数据可以用来检验一下。）- 测试结果1：与书中结果一致：0.13018四舍五入为0.13022- 测试结果2：与直接计算的结果一致- 从测试结果看，与直接计算法相比，前向算法的计算量要小很多<jupyter_code>import math

class MarkovForward(object):
    def probability(self, a, b, pi, output):
        an = len(a[0]) # a的状态的数量 = len(pi)
        bn = len(b[0]) # b的状态的数量
        m = len(output) # 观测序列的长度
        
        alphas = []
        alpha1 = [0] * an
        # 【p176，算法10.2，第（1）步，公式10.15】alpha1
        for i in range(an):
            alpha1[i] = pi[i] * b[i][output[0]]
        print(alpha1)
        alphas.append(alpha1)
        # 【p176，算法10.2，第（2）步，公式10.16】alpha2到alpha_T
        for i in range(1, m):
            alpha = [0] * an
            for j in range(an):
                alpha[j] = 0
                for k in range(an):
                    alpha[j] += alphas[-1][k] * a[k][j]
                print('%.3f * %.3f' % (alpha[j], b[j][output[i]]), end=' = ')
                alpha[j] *= b[j][output[i]]
                print('%.4f' % alpha[j])
            alphas.append(alpha)
        # 【p176，算法10.2，第（3）步，公式10.17】P(O|lambda)
        result = sum(alphas[-1])
        return result


# 测试数据1：测试数据：p177，例10.2（主要的测试数据）
a = [
    [0.5, 0.2, 0.3],
    [0.3, 0.5, 0.2],
    [0.2, 0.3, 0.5]
]
b = [
    [0.5, 0.5],
    [0.4, 0.6],
    [0.7, 0.3]
]
pi = [0.2, 0.4, 0.4]
output = [0, 1, 0]

mf = MarkovForward()
print(mf.probability(a, b, pi, output))

# 测试数据2：测试数据：p173，例10.1（盒子和球模型）
a = [
    [0, 1, 0, 0],
    [0.4, 0, 0.6, 0],
    [0, 0.4, 0, 0.6],
    [0, 0, 0.5, 0.5]
]
b = [
    [0.5, 0.5],
    [0.3, 0.7],
    [0.6, 0.4],
    [0.8, 0.2]
]
pi = (0.25, 0.25, 0.25, 0.25)
output = [0, 0, 1, 1, 0]

mf = MarkovForward()
print(mf.probability(a, b, pi, output))<jupyter_output>[0.125, 0.075, 0.15, 0.2]
0.030 * 0.500 = 0.0150
0.185 * 0.300 = 0.0555
0.145 * 0.600 = 0.0870
0.190 * 0.800 = 0.1520
0.022 * 0.500 = 0.0111
0.050 * 0.700 = 0.0349
0.109 * 0.400 = 0.0437
0.128 * 0.200 = 0.0256
0.014 * 0.500 = 0.0070
0.029 * 0.700 = 0.0200
0.034 * 0.400 = 0.0135
0.039 * 0.200 = 0.0078
0.008 * 0.500 = 0.0040
0.012 * 0.300 = 0.0037
0.016 * 0.600 = 0.0095
0.012 * 0.800 = 0.0096
0.026862016000000002
{'fraction_non_alphanumeric': 0.20836891545687447, 'fraction_numerical': 0.19214346712211786, 'mean_word_length': 2.1534320323014806, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '203357', 'license': 'MIT', 'n_tokens_mistral': 1551, 'n_tokens_neox': 1374, 'n_words': 207, 'path': 'statistical_learning_method/algorithm 10.2(forward stagewise algorithm of observation sequence).ipynb', 'repo_name': 'StudyExchange/CourseCode', 'size': '2342'}