文档章节

Clojure实现协同过滤原型

mahengyang
 mahengyang
发布于 2014/04/30 16:14
字数 973
阅读 231
收藏 0

本文是学习clojure的过程中写的第一个小程序,功能很简单,第一次使用clojure实现自己的想法,特此记录。 数据文件如下:

101,1
101,2
102,1
102,3
103,2
104,4
104,1
104,5

左列是item id,右列是user id 先简单的把文件读入内存,使用clojure.java.io/reader:

(use 'clojure.java.io)
;line-seq返回一个惰性序列,使用into强制把整个序列塞进vector中
(def data 
(with-open [rdr (reader "/tmp/test.txt")]
	(into [] (line-seq rdr))))
(println "data is: " data)

结果如下:

data is: [101,1 101,2 102,1 102,3 103,2 104,4 104,1 104,5]

每行是一个字符串,做为vector中的一个元素 下面考虑在读取每一行的时候进行解析:以逗号做为分隔符,切分为item和user两部分

(def data 
(with-open [rdr (reader "/tmp/test.txt")]
	(into [] (map 
			#(if % 
				(let [ [k v] (.split % ",") ] [k v])) 
			(line-seq rdr)))))
(println "原始数据:" data)

解析函数:用java.lang.split函数以逗号分隔字符串,再用let解析之,返回key、value组成的vector; 用map把解析函数做用于文件的每一行,把所有的解析结果放入vector返回。 结果如下:

原始数据:

[[101 1] [101 2] [102 1] [102 3] [103 2] [104 4] [104 1] [104 5]]

再考虑按照item做group by,形成{item => {user1,user2}}的map,以便计算item之间的相似度

(def tmp_data (group-by #(first %) data))
(println "按第一个元素group by之后:" tmp_data)

按item group by,user做为value,tmp_data如下:

按第一个元素group by之后:

 {101 [[101 1] [101 2]], 102 [[102 1] [102 3]], 103 [[103 2]], 104 [[104 4] [104 1] [104 5]]}

因为行成的map中values不是想要的结构,应该是{101 {1 2}, ... },下面把它转变为这种形式:

(def result 
    (for [ [k values] tmp_data]
        [k (into #{} (map second values))]))
(println "把values转为列表:" result)

这里用for遍历tmp_data,把其中的values中的第二个元素,也就是user id,提取出来放到集合中,输出如下:

把values转为列表:

([101 #{1 2}] [102 #{1 3}] [103 #{2}] [104 #{1 4 5}])

这就是最终想要的结果了,不过它是一个list,item和user集合组成的vector做为元素,这个不影响item-cf的计算。 上述把文件中的行转为item-user集合的方式有点麻烦,而且也不是clojure的惯用法,下面使用apply 配合merge-with得到最终结果:

(def data 
(with-open [rdr (reader "/tmp/test.txt")]
	(into [] (map 
			#(if % 
				(let [ [k v] (.split % ",")] {(Integer/parseInt k) v})) 
			(line-seq rdr)))))

这一步主要是文件中的每一行读出来并解析出item和user,与上面不同的是,把item和user先放进map中,最终再整体放入vector中(顺带把item由string转成int,方便后面的计算)

(defn to-set [set]
    (if (set? set) 
        set 
        #{set}))
;也可以使用apply转变
(def result 
    (apply merge-with 
        #(union (to-set %1) (to-set %2)) 
        data))
(println "使用apply和merge-with:" result)

这里用到了apply 函数,它的使用方法参见clojure文档; merge-with函数按key合并一组hashmap; union合并两个集合; 自定义的to-set函数检查参数是不是集合,如果不是,则把它转为集合返回;如果是,则返回原值 输出如下:

使用apply和merge-with:

{104 #{1 4 5}, 103 2, 102 #{1 3}, 101 #{1 2}}

最后计算item两两之间的相似度,先看相似度计算公式:

(defn sim [s1 s2]
    (/ 
    (count (clojure.set/intersection s1 s2)) 
    (Math/sqrt (* (count s1) (count s2)))))

clojure.set/intersection得到两个集合中共有的元素,计算相似度:

(def pair 
    (for [[k1 v1] result :when (set? v1)
          [k2 v2] result :when (and (< k1 k2) (set? v2))] 
        [k1 k2 (sim  v1 v2)]))
(println pair)

用for得到item列表的笛卡尔积(任意两个item的组合),由于101-102的计算结果与102-101的计算结果是一样的,这里为了减少重复计算,只在k1小于k2的时候计算相似度,最终结果:

([102 104 0.4082482904638631] [101 104 0.4082482904638631] [101 102 0.5])

© 著作权归作者所有

上一篇: GNU Parallel指南
下一篇: SBT管理java项目
mahengyang
粉丝 57
博文 46
码字总数 32090
作品 0
南京
程序员
私信 提问
分布式深度学习库--Deeplearning4j

Deeplearning4j(简称DL4J)是为Java和Scala编写的首个商业级开源分布式深度学习库。DL4J与Hadoop和Spark集成,为商业环境(而非研究工具目的)所设计。Skymind是DL4J的商业支持机构。 Deep...

匿名
2016/04/21
17.3K
11
Clojure:让我兴奋的编程语言

最近我一直有想写一点关于Clojure的东西的冲动。但不巧的是,还有一个更大的冲动经常出现,就是要用Clojure语言重写我的这个博客网站,这也就让这篇文章的出炉延迟了一段时间。那么,下面就让...

oschina
2014/05/22
21.1K
23
史上最全的机器学习资料(上)

摘要: 机器学习牵涉的编程语言十分之广,包括了MATLAB、Python、Clojure、Ruby等等。为了让开发者更加广泛、深入地了解机器学习,云栖社区组织翻译了GitHub Awesome Machine Learning 资源,...

NathanJoy
2016/08/30
725
0
各大平台的推荐系统原来是靠他来完成的,太牛了

1. 推荐系统概述 电子商务网站是个性化推荐系统重要地应用的领域之一,亚马逊就是个性化推荐系统的积极应用者和推广者,亚马逊的推荐系统深入到网站的各类商品,为亚马逊带来了至少30%的销售...

h8b6pk7m7r8
2017/11/30
0
0
R语言 文本分析(3) 协同过滤数据

在千里码上找到一题好玩的协同过滤。下面给各位朋友概述一下其原理以及实现 机器学习—协同过滤 什么是协同过滤 协同过滤是利用集体智慧的一个典型方法。要理解什么是协同过滤 (Collaborati...

语落心生
2017/08/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

作为一个(IT)程序员!聊天没有话题?试试这十二种技巧

首先呢?我是一名程序员,经常性和同事没话题。 因为每天都会有自己的任务要做,程序员对于其他行业来说;是相对来说比较忙的。你会经常看到程序员在发呆、调试密密麻麻代码、红色报错发呆;...

小英子wep
今天
12
0
【SpringBoot】产生背景及简介

一、SpringBoot介绍 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程,该框架使用了特定的方式来进行配置,从而使开发人员不再需要...

zw965
今天
4
0
简述并发编程分为三个核心问题:分工、同步、互斥。

总的来说,并发编程可以总结为三个核心问题:分工、同步、互斥。 所谓分工指的是如何高效地拆解任务并分配给线程,而同步指的是线程之间如何协作,互斥则是保证同一时刻只允许一个线程访问共...

dust8080
今天
6
0
OSChina 周四乱弹 —— 当你简历注水但还是找到了工作

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @花间小酌 :#今日歌曲推荐# 分享成龙的单曲《男儿当自强》。 《男儿当自强》- 成龙 手机党少年们想听歌,请使劲儿戳(这里) @hxg2016 :刚在...

小小编辑
今天
3.3K
22
靠写代码赚钱的一些门路

作者 @mezod 译者 @josephchang10 如今,通过自己的代码去赚钱变得越来越简单,不过对很多人来说依然还是很难,因为他们不知道有哪些门路。 今天给大家分享一个精彩的 GitHub 库,这个库整理...

高级农民工
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部