TextMate心得

July 23rd, 2008

折腾了多日,搞定了mac os x 和编译器,以及这个TextMate。很关键,一定要记录一下。

TextMate 介绍

TextMate is not an IDE but by using its powerful snippets, macros, and unique scoping system, it can often provide features that even a language specific IDE lacks. It has enough project management features to keep most users happy, but is otherwise kept lightweight with a clean and minimalistic GUI.

下载地址

http://macromates.com/

因为TextMate自带 Ruby on Rails 的 bundle 还是1.X 可是ror已经出到 2.1.0了,需要将他更新,所以要执行以下步骤:

更新 ROR bundle

請下載 Textmate bundle( http://github.com/drnic/ruby-on-rails-tmbundle/tree/master ),最好的方式是用 git,不過也可以直接下載放到 [~/Library/Application Support/TextMate/Bundles] 下,並命名為 Ruby on Rails.tmbundle,然後在 textmate 裡 reload bundle 即可。

另外也請在 [/Applications/TextMate.app/Contents/SharedSupport/Support/lib] 執行 mv Builder.rb Builder.rb.off (不然某些用到 rake 的 bundle 會有錯誤)。

TextMate破解 TextMate注册

至于破解的问题嘛,如果需要可以联系我 maxazure@gmail.com .

(版权问题,故不能公布到网站,大家见谅)

Web2.0:帮你辨别跟你聊天的是人还是狗

July 2nd, 2008

今晚心血来潮和哥几个一起吃饭,我们如是说:

8年前流行一句话:你不知道互联网另一端屏幕前坐着的是个人还是条狗。 那就是web.
今天:有了SNS你就可以辨别出互联网另一端的屏幕前坐着的是人还是狗。 这就是web2.0
好大的飞跃啊!

Ruby中“符号”Symbol 的意义

June 17th, 2008

在Ruby中,一个符号是就是一个Symbol类的实例,它的语法是在通常的变量名前加一个冒号,如
:my_sy

Ruby的符号像一个字符串,因为它内部表现形式是一个字符序列。而与字符串不同的是,每个符号的实例只有一个。看下面的例子:
array = [”foo”, “foo”, “foo”, :foo, :foo, :foo]

建立这个数组后,内存中将有三个内容为”foo”的字符串对象,而只有一个:foo对象。

一个符号有它唯一对应的一个整数值,可以用to_i来获取它。

符号常用的地方是用它来代表变量名或者方法名:
class SomeClass
attr_accessor :whatever
end

与上面程序对等的程序如下:
class SomeClass
def whatever
@whatever
end
def whatever=(val)
@whatever = val
end
end

你可能会问,为什么不用字符串来表示呢?其实,字符串也是可以的:
attr_reader :alpha
attr_reader “beta” # 也是合法的

那它们的区别在哪里?某种意义上来说,是为了提高程序性能,节省内存吧。

有的人说,”符号就如同不可变的字符串”,从它的行为上来说,可能是对的。但是,Symbol并是是继承至String,而且,与字符串相关
的那些典型操作方法,Symbol也不一定有,也不需要有。

符号不一定看起来是像变量一样,它也可以这样:
sym1 = :”This is a symbol”
sym2 = :”This is, too!”
sym3 = :”)(*&^%$”
你可以用这样奇怪的符号来定义实例变量名或方法,你可以使用诸如send或instance_variable_get来获取它们的引用。虽然是可行的,
但请尽量不要使用这么奇怪的符号。

用Symbol作为枚举
==========================================
像Pascal或版本稍晚的C语言,都存在enum这种类型。Ruby不能正真的拥有这样的类型,因为它没有类型检查。但使用Symbol可以用来产生
这样的效果:
North, South, East, West = :north, :south, :east, :west

用Symbol作为元数据
==========================================
通常我们使用捕获异常的方式来处理错误,避免使用老式的返回代码的方式。但是,如果你想用老式的方式,还是可以的。像nil就是这样一个元数据。
我们通常可以这样使用(因为符号是全局的,所以在之后的整个程序中,都可以使用这些符号来作为元数据):
str = get_string
case str
when String
# Proceed normally
when :eof
# end of file, socket closed, whatever
when :error
# I/O or network error
when :timeout
# didn’t get a reply
end

Symbols, Variables, Methods
==========================================
Symbol最常用的地方就是我们熟知的定义属性了:
class MyClass
attr_reader :alpha, :beta
attr_writer :gamma, :delta
attr_accessor :epsilon
# …
end
这里的方法,如attr_accessor,它以传入的符号来确定实例变量的名称,以及读写属性的方法的名称,但这不代表所有的情况
(即总是会自动精确匹配符号和实例变量的名称),例如,当使用instance_variable_set方法的时候,符号和实例变量名必须
精确给出:
sym1 = :@foo
sym2 = :foo
instance_variable_set(sym1,”str”) # 正常,匹配到@foo
instance_variable_set(sym2,”str”) # 错误

不过,记住,在这些地方不一定要使用符号,可以用字符串来替代。

转换Symbol
============================================
Symbol和字符串之间可以互相转换,使用to_s和to_sym来实现:
a = “foobar”
b = :foobar
a == b.to_str # true
b == a.to_sym # true

Dede cms(utf-8)中的问题及解决

June 9th, 2008

在dedecms4的utf8改版中,发布文档时可能出现:
更新数据库archives表时出错,请检查!

把数据保存到数据库archives表时出错,请检查!
以上两种情况分别为修改和新增,对应的php为
article_eidt_action.php和article_add_action.php,数据库操作为include/pub_db_mysql.php,中文字符串截取为

include/inc_functions.php中的cn_substr函数,此函数只支持双字节即gbk编码,所以要改成截取utf-8的.此时edit已正常,但add还出错,把
if(!$dsql->ExecuteNoneQuery()){
$dsql->Close();
ShowMsg(”把数据保存到数据库archives表时出错,请检查!”,”-1″);
exit();
}
改成
if(!$dsql->ExecuteNoneQuery()){
$errorSql = htmlSpecialchars($dsql->queryString);
$errorMsg = htmlSpecialchars(mysql_error());
$dsql->Close();
//ShowMsg(”把数据保存到数据库archives表时出错,请检查!”,”-1″);
//ShowMsg是document.write的js方法,不知为什么在加入$errorSql后不显示,所以用echo
echo “把数据保存到数据库archives表时出错,请检查!查询语句:
$errorSql
mysql错误提示:
$errorMsg “;
exit();
}
看提示是keywords字段长了,原来是中文分词时出错,include/pub_splitword_www.php调用字典include/data/dede_wwwdic.csv,可csv是gbk编

码的.改分词程序没成功,所以不分词了,关键字手工填就是了.把article_add_action.php中的

//自动获取文章中的关键字
//———————————-
if($autokey==1||$keywords==”"){

改成
//自动获取文章中的关键字
//———————————-
if(0 && ($autokey==1||$keywords==”")){

发布文档后的成功提示无法显示,
把include/win_templet.htm中
charset={dede:cfg_language/}改成
charset=utf-8

更新html那个框架中的字乱码,在浏览器中选utf8就行,但不知在哪个文件中改

图片栏目如果选分页显示,会在第2页开始图片上方有一行字:分页标题#e#,找不到在哪改,因此修改

dede/templates/default/article_iamge.htm,把

{dede:field name=’imgurls’/}

改成

{dede:field name=’imgurls’/}

也就是用js把这串字符替换

dede/article_eidt.php有错误,没有定义SelectTemplets函数,所以不能选择模板,在页面上方的js中把这个函数加上
function SelectTemplets(fname)
{
var posLeft = window.event.clientY-200;
var posTop = window.event.clientX-300;
window.open(”../include/dialog/select_templets.php?&activepath=&f=”+fname,

“poptempWin”, “scrollbars=yes,resizable=yes,statebar=no,width=600,height=400,left=”+posLeft+”, top=”+posTop);
}

程序的一些bug:
1.article_eidt.p,hp编辑选模板有js错误,并且无法在ff中使用这个函数,因为不支持window.event
2.栏目如果是频道列表,生成页后子频道的文档无法在该页显示,进入子频道才能看到
3.图片栏目如果选分页显示,会在第2页开始图片上方有一行字:分页标题#e#,不知是UTF-8改的原因还是bug
4.图片栏目修改文档后,最后一页没重新生成?选生成文档HTML才搞定
5.UTF8部分,分词和拼音还无法解决,生成html的提示乱码,一定要手工指定编码为utf8
6.图片栏目中生成缩略图有问题.好在不会在列表页显示出错
7.文章栏目中GIF图片似乎都无法生成缩略图?
8.dede/inc/writer.txt和dede/inc/source.txt都应该设成可写
9.两个广告紧连着会出问题,如{dede:myad name=’abc’/}和{dede:myad name=”efg” /}连着,后一个就会显示成文字.只有分开
10.在本地测试时安装在非根目录下,首页连接用cfg_cmspath正确,上传到网站后,这儿改成空,页面中这儿竟然被解析成当前目录

如何生成搜索结果中的动态摘要

June 9th, 2008

在搜索的结果页面,标题下要显示文本的摘要,但是怎样能使用简短的几句话就可以实现动态摘要呢?

本文提供了三个思路方法:

方法一. 只记录关键字在一篇文档中第一次出现的位置
产生动态摘要时, 根据关键字第一次出现的位置p向前后扩展, 扩展至完整的句子, 扩展到需要的摘要的长度为止. 如果同时检索多个关键字, 那么各句动态摘要合并起来, 可能中间需要用省略号连接.
这种方法产生动态摘要的速度最快, 存储位置占用的空间最小; 但是可能产生的动态摘要不是最好的.

方法二. 记录关键字在一篇文档中所有出现的位置
记录所有的位置可以计算出文档的哪一部分与查询最相关, 尤其进行多关键字查询时, 将每个关键字出现的所有位置进行统计, 计算出文档的哪一部分同时出现了这几个关键字, 从而产生动态摘要. 这样产生的动态摘要比较准确, 但是存储位置占用的空间比较大.

方法三. 对文档事先进行断句(分块)处理, 记录关键字出现的所有句子编号.
生成动态摘要时, 对包含查询关键字的句子进行打分, 将得分最高的句子做为摘要.
这样产生的动态摘要也比较准确, 但是这种方法需要对文档事先进行断句(或是分块)的预处理.

中文分词的重要概念:条件随机场(Conditional Random Fields, CRFs)

June 9th, 2008

一般序列分类模型常常采用隐马模型(HMM), 像基于类的中文分词, 但隐马 模型中存在两个假设: 输出独立性假设和马尔可夫性假设. 其中, 输出独立性假设要求序列数据严格相互独立才能保证推导的正确性, 而事实上大多数序列数据不能 被表示成一系列独立事件. 而条件随机场则使用一种概率图模型, 具有表达长距离依赖性和交叠性特征的能力, 能够较好地解决标注(分类)偏置等问题的优点, 而且所有特征可以进行全局归一化, 能够求得全局的最优解.

条件随机场是一个无向图上概率分布的学习框架, 由Lafferty 等首先引入到自然语言处理的串标引学习任务中来. 最常用的一类CRF是线性链CRF, 适用于我们的分词学习. 记观测串为W=w1w2…wn, 标记串(状态)序列 Y=y1y2…yn, 线性链CRF对一个给定串的标注, 其概率定义为:
2.gif
其中, Y是串的标注序列, W是待标记的字符, fk是特征函数, λk是对应的特征函数的权值, 而t是标记, Z(W)是归一化因子, 使得上式成为概率分布.
CRF模型的参数估计通常使用L-BFGS算法来完成. CRF的解码过程, 也就是求解未知串标注的过程, 需要搜索计算该串上的一个最大联合概率, 即:

Y* = arg max(y)P(Y|W)

在线性链CRF上, 这个计算任务可以用一般的Viterbi算法来有效地完成.

目前我发现的关于CRF的实现有:

* CRF++(http://crfpp.sourceforge.net/)
* Pocket CRF(http://sourceforge.net/project/showfiles.php?group_id=201943)

分词方法三:反向最大匹配分词(BMM)

June 9th, 2008

BMM方法和FMM过程类似,不同点仅在于BMM是从文本的末尾开始处理,每次匹配不成功时去掉的是最前面的一个字。BMM方法的精度要高一些,其错误率是1/245。

如何DIY你的标注语料库

June 9th, 2008

如果你想写分词器,那么就需要有标注语料库进行训练,以下是 成 彦 的一些方法:

语料库标注或加工就是对语料(书面语和口语)进行不同层次的语言学分析,并添加相应的“显性”解释性语言学信息的过程。 语料库很关键,只有经过不周层次加工的“熟”语料才可真正用于自然语言处理系统的训练,测试。

目前我在网上找到的标注语料库是北京大学计算语言学研究所免费提供的“PFR人民日报标注语料1.0”。

PFR人民日报标注语料库1.0是在得到人民日报社新闻信息中心许可的条件下,以1998年人民日报语料为对象,由北京大学计算语言学研究所和富士通研究开发中心有限公司共同制作的标注语料库。该语料库对600多万字节的中文文章进行了分词及词性标注,其被作为原始数据应用于大量的研究和论文中。

是不是感觉该标注语料库太小太旧了? 那我们去构建自己的标注语料库吧。

思路:用最好的分词器去处理语料库,生成标注语料。

工具:海量分词器研究版,搜狗互联网语料库

海量分词器:目前最好的中文分词器,无论在速度还是准确性都是国内第一。切分准确率达99.7%,速度高达2000万字/分钟。

搜狗互联网语料库:完整版本的压缩后近130G,这需要自己去到搜狐联系。网上提供示例版,解压后是1G,50万篇文章。注意的一点是,不知道是否故意还是无意,这个文件里有错误,处理的时候一定要注意。该文件中一篇文档的分界标志是:
文档内容
而不是
文档内容

写个简短的程序,查看海量的文档,设置海量分词相应的输出格式,然后用海量切每一篇文档。

如此训练出的标注语料库,应该是质量蛮高的吧!

分词方法四:基于统计分词

June 9th, 2008

即利用统计语言模型分词的方法。几乎所有准确率高的中文分词器都会使用统计语言模型实现分词。对于统计语言模型的介绍请参阅

http://googlechinablog.com/2006/04/blog-post.html

统计语言模型 (Statistical Language Models)

Google 的使命是整合全球的信息,所以我们一直致力于研究如何让机器对信息、语言做最好的理解和处理。长期以来,人类一直梦想着能让机器代替人来翻译语言、识别语音、认识文字(不论是印刷体或手写体)和进行海量文献的自动检索,这就需要让机器理解语言。但是人类的语言可以说是信息里最复杂最动态的一部分。为了解决这个问题,人们容易想到的办法就是让机器模拟人类进行学习 - 学习人类的语法、分析语句等等。尤其是在乔姆斯基(Noam Chomsky 有史以来最伟大的语言学家)提出 “形式语言” 以后,人们更坚定了利用语法规则的办法进行文字处理的信念。遗憾的是,几十年过去了,在计算机处理语言领域,基于这个语法规则的方法几乎毫无突破。

其实早在几十年前,数学家兼信息论的祖师爷 香农 (Claude Shannon)就提出了用数学的办法处理自然语言的想法。遗憾的是当时的计算机条件根本无法满足大量信息处理的需要,所以他这个想法当时并没有被人们重视。七十年代初,有了大规模集成电路的快速计算机后,香农的梦想才得以实现。

首先成功利用数学方法解决自然语言处理问题的是语音和语言处理大师贾里尼克 (Fred Jelinek)。当时贾里尼克在 IBM 公司做学术休假 (Sabbatical Leave),领导了一批杰出的科学家利用大型计算机来处理人类语言问题。统计语言模型就是在那个时候提出的。

给大家举个例子:在很多涉及到自然语言处理的领域,如机器翻译、语音识别、印刷体或手写体识别、拼写纠错、汉字输入和文献查询中,我们都需要知道一个文字序列是否能构成一个大家能理解的句子,显示给使用者。对这个问题,我们可以用一个简单的统计模型来解决这个问题。

如果 S 表示一连串特定顺序排列的词 w1, w2,…, wn ,换句话说,S 可以表示某一个由一连串特定顺序排练的词而组成的一个有意义的句子。现在,机器对语言的识别从某种角度来说,就是想知道S在文本中出现的可能性,也就是数学上所说的S 的概率用 P(S) 来表示。利用条件概率的公式,S 这个序列出现的概率等于每一个词出现的概率相乘,于是P(S) 可展开为:

P(S) = P(w1)P(w2|w1)P(w3| w1 w2)…P(wn|w1 w2…wn-1)

其中 P (w1) 表示第一个词w1 出现的概率;P (w2|w1) 是在已知第一个词的前提下,第二个词出现的概率;以次类推。不难看出,到了词wn,它的出现概率取决于它前面所有词。从计算上来看,各种可能性太多,无法实现。因此我们假定任意一个词wi的出现概率只同它前面的词 wi-1 有关(即马尔可夫假设),于是问题就变得很简单了。现在,S 出现的概率就变为:

P(S) = P(w1)P(w2|w1)P(w3|w2)…P(wi|wi-1)…
(当然,也可以假设一个词又前面N-1个词决定,模型稍微复杂些。)

接下来的问题就是如何估计 P (wi|wi-1)。现在有了大量机读文本后,这个问题变得很简单,只要数一数这对词(wi-1,wi) 在统计的文本中出现了多少次,以及 wi-1 本身在同样的文本中前后相邻出现了多少次,然后用两个数一除就可以了,P(wi|wi-1) = P(wi-1,wi)/ P (wi-1)。

也许很多人不相信用这么简单的数学模型能解决复杂的语音识别、机器翻译等问题。其实不光是常人,就连很多语言学家都曾质疑过这种方法的有效性,但事实证明,统计语言模型比任何已知的借助某种规则的解决方法都有效。比如在 Google 的中英文自动翻译中,用的最重要的就是这个统计语言模型。去年美国标准局(NIST) 对所有的机器翻译系统进行了评测,Google 的系统是不仅是全世界最好的,而且高出所有基于规则的系统很多。

现在,读者也许已经能感受到数学的美妙之处了,它把一些复杂的问题变得如此的简单。当然,真正实现一个好的统计语言模型还有许多细节问题需要解决。贾里尼克和他的同事的贡献在于提出了统计语言模型,而且很漂亮地解决了所有的细节问题。十几年后,李开复用统计语言模型把 997 词语音识别的问题简化成了一个 20 词的识别问题,实现了有史以来第一次大词汇量非特定人连续语音的识别。

常用于中文分词的统计语言模型有条件随机场,隐马尔科夫模型,互信息,N元等。

分词方法二:正向最大匹配分词(FMM)

June 9th, 2008

正向最大匹配分词方法的基本思想是:假设字典中最长的关键字的长度为i,取当前待处理文本的前i个字作为匹配字段w,在字典中查找,若字典中有w, 则匹配成功,w即做为一个词被切分出来;如果匹配失败,则去掉w的最后一个字,继续去字典中查找. 切分出w后,继续对w之后的字词进行上面步骤的切分,直到切分出所有的词为止.

梁南元先生在其论文《书面汉语的自动分词与另一个自动分词系统CDWS》提到,FMM方法的错误切分率为1/169. 一般不单独使用,而是和其它方法配合使用。