基于信息熵原理分词的php实现

基于信息熵原理分词这个概念很早了,用php实现了个,一气呵成,代码自然是,反正我也没有二次检查,呵呵。不过耗费内存是真的,真的很消耗内存!

写这个的好处就是我明白了很多东西...

代码如下

<?php
/**
 * 基于信息熵的无词典分词
*/

class partword{
    
    /**
     * 词语最大长度
    */
    public $maxwordlen = 5;

    /**
     * 需要进行分词的文字
    */
    public $text;

    /**
     * 字符串长度
    */
    private $len;

    /**
     * 切分的单个文字
    */
    private $textarr;

    /**
     * 文字信息数组
    */
    private $wordinfo;

    /**
     * 初始化文字,将文字进行分割
    */
    public function initWords(){

        $i = 0;
        $len = strlen($this->text);
        $strarr = array();
        $word = '';//单词缓存
        $en_write = False;

        while( $i<$len ){
            $ascnum = ord($this->text[$i]);

            if( $ascnum >=224 ){ //高位大于244,utf8规定为3个字节

                $zh_word = substr($this->text, $i, 3);
                $en_write = True;
                $i += 3;

            }elseif( $ascnum >=192 ){ //高位大于192,utf8规定为2个字节

                $zh_word = substr($this->text, $i, 2);
                $i+=2;
                $en_write = True;

            }elseif( $ascnum <= 32 ){
                //空字符,英文的空格
                $en_write = True;
                $i += 1;

            }else{

                $en_write = False;
                $word .= substr($this->text, $i, 1);
                $i += 1;
                
            }
            
            if( $en_write && $word != '' ){
                $strarr[] = $word;
                $word = '';
                $en_write = False;
                $this->len += 1;
            }

            if( $zh_word !='' ){
                $strarr[] = $zh_word;
                $zh_word = '';
                $this->len += 1;
            }


        }

        return $this->textarr = $strarr;
    }

    /**
     * 发送文本
    */
    public function sendText($text){
        $this->text = $text;
        $this->initWords();
        $this->calInfo();
        $this->calEntropy();
    }


    /**
     * 整理词汇,用于后面的凝聚度和信息熵获取
    */
    public function calInfo(){
        //
        if( !isset($this->textarr) ) die("no text");

        $newarr = array();
        $word = '';
        $i = 0;

        /*
            遍历整个单个文字数组
            将所设定的词组阈值之内的所有可能的词进行提取
            l=> 左边文字的位置
            r=> 右侧文字的位置
            c=> 词频
        */

        for ($i=0,$len = count($this->textarr); $i<$len; $i++) {
            $word = '';

            for( $wordlen = 0; $wordlen < $this->maxwordlen; $wordlen++ ){

                if( !isset( $this->textarr[$i+$wordlen] ) ) continue;

                $word .= $this->textarr[$i+$wordlen];

                $newarr[$word]['w'] = $word; //左侧词
                $newarr[$word]['l'][] = $i; //左侧词
                $newarr[$word]['r'][] = $i+$wordlen; //右侧词

                //统计词频
                if( !isset($newarr[$word]['c']) ) $newarr[$word]['c'] = 1;
                else $newarr[$word]['c'] += 1;

            }

        }


        return $this->wordinfo = $newarr;
    }


    /**
     * 计算信息熵
    */
    public function calEntropy(){
        foreach ($this->wordinfo as $key => $v) {

            $left_entropy = 0;
            $right_entropy = 0;
            //求左邻字的信息熵,需要大于0才可以
            $left_word = array();
            //print_r($v);
            foreach( $v['l'] as $l ){
                
                if( $l >0 ){
                    if( !isset($left_word[ $this->textarr[$l-1] ]) )
                        $left_word[ $this->textarr[$l-1] ] = 1;
                    else
                        $left_word[ $this->textarr[$l-1] ] += 1;
                }

            }
            foreach( $left_word as $word=>$num ){
                $left_entropy += -($num/$v['c'])*log($num/$v['c']);
            }


            //求右邻字的信息熵,需要小于整个长度
            $right_word = array();
            foreach( $v['r'] as $r ){
                if( $r < $this->len-1 ){
                    if( !isset($right_word[ $this->textarr[$r+1] ]) )
                        $right_word[ $this->textarr[$r+1] ] = 1;
                    else
                        $right_word[ $this->textarr[$r+1] ] += 1;
                }
            }
            foreach( $right_word as $word=>$num ){
                $right_entropy += -($num/$v['c'])*log($num/$v['c']);
            }



            //echo $key."--".$left_entropy."--".$right_entropy."\n";
            //取坐信息熵和又信息熵里面最小的一个
            $entropy = ($left_entropy < $right_entropy) ? $left_entropy : $right_entropy;
            $this->wordinfo[$key]['entropy'] = $entropy;
            unset($this->wordinfo[$key]['l']);
            unset($this->wordinfo[$key]['r']);

        }
        unset($this->textarr);
        return $this->wordinfo;
    }

    /**
     * 对词进行排序,根据信息熵排序
    */
    public function sortResult(){
        usort($this->wordinfo, array(&$this,'sortByEntropy'));
        return $this->wordinfo;
    }

    private function sortByEntropy($a,$b){
        if( $a['entropy'] === $b['entropy'] ) return 0;

        return ($a['entropy'] > $b['entropy']) ? -1: 1;
    }



}

//应用
header("Content-type:text/html;charset=utf-8");
$smen = memory_get_usage();
$partword = new partword();
$text = "吃葡萄不吐葡萄皮不吃葡萄倒吐葡萄皮";
$partword->sendText($text);
print_r( $partword->sortResult() );
$emen = memory_get_usage();
echo (($emen - $smen)/1024) ."kb";
?>

你可能还喜欢下面这些文章

基于信息熵分词以及新词发现的实践过程

原标题: 互联网时代的社会语言学:基于SNS的文本数据挖掘今年上半年,我在人人网实习了一段时间,期间得到了很多宝贵的数据,并做了一些还算有意义的事情,在这里和大家一块儿分享。感谢人人网提供的数据与工作环境,感谢赵继承博士、詹卫东老师的支持和建议。在这项工作中,我得到了很多与众人交流的机会,特别感谢 OpenParty 、 TEDxBeijing 提供的平台。本文已发表在了《程序员》杂志,分上下两部分刊于 2012 年 7 月刊和 8 月刊,在此感谢卢鸫翔编辑的辛勤工作。由于众所周知的原因,《程序员》刊出的文章被和谐过(看到后面大家就自动地知道被和谐的内容是什么了),因而我决定把完整版发在 Bl

互联网时代的社会语言学:基于SNS的文本数据挖掘

今年上半年,我在人人网实习了一段时间,期间得到了很多宝贵的数据,并做了一些还算有意义的事情,在这里和大家一块儿分享。感谢人人网提供的数据与工作环境,感谢赵继承博士、詹卫东老师的支持和建议。在这项工作中,我得到了很多与众人交流的机会,特别感谢 OpenParty 、 TEDxBeijing 提供的平台。本文已发表在了《程序员》杂志,分上下两部分刊于 2012 年 7 月刊和 8 月刊,在此感谢卢鸫翔编辑的辛勤工作。由于众所周知的原因,《程序员》刊出的文章被和谐过(看到后面大家就自动地知道被和谐的内容是什么了),因而我决定把完整版发在 Blog 上,同时与更多的人一同分享。对此感兴趣的朋友可以给我

股票获取接口

最近开始研究股票了,自己一个一个的去看,几千支股票完全看不过来啊,想着自己写一个程序,让程序来看股票吧!股票接口首先我们需要得到所有的股票代码,好在已经有网页帮我们列出了所有的股票名称和代码,地址是:http://quote.eastmoney.com/stocklist.html通过这个页面,就可以抓取了。抓取之后我们就可以存入mysql中,每一个股票可以存一张表,而每一张表中则可以存入股票的动态数据。这里我们只能获取到一些最简单的数据,一些更加详细的数据还需要获取,这里需要使用一个腾讯财经的接口http://qt.gtimg.cn/q=sz000858该接口为获取五粮液的股票数据,返回结果

iterm2 使用 rz、sz 的方法

如果没有额外的设置,iterm2 使用 rzsz 的时候会卡在这个时候就需要使用iterm2提供的trigger来实现rzsz的功能。第一步:本机安装rzsz使用rzsz之前本地也需要安装如果没有安装brew,请先安装brew,mac必备的包管理器!第二步:创建发送和接收脚本发送文件的脚本如下,可以复制下面的内容,保存在 /usr/local/bin/iterm2-send-zmodem.sh中。接收文件的脚本如下,同样可以复制保存在/usr/local/bin/iterm2-recv-zmodem.sh第三步:设置Triggerteigger需要设置两个,一个实发送文件的trigger,一个

centos7系统初初始化工作以及网站环境搭建(php7+nginx+mysql)

拿到一台做网站的主机, 我们先要做一些环境初始化的工作, 由于这些工作会有些繁琐,因此记录一下. 后面将这些流程写成一个shell脚本,一次性完成.此次工作流程如下: 安全性设置 额外的目录创建 网站环境搭建安全性设置一般从某云上买的主机, 默认账户是root, 为了不被暴力破解, 我们首先需要设置一个强一点的密码,不过更好的方法是禁用root, 另外创建一个用户来作为日常管理的账户.第一步: 创建一个新的账户,并且能够切换到root权限比如我的用户名叫xiaobai, 添加用户名就是useradd xiaobai设置密码passwd xiaobai之后输入密码,一个新的账户就设定好了.

从PHP到Go的程序员需要注意的一些事项

PHP转Go的程序员很多,使用Go重写Web应用,代价不高,并且所带来性能的提升很明显,因此很多PHP程序员正在转Go。PHP是一个弱类型,解释型的语言,Go是一个强类型,编译型语言,两者的差别很大。如果长期使用PHP,使用Go的时候,一些惯性思维会带来不太好的效果。这里总结一些从PHP转到Go需要注意的点。警惕内存越界访问一个数组,在php中,如果a是一个空数组,直接访问a会出现警告,但程序还能继续运行,而在Go中,由于访问一个不存在的地址,程序会直接崩溃。因此Go中需要时刻警惕内存越界。在访问数组下标的时候,如果不能确认需要访问数据一定存在,那么一定要使用len判断数组长度,需要访问的下标

shell中map的使用

bash 4.1.2 版本增加了map数据结构。map是一种常用的数据结构,通过map可以将key映射到一个value。使用方法map在使用之前需要先声明,声明的方式如下map需要先声明再使用。参数-A表示声明的变量是一个map。需要注意的是这里的A是大写的字母A。赋值操作map的赋值有两种方式,一种是直接给map赋值,如下:另一种是使用下标给map添加key-value对输出所有的key在文中最开始提到map的使用需要先声明,在没有声明的情况下此处会输出一个0,如下图:输出所有value输出map长度遍历,根据key找到对应的value遍历所有的key遍历所有的value问题FAQQ:为什么

Redis持久化

在一个高并发,但是数据量不大的系统中,使用Redis做数据库再好不过,结合Swoole,只需要很少的机器就能抗住很大的量。Redis大多数的应用可能都是当做缓存,当作为一个数据库用的时候,就必须要考虑持久化的问题了。持久化的意思就是将内存中的数据写到磁盘中,当再次重启之后,数据可以从磁盘中进行恢复,不会丢失。Redis持久化有两个策略,一个是RDB快照,一个AOF日志,不管是什么策略,最终的目的都是将数据保存在磁盘上,并不高深。只需要耐心的看看这两种策略,就能明白了。RDB快照从名字上我们就能知道这是RedisDB的缩写了,Redis快照是这样生成的,到了需要生成快照的时候,通过fork当前进

布隆过滤器(bloom filter)介绍以及php和redis实现布隆过滤器实现方法

引言在介绍布隆过滤器之前我们首先引入几个场景。场景一在一个高并发的计数系统中,如果一个key没有计数,此时我们应该返回0。但是访问的key不存在,相当于每次访问缓存都不起作用了。那么如何避免频繁访问数量为0的key而导致的缓存被击穿?有人说, 将这个key的值置为0存入缓存不就行了吗?这是确实是一种解决方案。当访问一个不存在的key的时候,设置一个带有过期时间的标志,然后放入缓存。不过这样做的缺点也很明显:浪费内存和无法抵御随机key攻击。场景二在一个黑名单系统中,我们需要设置很多黑名单内容。比如一个邮件系统,我们需要设置黑名单用户,当判断垃圾邮件的时候,要怎么去做。比如爬虫系统,我们要记录下

强化twenty fifteen主题,twenty fifteen pro主题制作过程

被最新的twenty fifteen主题迷上了,这就是我心目中的样式!但有功能还是需要添加的,因此在twenty fifteen的主题基础上,增加了一些功能,命名为twenty fifteen pro主题,目前我所用的主题就是twenty fifteen pro主题。目前增加的功能有这些1.专辑文章将一些文章整个成专辑,比如之前胡超的sublime这个专辑,随便点进去一篇文章,左侧栏都会出现该专辑的系列文章,并且在后台还可以手动控制其排序。这样的好处就是能够将同类别,教程之类的文章聚合起来,更加利于阅读。2.页脚文字增加统计或者版权文字,备案号等等一些附加的信息可能是需要的,但很遗憾twent

赞赏

微信赞赏支付宝赞赏

作品

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注