相对熵(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的值就会使结果不正确。
分享到:
相关推荐
在本项目中,我们关注的是如何使用Java编程语言来计算两段文字的KL熵。这个任务对于理解文本的相似性、信息熵以及在信息检索、文本分类等领域都有重要的应用。 首先,我们需要理解KL熵的基本概念。KL熵是信息论中的...
在给定的`KLw.m`文件中,我们可以预想这是一个MATLAB脚本,用于计算两个概率分布之间的KL距离。为了详细解释这个过程,我们需要了解KL散度的基本概念和计算方法。 KL散度定义为两个概率分布P和Q的积分(对于离散...
2. **计算KL散度**:使用MATLAB内置函数或自定义函数计算这两个分布的KL散度。MATLAB可能使用`kldiv`函数或者自定义的循环结构来实现。 3. **效果评价**:根据计算出的KL散度值,评估模型的性能。如果模型预测的...
数据挖掘中计算KL距离在matlab环境下的代码
KL距离,又称相对熵或信息增益,是衡量两个概率分布差异的一种度量。在人脸识别中,使用KL距离可以更好地刻画样本之间的相似性,尤其是在处理面部表情、光照变化等引起的微小差异时。相比于欧氏距离,KL距离更能够...
- `KLDiv.m`:这是一个可能的KL散度计算函数,它接受两个概率分布向量作为输入,并返回它们之间的KL散度值。这个函数可能实现了上述的计算过程。 - `KL.m`:这个文件可能是另一个KL散度的实现,或者它可能包含了与KL...
衡量两个概率分布P(x);Q(x) 的距离 包括 Kullback–Leibler divergence和Jensen–Shannon divergence
`KLDiv.m`文件很可能包含了计算两个概率分布KL散度的函数。这个函数可能接收两个参数,分别代表两个概率分布,然后返回它们之间的KL散度值。计算过程通常是通过将一个分布视为"参考"分布,另一个分布视为"被观测...
KL距离是一种常用的概率分布距离度量方法,它可以度量两个概率分布之间的差异。该方法在人脸特征提取中具有重要作用,因为人脸特征是基于概率分布的。在该模型中,KL距离用于度量不同样本之间概率分布的差异,从而...
基于KL变换的特征提取的方法。 选取数据库中的部分样本(每个人的...从训练样本中得到KL变换矩阵,然后对训练样本和测试样本都进行变换,用变换后的数据作最近邻识别,距离可以为对应灰度值之差的平方和,统计识别率。
使用这个脚本,用户可以轻松地计算两个概率分布的KL散度,这对于论文中的数据分析和模型比较非常有用。 许可证文件“license.txt”则可能包含了脚本的使用条款和条件,确保用户在合规的范围内使用和修改代码。 在...
KL距离,也称为相对熵,衡量了两个概率分布P和Q之间的差异。数学表达式为: \[ D_{KL}(P \| Q) = \sum_{x} P(x) \log{\frac{P(x)}{Q(x)}} \] 在图像处理中,我们通常将图像视为像素的概率分布。对于两幅图像,如果...
在遥感领域,KL变换可以用于图像分类,通过计算不同像素之间的KL距离,识别出具有相似特性或异常的区域。在摄影测量中,它可以辅助进行图像配准和三维重建,通过分析图像特征的分布差异来优化匹配过程。测绘中,KL...
此函数计算具有指定参数(均值和协方差矩阵)的两个多元高斯分布之间的Kullback-Leibler(KL)散度。 协方差矩阵必须是正定的。 该代码高效且数值稳定。 例子: 1)计算两个单变量高斯之间的KL散度:KL(N(-1,1)|...
KL散度是两个概率分布P和Q之间的距离度量,定义为: \[ D_{KL}(P \| Q) = \sum_{x} P(x) \log{\frac{P(x)}{Q(x)}} \] 这个度量表达了从分布Q到分布P的信息损失。在社区划分中,我们通常将网络节点视为随机变量,而...
KL变换的基本思想是衡量一个概率分布P相对于另一个概率分布Q的“信息距离”。其数学表达式为: \[ D_{KL}(P \| Q) = \sum_{x} P(x) \log{\frac{P(x)}{Q(x)}} \] 其中,\( P(x) \) 和 \( Q(x) \) 分别代表两个概率...
4. 人脸识别:通过比较待识别图像与数据库中的人脸在KL空间的表示,计算它们之间的距离或相似度,从而判断身份。 5. 结果展示:可视化识别结果,包括原始图像、特征脸和KL变换后的表示,以便理解和分析。 在实际...