您的位置:www.85058.com > 互联网资讯 > 计算机也能写宋词!

计算机也能写宋词!

发布时间:2019-10-22 21:26编辑:互联网资讯浏览(60)

    最大概率法

    但是我们可以换一个角度来看待这种歧义问题。对于两种切分方式,“乒乓/球拍/卖/完/了”和“乒乓球/拍卖/完/了”,我们会认为前者更合理,因为通常乒乓球和拍卖不太可能联系在一起。也就是说,后者在语料库中出现的概率会比较小。所以,如果同一个句子出现若干种不同的划分,我们就希望找到可能出现概率最大的那个。

    为了表述简便,这里用 {A1, A2, A3, A4, A5} 和 {B1, B2, B3, B4} 来分别表示 {乒乓,球拍,卖,完,了} 和 {乒乓球,拍卖,完,了} ,我们的任务是比较 P(A1, A2, A3, A4, A5) 和 P(B1, B2, B3, B4) 的大小。

    根据条件概率公式,有

    P(A1, A2, A3, A4, A5) = P(A1) P(A2|A1) P(A3|A1, A2) P(A4|A1, A2, A3) P(A5 | A1, A2, A3, A4)

    其中 P(A1) 表示 A1 在语料库中出现的概率,P(A2|A1) 表示当上一个词语是A1时,在它后面 A2 出现的概率,类似的, P(A3|A1, A2) 表示当前面两个词语是 A1 和 A2 时下一个词语是 A3 的概率,等等……

    但是我们发现,当句子很长时,这个概率表达式的尾巴会越来越长,给计算带来很大的麻烦,所以一般采用 马尔可夫链 (Markov Chain)的假设。

    在马尔可夫链假定下,我们认为下一个词出现的概率只与前一个词有关,也就是说,在给定前文时,“卖”出现的概率只与紧接着的“球拍”有关,而与“乒乓”无关。有了这个假定,之前的概率就简化为

    P(A1, A2, A3, A4, A5) = P(A1) P(A2|A1) P(A3|A2) P(A4|A3) P(A5|A4)

    这就大大减小了计算量。在利用这个模型时,需要先对一个很大的语料库进行分析,这被称为“训练”的过程,其意义就在于把任意两个词语之间关联的概率都计算出来。当然在实际操作中,还牵涉到很多其他非常复杂细节,在此就不一一细说了。

    分词

    我们先人工对上面的句子来进行一下切词,使用斜线分割:“你/假如/上午/没/给/我/吃/冰淇淋/,/我/绝对/会/不/happy/的/。/”。但是程序如何做到自动切分?这个其实中国的前辈们已经做了很多中文分词的研究,常见的分词算法有:

    1. 基于词典的分词,需要先预设一个分词词典,比如上面句子切分出来的“假如、上午”这些词先存放在词典,然后把句子切分成单字组合成词语去词典里查找,匹配上了就挑选出来一个词。没有匹配上的就切分成单字。

    2. 基于统计的分词,需要先获取大量的文本语料库(比如新闻、微博等),然后统计文本里相邻的字同时出现的次数,次数越多就越可能构成一个词。当达到一定次数时就构成了一个词,即可形成语料概率库。再对上面句子进行单字切分,把字与字结合后在语料概率库里查找对应的概率,如果概率大于一定值就挑选出来形成一个词。这个是大概描述,实际生产环境中还需要对句子的上下文进行结合才能更准确的分词。

    3. 基于语义的分词,简而言之就是模拟人类对句子的理解来进行分词。需要先整理出中文语句的句法、语义信息作为知识库,然后结合句子的上下文,对句子进行单字切分后组合成词逐个带入知识库进行识别,识别出来就挑选出一个词。目前还没有特别成熟的基于语义的分词系统。

    基于词典的分词

    为了让大家快速的了解分词技术,我们采用第一个方式来做测试:基于词典的分词,这种方式简单暴力可以解决百分之七八十的问题。基于词典的分词大概分为以下几种方式:

    1. 正向最大匹配,沿着我们看到的句子逐字拆分后组合成词语到词典里去匹配,直到匹配不到词语为止。举个实际的例子:“人民大会堂真雄伟”,我们先拆分为单字“人”去词典里去查找,发现有“人”这个词,继续组合句子里的单字组合“人民”去词典里查找,发现有“人民”这个词,以此类推发现到“人民大会堂”,然后会结合“人民大会堂真”去词典里查找没有找到这个词,第一个词“人民大会堂”查找结束。最终分词的结果为:“人民大会堂/真/雄伟”。如下图演示了用正向最大匹配算法识别人民大会堂的过程,“真”,“雄伟”的识别类似。

     

    2. 逆向最大匹配,这个和上面相反,就是倒着推理。比如“沿海南方向”,我们按正向最大匹配来做就会切分成 “沿海/南方/向”,这样就明显不对。采用逆向最大匹配法则来解决这个问题,从句子的最后取得“方向”这两个字查找词典找到“方向”这个词。再加上“南方向”组成三字组合查找词典没有这个词,查找结束,找到“方向”这个词。以此类推,最终分出“沿/海南/方向”。

    3. 双向最大匹配,顾名思义就是结合正向最大匹配和逆向最大匹配,最终取其中合理的结果。最早由哈工大王晓龙博士理论化的取最小切分词数,比如“我在中华人民共和国家的院子里看书”,正向最大匹配切分出来为“我/在/中华人民共和国/家/的/院子/里/看书”工8个词语,逆向最大匹配切分出来为“我/在/中华/人民/共/和/国家/的/院子/里/看书”共11个词语。取正向最大匹配切出来的结果就是正确的。但是如果把上面那个例子“沿海南方向”双向切分,都是3个词语,改如何选择?看第4个《最佳匹配法则》。

    4. 最佳匹配法则,先准备一堆文本语料库、一个词库,统计词库里的每一个词在语料库里出现的次数记录下来。最后按照词频高的优先选出,比如“沿海南方向”,正向切分为:“沿海/南方/向”,逆向切分为:“沿/海南/方向”。其中“海南”的频度最高,优先取出来。剩下“沿”、“方向”也就正常切分了。是不是这就是基于词典分词的最佳方案?比如数学之美中提到的:“把手抬起来” 和 “这扇门的把手”,可以分为“把”、“手”、“把手”,不管怎么分总有一句话的意思不对。后续再介绍如何通过统计的分词处理这些问题。

    图片 1

    说了这么多,我们来实战一下如何基于词典的分词:

     

    public class TestPositiveMatch {
        public static void main(String[] args) {
       String str = "我爱这个中华人民共和国大家庭";
       List<String> normalDict = new ArrayList<String>();
    
       normalDict.add("");
       normalDict.add("爱");
      normalDict.add("中华");  //测试词库里有中华和中华人民共和国,按照最大匹配应该匹配出中华人民共和国
       normalDict.add("中华人民共和国");
    
      int strLen = str.length();  //传入字符串的长度
       int j = 0;
      String matchWord = ""; //根据词库里识别出来的词
      int matchPos = 0; //根据词库里识别出来词后当前句子中的位置
      while (j < strLen) {  //从0字符匹配到字符串结束
      int matchPosTmp = 0;  //截取字符串的位置
       int i = 1;
      while (matchPosTmp < strLen) {  //从当前位置直到整句结束,匹配最大长度
       matchPosTmp = i + j;
      String keyTmp = str.substring(j, matchPosTmp);//切出最大字符串
      if (normalDict.contains(keyTmp)) { //判断当前字符串是否在词典中
      matchWord = keyTmp;  //如果在词典中匹配上了就赋值
      matchPos = matchPosTmp; //同时保存好匹配位置
       }
       i++;
       }
       if (!matchWord.isEmpty()) {
      //有匹配结果就输出最大长度匹配字符串
       j = matchPos;
      //保存位置,下次从当前位置继续往后截取
       System.out.print(matchWord + " ");
       } else {
      //从当前词开始往后都没有能够匹配上的词,则按照单字切分的原则切分
       System.out.print(str.substring(j, ++j) + " ");
       }
       matchWord = "";
       }
       }
     }
    

     

    输出结果为:我爱这个中华人民共和国大家庭

    按照这样我们一个基本的分词程序开发完成。

    对于文章一开始提到的问题还没解决,如何让程序识别文本中的感情色彩。现在我们先要构建一个感情色彩词库“高兴”,修饰词库“没”、”不”。再完善一下我们的程序:

     

    public class TestSentimentPositiveMatch {
       public static void main(String[] args) {
       String str = "你假如上午没给我吃冰淇淋,我绝对会不happy的。";
    
      //语义映射
       Map<String, String> sentimentMap = new HashMap<String, String>();
       sentimentMap.put("happy", "高兴");
    
      //情感词库
       List<String> sentimentDict = new ArrayList<String>();
       sentimentDict.add("happy");
    
      //修饰词
       List<String> decorativeDict = new ArrayList<String>();
       decorativeDict.add("不");
       decorativeDict.add("没");
    
      //修饰词衡量分数
       Map<String, Double> decorativeScoreMap = new HashMap<String, Double>();
       decorativeScoreMap.put("不", -0.5);
       decorativeScoreMap.put("没", -0.5);
    
      List<String> decorativeWordList = new ArrayList<String>();  //修饰词
      String sentimentResult = ""; //情感结果
    
      int strLen = str.length();  //传入字符串的长度
       int j = 0;
      String matchSentimentWord = ""; //根据词库里识别出来的情感词
      String matchDecorativeWord = ""; //根据词库里识别出来的修饰词
      int matchPos = 0; //根据词库里识别出来词后当前句子中的位置
      while (j < strLen) {  //从0字符匹配到字符串结束
      int matchPosTmp = 0;  //截取字符串的位置
       int i = 1;
      while (matchPosTmp < strLen) {  //从当前位置直到整句结束,匹配最大长度
       matchPosTmp = i + j;
      String keyTmp = str.substring(j, matchPosTmp);//切出最大字符串
      if (sentimentDict.contains(keyTmp)) { //判断当前字符串是否在词典中
      matchSentimentWord = keyTmp;  //如果在词典中匹配上了就赋值
      matchPos = matchPosTmp; //同时保存好匹配位置
       }
      if (decorativeDict.contains(keyTmp)) { //判断当前字符串是否在词典中
      matchDecorativeWord = keyTmp;  //如果在词典中匹配上了就赋值
      matchPos = matchPosTmp; //同时保存好匹配位置
       }
       i++;
       }
       if (!matchSentimentWord.isEmpty()) {
      //有匹配结果就输出最大长度匹配字符串
       j = matchPos;
      //保存位置,下次从当前位置继续往后截取
       System.out.print(matchSentimentWord + " ");
       sentimentResult = sentimentMap.get(matchSentimentWord);
       }
       if (!matchDecorativeWord.isEmpty()) {
      //有匹配结果就输出最大长度匹配字符串
       j = matchPos;
      //保存位置,下次从当前位置继续往后截取
       System.out.print(matchDecorativeWord + " ");
       decorativeWordList.add(matchDecorativeWord);
       } else {
      //从当前词开始往后都没有能够匹配上的词,则按照单字切分的原则切分
       System.out.print(str.substring(j, ++j) + " ");
       }
       matchSentimentWord = "";
       matchDecorativeWord = "";
       }
    
       double totalScore = 1;
       for (String decorativeWord : decorativeWordList) {
       Double scoreTmp = decorativeScoreMap.get(decorativeWord);
       totalScore *= scoreTmp;
       }
    
       System.out.print("rn");
       if (totalScore > 0) {
       System.out.println("当前心情是:" + sentimentResult);
       } else {
       System.out.println("当前心情是:不" + sentimentResult);
       }
       }
     }
    

     

    通过传入“你假如上午没给我吃冰淇淋,我绝对会不happy的。”,结果输出为:“当前心情是:高兴”。当然你也可以改变其中的修饰词,比如改为:“你假如上午没给我吃冰淇淋,我绝对会happy的。”,结果输出为:“当前心情是:不高兴”。

    机器再也不是冷冰冰的,看起来他能读懂你的意思了。不过这只是一个开始,抛出几个问题:

    1. 如何让程序识别句子中的时间?比如“上午”、“下午2点”。

    2. 如何处理“把手抬起来” 和 “这扇门的把手”中的“把”与“手”的问题?

    3. 如何构建海量的知识库,让程序从“婴儿”变成“成年人”?

    4. 如何使用有限的存储空间存储海量的知识库?

    5. 如何提高程序在海量知识库中查找定位信息的效率?

    6. 如何识别新词、人名、新鲜事物等未知领域?

    宇宙芸芸众生都是相通的,大脑也许就是一个小宇宙,在这个小宇宙又有很多星球、住着很多生物。而电脑也是宇宙中地球上的一个产物,只要存储计算速度发展到足够强大一定可以构建成一个强大的大脑。

    你看这个单词 “testaword” 认识吗?可能不认识,因为我们五官先获取到的信息,然后根据大脑以往学习的经验做出判断。但是你看这个短语 ” test a word” 认识吗?再看看开始那个单词“testaword”是不是就亲切多了?

    To Be Continued……

    关于作者:严澜现成都创行负责人,历任上海创行科技技术总监。曾任中国平安平台开发工程师,腾讯拍拍网B2C架构工程师。Web3.0语义搜索引擎探索者,海量数据处理,互联网高性能低成本平台架构搭建实践者,构建让更多普通开发者快速掌握高性能技术的框架,自由机器人研发爱好者。

    自动作词:离我们有多遥远?

    图片 2

    分词完成后,词频的统计就是小事一桩了。之前有人把宋词的高频词语统计表 发到网上 ,一时间几乎每个理科生都能写宋词了。就技术层面而言,大部分自动作诗词的尝试都是在“高频——关联”这样的框架下完成的。即给定一个词语,搜索与之关联度较大的另外一批词作为候选集合,再通过预先设定好的准则进行筛选。

    但这样的方法显然比较简陋。相比之下,有人研究了更高级的方法,例如有一篇名为 一种宋词自动生成的遗传算法及其机器实现 的论文就采用填词的思想:给定一个词牌,就相应地给出了格律、押韵和平仄等硬性要求,将满足要求的词语填入相应的句法中,再通过一系列评价指标计算每个填词组合的“得分”,最后利用 遗传算法 计算出“得分”最高的填词方案。

    以“清平乐”这个词牌为例,其填词约束为

    *0 / *1, *1 / 0 / 01.    *1 / *0 / 0 / 11, *1 / *0 / *1.*0 / *1 / 00, *0 / *1 / 00.   *1 / *0 / *1, *0 / *1 / 00.
    

    其中 0 表示平声, 1 表示仄声, * 表示两者皆可, / 是词语的分割。可以看到,对于“清平乐”这个词牌,实际上就是要将 24 个词填入相应的空档中,其中第一个词以平声结尾,第二个词以仄声结尾,第四个词是一个平声单字……此外如果再考虑押韵,那么搜索的词语空间又会进一步减小。

    在给定了一种填词方案后,就可以构造这种方案的评分体系。上述的论文从四个方面(句法合法性、主题相关性、词句搭配的适当性、风格和情感统一性)考虑,最后得到一个综合加权的指标。因此,自动作词的过程就抽象为了一个高维的最优化问题,即试图找到一种填词的组合,使得最终这个加权指标达到最大。

    这篇论文的一个亮点在于使用了遗传算法作为主要的优化方法。遗传算法的细节比较复杂,在自动作词这一特定问题中,其主要思想是:

    1、 随机生成若干个满足约束条件(格律、押韵等)的填词方案;

    2、 选取其中较优的一些结果作为父代,然后利用遗传算法中的交叉和变异操作,从父代来生成子代。换言之,就是在已有的填词方案基础上生成新的填词方案;

    3、 不断进行评判和迭代,直到跳出循环。

    遗传算法的好处在于其算法的不确定性和可变异性,这是受生物的进化得到启发而发展起来的。虽然遗传算法作出的算词像模像样(例如本文开头的例子),但需要说明的是,遗传算法本质上是一个最优化算法,因此填词的好坏仍然与词库和评价指标直接相关。从某种意义上说,计算机作词实际上是利用已有的词库进行组合,而不是创造。

    无论如何,一个丰富而优秀的词库仍然是有意义的——对于电脑来说,这是它进行“创作”的基石;对于人来说,它至少能告诉读者以往词人常用的意象是什么,从而提供一些创作上的灵感(当然不应该是词作本身)。

    数据挖掘入门——分词

    图片 3

     

    谷歌4亿英镑收购人工智能公司DeepMind,百度目前正推进“百度大脑”项目,腾讯、阿里等各大巨头也在积极布局深度学习。随着社会化数据大量产生,硬件速度上升、成本降低,大数据技术的落地实现,让冷冰冰的数据具有智慧逐渐成为新的热点。要从数据中发现有用的信息就要用到数据挖掘技术,不过买来的数据挖掘书籍一打开全是大量的数学公式,而课本知识早已还给老师了,着实难以下手、非常头大!

    我们不妨先跳过数学公式,看看我们了解数据挖掘的目的——发现数据中价值。这个才是关键,如何发现数据中的价值。那什么是数据呢?比如大家要上网首先需要输入网址,打开网页后会自动判断哪些是图片、哪些是新闻、哪些是用户名称、游戏图标等。大脑可以存储大量的信息,包括文字、声音、视频、图片等,这些同样可以转换成数据存储在电脑。人的大脑可以根据输入自动进行判断,电脑可以通过输入判断吗?

    答案是肯定的! 不过需要我们编写程序来判断每一种信息,就拿文字识别来说吧,怎么从一个人在社交网络的言论判断他今天的心情是高兴还是愤怒!比如:“你假如上午没给我吃冰淇淋,我绝对会不happy的。” 信息发布时间为下午2点。对于我们人类一看这个句子就知道他是吃过冰淇淋了,心情肯定不会是愤怒。那计算机怎么知道呢?

    这就是今天的主题,要让计算机理解句子的语义,必须要有个程序,上面的句子和发布时间是输入,输出就是 “高兴”。要得到“高兴”就要建立 “高兴”的规则,可以建一个感情色彩词库,比如高兴(识别词是高兴、happy),愤怒(识别词是愤怒、生气)。这里的识别词就是输入中出现的词语,比如上面的句子中的“happy”就识别出了“高兴”这个感情色彩词。但是光识别出“happy”肯定是不行的,前面的“假如……没……,我……不……”等关键词都需要识别出来,才能完整判断一个句子的意思。为了达到这个效果,就必须要用分词技术了。

    最大匹配法

    图片 4

    在诸多复杂的分词方法中,最大匹配法(Maximum Matching,简称MM)是最简单直接的一种。它需要事先给定一个词库作为词典,然后从左到右匹配尽可能长的词语。举个例子,假设我们的词典里只有“计算机、超越、人脑”这三个词,对于“计算机会超越人脑吗”这句话,最大匹配法的计算过程是这样的:

    1、 创建指针 A 并将它置于句子的最开始位置:A计算机会超越人脑吗;

    2、 由于词典中最长的词语长度为3,所以创建新指针 B,置于 A 后的三个单位:A计算机B会超越人脑吗;

    3、 检验 A 和 B 之间的字符串是否在词典中,如果在,就将 A 移动到 B 的位置, B 相应地往后移(直至移到句子末尾):计算机/A会超越B人脑吗;

    4、 而如果A 和 B 之间的字符串不在词典中,就将 B 不断左移,直到能够有词语匹配或与 A的距离为 1 (也就是 A、B 之间没有匹配的词语,用单字切分),我们的例子在第一次切分后就属于这种情况,所以再次操作的结果就是:计算机/A会B超越人脑吗;

    5、 重复步骤 3 或 4,直到 A 移动到句子末尾:计算机/会/超越/人脑/吗。

    这种算法非常高效和简便,同时可以避免“计算/机会/超越/人脑/吗”这种切分方式(即便计算机和机会两个词同时在词典中)。但它的缺点也是很明显的,比如之前的“乒乓球拍卖完了”,就很可能被切分成“乒乓球/拍卖/完了”。为了消除这种歧义,人们也不断提出了一些改进算法,比如逆向匹配法,双向匹配法等等。

    点绛唇:人静风清,兰心蕙性盼如许。夜寒疏雨,临水闻娇语。佳人多情,千里独回首。别离后,泪痕衣袖,惜梦回依旧。

    ——一台计算机

    本文由www.85058.com发布于互联网资讯,转载请注明出处:计算机也能写宋词!

    关键词: