NLP—WordNet——词与词之间的最小距离

WordNet,是由Princeton 大学的心理学家,语言学家和计算机工程师联合设计的一种基于认知语言学的英语词典。它不是光把单词以字母顺序排列,而且按照单词的意义组成一个“单词的网络”。我们这次的任务就是求得词与词之间的最短路径,是对“图”这个数据结构再次灵活运用。

以下为SentiWordNet_3.0.0_20130122.txt文件截图:

应考虑如何存储“单词的网络”,此程序是以作为基本单元,词与词之间的联系是通过语义。

我们简单地构造类(ListofSeg存储词的语义id):

class C_word
{
    public string word;
    public List<int> ListofSeg = new List<int>();

    public C_word(string a)
    {
        ListofSeg = new List<int>();
        word = a;
    }
}

程序大约分成两部分:

第一部分,将“语义-词-词-...-词”格式转换成“词-语义-语义-...-语义”格式;

第二部分,构造单词网络,通过广度遍历寻找最小距离。

(运行程序的过程中发现第一部分耗时较长,担心调试第二部分时花费额外无用时间,故将第一部分结果生成文本第二部分通过读文本来获得信息,而不是再执行一遍第一部分:),第一次将中期结果生成文本存储,觉得要这方法不错,节省大量时间!)

PART1:

using System.Collections.Generic;
using System.Text;
using System.IO;

namespace WordNet
{
    class Program
    {
        static void Main(string[] args)
        {
            List<C_word> ListofCword = new List<C_word>();

            //读取文件
            string dicpath = @"C:\Users\Lian\Desktop\SentiWordNet_3.0.0_20130122.txt";
            StreamReader sr = new StreamReader(dicpath, Encoding.Default);

            //我们用行号作为词的语义id标识,而没有使用wordnet文本中的语义id
            int sen_count = 0;

            string line;
            //将所有的词以及它的语义编号存在ListofCword中
            while ((line = sr.ReadLine()) != null)
            {
                //选择需要的信息
                if(line[0]!=‘#‘)
                {
                    //通过制表符‘\t‘分割line
                    string[] a = line.Split(‘\t‘);
                    //将我们需要的词拿出来
                    string[] b = a[4].Split(‘ ‘);

                    if(b.Length>1)
                    {
                        //c来存储这一行中的词
                        string[] c = new string[b.Length];
                        //去掉‘#‘
                        for (int i = 0; i < b.Length; i++)
                        {
                            int tip = b[i].IndexOf(‘#‘);
                            c[i] = b[i].Substring(0, tip);
                        }

                        //将c[]的词存入ListofCword中
                        for (int j = 0; j < c.Length; j++)
                        {
                            //向ListofCword中存储第一个WORD
                            if (ListofCword.Count == 0)
                            {
                                C_word tempword = new C_word(c[j]);
                                ListofCword.Add(tempword);
                                ListofCword[0].ListofSeg.Add(sen_count);
                            }
                            else
                            {
                                //用来判断这个词是否出现在ListofCword中
                                bool e = true;
                                //遍历整个ListofCword,查找词是否出现
                                for (int i = 0; i < ListofCword.Count; i++)
                                    //若出现,则存储行号(即语义id)至这个词的ListofSeg中,并且跳出循环。
                                    if (ListofCword[i].word == c[j])
                                    {
                                        ListofCword[i].ListofSeg.Add(sen_count);
                                        e = false;
                                        break;
                                    }
                                //若这个词在整个ListofCword中没有出现,则将此词加入ListofCword中
                                if (e)
                                {
                                    C_word tempword = new C_word(c[j]);
                                    ListofCword.Add(tempword);
                                    ListofCword[ListofCword.Count - 1].ListofSeg.Add(sen_count);
                                }
                            }
                        }
                    }
                }
                //行号(语义id)++
                sen_count++;
            }

            //将ListofCword存储至文件中,方便以后使用。
            string path = @"C:\Users\Lian\Desktop\wordnet.txt";
            FileStream fs = new FileStream(path, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);
            for (int i = 0; i < ListofCword.Count; i++)
            {
                sw.Write(ListofCword[i].word);
                for (int j = 0; j < ListofCword[i].ListofSeg.Count; j++)
                    sw.Write("\t" + ListofCword[i].ListofSeg[j]);
                sw.Write("\r\n");
            }

            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();
        }
    }
}

----------------------------------------------------------------------------------

PART2:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace WordNet_Next
{
    class Program
    {
        static void Main(string[] args)
        {
            List<C_word> ListofCword = new List<C_word>();

            string path = @"C:\Users\Lian\Desktop\wordnet.txt";
            StreamReader sr = new StreamReader(path, Encoding.Default);
            String line;
            while ((line = sr.ReadLine()) != null)
            {
                string[] temp = line.Split(‘\t‘);
                C_word tempword = new C_word(temp[0]);

                for (int i = 1; i < temp.Length; i++)
                    tempword.ListofSeg.Add(int.Parse(temp[i]));

                ListofCword.Add(tempword);
            }

            string worda="dog", wordb="robot";

            //需要查询的
            List<int> ListofSearch = new List<int>();
            //已查询过的
            List<int> ListofHaved = new List<int>();
            //临时存放的
            List<int> ListofTemp = new List<int>();

            //初始化工作
            int worda_index, wordb_index;
            for (worda_index = 0; worda != ListofCword[worda_index].word; worda_index++) ;
            for (wordb_index = 0; wordb != ListofCword[wordb_index].word; wordb_index++) ;

            //把worda的语义id存入ListofSearch,ListofHaved,ListofTemp中
            for (int i = 0; i < ListofCword[worda_index].ListofSeg.Count; i++)
            {
                ListofSearch.Add(ListofCword[worda_index].ListofSeg[i]);
                ListofHaved.Add(ListofCword[worda_index].ListofSeg[i]);
                ListofTemp.Add(ListofCword[worda_index].ListofSeg[i]);
            }

            int distance = -1;
            Boolean Searched = false;

            while(true)
            {
                distance++;
                //判断wordb中是否拥有Temp列表中的语义
                for(int apple=0;apple<ListofCword[wordb_index].ListofSeg.Count;apple++)
                    for(int pear=0;pear<ListofTemp.Count;pear++)
                    {
                        if(ListofCword[wordb_index].ListofSeg[apple]==ListofTemp[pear])
                        {
                            Searched = true;
                            break;
                        }
                    }

                //若有,则退出循环,准备输出Distance
                if (Searched)
                    break;

                //清空搜索列表
                ListofSearch.Clear();
                //将需要搜索的临时列表添加入搜索列表
                for (int apple = 0; apple < ListofTemp.Count; apple++)
                    ListofSearch.Add(ListofTemp[apple]);
                //清空临时列表
                ListofTemp.Clear();

                //用来判断judge在整个ListofCword中,哪个词拥有在search的语义
                for (int apple = 0; apple < ListofCword.Count; apple++)
                {
                    //用来判断一个词是否拥有任何一个在search的语义
                    Boolean judge = false;
                    //循环一个词的全部语义
                    for (int pear = 0; pear < ListofCword[apple].ListofSeg.Count; pear++)
                    {
                        //循环要search的语义
                        for (int orange = 0; orange < ListofSearch.Count; orange++)
                            //如果匹配上了,那么就直接跳出两层循环
                            if (ListofCword[apple].ListofSeg[pear] == ListofSearch[orange])
                            {
                                judge = true;
                                break;
                            }
                        if (judge)
                            break;
                    }

                    //如果这个词拥有search的语义,那么将这个词的语义存入temp队列中(若在Haved队列中,则不存储)
                    //否则,直接判断下一个词
                    if (judge)
                    {
                        //循环一个词的全部语义
                        for (int pear = 0; pear < ListofCword[apple].ListofSeg.Count; pear++)
                        {
                            Boolean judge_temp = true;
                            //循环Haved中已有的语义
                            for (int orange = 0; orange < ListofHaved.Count; orange++)
                            {
                                //判断这个词的某一个语义是否存在于Haved队列中,若存在,则跳出一层循环,继续判断这个词的另一语义
                                if (ListofHaved[orange] == ListofCword[apple].ListofSeg[pear])
                                {
                                    judge_temp = false;
                                    break;
                                }
                            }
                            //若这个词的这个语义不存在于Haved队列中,则存入Temp队列以及Haved队列中
                            if (judge_temp)
                            {
                                ListofTemp.Add(ListofCword[apple].ListofSeg[pear]);
                                ListofHaved.Add(ListofCword[apple].ListofSeg[pear]);
                            }
                        }
                    }
                }

                if (ListofTemp.Count == 0)
                {
                    Console.WriteLine("UNREACHABLE!");
                    break;
                }
            }
            Console.WriteLine(distance);
        }
    }
}

程序本身,有很多细节可以优化,有些偷懒,没有耐心去思考如何可以更快地解决词与词之间最小距离问题。

如有建议,请尽情指点!

PS:第二部分一气呵成,没有调试一次。。。一次成功,感到惊奇,故留念一下:)

                                                                                                                                               小LiAn

                                                                                                                                         2017/4/15夜

时间: 2024-10-12 22:10:01

NLP—WordNet——词与词之间的最小距离的相关文章

Deep Learning in NLP (一)词向量和语言模型

Deep Learning in NLP (一)词向量和语言模型 这篇博客是我看了半年的论文后,自己对 Deep Learning 在 NLP 领域中应用的理解和总结,在此分享.其中必然有局限性,欢迎各种交流,随便拍. Deep Learning 算法已经在图像和音频领域取得了惊人的成果,但是在 NLP 领域中尚未见到如此激动人心的结果.关于这个原因,引一条我比较赞同的微博. @王威廉:Steve Renals算了一下icassp录取文章题目中包含deep learning的数量,发现有44篇,

Word2Vec之Deep Learning in NLP (一)词向量和语言模型

转自licstar,真心觉得不错,可惜自己有些东西没有看懂 这篇博客是我看了半年的论文后,自己对 Deep Learning 在 NLP 领域中应用的理解和总结,在此分享.其中必然有局限性,欢迎各种交流,随便拍. Deep Learning 算法已经在图像和音频领域取得了惊人的成果,但是在 NLP 领域中尚未见到如此激动人心的结果.关于这个原因,引一条我比较赞同的微博. @王威廉:Steve Renals算了一下icassp录取文章题目中包含deep learning的数量,发现有44篇,而na

NLP之分词、词向量、预训练篇

不同分词工具原理解析 对各种分词工具的介绍,具体参考: http://www.cnblogs.com/en-heng/p/6234006.html 1) jieba 具体参考: https://blog.csdn.net/rav009/article/details/12196623 jieba分词原理解析 采用的是Unigram + HMM,Unigram假设每个词相互独立 具体参考: http://www.cnblogs.com/en-heng/p/6234006.html 先总结一下jie

【NLP面试QA】词向量

目录 文本表示哪些方法? one-hot存在的问题 SoW & BoW tf-idf PMI 统计语言模型(N-gram模型) 神经网络语言模型(NNLM) word2vec word2vec 与 NNLM 的区别 CBoW Skip-gram 层次softmax 负采样 word2vec的其他细节 GloVe word2vec 和 fastText 对比有什么区别? 文本表示哪些方法? 基于one-hot.tf-idf等的bag-of-words: 基于词向量的固定表征:word2vec.fa

English-名词-冠词-形容词

名词 n.  世间万物都有一个名称,比如 苹果apple.香蕉banana.女孩girl等这类词汇就叫做名词 可数名词 1.规则可数名词的复数形式 a.一般情况下在名词的末尾加 s girl -> girls    banana -> bananas b.以s,x,ch,sh结尾的名词后加 es class -> classes    box -> boxes    watch -> watches    dish -> dishes c.以辅音字母+o结尾的有生命的名

有道词典for Mac如何在屏幕取词划词?有道词典屏幕取词划词功能使用教程

Mac电脑英文软件看不懂又不会用怎么办?我想你需要翻译软件来帮忙!试试网易有道词典 for Mac吧!最新版网易有道词典 for Mac添加了强力的屏幕取词和划词功能.但是mac版有道词典如何在屏幕取词划词呢?下面为大家带来详细的屏幕取词划词功能的使用教程!一.打开授权因为取词是系统级别功能,因此还需要给APP授权才能使用.第一步点击取词,然后选取打开系统偏好设置,授权给APP,只需要在APP前面打钩就代表已经授权了.这时候返回APP使用取词就可以使用了.如下图所示:二.屏幕取词划词接着再次在词

783. Minimum Distance Between BST Nodes BST节点之间的最小距离

Given a Binary Search Tree (BST) with the root node root, return the minimum difference between the values of any two different nodes in the tree. Example : Input: root = [4,2,6,1,3,null,null] Output: 1 Explanation: Note that root is a TreeNode objec

基于WordNet的英文同义词、近义词相似度评估及代码实现

作者:max_xbw 1.确定要解决的问题及意义 在基于代码片段的分类过程中,由于程序员对数据变量名的选取可能具有一定的规范性,在某一特定业务处理逻辑代码中,可能多个变量名之间具有关联性或相似性(如“trade”(商品交易)类中,可能存在“business”,“transaction”,“deal”等同义词),在某些情况下,它们以不同的词语表达了相同的含义.因此,为了能够对代码片段做出更加科学的类别判断,更好地识别这些同义词,我们有必要寻找一种能够解决避免由于同义词的存在而导致误分类的方法.说白

NLP︱R语言实现word2vec(词向量)经验总结(消除歧义、词向量的可加性)

R语言由于效率问题,实现自然语言处理的分析会受到一定的影响,如何提高效率以及提升词向量的精度是在当前软件环境下,比较需要解决的问题. 笔者认为还存在的问题有: 1.如何在R语言环境下,大规模语料提高运行效率? 2.如何提高词向量的精度,或者说如何衡量词向量优劣程度? 3.词向量的功能性作用还有哪些值得开发? 4.关于语义中的歧义问题如何消除? 5.词向量从"词"往"短语"的跨越? 转载请注明出处以及作者(Matt),欢迎喜欢自然语言处理一起讨论~ ---------