CentOS 服务器安装操作全记录

2012年4月23日 没有评论

# 这是我安装CentOS服务器的过程,记录下来,与大家一起分享。

#CentOS 6.2 ,CentOS-6.2-i386-bin-DVD1.iso(32位) ,CentOS-6.2-x86_64-bin-DVD1.iso(64位)

#安装 CentOS时,选择 “Basic Server”

#root密码:root123

#CentOS 自带了ssh

#安装完操作系统后,添加一个用户 dev

[root@localhost ~]$ useradd dev

#然后密码设为 dev123

[root@localhost ~]$ passwd dev

# 给予 sudo 权限

[root@localhost ~]$ chmod u+w /etc/sudoers

[root@localhost ~]$ vi /etc/sudoers
# 在root ALL=(ALL) ALL 下 添加dev ALL=(ALL) ALL
[root@localhost ~]$ chmod u-w /etc/sudoers

#
#安装完操作系统后,还不能上网,按如下命令配置DHCP方式上网:

vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=”eth0″
HWADDR=”00:0C:29:BD:E1:19″
NM_CONTROLLED=”yes”
ONBOOT=”yes”
BOOTPROTO=dhcp
USECTL=no
TYPE=Ethernet
PEERDNS=yes

#安装常用软件
# 有两种方式方法一,去官网下载已经编译好的二进制文件,或源代码,编译安装

# 方法二,用yum 命令安装,安装官方yum源里已经编译好的程序包。

# 第一种方式要敲很多命令,比yum麻烦,但是可以预先下载好文件,省略了下载的时间,整体速度比

#yum安装方式快很多,而且可以安装最新版。推荐第一种方式

#第二种方式操作简单,敲打的命令少,但是往往yum源的更新速度跟不上各个软件的官网速度,

#用Yum安装的版本经常比较旧

#

#yum的命令形式一般是如下:yum [options] [command] [package ...]
#其中的[options]是可选的,选项包括-h(帮助),-y(当安装过程提示选择全部为”yes”),-q(不显示安装的过程)等等。[command]为所要进行的操作,[package ...]是操作的对象。
#
#yum search package-name # 在线搜索包

#yum list installed # 列出所有已经安装的包

#

#sudo yum install package-name # 安装程序包

#sudo yum groupinsall group-name 安装程序组

#

#sudo yum remove package-name 删除程序包
#sudo yum groupremove group-name 删除程序组
#
#yum update #全部更新
#yum update package-name #更新程序包

#sudo yum groupupdate groupn-name 升级程序组

#sudo yum upgrade # 更新源列表
#yum upgrade package-name #升级程序包
#sudo yum clean all # 清除缓存

#更新
sudo yum update

#清理缓存
sudo yum clean all && yum clean metadata && yum clean dbcache

################### 必须 ####################

#安装编译工具

#方法一

# 去 http://gcc.gnu.org/ 下载源码

# TODO

#方法二

sudo yum groupinstall “Development Tools”

#该命令类似于 Ubuntu 下的apt-get install build-essential

#安装了:autoconf automake bison byacc cscope ctags diffstat doxygen flex gcc gcc-c++
# gcc-gfortran git indent intltool libtool patchutils rcs redhat-rpm-config
# rpm-build subversion swig systemtap

# 同时安装了以下依赖包:apr, apr-util, 等等

# 安装JDK

#删除旧的JDK

java -version

yum list installed | grep jdk

#复制显示出来的JDK,卸载

sudo yum remove java-1.6.0-openjdk.x86_64

#安装新的jdk

#方法一

#从官网下载最新版的,当前是jdk6u31

#开始安装

阅读全文…

分类: 开源工具 标签:

制作 VMware ESXI 5 U盘安装盘

2012年4月18日 没有评论

有两种方法,使用 unetbootin ,使用 LinuxLive USB Creator刻录可启动U盘。
一、 使用 unetbootin,这个方法最自动化,点击两下按钮即可,但是有时候会失败(我用EXSi 5.0 的ISO失败,但是用 EXSi 5.0U1可以成功),U盘启动不了。
1. 单击 光盘镜像,选择ISO文件VMware-VMvisor-Installer-5.0.0.update01-623860.x86_64.iso。
2. 选择U盘,点击“确定”开始刻录。刻录后用U盘启动机器开始安装即可。如下图所示。

unetbootin

二、 使用 LinuxLive USB Creator()
1. 格式化U盘,文件系统为FAT32,并设置为主分区,命令如下:

# 使用管理员权限运行cmd
diskpart
list disk
select disk USB number (例如 select dist 1)
clean
create partition primary
active
format fs=fat32 quick
assign
exit

2. 下载,安装 LinuxLive USB Creator(http://www.linuxliveusb.com/)
3. 按照步骤 1,2,4,选择ISO文件VMware-VMvisor-Installer-5.0.0.update01-623860.x86_64.iso,然后点击 5 ,开始创建U盘安装盘。等待U盘刻录结束。

liliusb
4. 大功告成,是不是很简单?!
4. 编辑U盘根目录下的BOOT.CFG文件。注意,不要添加 "ks=usb",因为下面会用交互模式来安装。
5. 大功告成

6. 注意,本文主要参考了末尾的参考资料。但是不需要原文的第4步和第5步。因为用普通的 “interactive installation”安装就很方便了。第4步和第5步用于一键自动化安装,适用于大量安装的情况,这里不详细讨论。
见文章末尾的评论,@Cesar: if you do not edit the boot.cfg with the “ks=usb” option and select a interactive installation it will work。

 

参考:
Create a bootable VMware ESXi 5 USB stick in Windows and perform a scripted installation

Hadoop 集群安装详细步骤

2012年1月3日 没有评论

本文所使用的版本是 hadoop 1.0.0,即 2011年12月27日发布的1.0正式版

详细安装步骤如下,有大步骤,每个步骤里面有小步骤,绝大部分是必选,只有2步是可选的,红色部分表示要特别注意的地方。

1. 用vmware workstation 新建一台ubuntu server,然后用浅拷贝Create a linked clone 克隆出两台作为slave,这样有了三台ubuntu机器。启动三台机器,假设IP分别为192.168.1.131, 192.168.1.132, 192.168.1.133, 131做为master,132为 slave01, 133为slave02。

2. 修改机器名(这一步的作用是让命令行提示看起来好看点,由默认的 dev@bogon变为 dev@master,这步可选,可以跳过)

(1)192.168.1.131上执行

dev@bogon:~$ sudo vi /etc/hostname

master

重启,会发现命令提示符变为了 dev@master:~$

(2)192.168.1.132上执行

dev@bogon:~$ sudo vi /etc/hostname

slave01

重启,会发现命令提示符变为了 dev@slave01:~$

(3)192.168.1.133上执行

dev@bogon:~$ sudo vi /etc/hostname

slave02

重启,会发现命令提示符变为了 dev@slave02:~$

阅读全文…

用javac命令行编译多个java文件

2011年6月23日 没有评论

1. CLASSPATH一定要具体到jar路径,例如
export CLASSPATH=/usr/lib/jvm/java-6-sun/lib/commons-codec.jar:/usr/lib/jvm/java-6-sun/lib/commons-httpclient-3.1.jar:/usr/lib/jvm/java-6-sun/lib/commons-logging-1.1.jar:/usr/lib/jvm/java-6-sun/lib/dt.jar:/usr/lib/jvm/java-6-sun/lib/htmlconverter.jar:/usr/lib/jvm/java-6-sun/lib/jconsole.jar:/usr/lib/jvm/java-6-sun/lib/junit-4.1.jar:/usr/lib/jvm/java-6-sun/lib/mysql-connector-java-5.1.16-bin.jar:/usr/lib/jvm/java-6-sun/lib/sa-jdi.jar:/usr/lib/jvm/java-6-sun/lib/tools.jar

2. 每个java文件给出路径,最常见的是用通配符*,不支持目录递归。

3. 最好加上 -d,这样会在这个目录下生成class文件,而不会和java文件混在一起

看我的一个具体的例子
javac -d /home/dfq/crawler/bin crawler/*.java weibo4j/*.java weibo4j/org/json/*.java weibo4j/*.java weibo4j/util/*.java weibo4j/http/*.java

运行时用如下命令:
cd /home/dfq/crawler/bin
java -cp .:$CLASSPATH crawler.ManagerThread

分类: 语言与算法 标签:

基于朴素贝叶斯的文本分类算法

2010年5月28日 15 条评论

基于朴素贝叶斯的文本分类算法

作者: 灵魂机器

联系方式:soulmachine@gmail.com

作者博客:www.yanjiuyanjiu.com

摘要:常用的文本分类方法有支持向量机、K-近邻算法和朴素贝叶斯。其中朴素贝叶斯具有容易实现,运行速度快的特点,被广泛使用。本文详细介绍了朴素贝叶斯的基本原理,讨论了两种常见模型:多项式模型(MM)和伯努利模型(BM),实现了可运行的代码,并进行了一些数据测试。

关键字:朴素贝叶斯;文本分类

Text Classification Algorithm Based on Naive Bayes

Author: soulmachine

Email:soulmachine@gmail.com

Blog:www.yanjiuyanjiu.com

Abstract:Usually there are three methods for text classification: SVM、KNN and Naïve Bayes. Naïve Bayes is easy to implement and fast, so it is widely used. This article introduced the theory of Naïve Bayes and discussed two popular models: multinomial model(MM) and Bernoulli model(BM) in details, implemented runnable code and performed some data tests.

Keywords: naïve bayes; text classification

第1章 贝叶斯原理

1.1 贝叶斯公式

设A、B是两个事件,且P(A)>0,称

clip_image002

为在事件A发生的条件下事件B发生的条件概率

乘法公式 P(XYZ)=P(Z|XY)P(Y|X)P(X)

全概率公式 P(X)=P(X|Y1)+ P(X|Y2)+…+ P(X|Yn)

贝叶斯公式clip_image004

在此处,贝叶斯公式,我们要用到的是clip_image006

以上公式,请读者参考《概率论与数理统计(第五版)》的1.4节“条件概率”(这里将原书中的A换成了X,B换成了Y),获得更深的理解。

1.2贝叶斯定理在分类中的应用

在分类(classification)问题中,常常需要把一个事物分到某个类别。一个事物具有很多属性,把它的众多属性看做一个向量,即x=(x1,x2,x3,…,xn),用x这个向量来代表这个事物。类别也是有很多种,用集合Y={y1,y2,…ym}表示。如果x属于y1类别,就可以给x打上y1标签,意思是说x属于y1类别。这就是所谓的分类(Classification)

x的集合记为X,称为属性集。一般X和Y的关系是不确定的,你只能在某种程度上说x有多大可能性属于类y1,比如说x有80%的可能性属于类y1,这时可以把X和Y看做是随机变量,P(Y|X)称为Y的后验概率(posterior probability),与之相对的,P(Y)称为Y的先验概率(prior probability)[2]

在训练阶段,我们要根据从训练数据中收集的信息,对X和Y的每一种组合学习后验概率P(Y|X)。分类时,来了一个实例x,在刚才训练得到的一堆后验概率中找出所有的P(Y|x), 其中最大的那个y,即为x所属分类。根据贝叶斯公式,后验概率为

clip_image008

在比较不同Y值的后验概率时,分母P(X)总是常数,因此可以忽略。先验概率P(Y)可以通过计算训练集中属于每一个类的训练样本所占的比例容易地估计。

我们来举个简单的例子,让读者对上述思路有个形象的认识[3]

考虑一个医疗诊断问题,有两种可能的假设:(1)病人有癌症。(2)病人无癌症。样本数据来自某化验测试,它也有两种可能的结果:阳性和阴性。假设我们已经有先验知识:在所有人口中只有0.008的人患病。此外,化验测试对有病的患者有98%的可能返回阳性结果,对无病患者有97%的可能返回阴性结果。

上面的数据可以用以下概率式子表示:

P(cancer)=0.008,P(无cancer)=0.992

P(阳性|cancer)=0.98,P(阴性|cancer)=0.02

P(阳性|无cancer)=0.03,P(阴性|无cancer)=0.97

假设现在有一个新病人,化验测试返回阳性,是否将病人断定为有癌症呢?

在这里,Y={cancer,无cancer},共两个类别,这个新病人是一个样本,他有一个属性阳性,可以令x=(阳性)。

我们可以来计算各个类别的后验概率:

P(cancer | 阳性) = P(阳性 | cancer)p(cancer)=0.98*0.008 = 0.0078

P(无cancer | 阳性) =P(阳性 | 无cancer)*p(无cancer)=0.03*0.992 = 0.0298

因此,应该判断为无癌症。

在这个例子中,类条件概率,P(cancer|阳性)和P(无cancer|阳性)直接告诉了我们。

一般地,对类条件概率P(X|Y)的估计,有朴素贝叶斯分类器和贝叶斯信念网络两种方法,这里介绍朴素贝叶斯分类器。

1.3朴素贝叶斯分类器

1、条件独立性

给定类标号y,朴素贝叶斯分类器在估计类条件概率时假设属性之间条件独立。条件独立假设可以形式化的表达如下:

clip_image010

其中每个训练样本可用一个属性向量X=(x1,x2,x3,…,xn)表示,各个属性之间条件独立。

比如,对于一篇文章,

Good good study,Day day up.

可以用一个文本特征向量来表示,x=(Good, good, study, Day, day , up)。一般各个词语之间肯定不是相互独立的,有一定的上下文联系。但在朴素贝叶斯文本分类时,我们假设个单词之间没有联系,可以用一个文本特征向量来表示这篇文章,这就是“朴素”的来历。

2、朴素贝叶斯如何工作

有了条件独立假设,就不必计算X和Y的每一种组合的类条件概率,只需对给定的Y,计算每个xi的条件概率。后一种方法更实用,因为它不需要很大的训练集就能获得较好的概率估计。

3、估计分类属性的条件概率

P(xi|Y=y)怎么计算呢?它一般根据类别y下包含属性xi的实例的比例来估计。以文本分类为例,xi表示一个单词,P(xi|Y=y)=包含该类别下包含单词的xi的文章总数/ 该类别下的文章总数。

4、贝叶斯分类器举例

假设给定了如下训练样本数据,我们学习的目标是根据给定的天气状况判断你对PlayTennis这个请求的回答是Yes还是No。

Day Outlook Temperature Humidity Wind PlayTennis
D1 Sunny Hot High Weak No
D2 Sunny Hot High Strong No
D3 Overcast Hot High Weak Yes
D4 Rain Mild High Weak Yes
D5 Rain Cool Normal Weak Yes
D6 Rain Cool Normal Strong No
D7 Overcast Cool Normal Strong Yes
D8 Sunny Mild High Weak No
D9 Sunny Cool Normal Weak Yes
D10 Rain Mild Normal Weak Yes
D11 Sunny Mild Normal Strong Yes
D12 Overcast Mild High Strong Yes
D13 Overcast Hot Normal Weak Yes
D14 Rain Mild High Strong No

可以看到这里样本数据集提供了14个训练样本,我们将使用此表的数据,并结合朴素贝叶斯分类器来分类下面的新实例:

x = (Outlook = Sunny,Temprature = Cool,Humidity = High,Wind = Strong)

在这个例子中,属性向量X=(Outlook, Temperature, Humidity, Wind),类集合Y={Yes, No}。我们需要利用训练数据计算后验概率P(Yes|x)和P(No|x),如果P(Yes|x)>P(No|x),那么新实例分类为Yes,否则为No。

为了计算后验概率,我们需要计算先验概率P(Yes)和P(No)和类条件概率P(xi|Y)。

因为有9个样本属于Yes,5个样本属于No,所以P(Yes)=9/14, P(No)=5/14。

类条件概率计算如下:

P(Outlook = Sunny|Yes)=2/9 P(Outlook = Sunny|No)=3/5

P(Temprature = Cool |Yes) =3/9 P(Temprature = Cool |No) =1/5

P(Humidity = High |Yes) =3/9 P(Humidity = High |No) =4/5

P(Wind = Strong |Yes) =3/9 P(Wind = Strong |No) =3/5

后验概率计算如下:

P(Yes | x)= P(Outlook = Sunny|Yes)×P(Temprature = Cool |Yes)×P(Humidity = High |Yes)×P(Wind = Strong |Yes)×P(Yes)=2/9×3/9×3/9×3/9×3/9×9/14=2/243=9/1701≈0.00529

P(No | x)= P(Outlook = Sunny|No)×P(Temprature = Cool |No)×P(Humidity = High |No)× P(Wind = Strong |No)×P(No)=3/5×1/5×4/5×3/5×5/14=18/875≈0.02057

通过计算得出P(No | x)> P(Yes | x),所以该样本分类为No[3]。

5、条件概率的m估计

假设有来了一个新样本 x1= (Outlook = Cloudy,Temprature = Cool,Humidity = High,Wind = Strong),要求对其分类。我们来开始计算,

P(Outlook = Cloudy|Yes)=0/9=0 P(Outlook = Cloudy |No)=0/5=0

计算到这里,大家就会意识到,这里出现了一个新的属性值,在训练样本中所没有的。如果有一个属性的类条件概率为0,则整个类的后验概率就等于0,我们可以直接得到后验概率P(Yes | x1)= P(No | x1)=0,这时二者相等,无法分类。

当训练样本不能覆盖那么多的属性值时,都会出现上述的窘境。简单的使用样本比例来估计类条件概率的方法太脆弱了,尤其是当训练样本少而属性数目又很大时。

解决方法是使用m估计(m-estimate)方法来估计条件概率:

clip_image012

n是类yj中的样本总数,nc是类yj中取值xi的样本数,m是称为等价样本大小的参数,而p是用户指定的参数。如果没有训练集(即n=0),则P(xi|yj)=p, 因此p可以看作是在类yj的样本中观察属性值xi的先验概率。等价样本大小决定先验概率和观测概率nc/n之间的平衡[2]。

第2章 朴素贝叶斯文本分类算法

现在开始进入本文的主旨部分:如何将贝叶斯分类器应用到文本分类上来。

2.1文本分类问题

在文本分类中,假设我们有一个文档d∈X,X是文档向量空间(document space),和一个固定的类集合C={c1,c2,…,cj},类别又称为标签。显然,文档向量空间是一个高维度空间。我们把一堆打了标签的文档集合<d,c>作为训练样本,<d,c>∈X×C。例如:

<d,c>={Beijing joins the World Trade Organization, China}

对于这个只有一句话的文档,我们把它归类到 China,即打上china标签。

我们期望用某种训练算法,训练出一个函数γ,能够将文档映射到某一个类别:

γ:X→C

这种类型的学习方法叫做有监督学习,因为事先有一个监督者(我们事先给出了一堆打好标签的文档)像个老师一样监督着整个学习过程。

朴素贝叶斯分类器是一种有监督学习,常见有两种模型,多项式模型(multinomial model)和伯努利模型(Bernoulli model)。

2.2多项式模型

1、基本原理

在多项式模型中, 设某文档d=(t1,t2,…,tk),tk是该文档中出现过的单词,允许重复,则

先验概率P(c)= 类c下单词总数/整个训练样本的单词总数

类条件概率P(tk|c)=(类c下单词tk在各个文档中出现过的次数之和+1)/(类c下单词总数+|V|)

V是训练样本的单词表(即抽取单词,单词出现多次,只算一个),|V|则表示训练样本包含多少种单词。在这里,m=|V|, p=1/|V|。

P(tk|c)可以看作是单词tk在证明d属于类c上提供了多大的证据,而P(c)则可以认为是类别c在整体上占多大比例(有多大可能性)。

2、伪代码

//C,类别集合,D,用于训练的文本文件集合

TrainMultiNomialNB(C,D) {

// 单词出现多次,只算一个

V←ExtractVocabulary(D)

// 单词可重复计算

N←CountTokens(D)

for each c∈C

// 计算类别c下的单词总数

// N和Nc的计算方法和Introduction to Information Retrieval上的不同,个人认为

//该书是错误的,先验概率和类条件概率的计算方法应当保持一致

Nc←CountTokensInClass(D,c)

prior[c]←Nc/N

// 将类别c下的文档连接成一个大字符串

textc←ConcatenateTextOfAllDocsInClass(D,c)

for each t∈V

// 计算类c下单词t的出现次数

Tct←CountTokensOfTerm(textc,t)

for each t∈V

//计算P(t|c)

condprob[t][c]←clip_image014

return V,prior,condprob

}

ApplyMultiNomialNB(C,V,prior,condprob,d) {

// 将文档d中的单词抽取出来,允许重复,如果单词是全新的,在全局单词表V中都

// 没出现过,则忽略掉

W←ExtractTokensFromDoc(V,d)

for each c∈C

score[c]←prior[c]

for each t∈W

if t∈Vd

score[c] *= condprob[t][c]

return max(score[c])

}

3、举例

给定一组分类好了的文本训练数据,如下:

docId doc 类别

In c=China?

1 Chinese Beijing Chinese yes
2 Chinese Chinese Shanghai yes
3 Chinese Macao yes
4 Tokyo Japan Chinese no

给定一个新样本Chinese Chinese Chinese Tokyo Japan,对其进行分类。

该文本用属性向量表示为d=(Chinese, Chinese, Chinese, Tokyo, Japan),类别集合为Y={yes, no}。

类yes下总共有8个单词,类no下总共有3个单词,训练样本单词总数为11,因此P(yes)=8/11, P(no)=3/11。类条件概率计算如下:

P(Chinese | yes)=(5+1)/(8+6)=6/14=3/7

P(Japan | yes)=P(Tokyo | yes)= (0+1)/(8+6)=1/14

P(Chinese|no)=(1+1)/(3+6)=2/9

P(Japan|no)=P(Tokyo| no) =(1+1)/(3+6)=2/9

分母中的8,是指yes类别下textc的长度,也即训练样本的单词总数,6是指训练样本有Chinese,Beijing,Shanghai, Macao, Tokyo, Japan 共6个单词,3是指no类下共有3个单词。

有了以上类条件概率,开始计算后验概率,

P(yes | d)=(3/7)3×1/14×1/14×8/11=108/184877≈0.00058417

P(no | d)= (2/9)3×2/9×2/9×3/11=32/216513≈0.00014780

因此,这个文档属于类别china。

2.3伯努利模型

1、基本原理

P(c)= 类c下文件总数/整个训练样本的文件总数

P(tk|c)=(类c下包含单词tk的文件数+1)/(类c下单词总数+2)

在这里,m=2, p=1/2。

后验概率的计算,也有点变化,见下面的伪代码。

2、伪代码

//C,类别集合,D,用于训练的文本文件集合

TrainBernoulliNB(C, D) {

// 单词出现多次,只算一个

V←ExtractVocabulary(D)

// 计算文件总数

N←CountDocs(D)

for each c∈C

// 计算类别c下的文件总数

Nc←CountDocsInClass(D,c)

prior[c]←Nc/N

for each t∈V

// 计算类c下包含单词t的文件数

Nct←CountDocsInClassContainingTerm(D,c,t)

//计算P(t|c)

condprob[t][c]←(Nct+1)/(Nct+2)

return V,prior,condprob

}

ApplyBernoulliNB(C,V,prior,condprob,d) {

// 将文档d中单词表抽取出来,如果单词是全新的,在全局单词表V中都没出现过,

// 则舍弃

Vd←ExtractTermsFromDoc(V,d)

for each c∈C

score[c]←prior[c]

for each t∈V

if t∈Vd

score[c] *= condprob[t][c]

else

score[c] *= (1-condprob[t][c])

return max(score[c])

}

3、举例

还是使用前面例子中的数据,不过模型换成了使用伯努利模型。

类yes下总共有3个文件,类no下有1个文件,训练样本文件总数为11,因此P(yes)=3/4, P(Chinese | yes)=(3+1)/(3+2)=4/5

P(Japan | yes)=P(Tokyo | yes)=(0+1)/(3+2)=1/5

P(Beijing | yes)= P(Macao|yes)= P(Shanghai |yes)=(1+1)/(3+2)=2/5

P(Chinese|no)=(1+1)/(1+2)=2/3

P(Japan|no)=P(Tokyo| no) =(1+1)/(1+2)=2/3

P(Beijing| no)= P(Macao| no)= P(Shanghai | no)=(0+1)/(1+2)=1/3

有了以上类条件概率,开始计算后验概率,

P(yes | d)=P(yes)×P(Chinese|yes) ×P(Japan|yes) ×P(Tokyo|yes)×(1-P(Beijing|yes)) ×(1-P(Shanghai|yes))×(1-P(Macao|yes))

=3/4×4/5×1/5×1/5×(1-2/5) ×(1-2/5)×(1-2/5)=81/15625≈0.005

P(no | d)= 1/4×2/3×2/3×2/3×(1-1/3)×(1-1/3)×(1-1/3)=16/729≈0.022

因此,这个文档不属于类别china。

2.4两个模型的区别

二者的计算粒度不一样,多项式模型以单词为粒度,伯努利模型以文件为粒度,因此二者的先验概率和类条件概率的计算方法都不同。

计算后验概率时,对于一个文档d,多项式模型中,只有在d中出现过的单词,才会参与后验概率计算,伯努利模型中,没有在d中出现,但是在全局单词表中出现的单词,也会参与计算,不过是作为“反方”参与的。

第3章 代码详解

本文附带了一个eclipse工程,有完整的源代码,以及一个微型文本训练库。

ChineseSpliter用于中文分词,StopWordsHandler用于判断一个单词是否是停止词,ClassifyResult用于保存结果,IntermediateData用于预处理文本语料库,TrainnedModel用于保存训练后得到的数据,NaiveBayesClassifier是基础类,包含了贝叶斯分类器的主要代码,MultiNomialNB是多项式模型,类似的,BernoulliNB是伯努利模型,二者都继承自NaiveBayesClassifier,都只重写了父类的计算先验概率,类条件概率和后验概率这3个函数。

3.1中文分词

中文分词不是本文的重点,这里我们直接使用第三方工具,本源码使用的是极易中文分词组件,你还可以使用MMSEG,中科院的ICTCLAS等等。

/**

* 对给定的文本进行中文分词.

*

* @param text

* 给定的文本

* @param splitToken

* 用于分割的标记,如”|”

* @return 分词完毕的文本

*/

public String split(final String text, final String splitToken) {

String result = null;

try {

result = analyzer.segment(text, splitToken);

} catch (IOException e) {

e.printStackTrace();

}

return result;

}

3.2停止词处理

停止词(Stop Word)是指那些无意义的字或词,如“的”、“在”等。去掉文档中的停止词也是必须的一项工作,这里简单的定义了一些常见的停止词,并根据这些常用停止词在分词时进行判断。

/** 常用停用词. */

private static String[] stopWordsList = {

// 来自 c:\Windows\System32\NOISE.CHS

“的”, “一”, “不”, “在”, “人”, “有”, “是”, “为”, “以”, “于”, “上”, “他”, “而”,

“后”, “之”, “来”, “及”, “了”, “因”, “下”, “可”, “到”, “由”, “这”, “与”, “也”,

“此”, “但”, “并”, “个”, “其”, “已”, “无”, “小”, “我”, “们”, “起”, “最”, “再”,

“今”, “去”, “好”, “只”, “又”, “或”, “很”, “亦”, “某”, “把”, “那”, “你”, “乃”,

“它”,

// 来自网络

“要”, “将”, “应”, “位”, “新”, “两”, “中”, “更”, “我们”, “自己”, “没有”, ““”, “””,

“,”, “(”, “)”, “” };

/**

* 判断一个词是否是停止词.

*

* @param word

* 要判断的词

* @return 是停止词,返回true,否则返回false

*/

public static boolean isStopWord(final String word) {

for (int i = 0; i < stopWordsList.length; ++i) {

if (word.equalsIgnoreCase(stopWordsList[i])) {

return true;

}

}

return false;

}

3.3预处理数据

我们这里使用搜狗的文本分类语料库作为训练样本,把SogouC.reduced.20061102.tar.gz解压到D盘,目录结构为

D:\Reduced

|– C000008

|– C000010

|– C000013

|– C000014

|– C000016

|– C000020

|– C000022

|– C000023

|– C000024

IntermediateData.java主要用于处理文本数据,将所需要的信息计算好,存放到数据库文件中。

中间数据文件主要保存了如下信息,

/** 单词X在类别C下出现的总数. */

public HashMap[] filesOfXC;

/** 给定分类下的文件数目. */

public int[] filesOfC;

/** 根目录下的文件总数. */

public int files;

/** 单词X在类别C下出现的总数 */

public HashMap[] tokensOfXC;

/** 类别C下所有单词的总数. */

public int[] tokensOfC;

/** 整个语料库中单词的总数. */

public int tokens;

/** 整个训练语料所出现的单词. */

public HashSet<String> vocabulary;

我们使用命令

IntermediateData d:\Reduced\ gbk d:\reduced.db

将文本训练库的信息计算好,保存到中间文件中。以后的阶段,我们都不再需要文本语料库了,只需要reduced.db。

3.3训练

基本的框架代码都在NaiveBayesClassifier中,MultiNomialNB和BernoulliNB都只是重新实现(override)了

/** 计算先验概率P(c). */

protected void calculatePc() {

}

/** 计算类条件概率P(x|c). */

protected void calculatePxc() {

}

/**

* 计算文本属性向量X在类Cj下的后验概率P(Cj|X).

*

* @param x

* 文本属性向量

* @param cj

* 给定的类别

* @return 后验概率

*/

protected double calcProd(final String[] x, final int cj) {

return 0;

}

这三个函数。

训练函数如下:

public final void train(String intermediateData, String modelFile) {

// 加载中间数据文件

loadData(intermediateData);

model = new TrainnedModel(db.classifications.length);

model.classifications = db.classifications;

model.vocabulary = db.vocabulary;

// 开始训练

calculatePc();

calculatePxc();

db = null;

try {

// 用序列化,将训练得到的结果存放到模型文件中

ObjectOutputStream out = new ObjectOutputStream(

new FileOutputStream(modelFile));

out.writeObject(model);

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

我们使用命令:

MultiNomialNB –t d:\reduced.db d:\reduced.mdl

开始训练,得到的模型文件保存在reduced.mdl中。

3.4分类

有了模型文件,就可以用它来进行分类了。

可以使用命令

MultiNomialNB d:\reduced.mdl d:\temp.txt gbk

对文本文件temp.txt进行分类。

还可以将当初训练出这个模型文件的文本库,进行分类,看看正确率有多少,即“吃自己的狗食”,命令行如下

MultiNomialNB -r d:\reduced\ gbk d:\reduced.mdl

分类函数如下:

/**

* 对给定的文本进行分类.

*

* @param text

* 给定的文本

* @return 分类结果

*/

public final String classify(final String text) {

String[] terms = null;

// 中文分词处理(分词后结果可能还包含有停用词)

terms = textSpliter.split(text, ” “).split(” “);

// 去掉停用词,以免影响分类

terms = ChineseSpliter.dropStopWords(terms);

double probility = 0.0;

// 分类结果

List<ClassifyResult> crs = new ArrayList<ClassifyResult>();

for (int i = 0; i < model.classifications.length; i++) {

// 计算给定的文本属性向量terms在给定的分类Ci中的分类条件概率

probility = calcProd(terms, i);

// 保存分类结果

ClassifyResult cr = new ClassifyResult();

cr.classification = model.classifications[i]; // 分类

cr.probility = probility; // 关键字在分类的条件概率

System.out.println(“In process….”);

System.out.println(model.classifications[i] + “:” + probility);

crs.add(cr);

}

// 找出最大的元素

ClassifyResult maxElem = (ClassifyResult) java.util.Collections.max(

crs, new Comparator() {

public int compare(final Object o1, final Object o2) {

final ClassifyResult m1 = (ClassifyResult) o1;

final ClassifyResult m2 = (ClassifyResult) o2;

final double ret = m1.probility – m2.probility;

if (ret < 0) {

return -1;

} else {

return 1;

}

}

});

return maxElem.classification;

}

测试正确率的函数getCorrectRate(),核心代码就是对每个文本文件调用classify(),将得到的类别和原始的类别比较,经过统计后就可以得到百分比。

更多细节请读者阅读源代码。

参考文献

[1] Christopher D. Manning, Prabhakar Raghavan, Hinrich Schütze, Introduction to Information Retrieval, Cambridge University Press, 2008, chapter 13, Text classification and Naive Bayes.

[2]Pang-Ning Tan, Michael Steinbach, Vipin Kumar, 《数据挖掘导论》,北京:人民邮电出版社,2007,第140~145页。

[2] 石志伟, 吴功宜, “基于朴素贝叶斯分类器的文本分类算法”, 第一届全国信息检索与内容安全学术会议,2004

[3] 洞庭散人,“基于朴素贝叶斯分类器的文本分类算法(上)”,“基于朴素贝叶斯分类器的文本分类算法(下)”,2008

[4]DL88250, “朴素贝叶斯中文文本分类器的研究与实现(1)”,“朴素贝叶斯中文文本分类器的研究与实现(2)”,2008

由于笔者水平有限,本文出现错误在所难免,欢迎读者批评指正,请到原文发表评论或给我发email,谢谢 :)

原文地址:http://www.yanjiuyanjiu.com/2010/05/28/naive-bayes-text-classification/

PDF版本  源码下载

推荐给TeX新手的电子书和书籍

2010年4月17日 没有评论

CTEX自带的文档:
1、安装好CTEX后,c:\CTEX\CTeX\ctex\doc\下的两个文档,ctex-faq.pdf和lshort-cn.pdf(即93 分钟学会 LaTeX2e)
2、ftp://ftp.ctex.org/pub/tex/documents/bible/ 下的 LaTeX_manual.zip
对于初学者,上面3个文档足够了,在c:\CTEX\CTeX\ctex\doc\目录下的其他几个文档也非常好。

如果想进一步学习,推荐下面一本书。
3、《LaTeX入门与提高》,陈志杰,2008,高等教育出版社,卓越上有卖的。这里有个PDF扫描版

网上的免费电子书:
4、A Guide to LaTeX
5、the latex companion,和第2个文档 LaTeX_manual 在同一个ftp目录下,还有另一个下载地址
6、LaTeX2e使用手册
7、LaTeX2e插图指南

参考资料:
陈志杰老师的《latex入门与提高》这本书怎么样啊?
中国LaTeX 新用户,LaTeX中文必读教程

分类: 开源工具 标签: , ,

Java 读写图像

2010年4月1日 没有评论

Java中进行图像I/O(即读图片和写图片,不涉及到复杂图像处理)有三个方法:
1. Java Image I/O API,支持常见图片,从Java 2 version 1.4.0开始就内置了。
主页:http://java.sun.com/javase/6/docs/technotes/guides/imageio/index.html
2. JAI 中的 Image I/O Tools,支持更多图片类型,例如JPEG-LS, JPEG2000, 和 TIFF。
主页:https://jai-imageio.dev.java.net/。JAI 是一个关于图像处理的框架,很庞大,
其中仅仅jai-imageio是关于图像I/O的,其他的可以不看。
3. JAI的com.sun.media.jai.codec 也有一定的图像解码能力

当然,还有众多的java开源工具包可以读写图像,例如JIMI, JMagic等,但JDK目前本身能
够读写图片,就用JDK的,开发和部署方便,不需要额外下载jar包。

由于JAI是Java新加入的,很多组件不是正式规范,JDK不自带,因此开发和部署需要额外
安装,安装文件在官网https://jai.dev.java.net/下载得到。

如果你仅仅想读取常见格式的图片,不需要用JAI这么高级这么庞大的东西,
用Java Image I/O API即可。

下面重点介绍 Java Image I/O API。

Java Image I/O API 主要在 javax.imageio 下面。JDK已经内置了常见图片格式的插件,
但它提供了插件体系结构,第三方也可以开发插件支持其他图片格式。

下面这段代码可以展示,JDK内置支持的图片格式。
import javax.imageio.*;
import java.util.Arrays;

public class HelloWorld {
public static void main(String args[]) {
String readFormats[] = ImageIO.getReaderFormatNames();
String writeFormats[] = ImageIO.getWriterFormatNames();
System.out.println(“Readers:  ” + Arrays.asList(readFormats));
System.out.println(“Writers:  ” + Arrays.asList(writeFormats));
}
}

主页上有一个文档,Java Image I/O API Guide,很通俗易懂,可以让你快速上手。以下
内容主要来自这个文档的第3章。

第3章 编写图像I/O程序
3.1 读写图片
javax.imageio.ImageIO类提供了一组静态方法进行最简单的图像I/O操作。
读取一个标准格式(GIF, PNG, or JPEG)的图片很简单:
File f = new File(“c:\images\myimage.gif”);
BufferedImage bi = ImageIO.read(f);

Java Image I/O API 会自动探测图片的格式并调用对应的插件进行解码,当安装了一个新
插件,新的格式会被自动理解,程序代码不需要改变。

写图片同样简单:
BufferedImage bi;
File f = new File(“c:\images\myimage.png”);
ImageIO.write(im, “png”, f);

3.2 更进一步
上一节谈到的方法对于简单程序已经足够了。不过,Java Image I/O API 提供了为编写复
杂程序的能力。为了利用API的高级特性,应用程序应当直接使用类ImageReader 和
ImageWriter。

3.3 ImageReader 类
与其用ImageIO类来进行所有的解码操作,不如用ImageIO类去得到一个ImageReader对象,
再用这个对象去进行读操作:
Iterator readers = ImageIO.getImageReadersByFormatName(“gif”);
ImageReader reader = (ImageReader)readers.next();

ImageReader对象也可以基于文件内容、文件后缀或MIME类型获得。这个用于查找和初始
化ImageReader对象的机制用到了javax.imageio.spi.ImageReaderSpi类,它可以在不用初
始化插件的情况下获得插件的信息。”service provider interfaces” (SPIs)将会在下一
章详细讨论。一旦获得了一个ImageReader对象,必须给它是指一个输入源。大部分
ImageReader对象可以从ImageInputStream类输入源读取数据,ImageInputStream是Image
I/O API定义的专用输入源。

获得一个ImageInputStream 是简单的。给定一个File或InputStream,一个
ImageInputStream对象可以通过调用如下函数产生:
Object source; // File or InputStream
ImageInputStream iis = ImageIO.createImageInputStream(source);

一旦有了输入源,可以把它与一个ImageReader对象关联起来:
reader.setInput(iis, true);

如果输入源文件包含多张图片,而程序不保证按顺序读取时,第二个参数应该设置为
false。对于那些只允许存储一张图片的文件格式,永远传递true是合理的。

当ImageReader对象有了输入源后,我们就可以获取图片信息而不用把整张图片数据都读入
内存。例如,调用reader.getImageWidth(0)可以让我们获得文件中第一张图片的宽度。一
个好的插件会试图解码文件的必要部分,去获得图片的宽度,而不用读取任何一个像素。

为读取图片,可以调用reader.read(imageIndex), imageIndex是文件(当包含多张图片时)
中图片的索引。这与上一节调用ImageIO.read()产生的结果相同。

3.3.1 ImageReadParam
如果需要更多的控制,可以向read()方法传递一个ImageReadParam类型的参数。一个
ImageReadParam对象可以让程序更好的利用内存。它不仅允许指定一个感兴趣的区域,还
可以指定一个抽样因子,用于向下采样。

例如,为了只解码图片的左上角的1/4,程序可以先获取一个合适的ImageReadParam对象:
ImageReadParam param = reader.getDefaultReadParam();

接下来,指定图片区域:
import java.awt.Rectangle;
int imageIndex = 0;
int half_width = reader.getImageWidth(imageIndex)/2;
int half_height = reader.getImageHeight(imageIndex)/2;
Rectangle rect = new Rectangle(0, 0, half_width, half_height);
param.setSourceRegion(rect);

最后,读取图片:
BufferedImage bi = reader.read(imageIndex, param);

结果是一张新图片,宽和高都只有原图片的一半。

另一个例子,为了读取每三个像素中的一个,产生一个原图片1/9大小的图片,可以用
ImageReadParam指定抽样因子:
param = reader.getDefaultImageParam();
param.setSourceSubsampling(3, 3, 0, 0);
BufferedImage bi3 = reader.read(0, param);

3.3.2 IIOParamController
插件有时会提供一个IIOParamController类,这是可选的。略。

3.3.3 读多图片文件
ImageReader 中所有与图片打交道的方法都有一个imageIndex 参数,这个参数用于读取多
图片文件中的一张。

ImageReader.getNumImages()返回多图片文件中的图片个数。这个方法有一个boolean参数,
allowSearch。有的图片格式,典型的GIF,没有提供任何获取文件中的图片个数方法,除
非读取整个进行解析。这样代价很高,因此设置allowSearch为false可以让方法直接返回
-1,而不是实际的图片个数。如果此参数是true,则该方法总会返回文件中实际的图片个
数。

即使在不知道文件中图片个数的情况下,仍可以调用read(imageIndex); 如果索引值过大,
该方法会抛出IndexOutOfBoundsException异常。因此,程序可以递增索引去获取图片,
直到异常。

3.3.4 读缩略图
有的图片格式允许一个(或多个)小的预览图,与主图片一起存储在文件中。这些
“缩略图”对于快速识别图片很有用,不用解码整个图片。

程序可以调用如下代码,探测一张图片有多少张缩略图:
reader.getNumThumbnails(imageIndex);

如果存在缩略图,可以调用如下代码获取:
int thumbailIndex = 0;
BufferedImage bi;
bi = reader.readThumbnail(imageIndex, thumbnailIndex);

3.4 ImageWriter 类
就像我们可以用ImageIO 的一个方法获取某种图片格式的ImageReader对象一样,我们也可
以获取ImageWriter对象:
Iterator writers = ImageIO.getImageWritersByFormatName(“png”);
ImageWriter writer = (ImageWriter)writers.next();

一旦获取了一个ImageWriter对象,必须给它设置一个输出源ImageOutputStream。
File f = new File(“c:\images\myimage.png”);
ImageOutputStream ios = ImageIO.createImageOutputStream(f);
writer.setOutput(ios);

最后,可以把图片写入到输出源:
BufferedImage bi;
writer.write(bi);

3.4.1 写多图片文件
IIOImage类用于存储图片,缩略图或元信息的引用。下一节将讨论Metadata,目前,我们
简单地给Metadata相关参数传递null。
ImageWriter 类有一个方法write(),用于从IIOImage创建一个新文件,还有一个方法
writeInsert(),用于向一个已存在文件添加一个IIOImage对象。通过调用这两者,可以创
建一个多图片文件:
BufferedImage first_bi, second_bi;
IIOImage first_IIOImage = new IIOImage(first_bi, null, null);
IIOImage second_IIOImage = new IIOImage(second_bi, null, null);
writer.write(null, first_IIOImage, null);
if (writer.canInsertImage(1)) {
writer.writeInsert(1, second_IIOImage, null);
} else {
System.err.println(“Writer can’t append a second image!”);
}

3.5  处理 Metadata
所有与像素无关的信息,都属于在Metadata。javax.imageio.metadata 包含了用于访问
Metadata的类和接口。

Image I/O API 将stream metadata 和image metadata区别对待。stream metadata与一个
文件中存储了多张图片有关,image metadata只与单个图片有关。如果一个文件只包含一张
图片,那么就只存在image metadata。

可以通过调用ImageReader.getStreamMetadata 和 getImageMetadata(int imageIndex)来
获取metadata。这些方法会返回一个实现了IIOMetadata接口的对象,该对象会被向上转化
为ImageReader类型,

3.6 编码转换

3.7 事件监听

分类: 开源工具 标签:

Java质量检测评估工具

2010年3月31日 没有评论

Java代码质量检测评估工具
“五大” 代码分析领域:
* 编码风格
* 冗余代码
* 代码覆盖率
* 依赖项分析
* 复杂度监控

一下列举了一些目前比较流行的工具。网址后面列出了其PR值,可以反映此工具的流行度。
1、编码风格
CheckStyle
Home page: http://checkstyle.sourceforge.net/ (6)
对应的eclipse插件有多个,其中eclipsecs最常用
Home page: http://eclipse-cs.sourceforge.net/ (6)
eclipse插件URL:http://eclipse-cs.sf.net/update/

2、冗余代码
Simian http://www.redhillconsulting.com.au/products/simian/ (5)
PMD 的 CPD http://pmd.sourceforge.net/cpd.html (5)

3、代码覆盖率
EMMA  http://emma.sourceforge.net/ (6)
Cobertura  http://cobertura.sourceforge.net/ (6)
EclEmma http://update.eclemma.org/ (5)
Coverlipse http://coverlipse.sourceforge.net/ (3)

4、依赖项分析
JDepend http://clarkware.com/software/JDepend.html (6)

5、复杂度监控
Metrics http://metrics.sourceforge.net/ (4)

具有以上两项或两项以上的综合工具(也称为静态分析工具):
1、PMD
Home page: http://pmd.sourceforge.net/ (6)
eclipse插件URL:http://pmd.sourceforge.net/eclipse

2、FindBugs http://findbugs.sourceforge.net/ (6)
eclipse插件URL:http://findbugs.cs.umd.edu/eclipse

FindBugs 检查程序生成的class文件,即分析字节码
PMD 检查源码,分析源代码

3、Jtest http://www.parasoft.com/jtest

4、Jlint http://artho.com/jlint/ (5)

5、Lint4j http://www.jutils.com/ (4)

参考资料:http://blog.csdn.net/cb_121/archive/2009/05/22/4208792.aspx

我个人平时最常用的是Checkstyle,其次是PMD,读者可以参考一下。

分类: 开源工具 标签:

使用pdfbox 抽取PDF文件中的文本

2010年3月28日 没有评论
[code lang="java"]
package com.yanjiuyanjiu.search;

import java.io.File;
import java.io.IOException;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFTextStripper;

/**
 * 抽去PDF文件中的文本.
 * @author soulmachine
 *
 */
public final class PDFboxTest {
 /** 禁止创建对象. */
 private PDFboxTest() {
 }
 /**
 * 抽取PDF中的文本.
 * @param f PDF文件
 * @return PDF对应的文本字符串
 */
 public static String getText(final File f) {
 String text = "";
 try {
 PDDocument pdfdocument = PDDocument.load(f);
 PDFTextStripper stripper = new PDFTextStripper();
 stripper.setStartPage(1); // 只抽取第1页和第2页
 stripper.setEndPage(2);
 text = stripper.getText(pdfdocument);
 pdfdocument.close();

 } catch (IOException e) {
 e.printStackTrace();
 }

 return text;
 }

 /** 测试.
 *
 * @param args PDF文件路径
 */
 public static void main(final String[]  args) {
 File file = new File(args[0]);
 System.out.println(PDFboxTest.getText(file));
 }
}

[/code]

eclipse工程文件下载
分类: 开源工具 标签:

java命令行下运行class文件

2010年2月15日 3 条评论

今天碰到了一个很变态的问题,写了一个很简单的HelloWord.java,内容如下:
package com.yanjiuyanjiu;

public class HelloWorld {
public static void main(String args[]) {
System.out.println(“Hello World!”);
}
}

在eclipse中运行是可以的,但是在命令行下运行总是失败。我的工程位置为 d:\workspace\HelloWorld\。

尝试了很多次,如下

d:\workspace\HelloWorld\bin\com\yanjiuyanjiu\>java HelloWorld

Exception in thread “main” java.lang.NoClassDefFoundError: HelloWorld (wrong name: com/yanjiuyanjiu/HelloWorld)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: HelloWorld.  Program will exit.
Exception in thread “main”

d:\workspace\HelloWorld\bin\com\yanjiuyanjiu\>java -classpath .; HelloWorld
Exception in thread “main” java.lang.NoClassDefFoundError: HelloWorld (wrong name: com/yanjiuyanjiu/HelloWorld)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: HelloWorld.  Program will exit.
Exception in thread “main”

d:\workspace\HelloWorld\bin\com\yanjiuyanjiu\>cd..

d:\workspace\HelloWorld\bin\com\>cd..

d:\workspace\HelloWorld\bin\>java -classpath .; com/yanjiuyanjiu/HelloWorld    只有这个成功

Hello World!

d:\workspace\HelloWorld\bin\>java -classpath .; com\yanjiuyanjiu\HelloWorld    换了个斜杠就不行了

Exception in thread “main” java.lang.NoClassDefFoundError: com\yanjiuyanjiu\HelloWorld (wrong name: com/yanjiuyanjiu/HelloWorld)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: com\yanjiuyanjiu\HelloWorld.  Program will exit.
Exception in thread “main”

d:\workspace\HelloWorld\bin\>java -classpath ./com/yanjiuyanjiu/; HelloWorld

Exception in thread “main”java.lang.NoClassDefFoundError: HelloWorld (wrong name: com/yanjiuyanjiu/HelloWorld)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: HelloWorld.  Program will exit.
Exception in thread “main”

在网上搜索了大半天,大部分说是环境 变量,classpath或JDK 版本的问题,还有执行时文件名 class后缀不要。我一一试过,都没有解决。最后无意中换了一下命令符的位置,成功了。总结如下:
1. 环境变量,CLASSPATH当然要设置好,执行时不要带class后缀;
2. 路径中的斜杠用“/”而不是“\”;
3. 命令符的当前目录要在包的起点。比如这里应该在 d:\workspace\HelloWorld\bin\>,如果在 d:\workspace\HelloWorld\bin\com\yanjiuyanjiu\>,反而不行,有点“近水楼台不得月”的意思,不知 道为什么,还请高手解释一下。

分类: 语言与算法 标签: