HMM(hidden markov model)可以用于模式识别,李开复老师就是采用了HMM完成了语音识别。

一下的例子来自于《统计学习方法》

一个HMM由初始概率分布,状态转移概率分布,观测概率分布确定。并且基于两个假设:

1 假设任意时刻t的状态只依赖于前一个时刻的状态,与其他时刻的状态和观测序列无关

2 假设任意时刻的观测只依赖与该市可的马尔科夫的状态,与其他观测,状态无关。

基于此,HMM有三个基本问题:

1 概率计算问题,给定模型和观测序列,计算在模型下的观测序列出现的概率

2 预测问题,已知模型和观测序列,求最有可能的状态序列

3 学习问题,给出若干个观测序列,估计模型的参数,使得该模型下观测序列概率最大

由于第三个问题涉及到EM算法,而今天还没有看,所以这里只解决了两个,明天写第三个。

给出上面两个问题的实际例子

有三个盒子,每个盒子有红球白球

盒子   红球  白球

1   5  5

2  4  6

3  7  3

第一次从这三个盒子中随机取一个盒子的概率为0.2,0.4,0.4

并且如果上一次抽取的是盒子1那么下一次抽取盒子1的概率为0.5,抽取盒子2的概率为0.2,盒子3的概率为0.3,我们通过一个状态转移矩阵来描述

0.5  0.2  0.3

0.3  0.5  0.2

0.2  0.3  0.5    Aij表示从状态i转移到状态j的概率

通过以上描述,我们能得到该HMM的模型参数

状态转移矩阵:

0.5  0.2  0.3

0.3  0.5  0.2

0.2  0.3  0.5

观测概率分布:

0.5  0.5

0.4  0.6

0.7  0.3 Bij表示第i个状态下观测值为j的概率,这里就是抽到红球和白球的概率

初始概率:

0.2,0.4,0.4表示一开始到各个状态的概率

对于问题1:

现在我们抽取三次,结果为:红白红,求其出现的概率。

解决方法:

采用前向算法

就是我们从时刻1开始,先计算所有状态下观测为红的概率,接下来再求t2时刻会转移到某个状态的概率和,以此类推

具体的可以看《统计学习方法》,http://www.cnblogs.com/tornadomeet/archive/2012/03/24/2415583.html这个说的也比较详细

对于问题2:

抽三次后,结果为红白红,求被抽到最有可能的盒子的序列

解决方法:

这里采用了维特比算法,其实就是很常见的动态规划的算法,和求最短路径一样。如果说t+1时刻的状态序列概率最大,那么t时刻的状态序列也应该是最大的。

具体可以看《统计学习方法》

 import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map; class Alaph{//Alaph和delta两个一样。。。一开始的时候delta思路错了,后来就不改了
double pro;//用于存放概率
int state;//存放状态值
public String toString(){
return "pro:"+pro+" state:"+state;
}
} class Delta{
public double pro;
public int pos;
public String toString(){
return "pro is "+pro+" pos is "+pos;
}
} class Utils{
public static ArrayList<ArrayList<Double>> loadMatrix(String filename) throws IOException{//读取数据
ArrayList<ArrayList<Double>> dataSet=new ArrayList<ArrayList<Double>>();
FileInputStream fis=new FileInputStream(filename);
InputStreamReader isr=new InputStreamReader(fis,"UTF-8");
BufferedReader br=new BufferedReader(isr);
String line=""; while((line=br.readLine())!=null){
ArrayList<Double> data=new ArrayList<Double>();
String[] s=line.split(" "); for(int i=0;i<s.length;i++){
data.add(Double.parseDouble(s[i]));
}
dataSet.add(data);
}
return dataSet;
} public static ArrayList<Double> loadState(String filename)throws IOException{//读取数据,这个和上面那个很像,
FileInputStream fis=new FileInputStream(filename);
InputStreamReader isr=new InputStreamReader(fis,"UTF-8");
BufferedReader br=new BufferedReader(isr);
String line="";
ArrayList<Double> data=new ArrayList<Double>();
while((line=br.readLine())!=null){ String[] s=line.split(" "); for(int i=0;i<s.length;i++){
data.add(Double.parseDouble(s[i]));
} }
return data;
} public static ArrayList<Double> getColData(ArrayList<ArrayList<Double>> A,int index){//根据index值,获取相应的列的数据,后来好像没什么用到。。。囧
ArrayList<Double> col=new ArrayList<Double>();
for(int i=0;i<A.size();i++){
col.add(A.get(i).get(index));
}
return col;
} public static void showData(ArrayList<ArrayList<Double>> data){//debug的时候用的,打印
for(ArrayList<Double> a:data){
System.out.println(a);
}
} public static void showAlaph(ArrayList<Alaph> list){
for(Alaph a:list){
System.out.println(a);
}
} public static ArrayList<Alaph> copy(ArrayList<Alaph> list){//复制
ArrayList<Alaph> temp=new ArrayList<Alaph>();
for(Alaph a:list){
Alaph b=new Alaph();
b.pro=a.pro;
b.state=a.state;
temp.add(b);
}
return temp;
} public static Delta copyDelta(Delta src){//和上面一样,没有什么用
Delta d=new Delta();
d.pro=src.pro;
d.pos=src.pos;
return d;
} public static ArrayList<Delta> copyDeltaList(Delta[] list){//复制
ArrayList<Delta> deltaList=new ArrayList<Delta>();
for(Delta delta:list){
Delta temp=copyDelta(delta);
deltaList.add(temp);
}
return deltaList;
} public static void showDeltaList(ArrayList<Delta> list){//debug
for(Delta d:list){
System.out.println(d);
}
} public static int getMaxIndex(ArrayList<Delta> list){//求list中值最大的下标
double max=-1.0;
int index=-1;
for(int i=0;i<list.size();i++){
if(list.get(i).pro>max){
max=list.get(i).pro;
index=i;
}
}
return index;
} } public class HMM {
public static ArrayList<Alaph> getInitAlaph(ArrayList<Double> initState,ArrayList<ArrayList<Double>> B,int index){//第一步的时候,用于求各个状态下的初始情况
ArrayList<Double> col=Utils.getColData(B,index);
ArrayList<Alaph> alaphSet=new ArrayList<Alaph>();
for(int i=0;i<col.size();i++){
Alaph a=new Alaph();
a.pro=col.get(i)*initState.get(i);//初始情况为初始状态*对应的观测概率矩阵的值
a.state=i;
alaphSet.add(a);
}
return alaphSet;
}
public static ArrayList<Delta> getInitDelta(ArrayList<Double> initState,ArrayList<ArrayList<Double>> B,int index){//和上面一样
ArrayList<Double> col=Utils.getColData(B,index);
ArrayList<Delta> alaphSet=new ArrayList<Delta>();
for(int i=0;i<col.size();i++){
Delta d=new Delta();
d.pro=col.get(i)*initState.get(i);
d.pos=i;
alaphSet.add(d);
}
return alaphSet;
} //用于求给定模型和观测序列下求,该模型下的观测序列出现的概率
public static double calProb(ArrayList<ArrayList<Double>> A,ArrayList<ArrayList<Double>> B,ArrayList<Double> initState,String[] observe,Map<String,Integer> map){
int index=map.get(observe[0]);
ArrayList<Alaph> alaphList=getInitAlaph(initState,B,index);//先求第一步的状态概率
for(int i=1;i<observe.length;i++){//对各个观测值进行求解
String s=observe[i];
int tag=map.get(s);
ArrayList<Alaph> temp=Utils.copy(alaphList);
for(Alaph alaph:alaphList){
int destState=alaph.state;
double pro=0;
for(Alaph a:temp){
int srcState=a.state;
pro+=a.pro*A.get(srcState).get(destState);
}
pro=pro*B.get(destState).get(tag);
alaph.pro=pro;
}
}
double result=0;
for(Alaph alaph:alaphList){
result+=alaph.pro;
}
return result;
} //用于求给定模型和观测序列下,求其最大可能性的状态序列
public static void decoding(ArrayList<ArrayList<Double>> A,ArrayList<ArrayList<Double>> B,ArrayList<Double> initState,String[] observe,Map<String,Integer> map){
int index=map.get(observe[0]); ArrayList<Delta> deltaList=getInitDelta(initState,B,index);
int length=B.size();
Delta maxDeltaList[]=new Delta[B.size()];//用于存放各个状态下的最大概率对应的delta值
ArrayList<ArrayList<Integer>> posList=new ArrayList<ArrayList<Integer>>();//用于存放各个状态下的最佳状态值 for(int i=0;i<B.size();i++){
ArrayList<Integer> a=new ArrayList<Integer>();
a.add(i);
posList.add(a);
} for(int j=1;j<3;j++){
ArrayList<Delta> maxList=new ArrayList<Delta>();
String s=observe[j];
int tag=map.get(s);
for(int i=0;i<B.size();i++){
Delta max=new Delta();
double maxPro=-1.0;
int maxPos=-1;
int maxIndex=-1;
for(int k=0;k<deltaList.size();k++){
Delta delta=deltaList.get(k);
double pro=delta.pro*A.get(delta.pos).get(i)*B.get(i).get(tag);
if(pro>maxPro){
maxPro=pro;
maxPos=i;
maxIndex=k;
}
}
max.pro=maxPro;
max.pos=maxPos;
maxDeltaList[i]=max;
posList.get(i).add(maxIndex);
} deltaList=Utils.copyDeltaList(maxDeltaList);
System.out.println(" ");
} System.out.println(posList.get(Utils.getMaxIndex(deltaList))); } /**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
String dataA="C:/Users/Administrator/Desktop/upload/HMM/A.txt";
String dataB="C:/Users/Administrator/Desktop/upload/HMM/B.txt";
String state="C:/Users/Administrator/Desktop/upload/HMM/init.txt";
ArrayList<ArrayList<Double>> A=Utils.loadMatrix(dataA);
ArrayList<ArrayList<Double>> B=Utils.loadMatrix(dataB);
ArrayList<Double> initState=Utils.loadState(state);
String[] s={"Red","White","Red"};
Map<String,Integer> map=new HashMap();
map.put("Red",0);
map.put("White",1);
double pro=calProb(A,B,initState,s,map);
// System.out.println("pro is "+pro);
decoding(A,B,initState,s,map);
} }

HMM的概率计算问题和预测问题的java实现的更多相关文章

  1. 隐马尔可夫模型HMM(二)概率计算问题

    摘自 1.李航的<统计学习方法> 2.http://www.cnblogs.com/pinard/p/6955871.html 一.概率计算问题 上一篇介绍了概率计算问题是给定了λ(A,B ...

  2. 条件随机场(CRF) - 3 - 概率计算问题

    声明: 1,本篇为个人对<2012.李航.统计学习方法.pdf>的学习总结,不得用作商用,欢迎转载,但请注明出处(即:本帖地址). 2,由于本人在学习初始时有很多数学知识都已忘记,所以为了 ...

  3. nyoj 概率计算

    概率计算 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 A和B两个人参加一场答题比赛.比赛的过程大概是A和B两个人轮流答题,A先答.一旦某人没有正确回答问题,则对手 ...

  4. JAVA实现概率计算(数字不同范围按照不同几率产生随机数)

    程序中经常遇到随机送红包之类的情景,这个随机还得指定概率,比如10%的机率可以得到红包.那么java怎么实现一个简单的概率计算了,见如下例子: int randomInt = RandomUtils. ...

  5. 算法笔记_155:算法提高 概率计算(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 生成n个∈[a,b]的随机整数,输出它们的和为x的概率. 输入格式 一行输入四个整数依次为n,a,b,x,用空格分隔. 输出格式 输出一行 ...

  6. jquery抽奖插件+概率计算

    写了一个抽奖的jquery插件和计算概率的方法, 结合起来就是一个简单的概率抽奖, 不过实际项目中基本不会把抽奖概率的计算放在前端处理~. demo lottery.jquery.js $.fn.ex ...

  7. 紫书 例题 10-10 UVa 10491(概率计算)

    公式很好推,表示被高中生物遗传概率计算虐过的人 这个公式简直不需要动脑 #include<cstdio> using namespace std; int main() { double ...

  8. Java实现 蓝桥杯 算法提高 概率计算

    算法提高 概率计算 时间限制:1.0s 内存限制:256.0MB 问题描述 生成n个∈[a,b]的随机整数,输出它们的和为x的概率. 输入格式 一行输入四个整数依次为n,a,b,x,用空格分隔. 输出 ...

  9. ROC曲线是通过样本点分类概率画出的 例如某一个sample预测为1概率为0.6 预测为0概率0.4这样画出来,此外如果曲线不是特别平滑的话,那么很可能存在过拟合的情况

    ROC和AUC介绍以及如何计算AUC from:http://alexkong.net/2013/06/introduction-to-auc-and-roc/ ROC(Receiver Operat ...

随机推荐

  1. Swift 学习笔记(五)

    126. 协议(Protocols) 协议语法(Protocol Syntax) 属性要求(Property Requirements) 方法要求(Method Requirements) Mutat ...

  2. java 接口参数

    Example6_5.java interface SpeakHello { void speakHello(); } class Chinese implements SpeakHello { pu ...

  3. java类对象

    不错的文章 原文地址:(转载)java中的Class类与Class对象作者:albert1017 本文用作笔记之用,引用的网上资料: http://www.blogjava.net/formatmys ...

  4. android sql Cursor

    Cursor 是每行的集合. 使用 moveToFirst() 定位第一行. 你必须知道每一列的名称.你必须知道每一列的数据类型.Cursor 是一个随机的数据源. 所有的数据都是通过下标取得. Cu ...

  5. java 设计模式之工厂模式与反射的结合

    工厂模式: /**  * @author Rollen-Holt 设计模式之 工厂模式  */   interface fruit{     public abstract void eat(); } ...

  6. CodeForces 546 D. Soldier and Number Game(素数有关)

    Description Two soldiers are playing a game. At the beginning first of them chooses a positive integ ...

  7. 使用curl获取乱码问题

    今天通过curl获取百度地图接口数据,获取到居然是乱码,于是我查看是不是编码问题,发现返回的编码和自己的编码都是utf-8, 继续找原因,发现header报文中  Content-encoding 为 ...

  8. string 与wstring 的转换

    std::wstring StringToWString(const std::string &str) { std::wstring wstr(str.length(),L' '); std ...

  9. 简单的js实现网页时钟

    js实现时钟. <div id="clock"></div> <script type="text/javascript"> ...

  10. android UI中添加一张图片如何将这张图片中某一部分设为透明的

    可以利用canvas画布类,这个类的具体方法可以参看官方api.http://developer.android.com/reference/android/graphics/Canvas.html ...