相对熵(relative entropy或 Kullback-Leibler divergence,KL距离)的java实现(一)
利用信息论的方法可以进行一些简单的自然语言处理
比如利用相对熵进行分类或者是利用相对熵来衡量两个随机分布的差距,当两个随机分布相同时,其相对熵为0.当两个随机分布的差别增加时,器相对熵也增加。我们下面的实验是为了横量概率分布的差异。
试验方法、要求和材料
要求:
1.任意摘录一段文字,统计这段文字中所有字符的相对频率。假设这些相对频率就是这些字符的概率(即用相对频率代替概率);
2.另取一段文字,按同样方法计算字符分布概率;
3.计算两段文字中字符分布的KL距离;
4.举例说明(任意找两个分布p和q),KL距离是不对称的,即D(p//q)!=D(q//p);
方法:
D(p//q)=sum(p(x)*log(p(x)/q(x)))。其中p(x)和q(x)为两个概率分布
约定 0*log(0/q(x))=0;p(x)*log(p(x)/0)=infinity;
实验材料:
从凤凰新闻网,提取的两篇新闻名字为:
《《小团圆》究竟泄了张爱玲什么“秘密”?》
《《小团圆》:张爱玲的一个梦》
《1945年毛zedong和蒋介石在重庆谈判前的秘密情报战》
三篇新闻的编码均为utf-8,大小都是11k左右,都为多页新闻。
三篇新闻的内容如下
[img]相对熵(relative entropy或 Kullback-Leibler divergence,KL距离)的java实现(一)
利用信息论的方法可以进行一些简单的自然语言处理
比如利用相对熵进行分类或者是利用相对熵来衡量两个随机分布的差距,当两个随机分布相同时,其相对熵为0.当两个随机分布的差别增加时,器相对熵也增加。我们下面的实验是为了横量概率分布的差异。
试验方法、要求和材料
要求:
1.任意摘录一段文字,统计这段文字中所有字符的相对频率。假设这些相对频率就是这些字符的概率(即用相对频率代替概率);
2.另取一段文字,按同样方法计算字符分布概率;
3.计算两段文字中字符分布的KL距离;
4.举例说明(任意找两个分布p和q),KL距离是不对称的,即D(p//q)!=D(q//p);
方法:
D(p//q)=sum(p(x)*log(p(x)/q(x)))。其中p(x)和q(x)为两个概率分布
约定 0*log(0/q(x))=0;p(x)*log(p(x)/0)=infinity;
实验材料:
从凤凰新闻网,提取的两篇新闻名字为:
《《小团圆》究竟泄了张爱玲什么“秘密”?》
《《小团圆》:张爱玲的一个梦》
《1945年毛zedong和蒋介石在重庆谈判前的秘密情报战》
三篇新闻的编码均为utf-8,大小都是11k左右,都为多页新闻。
实验中,我们采用两种方法计算概率。一:以字符为单位计算概率;二:以汉语词为单位计算概率在第二种情况下,我们采用Jeasy分词组件进行分词处理,该分词组件为基于前向最大匹配的分词方法,分词结果在绝大多数情况下是正确的。
**
* @author liuyu
* 此实体作为每个字符的一个单位
*
*/
public class Entity
{
String word;//存储字符
float pValue;//存储该字符对应的概率值
public Entity()//类的构造函数
{
pValue=0;
word="";
}
}
读取文件
public static String GetFileText(String path) throws FileNotFoundException,IOException
{
InputStreamReader inStreamReader=new InputStreamReader(new FileInputStream(path),"UTF-8");
//String strFile1=
BufferedReader bufReader=new BufferedReader(inStreamReader);
String line;
StringBuilder sb=new StringBuilder();
while((line=bufReader.readLine())!=null)
{
sb.append(line+" ");
}
inStreamReader.close();
bufReader.close();
String strFile=sb.toString();
return strFile;
}
3.分割字符
(1)分词
public static String CutText(String path)throws FileNotFoundException,IOException
{
String fileText=GetFileText(path);
MMAnalyzer analyzer=new MMAnalyzer();
String result =null;
String spliter="|";
try
{
result = analyzer.segment(fileText, spliter);
}
catch (IOException e)
{
e.printStackTrace();
}
//System.out.print(result);
return result;
}
(2)分单字
public static String CutTextSingleCharacter(String path)throws FileNotFoundException,IOException
{ String text=GetFileText(path);
String proText=null;
Pattern pattern=Pattern.compile("[\\u4E00-\\u9FA5\\uF900-\\uFA2D]");
Matcher m=pattern.matcher(text);
StringBuffer sb=new StringBuffer();
Boolean flag=m.find();
while(flag)
{
int start=m.start();
int end=m.end();
sb.append(text.substring(start, end)+"|");
//System.out.println(text.substring(start,end));
flag=m.find();
}
proText=sb.toString();
return proText;
}
4.计算字符的概率
public static ArrayList<Entity> CalcuP(String path) throws IOException
{ //以词为单位计算相对熵
//String result=CutText(path);
//以字为单位计算相对熵
String result=CutTextSingleCharacter(path);
String []words=result.split("\\|");
ArrayList<Entity> enList=new ArrayList();
for(String w: words)
{ w=w.trim();
Entity en=new Entity();
en.word=w;
en.pValue=1;
enList.add(en);
//System.out.println(w);
}
float total=enList.size();
for(int i=0;i<enList.size()-1;i++)
{
if(!enList.get(i).word.isEmpty())
{
for(int j=i+1;j<enList.size();j++)
{
if(enList.get(i).word.equals(enList.get(j).word))
{
enList.get(i).pValue++;
enList.get(j).pValue=0;
enList.get(j).word="";
}
}
}
}
for(int i=enList.size()-1;i>=0;i--)
{
if(enList.get(i).pValue<1.0)
enList.remove(i);
}
for(int i=0;i<enList.size();i++)
{
enList.get(i).pValue=enList.get(i).pValue/total;
}
return enList;
}
5.计算相对熵
/*用于计算两段文本的相对熵*/
public static float CalKL(ArrayList<Entity>p,ArrayList<Entity>q)
{
float kl=0;
float infinity=10000000;//无穷大
double accretion=infinity;//设置熵增加量的初始值为无穷大。
//从q中找出与p中相对应词的概率,如果找到了,就将accretion的值更新,并累加到相对熵上面;如果没找到,则增加了为无穷大
for(int i=0;i<p.size();i++)
{
if(q.size()!=0)
{ for(int j=q.size()-1;j>=0;j--)
{
if(p.get(i).word.equals(q.get(j).word))
{ accretion=p.get(i).pValue*Math.log(p.get(i).pValue/q.get(j).pValue);
//q.remove(j);
break;
}
}
kl+=accretion;
accretion=infinity;
}
}
return kl;
}
}
结果分析
主函数代码
public static void main(String[] args) throws FileNotFoundException,IOException
{
// TODO Auto-generated method stub;
ArrayList<Entity> enList1=new ArrayList<Entity>();
enList1=CalcuP("C:/Users/liuyu/workspace/KL/KL/zhangailing.txt");
ArrayList<Entity> enList2=new ArrayList<Entity>();
enList2=CalcuP("C:/Users/liuyu/workspace/KL/KL/zhangailing2.txt");
ArrayList<Entity>enList3=new ArrayList<Entity>();
enList3=CalcuP("C:/Users/liuyu/workspace/KL/KL/maozedong.txt");
double f1=CalKL(enList1,enList2);
double f2=CalKL(enList2,enList1);
double f3=CalKL(enList1,enList3);
double f4=CalKL(enList3,enList1);
double f5=CalKL(enList2,enList3);
double f6=CalKL(enList3,enList2);
System.out.println("《《小团圆》究竟泄了张爱玲什么“秘密”?》与《《小团圆》:张爱玲的一个梦》的KL距离: "+f1);
System.out.println("《《小团圆》:张爱玲的一个梦》与《《小团圆》究竟泄了张爱玲什么“秘密”?》的KL距离"+f2);
System.out.println("《《小团圆》究竟泄了张爱玲什么“秘密”?》与《1945年毛和蒋介石在重庆谈判前的秘密情报战》的KL距离 "+f3);
System.out.println("《1945年毛和蒋介石在重庆谈判前的秘密情报战》与《《小团圆》究竟泄了张爱玲什么“秘密”?》的KL距离 "+f4);
System.out.println("《“小团圆”张爱玲的一个梦》与《1945年毛和蒋介石在重庆谈判前的秘密情报战》的KL距离"+f5);
System.out.println("《1945年毛和蒋介石在重庆谈判前的秘密情报战》与《“小团圆”张爱玲的一个梦》的KL距离"+f6);
]
a.以字符为单位的计算结果如下:
《《小团圆》究竟泄了张爱玲什么“秘密”?》与《《小团圆》:张爱玲的一个梦》的KL距离: 2.269998592E9
《《小团圆》:张爱玲的一个梦》与《《小团圆》究竟泄了张爱玲什么“秘密”?》的KL距离4.099975168E9
《《小团圆》究竟泄了张爱玲什么“秘密”?》与《1945年毛和蒋介石在重庆谈判前的秘密情报战》的KL距离 3.029988864E9
《1945年毛和蒋介石在重庆谈判前的秘密情报战》与《《小团圆》究竟泄了张爱玲什么“秘密”?》的KL距离 4.289972736E9
《“小团圆”张爱玲的一个梦》与《1945年毛和蒋介石在重庆谈判前的秘密情报战》的KL距离4.10997504E9
《1945年东和蒋介石在重庆谈判前的秘密情报战》与《“小团圆”张爱玲的一个梦》的KL距离3.539982336E9
b.以词为单位计算结果如下
《《小团圆》究竟泄了张爱玲什么“秘密”?》与《《小团圆》:张爱玲的一个梦》的KL距离: 5.629955584E9
《《小团圆》:张爱玲的一个梦》与《《小团圆》究竟泄了张爱玲什么“秘密”?》的KL距离8.62991872E9
《《小团圆》究竟泄了张爱玲什么“秘密”?》与《1945年毛和蒋介石在重庆谈判前的秘密情报战》的KL距离 6.50994432E9
《1945年毛和蒋介石在重庆谈判前的秘密情报战》与《《小团圆》究竟泄了张爱玲什么“秘密”?》的KL距离 8.029924864E9
《“小团圆”张爱玲的一个梦》与《1945年毛和蒋介石在重庆谈判前的秘密情报战》的KL距离9.219941376E9
《1945年毛和蒋介石在重庆谈判前的秘密情报战》与《“小团圆”张爱玲的一个梦》的KL距离7.739928576E9
从上面结果可以看出:《张秘密》与《张梦》之间距离最近,《毛》与《张梦》直接的概率分布距离近于《毛》与《张秘密》之间的概率分布。
另外补充一点java传参的方式:对于简单类型采用值传递的方法;对于复杂类型采用的是引用传递的机制。这有点类似于matlab.所以,
double f1=CalKL(enList1,enList2);
double f2=CalKL(enList2,enList1);
double f3=CalKL(enList1,enList3);
CalKL函数中如果改变了enlist1,enlist2的值就会使结果不正确。
分享到:
相关推荐
自然语言处理学习中的一个小例子。具体请见 http://www.cnblogs.com/finallyliuyu/archive/2010/03/12/1684015.html
数据挖掘中计算KL距离在matlab环境下的代码
计算数据集间的Kl距离,用于评估数据间的分布一致性
KL距离是反应数据分布的距离,计算KL距离在数据挖掘中有着很重要的作用。
针对核主成分分析(KPCA)人脸识别算法中对全局特征变化敏感和忽略局部特征的问题,研究了一种基于KL距离的KPCA人脸识别算法。利用KL距离定义了类间距离和类内差异,设定了一个非线性优化函数来最大化类间距离,同时...
基于KL距离的KPCA人脸识别算法.pdf
这篇论文介绍了几种KL变换的实现方法,有兴趣的话可以看看。
基于KL变换的特征提取的方法。 选取数据库中的部分样本(每个人的...从训练样本中得到KL变换矩阵,然后对训练样本和测试样本都进行变换,用变换后的数据作最近邻识别,距离可以为对应灰度值之差的平方和,统计识别率。
衡量两个概率分布P(x);Q(x) 的距离 包括 Kullback–Leibler divergence和Jensen–Shannon divergence
此函数计算具有指定参数(均值和协方差矩阵)的两个多元高斯分布之间的Kullback-Leibler(KL)散度。 协方差矩阵必须是正定的。 该代码高效且数值稳定。 例子: 1)计算两个单变量高斯之间的KL散度:KL(N(-1,1)|...
利用KL散度进行效果评价的matlab仿真
基于KL距离的卷积神经网络人脸特征提取模型.pdf
kl散度计算 从网上找到的一个程序 论文中可以使用
KL散度计算的matlab代码函数
Kinetis L系列MCU由五...从应用的角度而言,KL0x属于入门级芯片,KL1x属于通用型芯片,而KL2x、KL3x、KL4x则更具针对性,KL2x系列具有USB OTG技术,KL3x系列支持段式LCD,KL4x系列为KL的旗舰系列,支持功能也最丰富。
- 输入2个变量,即可计算出2个变量之间的KL散度 - 并且绘制了2个变量各自的变量样本图和概率密度分布图 - 注释完整
联想Y460KL2A&KL2B电路图及KL2A_Dis点位图
matlab求两幅图像的kl距离代码
KL展开随机场的程序,利用伽辽金法计算,几个类型的相关函数