4

(对不起,如果标题是一个完整的红鲱鱼顺便说一句)

背景:

我正在使用 Twitter Streaming API 和 ASP.NET SignalR 实时开发世界上所有推文的地图。我正在使用 Tweetinvi C# Twitter 库使用 SignalR 将推文异步推送到浏览器。一切都按预期工作 - 请参阅http://dev.wherelionsroam.co.uk了解它。

开发的下一步涉及使用斯坦福自然语言解析库 ( http://nlp.stanford.edu/software/corenlp.shtml ) 解析每条推文的文本数据,特别是命名实体识别器(也称为 CRFClassifier),因此我可以从每条推文中提取有意义的元数据(即提到的人物、地点和组织)。期望的结果是我将能够确定很多人正在谈论的人员、地点和组织(类似于“趋势”的概念),并使用 SignalR 将它们广播给所有客户。我知道 Twitter API 有这些GET trends方法,但这不会很有趣吗?!

以下是我的应用程序中的主要类:

主要课程:

TweetModel.cs(保存有关推文的所有信息,作为从 Streaming API 向其广播的信息):

public class TweetModel
{
    public string User { get; set; }
    public string Text { get; set; }
    public DateTime CreatedAt { get; set; }
    public string ImageUrl { get; set; }
    public double Longitude { get; set; }
    public double Latitude { get; set; }
    public string ProfileUrl { get; set; }

    // This field is set later during Tokenization / Named Entity Recognition
    public List<NamedEntity> entities = new List<NamedEntity>();
}

抽象 NamedEntity 类:

public abstract class NamedEntity
{
    /// <summary>
    /// Abstract modelling class for NER tagging - overridden by specific named entities. Used here so that all classes inherit from a single base class - polymorphic list
    /// </summary>
    protected string _name;
    public abstract string Name { get; set; }
}

Person 类,一个覆盖抽象 NamedEntity 类的类的示例:

public class Person : NamedEntity
{
    public override string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }
    public string entityType = "Person";
}

TweetParser 类:

 public class TweetParser
    {
        // Static List to hold all of tweets (and their entities) - tweets older than 20 minutes are cleared out
        public static List<TweetModel> tweets = new List<TweetModel>();
        public TweetParser(TweetModel tweet)
        {
            ProcessTweet(tweet);
            // Removed all of NER logic from this class
        }
}

命名实体识别器的解释:

NER 识别库的工作方式是它对句子中的单词进行分类,其中包含诸如“Luis Suarez”的“PERSON”或“New York”的“PLACE”之类的标签。此信息存储在 NamedEntity 类的子类中,具体取决于 NER 库赋予单词的标签类型(选择PERSON, LOCATION, ORGANISATION

问题:

我的问题是,考虑到可能有多个版本的术语“Luis Suarez”出现(即 Luis Suarez、Luis Suárez),它们都将在各自不同的 NamedEntity 实例中定义(在实例内部List<NamedEntity>,在在TweetModel实例内部),将所有推文中“Luis Suarez”一词的匹配实例分组在一起,同时仍然保留TweetModel>List<NamedEntity>父子关系的最佳方法是什么。我被告知这实际上是一个倒排索引,但我不确定这个人有多了解情况!

结构可视化:

在此处输入图像描述

如果这个问题不清楚,我真的很抱歉;我真的无法用比这更简洁的方式表达它!到目前为止的完整 src,请参阅https://github.com/adaam2/FinalUniProject

4

2 回答 2

1

1-将List<TweetModel>属性添加到您的NamedEntity.

public abstract List<TweetModel> Tweets { get; set; }

2-保证您的标记化函数总是NamedEntity为相同的标签返回相同的对象。

3-当您将 a 添加NamedEntity到实体列表时,还将添加TweetModelNamedEntity.

Person p = this is the result of the Tokenization;
entities.Add(p);
p.Tweets.Add(this);

基本上,唯一困难的部分是让生成命名实体的函数在不同的推文上找到文本“Luis Suarez”和“Luis Suárez”时返回相同的对象。

于 2014-07-04T11:42:52.377 回答
1

如果您能够比较 Person,那么您应该能够找到一个唯一的名称来代表它们。

例如所有的 Luis Suarez, luis suarez, Suarez, L. Suárez 都翻译成“Suarez” 这由 MyHashFunctionForPerson 完成

然后使用哈希表:

Dictionary<string,List<Person>> map = new Dictionary<string,List<Person>>();

List<Person> FindMatches(Person p)
{
  string h = MyHashFunctionForPerson(p);
  if (!map.ContainsKey(h))
    map[h] = new List<person();
  map[h].add(p);
  return map[h];
}

MyHashFunction 可以是 NamedEntity 的抽象函数。您还可以检查覆盖 Equals、GethashCode 等的方向。

通常你有一张地图,每个人都有一个索引。在这种情况下,您执行反向查找,每个索引映射到一个 Person 列表。因此,“倒置”索引名称。

于 2014-07-04T10:15:57.073 回答