这个系列的文章已经写了5篇了。 点击可以查看往期。 本期更新第5篇文章, 聊聊文本挖掘中的 “找出相似的文章”, 为“推荐系统”做准备。 以下为正文。 先了解下文本挖掘的一般过程。 如何让计算机读懂一段文字? 本质上要解决的是从文字中提取计算机可以理解的特征, 然后把文本特征告诉计算机, 计算机根据特征来做出相应的行为。 文本挖掘的一般过程: 1、获取文本 使用爬虫技术,获取网页上的文本; 我前阵子更新的《数据可视化与爬取》系列,可以派上用场了~ 2、对文本进行预处理 主要是去掉一些标点符号、停顿词、空格等没有意义的字符串。 3、分词系统 转化为特征向量,这个在人工智能里应用很广,基本输入的数据都要转化为特征向量。 4、利用相关算法进行挖掘 比如 利用TF*IDF算法提取关键词, 从一篇或多篇文本中提取出有代表性的关键词; 机器学习算法CRFs算法,SVM和MaxEnt等用于情感分类,对文本中情感的倾向性和评价对象进行提取的过程; 文本信息分类,将文本按照预设的分类体系进行自动区分; 实体识别,用于从文本中发现有意义的信息,例如人名、公司名、产品名、时间、地点等; 典型意见,将消费者意见进行单句级别的语义聚合,提取出有代表性的意见; 相似文本聚类,指的是机器自动对给定的文本进行话题聚类,将语义上相似的内容归为一类,有助于海量文档、资讯的整理,和话题级别的统计分析。 如果觉得自己开发算法太麻烦, 可以用开放平台提供的api, 这里推荐用 玻森 中文语义分析 http:/// 在玻森的官网上有详细的示例, 有兴趣可以去看看。 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种之间的差异。 还有,这个实验是为推荐系统做准备的~ |
|
来自: Mixlab交叉学科 > 《待分类》