算法任务:

1. 给定一个文件,统计这个文件中所有字符的相对频率(相对频率就是这些字符出现的概率——该字符出现次数除以字符总个数,并计算该文件的熵)。

2. 给定另外一个文件,按上述同样的方法计算字符分布的概率,然后计算两个文件中的字符分布的KL距离。

(熵和KL距离都是NLP自然语言处理中术语,仅仅是涉及到一两个公式而已,不影响您对代码的理解,so just try!)

说明:

1. 给定的文件可以是两个中文文件或两个英文文件,也可以是两个中英文混合文件。对于中文,计算字符,对于英文,计算词。

2.有效字符不包括 空格 换行符 标点符号。

3.将中文字符、英文单词、其他非有效字符及其出现次数,分别写入三个文件中。

4.代码用java完成。

文章的重点:

1.如何判断一个字符是汉字,而不是ASCII、标点、日文、阿拉伯文……

2.了解汉字是如何编码的。“UTF8”绝逼是要花你一整个下午时间去弄明白的东西。

推荐博文:http://www.cnblogs.com/chenwenbiao/archive/2011/08/11/2134503.html

3.正则表达式。对于计算机科班出身的人应该不陌生,在此我就不造次了。

代码如下:

 import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern; public class NLPFileUnit {
public HashMap<String, Integer> WordOccurrenceNumber;//The Occurrence Number of the single Chinese character
//or Single English word in the file
public HashMap<String, Float> WordProbability;//The probability of single Chinese character or English word
public HashMap<String, Integer> Punctuations;//The punctuation that screened out from the file
public float entropy;//熵,本文主要计算单个汉字,或者单个英文单词的熵值
private String filePath; //构造函数
public NLPFileUnit(String filePath) throws Exception {
this.filePath = filePath;
WordOccurrenceNumber = createHash(createReader(filePath));
Punctuations = filterPunctuation(WordOccurrenceNumber);
WordProbability = calProbability(WordOccurrenceNumber);
this.entropy = calEntropy(this.WordProbability); System.out.println("all punctuations were saved at " + filePath.replace(".", "_punctuation.") + "!");
this.saveFile(Punctuations, filePath.replace(".", "_punctuation."));
System.out.println("all words(En & Ch) were saved at " + filePath.replace(".", "_AllWords.") + "!");
this.saveFile(this.WordOccurrenceNumber, filePath.replace(".", "_AllWords."));
} /**
* get the English words form the file to HashMap
* @param hash
* @param path
* @throws Exception
*/
public void getEnWords(HashMap<String, Integer> hash, String path) throws Exception {
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr); //read all lines into content
String content = "";
String line = null;
while((line = br.readLine())!=null){
content+=line;
}
br.close(); //extract words by regex正则表达式
Pattern enWordsPattern = Pattern.compile("([A-Za-z]+)");
Matcher matcher = enWordsPattern.matcher(content);
while (matcher.find()) {
String word = matcher.group();
if(hash.containsKey(word))
hash.put(word, 1 + hash.get(word));
else{
hash.put(word, 1);
}
}
} private boolean isPunctuation(String tmp) {
//Punctuation should not be EN words/ Chinese
final String cnregex = "\\p{InCJK Unified Ideographs}";
final String enregex = "[A-Za-z]+";
return !(tmp.matches(cnregex) || tmp.matches(enregex)) ;
} /**
* judge whether the file is encoded by UTF-8 (UCS Transformation Format)format.
* @param fs
* @return
* @throws Exception
*/
private boolean isUTF8(FileInputStream fs) throws Exception {
if (fs.read() == 0xEF && fs.read() == 0xBB && fs.read() == 0xBF)//所有utf8编码的文件前三个字节为0xEFBBBF
return true;
return false;
} /**
* utf8格式编码的字符,其第一个byte的二进制编码可以判断该字符的长度(汉字一般占三个字节)ASCII占一byte
* @param b
* @return
*/
private int getlength(byte b) {
int v = b & 0xff;//byte to 十六进制数
if (v > 0xF0) {
return 4;
}
// 110xxxxx
else if (v > 0xE0) {
return 3;
} else if (v > 0xC0) {
return 2;//该字符长度占2byte
}
return 1;
} /**
* 通过读取头一个byte来判断该字符占用字节数,并读取该字符,如1110xxxx,表示这个字符占三个byte
* @param fs
* @return
* @throws Exception
*/
private String readUnit(FileInputStream fs) throws Exception {
byte b = (byte) fs.read();
if (b == -1)
return null;
int len = getlength(b);
byte[] units = new byte[len];
units[0] = b;
for (int i = 1; i < len; i++) {
units[i] = (byte) fs.read();
}
String ret = new String(units, "UTF-8");
return ret;
} /**
* 把单词,标点,汉字等全都读入hashmap
* @param inputStream
* @return
* @throws Exception
*/
private HashMap<String, Integer> createHash(FileInputStream inputStream)
throws Exception {
HashMap<String, Integer> hash = new HashMap<String, Integer>();
String key = null;
while ((key = readUnit(inputStream)) != null) {
if (hash.containsKey(key)) {
hash.put(key, 1 + (int) hash.get(key));
} else {
hash.put(key, 1);
}
}
inputStream.close();
getEnWords(hash, this.filePath);
return hash;
} /**
* FileInputStream读取文件,若文件不是UTF8编码,返回null
* @param path
* @return
* @throws Exception
*/
private FileInputStream createReader(String path) throws Exception {
FileInputStream br = new FileInputStream(path);
if (!isUTF8(br))
return null;
return br;
} /**
* save punctuation filtered form (HashMap)hash into (HashMap)puncs,
* @param hash;remove punctuation form (HashMap)hash at the same time
* @return
*/
private HashMap<String, Integer> filterPunctuation(
HashMap<String, Integer> hash) {
HashMap<String, Integer> puncs = new HashMap<String, Integer>();
Iterator<?> iterator = hash.entrySet().iterator(); while (iterator.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>) iterator.next();
String key = entry.getKey().toString();
if (isPunctuation(key)) {
puncs.put(key, hash.get(key));
iterator.remove();
}
}
return puncs;
} /**
* calculate the probability of the word in hash
* @param hash
* @return
*/
private HashMap<String, Float> calProbability(HashMap<String, Integer> hash) {
float count = countWords(hash);
HashMap<String, Float> prob = new HashMap<String, Float>();
Iterator<?> iterator = hash.entrySet().iterator();
while (iterator.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>) iterator.next();
String key = entry.getKey().toString();
prob.put(key, hash.get(key) / count);
}
return prob;
} /**
* save the content in the hash into file.txt
* @param hash
* @param path
* @throws Exception
*/
private void saveFile(HashMap<String, Integer> hash, String path)
throws Exception {
FileWriter fw = new FileWriter(path);
fw.write(hash.toString());
fw.close();
} /**
* calculate the total words in hash
* @param hash
* @return
*/
private int countWords(HashMap<String, Integer> hash) {
int count = 0;
for (Entry<String, Integer> entry : hash.entrySet()) {
count += entry.getValue();
}
return count;
} /**
* calculate the entropy(熵) of the characters
* @param hash
* @return
*/
private float calEntropy(HashMap<String, Float> hash) {
float entropy = 0;
Iterator<Entry<String, Float>> iterator = hash.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, Float> entry = (Entry<String, Float>) iterator.next();
Float prob = entry.getValue();//get the probability of the characters
entropy += 0 - (prob * Math.log(prob));//calculate the entropy of the characters
}
return entropy;
}
} import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry; public class NLPWork { /**
* calculate the KL distance form file u1 to file u2
* @param u1
* @param u2
* @return
*/
public static float calKL(NLPFileUnit u1, NLPFileUnit u2) {
HashMap<String, Float> hash1 = u1.WordProbability;
HashMap<String, Float> hash2 = u2.WordProbability;
float KLdistance = 0;
Iterator<Entry<String, Float>> iterator = hash1.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, Float> entry = iterator.next();
String key = entry.getKey().toString(); if (hash2.containsKey(key)) {
Float value1 = entry.getValue();
Float value2 = hash2.get(key);
KLdistance += value1 * Math.log(value1 / value2);
}
}
return KLdistance;
} public static void main(String[] args) throws IOException, Exception {
//all punctuation will be saved under working directory
System.out.println("Now only UTF8 encoded file is supported!!!");
System.out.println("PLS input file 1 path:");
BufferedReader cin = new BufferedReader(
new InputStreamReader(System.in));
String file1 = cin.readLine();
System.out.println("PLS input file 2 path:");
String file2 = cin.readLine();
NLPFileUnit u1 = null;
NLPFileUnit u2 = null;
try{
u1 = new NLPFileUnit(file1);//NLP:Nature Language Processing
u2 = new NLPFileUnit(file2);
}
catch(FileNotFoundException e){
System.out.println("File Not Found!!");
e.printStackTrace();
return;
}
float KLdistance = calKL(u1, u2);
System.out.println("KLdistance is :" + KLdistance);
System.out.println("File 1 Entropy: " + u1.entropy);
System.out.println("File 2 Entropy: " + u2.entropy);
}
}

计算结果:

[NLP自然语言处理]计算熵和KL距离,java实现汉字和英文单词的识别,UTF8变长字符读取的更多相关文章

  1. 各种形式的熵函数,KL距离

    自信息量I(x)=-log(p(x)),其他依次类推. 离散变量x的熵H(x)=E(I(x))=-$\sum\limits_{x}{p(x)lnp(x)}$ 连续变量x的微分熵H(x)=E(I(x)) ...

  2. KL距离,Kullback-Leibler Divergence

    http://www.cnblogs.com/ywl925/p/3554502.html http://www.cnblogs.com/hxsyl/p/4910218.html http://blog ...

  3. (转载)KL距离,Kullback-Leibler Divergence

    转自:KL距离,Kullback-Leibler Divergence   KL距离,是Kullback-Leibler差异(Kullback-Leibler Divergence)的简称,也叫做相对 ...

  4. 【机器学习基础】熵、KL散度、交叉熵

    熵(entropy).KL 散度(Kullback-Leibler (KL) divergence)和交叉熵(cross-entropy)在机器学习的很多地方会用到.比如在决策树模型使用信息增益来选择 ...

  5. 深度学习中交叉熵和KL散度和最大似然估计之间的关系

    机器学习的面试题中经常会被问到交叉熵(cross entropy)和最大似然估计(MLE)或者KL散度有什么关系,查了一些资料发现优化这3个东西其实是等价的. 熵和交叉熵 提到交叉熵就需要了解下信息论 ...

  6. 【转载】 KL距离(相对熵)

    原文地址: https://www.cnblogs.com/nlpowen/p/3620470.html ----------------------------------------------- ...

  7. KL距离(相对熵)

    KL距离,是Kullback-Leibler差异(Kullback-Leibler Divergence)的简称,也叫做相对熵(Relative Entropy).它衡量的是相同事件空间里的两个概率分 ...

  8. NLP 自然语言处理实战

    前言 自然语言处理 ( Natural Language Processing, NLP) 是计算机科学领域与人工智能领域中的一个重要方向.它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和 ...

  9. 最大熵与最大似然,以及KL距离。

    DNN中最常使用的离散数值优化目标,莫过于交差熵.两个分布p,q的交差熵,与KL距离实际上是同一回事. $-\sum plog(q)=D_{KL}(p\shortparallel q)-\sum pl ...

随机推荐

  1. vim添加自己//解决方案

    使用vim从外面将代码复制并粘贴到时间,假设有一排//凝视.自己主动下一行加入//和每行增加一个<tab>.格全乱:其他编辑器*.c *cpp其他文件格当公式,假设有一排//凝视,按o换行 ...

  2. 归并排序 & 快速排序

    归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有 ...

  3. Unofficial Microsoft SQL Server Driver for PHP (sqlsrv)非官方的PHP SQL Server 驱动

    原文 Unofficial Microsoft SQL Server Driver for PHP (sqlsrv) Here are unofficial modified builds of Mi ...

  4. 查看oracle数据库服务器的名字

    原文:查看oracle数据库服务器的名字 windows 中 1. select name from v$database ; 直接运行就可以查看了, 2.查看tnsnames.ora 的连接,有个S ...

  5. YUV格式转换RGB(基于opencv)

    在编写代码将需要处理YUV格从每个视频帧中提取,然后将其保存为图片.有两种常见的方法在线,第一种是通过opencv自带cvCvtColor,可是这样的方法有bug.得到的图片会泛白.另外一种方法是公式 ...

  6. DirectX (13) 粒子系统

    笔者:i_dovelemon 资源:CSDN 日期:2014 / 10 / 16 主题:Point Sprite, Particle System 介绍 在游戏中.非常多的绚丽,灿烂的特效,都能够使用 ...

  7. 防止tab页重复的去请求服务端

    直接看图吧. 左边是企业树,右边是依据企业变化的一个tab页 实现功能:1.我们希望假设选中的企业不变,我们在切换旁边五个tab页的时候,仅仅是第一次进去的时候请求server端.以下来回切换tab页 ...

  8. 运维自动化之SALTSTACK简单入门

    运维自动化之SaltStack简单入门 饱食终日而无所事事,是颓也,废也.但看昨日,费九牛二虎之力除一BUG便流连于新番之中,不知东方之既黑,实乃颓颓然而荒废矣.故今日来缀一文以忏昨日之悔. Salt ...

  9. windows下oracle数据库定时备份与压缩批处理脚本(win7/win2008亲测通过)

    第一种方式:全备份,并直接覆盖原来的备份文件,固定命名. 脚本: @echo off exp system/a123@HZPG file=e:\db_backup\oradata.dmp log=e: ...

  10. C#网络编程系列(两)它Socket同步TCPserver

    声明原文 笔者:竹zz  本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处 文章系列文件夹 C#网络编程系列文 ...