来自麻省理工的信息抽取

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangyangzhizhou/article/details/78420817

MITIE

MITIE 即 MIT 的 NLP 团队发布的一个信息抽取库和工具。它是一款免费且先进的信息抽取工具,目前包含了命名实体抽取、二元关系检测功能,另外也提供了训练自定义抽取器和关系检测器的工具。

MITIE 是核心代码是使用 C++ 写的,建立在高性能的机器学习库 dlib 上。MIT 团队给我们提供了一些已训练好了的模型,这其中包含了英语、西班牙语和德语,这些模型都使用了大量的语料进行训练。我们发现并没有我们要的中文的模型,所以这个还得我们自己训练。

尽管 MITIE 是 C++ 写的,但它也提供了其他语言的调用 API 。在我自己的项目中常常会跟 Java 、 Python 混合用,所以只要编译成动态库再分别用 Java 和 Python 调用就行了,很方便。

为什么出现MITIE

看看 MIT 实验室的人怎么说就知道了。

I work at a lab and there are a lot of cool things about my job. In fact, I could go on all day about it, but in this post I want to talk about one thing in particular, which is that we recently got funded by the program to make an open source natural language processing library focused on information extraction.

Why make such a thing when there are already open source libraries out there for this (e.g. OpenNLP, NLTK, Stanford IE, etc.)? Well, if you look around you quickly find out that everything which exists is either expensive, not state-of-the-art, or GPL licensed. If you wanted to use this kind of NLP tool in a non-GPL project then you are either out of luck, have to pay a lot of money, or settle for something of low quality. Well, not anymore! We just released the first version of our MIT Information Extraction library which is built using state-of-the-art statistical machine learning tools.

怎么使用

提取实体为例,为方便可直接使用 MITIE 提供给我们的模型,否则你就需要自己训练了。从 https://github.com/mit-nlp/MITIE/releases/download/v0.4/MITIE-models-v0.2.tar.bz2 下载。

然后创建一个 test.txt 文件,待测试内容为

I met with john becker at HBU.
The other day at work I saw Brian Smith from CMU.

最后编写代码如下,

#include <mitie/named_entity_extractor.h>
#include <mitie/conll_tokenizer.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstdlib>

using namespace std;
using namespace mitie;

std::vector<string> tokenize_file (
    const string& filename
)
{
    ifstream fin(filename.c_str());
    if (!fin)
    {
        cout << "Unable to load input text file" << endl;
        exit(EXIT_FAILURE);
    }
    conll_tokenizer tok(fin);
    std::vector<string> tokens;
    string token;
    while(tok(token))
        tokens.push_back(token);

    return tokens;
}


int main(int argc, char** argv)
{
    try
    {
        if (argc != 3)
        {
            printf("You must give a MITIE ner model file as the first command line argument\n");
            printf("followed by a text file to process.\n");
            return EXIT_FAILURE;
        }
        string classname;
        named_entity_extractor ner;
        dlib::deserialize(argv[1]) >> classname >> ner;

        const std::vector<string> tagstr = ner.get_tag_name_strings();
        cout << "The tagger supports "<< tagstr.size() <<" tags:" << endl;
        for (unsigned int i = 0; i < tagstr.size(); ++i)
            cout << "   " << tagstr[i] << endl;

        std::vector<string> tokens = tokenize_file(argv[2]);

        std::vector<pair<unsigned long, unsigned long> > chunks;
        std::vector<unsigned long> chunk_tags;
        std::vector<double> chunk_scores;

        ner.predict(tokens, chunks, chunk_tags, chunk_scores);

        cout << "\nNumber of named entities detected: " << chunks.size() << endl;
        for (unsigned int i = 0; i < chunks.size(); ++i)
        {
            cout << "   Tag " << chunk_tags[i] << ": ";
            cout << "Score: " << fixed << setprecision(3) << chunk_scores[i] << ": ";
            cout << tagstr[chunk_tags[i]] << ": ";
            for (unsigned long j = chunks[i].first; j < chunks[i].second; ++j)
                cout << tokens[j] << " ";
            cout << endl;
        }

        return EXIT_SUCCESS;
    }
    catch (std::exception& e)
    {
        cout << e.what() << endl;
        return EXIT_FAILURE;
    }
}

执行结果为,

The tagger supports 4 tags:
   PERSON
   LOCATION
   ORGANIZATION
   MISC

Number of named entities detected: 4
   Tag 0: Score: 1.532: PERSON: john becker
   Tag 2: Score: 0.340: ORGANIZATION: HBU
   Tag 0: Score: 1.652: PERSON: Brian Smith
   Tag 2: Score: 0.471: ORGANIZATION: CMU

中文模型训练

主要是要训练所有词向量特征,后面的实名实体模型和关系模型都是建立在它的基础上,MITIE 给我们提供了工具完成上述操作,我们可以用 cmake 生成vs项目,但一般我们没有必要改动到代码,直接使用 cmake 构建一下就可直接使用。主要操作有

D:\MITIE\tools\wordrep>mkdir build
D:\MITIE\tools\wordrep>cd build
D:\MITIE\tools\wordrep\build>cmake ..
D:\MITIE\tools\wordrep\build>cmake --build . --config Release

再一个是需要收集大量的词汇,可以通过维基百科和百度百科收集,类似处理可以参加前面的文章 《如何使用中文维基百科语料》。

接着就可以开始训练了,参数e表示生成所有我们需要的模型,data为语料库的目录。

wordrep -e data
if (parser.option("e"))
        {
            count_words(parser);
            word_vects(parser);
            basic_morph(parser);
            cca_morph(parser);
            return 0;
        }

Java&Python调用

主要的一步都是要生成共享链接库,同样使用 cmake 可以很方便生成,到 mitielib 目录,

D:\MITIE\mitielib>mkdir build
D:\MITIE\mitielib>cd build
D:\MITIE\mitielib\build>cmake ..
D:\MITIE\mitielib\build>cmake --build . --config Release --target install

生成需要的链接库。

-- Install configuration: "Release"
-- Installing: D:/MITIE/mitielib/msvcp140.dll
-- Installing: D:/MITIE/mitielib/vcruntime140.dll
-- Installing: D:/MITIE/mitielib/concrt140.dll
-- Installing: D:/MITIE/mitielib/mitie.lib
-- Installing: D:/MITIE/mitielib/mitie.dll

然后 python 就能轻易完成调用。而对于 Java 也而需要类似的操作,但它的构建过程还需要有 SWIG 。生成如下的链接库和 jar 包,然后 Java就能轻易完成调用。

-- Install configuration: "Release"
-- Installing: D:/MITIE/mitielib/java/../javamitie.dll
-- Installing: D:/MITIE/mitielib/java/../javamitie.jar
-- Up-to-date: D:/MITIE/mitielib/java/../msvcp140.dll
-- Up-to-date: D:/MITIE/mitielib/java/../vcruntime140.dll
-- Up-to-date: D:/MITIE/mitielib/java/../concrt140.dll

github

一个文本分析项目使用MITIE,https://github.com/sea-boat/TextAnalyzer.git

以下是广告

========广告时间========

公众号的菜单已分为“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。

鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以购买。感谢各位朋友。

为什么写《Tomcat内核设计剖析》

=========================

欢迎关注:

这里写图片描述
这里写图片描述

阅读更多 登录后自动展开

扫码向博主提问

超人汪小建(seaboat)

博客专家

java深度,架构,AI,中间件,高并发
  • 擅长领域:
  • java
  • 架构
  • 中间件
  • tomcat
  • AI
去开通我的Chat快问
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页