首页 > 编程语言 >HanLP — 汉字转拼音 -- JAVA

HanLP — 汉字转拼音 -- JAVA

时间:2024-01-19 10:44:09浏览次数:32  
标签:byteArray JAVA -- pinyin System int length HanLP out

目录
HanLP 在汉字转拼音时,可以解决多音字问题,显示输出声调,声母、韵母,通过训练语料库,
本文代码为《自然语言处理入门》配套版本 HanLP-1.7.5

重载不是重任进行转拼音,效果如下:

原文:重载不是重任
拼音(数字音调):chong2,zai3,bu2,shi4,zhong4,ren4,
拼音(符号音调):chóng,zǎi,bú,shì,zhòng,rèn,
拼音(无音调):chong,zai,bu,shi,zhong,ren,
声调:2,3,2,4,4,4,
声母:ch,z,b,sh,zh,r,
韵母:ong,ai,u,i,ong,en,
输入法头:ch,z,b,sh,zh,r,

语料库

pinyin.txt

一丁点儿=yi1,ding1,dian3,er5
一不小心=yi1,bu4,xiao3,xin1
一丘之貉=yi1,qiu1,zhi1,he2
一丝不差=yi4,si1,bu4,cha1
一丝不苟=yi1,si1,bu4,gou3
一个=yi1,ge4
一个半个=yi1,ge4,ban4,ge4
一个巴掌拍不响=yi1,ge4,ba1,zhang3,pai1,bu4,xiang3
一个萝卜一个坑=yi1,ge4,luo2,bo5,yi1,ge4,keng1
一举两得=yi1,ju3,liang3,de2
一之为甚=yi1,zhi1,wei2,shen4

image

训练

训练,生成 pinyin.txt.bin

加载语料库

HanLP-1.7.5\src\main\java\com\hankcs\hanlp\corpus\dictionary\SimpleDictionary.java
加载语料库,每行读取,按 = 分隔,放入字典 trie
image
根据 = 右边每个字的拼音,通过 Pinyin.valueOf("yi1") 得到枚举中声母、韵母、音调、包含音调的字符串形式、不含音调的字符串形式
image

public enum Pinyin
{
    a1(Shengmu.none, Yunmu.a, 1, "ā", "a", Head.a, 'a'),
    a2(Shengmu.none, Yunmu.a, 2, "á", "a", Head.a, 'a'),
    a3(Shengmu.none, Yunmu.a, 3, "ǎ", "a", Head.a, 'a'),
    a4(Shengmu.none, Yunmu.a, 4, "à", "a", Head.a, 'a'),
    a5(Shengmu.none, Yunmu.a, 5, "a", "a", Head.a, 'a'),
    ai1(Shengmu.none, Yunmu.ai, 1, "āi", "ai", Head.a, 'a'),
    ai2(Shengmu.none, Yunmu.ai, 2, "ái", "ai", Head.a, 'a'),
    ai3(Shengmu.none, Yunmu.ai, 3, "ǎi", "ai", Head.a, 'a'),
    ai4(Shengmu.none, Yunmu.ai, 4, "ài", "ai", Head.a, 'a'),
    ......
}

训练模型

将Map构建成双数组树`trie.build(map)``,可查看:HanLP — 双数组字典树 (Double-array Trie) 实现原理 -- 代码 + 图文,看不懂你来打我

public void build(TreeMap<String, V> map)
{
    // 把值保存下来
    v = (V[]) map.values().toArray();
    l = new int[v.length];
    Set<String> keySet = map.keySet();
    // 构建二分trie树
    addAllKeyword(keySet);
    // 在二分trie树的基础上构建双数组trie树
    buildDoubleArrayTrie(keySet);
    used = null;
    // 构建failure表并且合并output表
    constructFailureStates();
    rootState = null;
    loseWeight();
}

保存模型

通过 saveDat(path, trie, map.entrySet()); 生成模型文件

static boolean saveDat(String path, AhoCorasickDoubleArrayTrie<Pinyin[]> trie, Set<Map.Entry<String, Pinyin[]>> entrySet)
{
    try
    {
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(IOUtil.newOutputStream(path + Predefine.BIN_EXT)));
        out.writeInt(entrySet.size());
        for (Map.Entry<String, Pinyin[]> entry : entrySet)
        {
            Pinyin[] value = entry.getValue();
            out.writeInt(value.length);
            for (Pinyin pinyin : value)
            {
                out.writeInt(pinyin.ordinal());
            }
        }
        trie.save(out);
        out.close();
    }
    catch (Exception e)
    {
        logger.warning("缓存值dat" + path + "失败");
        return false;
    }
    return true;
}
/**
 * 持久化
 *
 * @param out 一个DataOutputStream
 * @throws Exception 可能的IO异常等
 */
public void save(DataOutputStream out) throws Exception
{
    out.writeInt(size);
    for (int i = 0; i < size; i++)
    {
        out.writeInt(base[i]);
        out.writeInt(check[i]);
        out.writeInt(fail[i]);
        int output[] = this.output[i];
        if (output == null)
        {
            out.writeInt(0);
        }
        else
        {
            out.writeInt(output.length);
            for (int o : output)
            {
                out.writeInt(o);
            }
        }
    }
    out.writeInt(l.length);
    for (int length : l)
    {
        out.writeInt(length);
    }
}

加载模型

// path = data/dictionary/pinyin/pinyin.txt
static boolean loadDat(String path)
{
    ByteArray byteArray = ByteArray.createByteArray(path + Predefine.BIN_EXT);
    if (byteArray == null) return false;
    int size = byteArray.nextInt();
    Pinyin[][] valueArray = new Pinyin[size][];
    for (int i = 0; i < valueArray.length; ++i)
    {
        int length = byteArray.nextInt();
        valueArray[i] = new Pinyin[length];
        for (int j = 0; j < length; ++j)
        {
            valueArray[i][j] = pinyins[byteArray.nextInt()];
        }
    }
    if (!trie.load(byteArray, valueArray)) return false;
    return true;
}

public boolean load(ByteArray byteArray, V[] value)
{
    if (byteArray == null) return false;
    size = byteArray.nextInt();
    base = new int[size + 65535];   // 多留一些,防止越界
    check = new int[size + 65535];
    fail = new int[size + 65535];
    output = new int[size + 65535][];
    int length;
    for (int i = 0; i < size; ++i)
    {
        base[i] = byteArray.nextInt();
        check[i] = byteArray.nextInt();
        fail[i] = byteArray.nextInt();
        length = byteArray.nextInt();
        if (length == 0) continue;
        output[i] = new int[length];
        for (int j = 0; j < output[i].length; ++j)
        {
            output[i][j] = byteArray.nextInt();
        }
    }
    length = byteArray.nextInt();
    l = new int[length];
    for (int i = 0; i < l.length; ++i)
    {
        l[i] = byteArray.nextInt();
    }
    v = value;
    return true;
}

计算

通过 HanLP — Aho-Corasick DoubleArrayTire 算法 ACDAT - 基于双数组字典树的AC自动机 找出汉字的拼音

image
image

调用

public static void main(String[] args)
{
    String text = "重载不是重任";
    List<Pinyin> pinyinList = HanLP.convertToPinyinList(text);
    System.out.print("原文:");
    for (char c : text.toCharArray())
    {
        System.out.printf("%c", c);
    }
    System.out.println();

    System.out.print("拼音(数字音调):");
    for (Pinyin pinyin : pinyinList)
    {
        System.out.printf("%s,", pinyin);
    }
    System.out.println();

    System.out.print("拼音(符号音调):");
    for (Pinyin pinyin : pinyinList)
    {
        System.out.printf("%s,", pinyin.getPinyinWithToneMark());
    }
    System.out.println();

    System.out.print("拼音(无音调):");
    for (Pinyin pinyin : pinyinList)
    {
        System.out.printf("%s,", pinyin.getPinyinWithoutTone());
    }
    System.out.println();

    System.out.print("声调:");
    for (Pinyin pinyin : pinyinList)
    {
        System.out.printf("%s,", pinyin.getTone());
    }
    System.out.println();

    System.out.print("声母:");
    for (Pinyin pinyin : pinyinList)
    {
        System.out.printf("%s,", pinyin.getShengmu());
    }
    System.out.println();

    System.out.print("韵母:");
    for (Pinyin pinyin : pinyinList)
    {
        System.out.printf("%s,", pinyin.getYunmu());
    }
    System.out.println();

    System.out.print("输入法头:");
    for (Pinyin pinyin : pinyinList)
    {
        System.out.printf("%s,", pinyin.getHead());
    }
    System.out.println();
}

数据下载:http://download.hanlp.com/data-for-1.7.5.zip

标签:byteArray,JAVA,--,pinyin,System,int,length,HanLP,out
From: https://www.cnblogs.com/vipsoft/p/17972448

相关文章

  • docker构建java镜像,运行镜像出现 no main manifest attribute, in /xxx.jar
    背景本文主要是一个随笔,记录一下出现"nomainmanifestattribute"的解决办法问题原因主要是近期在构建一个镜像,在镜像构建成功后,运行一直提示"nomainmanifestattribute",但是还在想,是不是Dockerfile写错了,后来仔细检查了一下,发现是在pom文件下build节点下配置问题,修改配置......
  • ELK之Filebeat自动断开问题解决
     自动断开命令 解决自动断开命令nohup./filebeat-e-cfilebeat.yml>./filebeat.log 2>&1& disown 其他的方式(目前我没有使用) 在linux操作系统/etc/systemd/system目录下创建一个filebeat.service文件,写入如下内容需要注意替换文件的位置以及版本[Unit]D......
  • dremio 基于Options注解的配置技巧
    以前简单写过一个dremio配置相关的介绍,以下是一个简单的使用原理dremio自己定义了一个Options的注解,包含此注解的类会被启动的时候进行类扫描加载,Options的会存储起来(分为不用类型的)有session级别的,系统级别的。。。。简单使用pom.xml <?xmlversion="1.......
  • 集镇和集市和市镇的区别
     集镇和集市和市镇的区别1、规模不同集镇是乡村与城市之间的过渡型居民点。集市是指定期聚集进行的商品交易活动形式,规模较小。市镇则是指较大的集镇。规模最大。2、性质不同集镇是指乡、民族乡人民政府所在地和经县级人民政府确认由集市发展而成的作为农村一定区域经济......
  • Nginx的日志处理
    Nginx的日志处理背景之前一直被各种咨询nginx的使用问题.大部分都是性能,加模块,以及一些tcp端口等的问题.其实这些都还好,还有一个比较麻烦的问题时日志相关的.nginx的日志稍有不注意就会变的非常大.导致不可用.其实应该是实现logrotate的方式比较好一些.其实实......
  • java创建线程的4种方式
    1.Thread类一个线程在Java中使用一个Thread实例来描述。Thread类是Java语言一个重要的基础类,位于java.lang包中。Thread类有不少非常重要的属性和方法,用于存储和操作线程的描述信息。1.1线程ID属性:privatelongtid,此属性用于保存线程的ID。这是一个private类型属性,外......
  • GSSM加解密
    1、sm2packagecryptoimport( "crypto/rand" "github.com/emmansun/gmsm/sm2")funcSm2Decrypt(priKey,cipherText[]byte)(plainText[]byte,errerror){ varpK*sm2.PrivateKey ifpK,err=sm2.NewPrivateKey(priKey);err!=nil{......
  • 使用jenkins构建k8s项目怎么执行kubectl命令
    使用jenkins构建k8s项目时需要执行kubectl命令因为使用jenkins使用的用户是jenkins所以在执行kubectl时没有权限,但是在页面报错不会报权限错误而是报以下错误error:unabletorecognize"k8s/xiaoxing-labs-web-deployment.yaml":nomatchesforkind"Deployment"inversio......
  • 星座和属相哪个更准
     星座和属相哪个更准星座和属相在预测个性特质和命运走向方面都具有各自的理论基础和信仰体系,它们的准确性受到了人们的质疑。以下是两者的一些对比点:星座:历史渊源:星座的概念源自古希腊和古罗马时期,当时的观测者将天体运动与人类命运联系起来,这一观念延续......
  • TTE时间触发以太网交换机测试方法
    在本世纪初,TTE最早是由维也纳科技大学HermannKopetz赫尔曼·科佩茨教授等人提出来的,在国际上比较知名的TTE开发机构主要是以奥地利的TTTech公司为主,尔曼·科佩茨教授是该公司的创始人之一,这家公司是将教授的理论进行了产业化应用和推广,其中,开发的关于TTE网络产品包括:TTE交换机、......