写给设计师的人工智能指南:如何找出相似的文章
这个系列的文章已经写了5篇了。
点击可以查看往期。
本期更新第5篇文章,
聊聊文本挖掘中的
“找出相似的文章”,
为“推荐系统”做准备。
以下为正文。
先了解下文本挖掘的一般过程。
如何让计算机读懂一段文字?
本质上要解决的是从文字中提取计算机可以理解的特征,
然后把文本特征告诉计算机,
计算机根据特征来做出相应的行为。
文本挖掘的一般过程:
1、获取文本
使用爬虫技术,获取网页上的文本;
我前阵子更新的《数据可视化与爬取》系列,可以派上用场了~
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个向量越相似。
据此,
我们就得到了"找出相似文章"的一种算法:
通过分词,找出两篇文章的关键词;
每篇文章取出所有关键词,合并成一个集合,计算每篇文章对于这个集合中的词的词频;
生成两篇文章各自的词频向量;
计算两个向量的余弦相似度,值越大就表示越相似。
下面,我们实验下从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种之间的差异。
还有,这个实验是为推荐系统做准备的~