gamma[t][i] = alpha[t][i] * beta[t][i] / sum_alpha_beta_of_t


if __name__ == '__main__':
    # 测试
    pi = np.array([0.2, 0.5, 0.3])
    A = np.array([[0.5, 0.4, 0.1], [0.2, 0.2, 0.6], [0.2, 0.5, 0.3]])
    B = np.array([[0.4, 0.6], [0.8, 0.2], [0.5, 0.5]])
    Q = '白黑白白黑'
    beta = np.zeros((len(Q), len(A)))
    alpha = np.zeros((len(Q), len(A)))
    gamma = np.zeros((len(Q), len(A)))

    # 开始计算
    # 1. 计算beta
    backward.calc_beta(pi, A, B, Q, beta, common.convert_obs_seq_2_index)
    # 输出最终结果
    print("beta矩阵:")
    print(beta)
    # 2. 计算alpha
    forward.calc_alpha(pi, A, B, Q, alpha, common.convert_obs_seq_2_index)
    # 输出最终结果
    print("alpha矩阵:")
    print(alpha)
    # 3. 计算gamm矩阵
    calc_gamma(alpha, beta, gamma)
    # 输出最终结果
    print("gamma矩阵:")
    print(gamma)

    # 选择每个时刻最大的概率作为预测概率
Exemple #2
0
def baum_welch(pi, A, B, Q, max_iter=3, fetch_index_by_obs_seq=None):
    """
    根据传入的初始概率矩阵(pi、A、B)以及观测序列Q,使用baum_welch算法进行迭代求解最终的pi、A、B的值;最大迭代次数默认为3;最终更新结果保存在传入的参数矩阵中(pi\A\B)
    """
    # 0. 初始化相关变量
    # 初始化序列转换为索引的方法
    fetch_index_by_obs_seq_f = fetch_index_by_obs_seq
    if fetch_index_by_obs_seq_f is None:
        fetch_index_by_obs_seq_f = lambda obs, obs_index: ord(obs[obs_index])

    # 初始化相关的参数值: n、m、T
    T = len(Q)
    n = len(A)
    m = len(B[0])
    alpha = np.zeros((T, n))
    beta = np.zeros((T, n))
    gamma = np.zeros((T, n))
    ksi = np.zeros((T - 1, n, n))
    n_range = range(n)
    m_range = range(m)
    t_range = range(T)
    t_1_range = range(T - 1)

    # 1. 迭代更新(EM算法思想类型)
    for time in range(max_iter):
        # a. 在当前的pi,A,B的情况下对观测序列Q分别计算alpha、beta、gamma和ksi
        forward.calc_alpha(pi, A, B, Q, alpha, fetch_index_by_obs_seq_f)
        backward.calc_beta(pi, A, B, Q, beta, fetch_index_by_obs_seq_f)
        single.calc_gamma(alpha, beta, gamma)
        continuous.calc_ksi(alpha, beta, A, B, Q, ksi,
                            fetch_index_by_obs_seq_f)

        # b. 更新pi、A、B的值
        # b.1. 更新pi值
        for i in n_range:
            pi[i] = gamma[0][i]

        # b.2. 更新状态转移矩阵A的值
        tmp1 = np.zeros(T - 1)
        tmp2 = np.zeros(T - 1)
        for i in n_range:
            for j in n_range:
                # 获取所有时刻从状态i转移到状态j的值
                for t in t_1_range:
                    tmp1[t] = ksi[t][i][j]
                    tmp2[t] = gamma[t][i]

                # 更新状态i到状态j的转移概率
                A[i][j] = np.sum(tmp1) / np.sum(tmp2)

        # b.3. 更新状态和观测值之间的转移矩阵
        for i in n_range:
            for k in m_range:
                tmp1 = np.zeros(T)
                tmp2 = np.zeros(T)
                # 获取所有时刻从状态i转移到观测值k的概率和
                number = 0
                for t in t_range:
                    if k == fetch_index_by_obs_seq_f(Q, t):
                        # 如果序列Q中时刻t对应的观测值就是k,那么进行统计这个时刻t为状态i的概率值
                        tmp1[t] = gamma[t][i]
                        number += 1

                    tmp2[t] = gamma[t][i]

                # 更新状态i到观测值k之间的转移概率
                if number == 0:
                    # 没有转移,所以为0
                    B[i][k] = 0
                else:
                    # 有具体值,那么进行更新操作
                    B[i][k] = np.sum(tmp1) / np.sum(tmp2)