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

这个系列的文章已经写了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种之间的差异。

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


(0)

相关推荐