查看原文
其他

写给设计师的人工智能指南:如何找出相似的文章

2017-05-14 shadow 科技Mix设计Lab

这个系列的文章已经写了5篇了。

指南:图像

指南:虚拟私人助理

指南:Tensorflow快速入门

指南:   JS框架Synaptic

 点击可以查看往期。


本期更新第5篇文章,

聊聊文本挖掘中的

“找出相似的文章”,

为“推荐系统”做准备。


以下为正文。




先了解下文本挖掘的一般过程。


如何让计算机读懂一段文字?


本质上要解决的是从文字中提取计算机可以理解的特征

然后把文本特征告诉计算机,

计算机根据特征来做出相应的行为。


文本挖掘的一般过程:


1、获取文本

使用爬虫技术,获取网页上的文本;


我前阵子更新的《数据可视化与爬取》系列,可以派上用场了~


关于知乎Live的一些数据 

微信公众号文章爬取

可视化爬虫SPY

我开发的爬虫软件SPY!

使用Echarts制作可视化图表

技能之谷歌Chrome爬虫

基于位置的用户画像初探

 

2、对文本进行预处理

主要是去掉一些标点符号、停顿词、空格等没有意义的字符串


3、分词系统

转化为特征向量,这个在人工智能里应用很广,基本输入的数据都要转化为特征向量。

 

4、利用相关算法进行挖掘

比如

利用TF*IDF算法提取关键词

从一篇或多篇文本中提取出有代表性的关键词;

机器学习算法CRFs算法,SVM和MaxEnt等用于情感分类,对文本中情感的倾向性和评价对象进行提取的过程;

文本信息分类将文本按照预设的分类体系进行自动区分;

实体识别用于从文本中发现有意义的信息,例如人名、公司名、产品名、时间、地点等;

典型意见将消费者意见进行单句级别的语义聚合,提取出有代表性的意见;

相似文本聚类,指的是机器自动对给定的文本进行话题聚类,将语义上相似的内容归为一类,有助于海量文档、资讯的整理,和话题级别的统计分析。

 

如果觉得自己开发算法太麻烦,

可以用开放平台提供的api,

这里推荐用


玻森

中文语义分析

http://bosonnlp.com/


在玻森的官网上有详细的示例,

有兴趣可以去看看。


ps:顺便打个广告,

我的第三款独立开发的app:ACE Land,

将于近期上线IOS,

其中我运用了玻森的api,

提取文章关键词,

自动生成文章摘要。


上文是一般的文本挖掘的思路,


下面我们动手用nodejs做个实验,

自己编程实现用余弦相似性,找出相似的文章


可以用于判断文章是否抄袭,

信息的是否重复。


为了简单起见,我们先从句子着手。


句子A:我喜欢看电视,不喜欢看电影。

句子B:我不喜欢看电视,也不喜欢看电影。


这里借用阮一峰的例子


那怎样才能计算上面两句话的相似程度?


如果这两句话的用词越相似,

它们的内容就应该越相似。


因此,可以从词频入手,计算它们的相似程度。


第一步,分词。

这边我使用的是nodejieba,

"结巴"中文分词的Node.js版本。


终端输入

npm install nodejieba

安装nodejieba,


安装成功后,

终端输入:

node 

var nodejieba = require("nodejieba");

var result1 = nodejieba.cut("我喜欢看电视不喜欢看电影");

var result2 = nodejieba.cut("我不喜欢看电视也不喜欢看电影");


分词结果:

[ '我', '喜欢', '看电视', '不', '喜欢', '看', '电影' ]

[ '我', '不', '喜欢', '看电视', '也', '不', '喜欢', '看', '电影' ]


第二步,列出所有的词。


终端输入:

var sum=result1.concat(result2);


Array.prototype.unique = function () {
var newArr = [];
for (var i = 0; i < this.length; i++) {
   if (newArr.indexOf(this[i]) == -1) {
newArr.push(this[i]);
 }
}
return newArr;
};

//需要写个,去除重复元素的数组方法

sum=sum.unique();


结果:

[ '我', '喜欢', '看电视', '不', '看', '电影', '也' ]


第三步,计算词频。


function tf(res,sum){

  var obj={};     for(var i=0;i<res.length;i++){     for(var j=0;j<sum.length;j++){       if(res[i]==sum[j]){         obj[sum[j]]=obj[sum[j]]+1 || 1 ;        };      };    };  var tf=[];   for(var i=0;i<sum.length;i++){     tf.push(obj[sum[i]]||0);  };    console.log(JSON.stringify(obj));    return tf;

};


console.log(tf(res1,sum));

console.log(tf(res2,sum));


结果:

{"我":1,"喜欢":2,"看电视":1,"不":1,"看":1,"电影":1}

特征向量:

句子A:[1, 2, 1, 1, 1, 1, 0]


{"我":1,"不":2,"喜欢":2,"看电视":1,"也":1,"看":1,"电影":1}

特征向量:

句子B:[1, 2, 1, 2, 1, 1, 1]


第四步,计算两个向量的余弦相似度

余弦相似度,

又称为余弦相似性。

通过计算两个向量的夹角余弦值来评估他们的相似度。

夹角越小,

余弦值越接近于1,

它们的方向更加吻合,则越相似。


2个N维向量之间的余弦值公式:


下面是js写的代码:


function VectorN(n,m) {     var sum1=0,sum2=0,sum3=0;     for(var i=0;i<n.length;i++){         sum1=sum1+n[i]*n[i];         sum2=sum2+m[i]*m[i];         sum3=n[i]*m[i]+sum3;     };     console.log(sum1,sum2,sum3); return sum3/(Math.sqrt(sum1)*Math.sqrt(sum2)); };


终端输入:

VectorN(tf(res1,sum),tf(res2,sum));

结果:

0.9245003270420487


结果越接近1,2个向量越相似。


据此,

我们就得到了"找出相似文章"的一种算法:


  1. 通过分词,找出两篇文章的关键词;

  2. 每篇文章取出所有关键词,合并成一个集合,计算每篇文章对于这个集合中的词的词频;

  3. 生成两篇文章各自的词频向量;

  4. 计算两个向量的余弦相似度,值越大就表示越相似。


下面,我们实验下从5篇文章里找出相似的文章

这5篇文章都是写微软最新的设计语言Fluent Design System的。

乍一看,都长得差不多。


第一步,

先提取文本,

去除标点及空格等无效信息。


var text=document.querySelector('#js_content').innerText.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\(|\)|\)|\-|\_|\+|\=|\||\\|\[|\[|\]|\]|\{|\}|\;|\;|\:|\:|\"|\“|\”|\'|\,|\,|\<|\.|\。|\、|\>|\/|\!|\?]|\▼|\s/g,"");



第二步,

分别对5篇文章的文本进行分词。


var res1=nodejieba.cut(text);


第三步,

计算余弦相似度


var sum=res1.concat(res2).concat(res3).concat(res4).concat(res5);

var tf=[tf(res1,sum),tf(res2,sum),tf(res3,sum),tf(res4,sum),tf(res5,sum)];


var obj={}; for(var i=0;i<tf.length;i++){     if(i+1<tf.length){         for(var j=i;j<tf.length;j++){             if(j+1<tf.length){             obj[i+'x'+(j+1)]=VectorN(tf[i],tf[j+1]);             }         }     } };

输出结果:

console.log(obj)


{ '0x1': 0.9030530508723759,

  '0x2': 0.751374830490995,

  '0x3': 0.7540626460699467,

  '0x4': 0.7120954421773579,

  '1x2': 0.9545257989404156,

  '1x3': 0.9569961672645231,

  '1x4': 0.9373082646373901,

  '2x3': 0.9980777768720895,

  '2x4': 0.9977259425453167,

  '3x4': 0.9965644471023887 }


tf2、tf3基本就是同一篇文章。




看tf0、tf4这两篇文章就行了。



最后,补充说明下,


我在实验中是把文本所有的词都作为文本特征来计算的,考虑得不够精细;


英文单词由于直接忽略了空格,所以没法很好的分词;


关于文章的发布时间,可以作为自动判断哪篇文章是原稿的依据;


文章字数,可以考虑加入作为另一个维度的判断标准


算法采用的是词频的计算,把分词结果转化为特征向量,这是人工智能机器学习算法的基础,可以为文本相关的机器学习做一个基础准备;


另外,计算文本特征向量的相似程度,也可以采用机器学习的算法哦~


在做分类时常常需要估算不同样本之间的相似性度量

Similarity Measurement

这时通常采用的方法就是计算样本间的“距离”(Distance)。

采用什么样的方法计算距离是很讲究,甚至关系到分类的正确与否。


1. 欧氏距离

2. 曼哈顿距离

3. 切比雪夫距离

4. 闵可夫斯基距离

5. 标准化欧氏距离

6. 马氏距离

7.余弦相似度

8. 汉明距离

9. 杰卡德距离 & 杰卡德相似系数

10. 相关系数 & 相关距离

11. 信息熵

本文采用了余弦相似度,回头我再研究下这11种之间的差异。


还有,这个实验是为推荐系统做准备的~




欢迎长按二维码

关注本号

本号发布内容主要为设计&科技方面


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存