zoukankan      html  css  js  c++  java
  • 模板编写

    1. 模板的作用

      把用文本形式(String)的语言,转换成对应的一个关系(Relation),关系其实对应的是一个类(class),例如,string形式的“AB平行CD”,那么就有一个对应的class来表示,假设类名为ParallelRelation,那么这个类里面有2个成员变量,对应的平行的2个直线。这样就string类型转换成一个类,既保持了原有的信息,生成的类也方便进行推理。

          总之,String –> Relation。

    2. 模板的介绍

      以工程中已写好的一个模板文件(xml)为例介绍模板:

    2.1 Synsets标签

    <synset name="ANGLE_TYPE" core_term="钝角,直角,锐角为符号" expr="!?@angleType#钝角|直角|锐角|平角"/>

    Name:定义一个名字(相当于定义一个“ANGLE_TYPE”的变量,后面在模板中可以直接使用)

    core_term:对该变量的一些说明,不重要

    expr:分为3个部分:

    1. 重要性:有两个级别 “!”:重要的词;"N_I":不重要的词。
      (标记重要性的原则,如果具有数学意义的词,一般标为重要(用于机器学习中使用,对模板的编写没影响))
    2. 命名组:格式为"?@category#",为了方便提取出具体的值,从上面可以看出,该expr可以匹配 “钝角/直角/锐角/平角” 中的任意一个词, 由于该命名组为@angleType#,相当于@angleType#中就存放着具体的一个词(联想一下java的正则表达式,当Match.find()匹配成功后,使用Match.group() 来获取具体匹配字符串)

      如果你不需要该匹配出来的字符,则可以省略命名组,比如:

       <synset name="AND" core_term="和,与符号" expr="N_I和|,|与"/>

      3. 正则表达式:该expr具体正则表达式部分。
      

      简单来说 synset就是我们自己定义个标签,用来处理多词同义data提取。

    2.2 Template标签

      该部分也就是模板的主体部分,一个模板最基本的格式如下:

    <template id="Heart_Or_Excenter_Of_Triangle">
        <description>三角形的内心或外心</description>
        <pattern>(点|)%point%是#三角形#%triangle%的一个#心#</pattern>
        <pattern>#三角形#%triangle%(的)(一个|)#心#是(点|)%point%</pattern>
        <semantics type="JSON">
            <![CDATA[{"service":"cn.tsinghuabigdata.closedShape","code":"geo.JsonCoreAndShapeRelation",
            "data":{"point":"%point[0]%","heart":"@Heart","shape":"%triangle%","shapeStyle":"@triangleType","shapeType":"三角形"}}]]>
        </semantics>
    </template>

      属性说明:

    1. Id:描述标识符,见名识义。

    2. Pattern: 需要匹配某个句子的正则表达式(只是可以使用前面synsets 中定义的标签和全局标签)。

      synsets 中定义的标签:用 #name# 来表示,该标签实际是匹配其对应的 expr 中的正则表达式部分。
      全局定义的标签:用 %name% 来表示,一些全局通用的标签,例如 %triangle% 可以匹配一个类似 “ABC ”的字符串。(具体标签在NLPConstants类中可以查看)

    3. Semantics:重要部分,利用 Json 进行消息传递。

      其中"code": "geo.JsonCircularOnTriangleRelation",表示前面某个pattern匹配成功后,会进入JsonCircularOnTriangleRelation这个类中进行处理,其中传递的参数为"data": {"point":"%point[0]%","heart":"@Heart","shape":"%triangle%","shapeStyle":"@triangleType","shapeType":"三角形"}

      这是一种JSON的格式,也就是一种key-value的形式,相当于传递了5个变量:point、heart等。
      注:

      1. 第四个变量 key 为 shapeStyle,value 为 @triangleType ,注意我们在上面定义了一个synset:

      <synset name="三角形" core_term="等边,等腰为符号" expr="!?@triangleType#等边|等腰|正|直角|R|三角形|△"/>

      @triangleType 在命名组中(注意不是@triangleType#,没有#),因为在pattern中有一个#三角形#,上面expr中正则表达式匹配的成功字符串,使用名字组@triangleType 进行传递其具体的 data。

      2. 第一个变量 key 为 point,value 为 %point[0]%,  和上面类似,上面是我们自己定义的标签,而这个是全局定义的标签,而在pattern中出现的%point%,会存放在一个类似数组中,我们使用 %point[n]%(从0开始)来获取第 n-1 个 point 匹配的 value。
      例如:

      </template>
          <template id="TRIANGLE_BISECTOR_AND_MEDIAN">
              <description>三角形中的中线和角平分线2</description>
              <pattern>^(在)#三角形#%triangle%(中) %line% (是)(角平分线) #AND# %line% (是)(中线)$</pattern>
              <semantics type="JSON">
                  <![CDATA[{"service":"cn.tsinghuabigdata.line","code":"geo.JsonAngleBisectorRelation",
                  "data":{"triangle":"%triangle%","triangleType":"@triangleType","line":"%line[0]%"}}]]>
                  <![CDATA[{"service":"cn.tsinghuabigdata.closedShape","code":"geo.JsonMidianLinesOfTriangle",
                  "data":{"line":"%line[1]%","triangle":"%triangle%","triangleType":"@triangleType"}}]]>
              </semantics>
      </template>

      pattern部分中出现了2个 %line%, 在传递值的时候,如果传递的是第一个line,则在data中使用%line[0]%。

      上面还有个不同的地方是生成了2个Relation(准确的是说,通过geoJsonAngleBisectorRelation这个类处理了2次,每次的data不一样,每次都生成了relation)。

    3. 怎样写一个模板

    -src/main/java      //源代码
    -src/main/resource  //资源文件
    -src/test/java      //测试代码
    -src/test/resource  //测试资源文件

    3.1 首要工作

    1. 首先在 src/main/resource/xml 自己建一个写模板的xml文件,例如为 lz_template.xml
      (最好根据你们自己写哪一部分的模板命名,例如工程里面有draw_template.xml就是写作图语句的模板)

    2. 在建好的xml定义好一些标签,如下:
      <?xml version="1.0" encoding="UTF-8"?>
      <templates domainId="cn.tsinghuabigdata.lz">
          <tags>
              <tag name="lz"/>
          </tags>
      
      </templates>
    3. 建立一个模板测试类

      在 src/test/.../jsontorelation/generalTest.java 有一个已经建好的测试类,不过需要添加一些内容。
      把刚建立的xml添加进去,其他模板文件可以注释掉:

      ActionTemplate.getInstance().loadActionTemplate("xml\lz_template.xml");

      然后注册自己的服务:

      TreeSet<String> treeSet = new TreeSet<String>();

      treeSet.add("cn.tsinghuabigdata.lz");

      名字为xml的domainID

    3.2 开始写模板

      前提是已经知道正则表达式的基本使用语法,以编写 “AE 和 AF 分别为三角形 ABC 的中位线” 为例:

    1. 在 NLPConstants 查看全局标签,NLPContants 标签部分如下:
      public static final POINT = "Point";
      public static final TRIANGLE = "Triangle";
      public static final CIRCLE = "Circle";
    2. 用标签替换掉里面的具体数学对象,如:

      用 line 替换掉 AE 和 AF 这样具体的数学对象,用 triangle 替换掉 ABC
      “AE 和 AF 分别为三角形 ABC 的中位线” 的 pattern 即为:
      “%line%和%line%分别为三角形%triangle%的中位线”

    3. 考虑句子的多样性,如:

      上面的句子中,“和”可以用“与”或者“,”来替换,不影响表达意思
      “AE 与 AF 分别为三角形 ABC 的中位线”
      “AE , AF 分别为三角形 ABC 的中位线”
      因此,还要考虑句子的各种表达形式,这就要用到前面说的 synset 标签
      我们在 xml 文件中加入自己定义的标签:

      <synset>
          <synset name = "AND" core_term = "和,与符号" expr = "N_I和|,|与"/>
      </synset>

      这样pattern就变为类:
      “%line%#AND#%line%分别为三角形%triangle%的中位线”
      注意:自己定义的标签用# #,NLPConstants里面的全局标签用% %.

    4. 编写模板
    • 先找出这句话里面包含的Relation

      上面例子中,包含了2个三角形中线的关系(在863-model里面的relation包里面查找)
      三角形中线关系为 MidianLineOfTriangleRelation

    • 查看创建该关系所需要的信息,主要通过构造函数查看:
      public  MidianLineOfTriangleRelation(Segment segment, Triangle triangle) {
          super(segment);
          AssertConstructorDataUtil.assertNotNull(triangle);
          this.triangle = triangle;
          recogniseTopBottom();
      }

      在MidianLineOfTriangleRelation的构造函数中,要提取出 segment 和 triangle 这2个参数.

    • 继续编写模板

      生成一个MidianLineOfTriangleRelation需要一个Segment和一个Triangle,通过构造函数来看
      (有多个构造函数时候,选一个自己觉得最合适的)

      public static LineElement creatLineElement(String line) throws AssertIllegalException {
          LineUtil.LineType type = LineUtil.getLineType(line);
          if(type.equals(LineUtil.LineType.SingleLetterLine)) {
              return new LineElement(line,type);
          } else {
              return creatSegmentAndRayElement(line,type);
          }
      }

      Segment 通过 pattern 中的 %line% 提取

      public static TriangleElement creatTriangleElement(String attr, String triangle) 
          throws AssertIllegalException {
              checkAssert.AssertIllegal(attr,triangle);
              TriangleElementUtil.TriangleType angleAttr = TriangleElementUtil.getTriangAngle(attr);
              List<String> points = TriangleElementUtil.getPoints(triangle);
              return new TriangleElement(PointElement.createPointElement(points.get(0), 
                  PointElement.createPointElement(points.get(1), 
                  PointElement.createPointElement(points.get(2),
                  angleAttr);
          }

      Triangle 的构造函数中,有一个参数为attr,表示三角形的属性,例如“等腰三角形”,第二个triangle是具体三角形的名字,
      例如“ABC”,这样在构造Triangle的时候,除了提取出三角形的名字,还要有三角形的类别,所以继续添加提取三角形类别的
      synset.

      <synset>
          <synset name = "AND" core_term = "和,与符号" expr = "N_I和|,|与"/>
          <synset name = "三角形" core_term = "等边,等腰为符号" expr = "!?@triangle#三角形/等边三角形/等腰三角形/直角三角形"/>
      </synset>


      这样,模板的一切需要的东西都具备了。

      <?xml version="1.0" encoding="UTF-8"?>
      <templates domainId="cn.tsinghuabigdata.lz">
          <tags>
              <tag name="lz"/>
          </tags>
              <synsets>
              <synset name="AND" core_term="和,与符号" expr="N_I和|,|与"/>
                      <synset name="IS" core_term="是,为符号" expr="N_I是|为"/>
                      <synset name="三角形" core_term="等边,等腰为符号" expr="!?@triangleType#等边|等腰|正|直角|R|三角形|△"/>
              </synsets>
          <template id="Middle_Line_Of_Triangle">
                      <description>三角形的中线</description>
                      <pattern>^%line%#AND#%line%(分别|)#IS##三角形#%Triangle%(中位)(线)$</pattern>
                      <semantics type="JSON">
                              <![CDATA[{"service":"cn.tsinghuabigdata.closedShape","code":"geo.JsonMidianLinesOfTriangle",
                  "data":{"line":"%line[0]%","triangle":"%triangle%","triangleType":"@triangleType"}}]]>
                              <![CDATA[{"service":"cn.tsinghuabigdata.closedShape","code":"geo.JsonMidianLinesOfTriangle",
                  "data":{"line":"%line[1]%","triangle":"%triangle%","triangleType":"@triangleType"}}]]>
                      </semantics>
          </template>

      目前 JsonMidianLinesOfTriangle 还没有建,现在开始建。

    • 在863-nlu的 jsontorelation 包中,在对应的 子包 中建立一个类,用来处理模板提取的信息并生成relation
      例如:上面例子,在 geo 包中创建一个JsonMidianLinesOfTriangle类

      public class JsonMidianLinesOfTriangle {
           public static IRelation JsonToRelation(JsonInfo root, GlobalInfomation globalInformation) {
              Irelation iRelation = null;
      
              return iRelation;
           }
      }

      里面的 JsonToRelation 的函数名和参数是固定的

      JsonObject jsonObject = root.getJsonObject().getAsJsonObject("data");
      String line = jsonObject.get("line").toString().replace("","");
      String triangle = jsonObject.get("triangle").toString().replace("","");
      String triangleType = jsonObject.get("triangleType").toString().replace("","");

      上面的代码在模板那边,通过“data”传过来的json数据格式的参数
      (上面已经有函数处理,例如 String line = TransToRelationUntil.getStringDataFromJsonObject(jsonObject, "line"); 来提取line的data)

      下面该生成 MidianLineOfTriangleRelation,并返回

      try {
          Triangle triangle1 = TriangleElement.createTriangleElement(triangleType,triangle).transToData();
          Segment segment = (Segment)LineElement.creatLineElement(line).transToData();
          iRelation = new  MidianLineOfTriangleRelation(segment, triangle1);
          iRelation.setPosition(root.getLineBegin(), root.getLinePosBegin(), root.getLineEnd(), root.getLinePosEnd());
      } catch(Exception e) {
          e.printStackTrace();
      }

      生成对应的 Segment 和 Triangle, 最后生成 MidianLineOfTriangleRelation.

      写完后的完整代码如下:

      public class JsonMidianLinesOfTriangle {
           public static IRelation JsonToRelation(JsonInfo root, GlobalInfomation globalInformation) {
              Irelation iRelation = null;
      
              if(root == null) {
                  return iRelation;
              }
      
              JsonObject jsonObject = root.getJsonObject().getAsJsonObject("data");
              String line = jsonObject.get("line").toString().replace("","");
              String triangle = jsonObject.get("triangle").toString().replace("","");
              String triangleType = jsonObject.get("triangleType").toString().replace("","");
              
              try {
                  Triangle triangle1 = TriangleElement.createTriangleElement(triangleType,triangle).transToData();
                  Segment segment = (Segment)LineElement.creatLineElement(line).transToData();
                  iRelation = new  MidianLineOfTriangleRelation(segment, triangle1);
                  iRelation.setPosition(root.getLineBegin(), root.getLinePosBegin(), root.getLineEnd(), root.getLinePosEnd());
              } catch(Exception e) {
                  e.printStackTrace();
              }
              return iRelation;
           }
      }
    • 测试

      在generalTest中,把taggedText 改为" AE&&line 和 AF&&line 分别是三角形 ABC&&triangle 的中位线";
      taggerTest = " AE&&line 和 AF&&line 分别是三角形 ABC&&triangle 的中位线"

      这里需要说明的是,由于这个测试没有加入nlp,所以命名识别没有加入,需要我们手动加入tag
      比如我们测试的句子为 AE和AF分别是三角形ABC的中位线,通过NLPConstants中查询,AE和AF在命名识别中会识别为line
      所以在AE和AF后面加入 &&line(注意空格的位置)。

      运行结果:
      R_MidianLineOfTriangle:AE/△BAC
      R_MidianLineOfTriangle:AF/△BAC

      最后的最后,记得编写单元测试,通过工程中已有的单元测试编写即可(其实和generalTest类似)。

  • 相关阅读:
    peudoclass与pseudo的相同点与不同点
    第一个页面
    自我介绍
    Virtual IP Address 学习记录
    OpenStack 学习记录
    Dubbo学习记录 MAC
    售前 银行
    log4j2 学习记录 Pattern Layout
    Zookeeper学习记录 mac下安装部署
    P2695 骑士的工作
  • 原文地址:https://www.cnblogs.com/skyke/p/5024622.html
Copyright © 2011-2022 走看看