YzmCMS x 分词提取关键词插件(可做接口或自己使用)

683次浏览 更新日期:2024-05-12 15:07:28 分类:模板插件 评论:1

前言

这不仅仅是一篇介绍插件的文章 ,也是一篇自我成长的教程 灵感来于jieba-php


安装

上传文件夹到application 有默认的演示方法 直接访问 /Part/index/init 查看效果 


使用方法见控制器

功能描述

我们在控制器中 加载了插件依赖

比如:请不要忘记设置 

ini_set('memory_limit', '1024M');

image.png

1.我们先做最基础的分词

image.png

打印后结果为:


image.png


2.提取关键词

image.png

打印结果为:其中txt为举例文本

image.png


3.词性分词

image.png

打印结果为:可直接返回关键词

image.png

完整代码

<?php
ini_set('memory_limit', '1024M');
defined('IN_YZMPHP') or exit('Access Denied'); 

yzm_base::load_model('MultiArray', 'Part', 0);
yzm_base::load_model('MultiArrayFactory', 'Part', 0);
yzm_base::load_model('Part', 'Part', 0);
yzm_base::load_model('Finalseg', 'Part', 0);

// 提取关键词
yzm_base::load_model('Analyse', 'Part', 0);

// 词性分词
yzm_base::load_model('Posseg', 'Part', 0);

class Index
{
    /**
     * 初始化分词模型并进行分词
     *
     * @author zhaosong
     */
    public function init()
    {
        Part::init();
        Finalseg::init();
        $seg_list = Part::cut("怜香惜玉也得要看对象啊!");
        var_dump($seg_list);
    }

    /**
     * 初始化分词模型、最终分词模型和分析模型,并提取关键词
     *
     * @author zhaosong
     */
    public function inits()
    {
        Part::init(array('mode'=>'test','dict'=>'small'));
        Finalseg::init();
        Analyse::init();
        $top_k = 10;
        $content = file_get_contents(dirname(dirname(__FILE__))."/dict/lyric.txt", "r");
        $tags = Analyse::extractTags($content, $top_k);
        var_dump($tags);
    }

    /**
     * 初始化分词模型、最终分词模型和词性标注模型,并进行词性标注
     *
     * @author zhaosong
     */
    public function initss()
    {
        Part::init();
        Finalseg::init();
        Posseg::init();

        $seg_list = Posseg::cut("这是一个伸手不见五指的黑夜。我只会一丢丢PHP,我热爱YzmCms,我喜欢编程!");
        var_dump($seg_list);
    }
}

逻辑分析

加载词典和模型文件,需要加载预先训练好的词典和模型文件,


这些文件包含了词汇、词频、词性等信息。所以我字典很大 所以插件也是很大。


    /**
     * 加载模型文件
     *
     * @param string $f_name 模型文件名
     * @param array $options 选项数组
     * @return array 模型数据
     * @author zhaosong
     */
    public static function loadModel($f_name, $options = array())
    {

        $defaults = array(
            'mode'=>'default'
        );

        $options = array_merge($defaults, $options);

        return json_decode(file_get_contents($f_name), true);

    }


对输入的文本进行分词。使用维特比算法进行中文分词(待分词的句子,选项数组)。


$text = "我来到北京清华大学";
$seg_list = Part::cut($text);
print_r($seg_list);


什么是维特比算法 :是一种动态规划算法,用于在隐马尔可夫模型(Hidden Markov Model, HMM)中寻找最可能的状态序列。维特比算法广泛应用于自然语言处理、语音识别、生物信息学等领域。


以下是使用 PHP 实现维特比算法的示例:


// 初始状态概率
$pi = array('yzm' => 0.6, 'qh' => 0.4);

// 状态转移概率矩阵
$A = array(
    'yzm' => array('yzm' => 0.7, 'qh' => 0.3),
    'qh' => array('yzm' => 0.4, 'qh' => 0.6)
);

// 观测概率矩阵
$B = array(
    'yzm' => array('normal' => 0.5, 'cold' => 0.4, 'dizzy' => 0.1),
    'qh' => array('normal' => 0.1, 'cold' => 0.3, 'dizzy' => 0.6)
);

// 观测序列
$observations = array('normal', 'cold', 'dizzy');


举例:

function viterbis($pi, $A, $B, $observations) {
    $T = count($observations);
    $N = count($pi);
    $delta = array();
    $psi = array();

    // 初始化
    for ($i = 0; $i < $N; $i++) {
        $delta[0][$i] = $pi[$i] * $B[$i][$observations[0]];
        $psi[0][$i] = 0;
    }

    // 递推
    for ($t = 1; $t < $T; $t++) {
        for ($j = 0; $j < $N; $j++) {
            $max_prob = 0;
            $max_state = 0;
            for ($i = 0; $i < $N; $i++) {
                $prob = $delta[$t - 1][$i] * $A[$i][$j];
                if ($prob > $max_prob) {
                    $max_prob = $prob;
                    $max_state = $i;
                }
            }
            $delta[$t][$j] = $max_prob * $B[$j][$observations[$t]];
            $psi[$t][$j] = $max_state;
        }
    }

    // 终止
    $max_prob = 0;
    $max_state = 0;
    for ($i = 0; $i < $N; $i++) {
        if ($delta[$T - 1][$i] > $max_prob) {
            $max_prob = $delta[$T - 1][$i];
            $max_state = $i;
        }
    }

    // 回溯
    $states = array();
    $states[$T - 1] = $max_state;
    for ($t = $T - 2; $t >= 0; $t--) {
        $states[$t] = $psi[$t + 1][$states[$t + 1]];
    }

    return $states;
}


处理分词结果 返回一个包含分词结果的数组。可以对这个数组进行处理,例如将分词结果拼接成字符串、统计词频等。


分词模式精确模式、全模式和搜索引擎模式。精确模式是默认模式,将句子最精确地切开,


适用于文本分析;全模式是将句子中所有可以成词的词语都扫描出来,速度非常快,但是不能解决歧义;


搜索引擎模式在精确模式的基础上,对长词再次切分,提高召回率 列如:


   /**
     * 分词方法(搜索引擎模式)
     *
     * @param string $sentence 句子
     * @param array $options 选项数组
     * @return array 分词结果数组
     * @author zhaosong
     */    
    public static function cutForSearch($sentence, $options = array("HMM" => true))
    {
        $defaults = array(
            'mode'=>'default'
        );
        $options = array_merge($defaults, $options);
        $seg_list = array();
        $cut_seg_list = Part::cut($sentence, false, array("HMM" => $options["HMM"]));
        foreach ($cut_seg_list as $w) {
            $len = mb_strlen($w, 'UTF-8');
            if ($len>2) {
                for ($i=0; $i<($len-1); $i++) {
                    $gram2 = mb_substr($w, $i, 2, 'UTF-8');
                    if (isset(self::$FREQ[$gram2])) {
                        $seg_list[] = $gram2;
                    }
                }
            }
            if (mb_strlen($w, 'UTF-8')>3) {
                for ($i=0; $i<($len-2); $i++) {
                    $gram3 = mb_substr($w, $i, 3, 'UTF-8');
                    if (isset(self::$FREQ[$gram3])) {
                        $seg_list[] = $gram3;
                    }
                }
            }
            $seg_list[] = $w;
        }
        return $seg_list;
    }

总结:实现分词的逻辑主要包括加载词典和模型文件、对输入文本进行分词、处理分词结果以及释放资源。


在实际应用中,可以根据需求调整分词模式和处理分词结果的方式。


最后

使用插件要灵活 可自己添加字典 但基本的字典已经完全够用

附件下载:


登录后可查看详情!

我来说两句
作者信息
发布见解
发内容 回顶部