Viterbi算法实战案例(天气变化、词性预测)

奋斗吧
奋斗吧
擅长邻域:未填写

标签: Viterbi算法实战案例(天气变化、词性预测) 博客 51CTO博客

2023-05-05 18:24:08 295浏览

Viterbi算法实战案例(天气变化、词性预测),Viterbi算法实战案例(天气预测、词性预测)人类活动与天气的预测单词词性的预测Viterbi算法图解笔记人类活动与天气的预测案例Viterbi.java的代码:packagecom.hankcs.book.ch01;/***维特比算法*@authorhankcs*/publicclassViterbi{/**...


Viterbi算法实战案例(天气预测、词性预测)

前置知识:

  • 时间复杂度、递归算法、动态规划算法
  • 贝叶斯公式、条件概率、联合概率
  • NLP自然语言处理

本文讲解内容:

  • 天气变化的案例(代码):给定三个矩阵参数π、A、B。π是第一天为晴天、雨天的概率;A是晴天、雨天相互转换的状态矩阵,B是晴天雨天状态与活动(散步、购物、打扫卫生)的转移概率矩阵。 如果某人三天的活动分别是散步、购物、打扫卫生,问:这三天的天气怎么样?(下雨还是晴天))
  • 单词词性的预测案例(代码):使用维特比算法预测词性。
  • Viterbi算法图解笔记

天气变化的案例的笔记如下:

Viterbi算法实战案例(天气变化、词性预测)_System

Viterbi算法实战案例(天气变化、词性预测)_词性_02

Viterbi算法实战案例(天气变化、词性预测)_词性_03

天气变化的案例

Viterbi.java的代码:
package com.hankcs.book.ch01;

/**
 * 维特比算法
 * @author hankcs
 */
public class Viterbi
{
    /**
     * 求解HMM模型
     * @param obs 观测序列
     * @param states 隐状态
     * @param start_p 初始概率(隐状态)
     * @param trans_p 转移概率(隐状态)
     * @param emit_p 发射概率 (隐状态表现为显状态的概率)
     * @return 最可能的序列
     */
    public static int[] compute(int[] obs, int[] states, double[] start_p, double[][] trans_p, double[][] emit_p)
    {
        double[][] V = new double[obs.length][states.length];
        int[][] path = new int[states.length][obs.length];

        for (int y : states)
        {
            V[0][y] = start_p[y] * emit_p[y][obs[0]];
            path[y][0] = y;
        }

        for (int t = 1; t < obs.length; ++t)
        {
            int[][] newpath = new int[states.length][obs.length];

            for (int y : states)
            {
                double prob = -1;
                int state;
                for (int y0 : states)
                {
                    double nprob = V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]];
                    if (nprob > prob)
                    {
                        prob = nprob;
                        state = y0;
                        // 记录最大概率
                        V[t][y] = prob;
                        // 记录路径
                        System.arraycopy(path[state], 0, newpath[y], 0, t);
                        newpath[y][t] = y;
                    }
                }
            }

            path = newpath;
        }

        double prob = -1;
        int state = 0;
        for (int y : states)
        {
            if (V[obs.length - 1][y] > prob)
            {
                prob = V[obs.length - 1][y];
                state = y;
            }
        }

        return path[state];
    }
}
WeatherExample.java的代码:
package com.hankcs.book.ch01;
import static com.hankcs.book.ch01.WeatherExample.Weather.*;
import static com.hankcs.book.ch01.WeatherExample.Activity.*;
public class WeatherExample
{
    enum Weather
    {
        Rainy,
        Sunny,
    }
    enum Activity
    {
        walk,
        shop,
        clean,
    }
    static int[] states = new int[]{Rainy.ordinal(), Sunny.ordinal()};
    static int[] observations = new int[]{walk.ordinal(), shop.ordinal(), clean.ordinal(), shop.ordinal(), walk.ordinal()};
    static double[] start_probability = new double[]{0.6, 0.4};
    static double[][] transititon_probability = new double[][]{
            {0.7, 0.3},
            {0.4, 0.6},
    };
    static double[][] emission_probability = new double[][]{
            {0.1, 0.4, 0.5},
            {0.6, 0.3, 0.1},
    };

    public static void main(String[] args)
    {
        int[] result = Viterbi.compute(observations, states, start_probability, transititon_probability, emission_probability);
        for (int r : result)
        {
            System.out.print(Weather.values()[r] + " ");
        }
        System.out.println();
    }
}

运行结果如下:

Sunny Rainy Rainy Rainy Sunny

 

词性预测案例

#!/usr/bin/env python
# coding: utf-8

# In[1]:


tag2id, id2tag = {}, {}  # maps tag to id . tag2id: {"VB": 0, "NNP":1,..} , id2tag: {0: "VB", 1: "NNP"....}
word2id, id2word = {}, {} # maps word to id

for line in open('traindata.txt'):
    items = line.split('/')
    word, tag = items[0], items[1].rstrip()  # 抽取每一行里的单词和词性
    
    if word not in word2id:
        word2id[word] = len(word2id)
        id2word[len(id2word)] = word
    if tag not in tag2id:
        tag2id[tag] = len(tag2id)
        id2tag[len(id2tag)] = tag

M = len(word2id)  # M: 词典的大小、# of words in dictionary
N = len(tag2id)   # N: 词性的种类个数  # of tags in tag set


# In[2]:


# 构建 pi, A, B
import numpy as np
pi = np.zeros(N)   # 每个词性出现在句子中第一个位置的概率,  N: # of tags  pi[i]: tag i出现在句子中第一个位置的概率
A = np.zeros((N, M)) # A[i][j]: 给定tag i, 出现单词j的概率。 N: # of tags M: # of words in dictionary
B = np.zeros((N,N))  # B[i][j]: 之前的状态是i, 之后转换成转态j的概率 N: # of tags


# In[3]:


prev_tag = ""
for line in open('traindata.txt'):
    items = line.split('/')
    wordId, tagId = word2id[items[0]], tag2id[items[1].rstrip()]
    if prev_tag == "":  # 这意味着是句子的开始
        pi[tagId] += 1
        A[tagId][wordId] += 1
    else:  # 如果不是句子的开头
        A[tagId][wordId] += 1
        B[tag2id[prev_tag]][tagId] += 1
    
    if items[0] == ".":
        prev_tag = ""
    else:
        prev_tag = items[1].rstrip()

# normalize
pi = pi/sum(pi)
for i in range(N):
    A[i] /= sum(A[i])
    B[i] /= sum(B[i])

#  到此为止计算完了模型的所有的参数: pi, A, B


# In[4]:


def log(v):
    if v == 0:
        return np.log(v+0.000001)
    return np.log(v)


# In[5]:


def viterbi(x, pi, A, B):
    """
    x: user input string/sentence: x: "I like playing soccer"
    pi: initial probability of tags
    A: 给定tag, 每个单词出现的概率
    B: tag之间的转移概率
    """
    x = [word2id[word] for word in x.split(" ")]  # x: [4521, 412, 542 ..]
    T = len(x)
    
    dp = np.zeros((T,N))  # dp[i][j]: w1...wi, 假设wi的tag是第j个tag
    ptr = np.array([[0 for x in range(N)] for y in range(T)] ) # T*N
    # TODO: ptr = np.zeros((T,N), dtype=int)
    
    for j in range(N): # basecase for DP算法
        dp[0][j] = log(pi[j]) + log(A[j][x[0]])
    
    for i in range(1,T): # 每个单词
        for j in range(N):  # 每个词性
            # TODO: 以下几行代码可以写成一行(vectorize的操作, 会使得效率变高)
            dp[i][j] = -9999999
            for k in range(N): # 从每一个k可以到达j
                score = dp[i-1][k] + log(B[k][j]) + log(A[j][x[i]])
                if score > dp[i][j]:
                    dp[i][j] = score
                    ptr[i][j] = k
    
    # decoding: 把最好的tag sequence 打印出来
    best_seq = [0]*T  # best_seq = [1,5,2,23,4,...]  
    # step1: 找出对应于最后一个单词的词性
    best_seq[T-1] = np.argmax(dp[T-1])
    
    # step2: 通过从后到前的循环来依次求出每个单词的词性
    for i in range(T-2, -1, -1): # T-2, T-1,... 1, 0
        best_seq[i] = ptr[i+1][best_seq[i+1]]
        
    # 到目前为止, best_seq存放了对应于x的 词性序列
    for i in range(len(best_seq)):
        print (id2tag[best_seq[i]])
    


# In[6]:


x = "Social Security number , passport number and details about the services provided for the payment"
viterbi(x, pi, A, B)

词性预测的结果如下:

NNP
NNP
NN
,
NN
NN
CC
NNS
IN
DT
NNS
VBN
IN
DT
NN

Viterbi算法词性预测图解笔记

Viterbi算法实战案例(天气变化、词性预测)_词性_04

 

Viterbi算法实战案例(天气变化、词性预测)_词性_05

 

Viterbi算法实战案例(天气变化、词性预测)_维特比算法_06

 

Viterbi算法实战案例(天气变化、词性预测)_词性_07

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695