k pair of min jaccard distance
来源:互联网 发布:毕向东35天java教学 编辑:程序博客网 时间:2024/06/10 17:58
一个作业题,计算13万个用户的相似程度,每个用户有两个列表(L,U),分别是喜欢的电影和不喜欢的电影。找到最相似的100对用户。一共有90多亿次的计算。
jacard的计算公式:Jaccardij=(Li∩Lj)⋃(Ui∩UJ)(Li∪Lj)⋃(Ui∪UJ)
如果直接计算的话,利用set_union和set_intersection函数就可以获得。但是直接计算非常慢,下面给出几点优化的过程:
(1)使用一个Topk的堆,每次与最小的元素比较。如果超过则将最小元素出堆然后将新的元素入堆.
(2)然后我们可以利用一些技巧来进行优化:
[1] 可以发现计算的最大热点在于计算交集和并集. set_union有一个要求就是集合必须是有序的,所以我们选择开始就将所有的用户都排序好,这样后面就不用计算了。
[2] 对于交集和并集,可以写出几个不等式:a∪b≥max(a,b),a∩b≤min(a,b), 利用这两个基本的不等式就可以避免很多不必要的计算,比如说我们可以在计算jaccard之前, 先利用这两个不等式进行一个估算,如果超过Topk的最小值,就不需要计算。如果不能避免,就计算一次jaccard,然后可以将估计进一步优化,然后再比较。一共可以进行四次比较,每失败一次,都需要进行一次jaccard计算来增加估算的精度。
[3] 最后利用宏和一些类型提取,可以简化代码。
#include <fstream>#include <iostream>#include <string>#include <queue>#include <utility>#include <vector>#include <set>#include <algorithm>#include <map>#include <cstdio>#include <boost/algorithm/string/classification.hpp>#include <boost/algorithm/string/split.hpp>using namespace std;using rec_type = vector<int>;using pair_type = pair<pair<int, int>,float>;#define do(f,a,b,c) (f(a.begin(),a.end(),b.begin(),b.end(),inserter(c,c.begin())))#define check(a,b,c,d) do {if (cnt>100 && minimum>((float)(a+b)/(float)max(c,d))) return 0;}while(0)struct cmp { bool operator () (const pair_type &left, const pair_type &right) { return left.second > right.second; }};float minimum = 0;long long int cnt = 0;float jaccard(const rec_type& like_1, const rec_type& unlike_1, const rec_type& like_2, const rec_type& unlike_2);int main() { ifstream fin("result.txt"); string s; map<int, pair<rec_type, rec_type>> data; while (getline(fin, s)) { vector<string> line; boost::split(line, s, boost::is_any_of("\t"), boost::token_compress_on); vector<string> L,U; set<int> _L,_U; boost::split(L, line[1], boost::is_any_of(" "), boost::token_compress_on); if (line.size() == 3) boost::split(U, line[2], boost::is_any_of(" "), boost::token_compress_on); for(const auto &x:U) { if (x.size()!=0) _U.insert(stoi(x));} for(const auto &x:L) _L.insert(stoi(x)); data[stoi(line[0])] = pair<rec_type, rec_type> (rec_type(_L.begin(),_L.end()), rec_type(_U.begin(),_U.end())); } priority_queue<pair_type, vector<pair_type>, cmp> buf; for (auto it_1 = data.begin(); it_1 != data.end(); ++it_1) { rec_type& like_1 = it_1->second.first,unlike_1 = it_1->second.second;; for(auto it_2 = next(it_1); it_2 != data.end(); ++it_2) { rec_type& like_2 = it_2->second.first, unlike_2 = it_2->second.second; float result = jaccard(like_1, unlike_1, like_2, unlike_2); ++cnt; if (buf.size() < 100) { buf.push(make_pair(make_pair(it_1->first, it_2->first), result)); } else if (result > buf.top().second) { buf.pop(); buf.push(make_pair(make_pair(it_1->first, it_2->first), result)); minimum = buf.top().second; } if (cnt % 1000000 == 0) { cout << cnt / 1000000 << " "<<endl; } } } while (!buf.empty()) { printf("%d %d %f\n", buf.top().first.first, buf.top().first.second, buf.top().second); buf.pop(); } return 0;}float inline jaccard(const rec_type& like_1, const rec_type& unlike_1, const rec_type& like_2, const rec_type& unlike_2) { auto v1_approxiate = max(like_1.size(),like_2.size()); auto v2_approxiate = max(unlike_1.size(),unlike_2.size()); auto v3_approxiate = min(like_1.size(),like_2.size()); auto v4_approxiate = min(unlike_1.size(),unlike_2.size()); check(v3_approxiate,v4_approxiate,v1_approxiate,v2_approxiate); rec_type v3,v4; do(set_intersection,like_1,like_2,v3); do(set_intersection,unlike_1,unlike_2,v4); check(v3.size(),v4.size(),v1_approxiate,v2_approxiate); rec_type v1,v2; do(set_union,like_1,like_2,v1); do(set_union,unlike_1,unlike_2,v2); check(v3.size(),v4.size(),v1.size(),v2.size()); rec_type v6; do(set_union,v1,v2,v6); check(v3.size(),v4.size(),0.,(double)v6.size()); rec_type v5; do(set_union,v3,v4,v5); double jaccard = (double)v5.size() / (double)v6.size(); return jaccard;}
0 0
- k pair of min jaccard distance
- 719. Find K-th Smallest Pair Distance
- LeetCode Find K-th Smallest Pair Distance
- LWC 56:719. Find K-th Smallest Pair Distance
- LeetCode Weekly Contest 56 Find K-th Smallest Pair Distance
- LEETCODE: 719 Find K-th Smallest Pair Distance
- leetcode 719. Find K-th Smallest Pair Distance
- 算法第15周Find K-th Smallest Pair Distance[hard]
- Find K-th Smallest Pair Distance:查找数组元素中差值第K大的两个元素的差值
- 找最小的第k个数 k min (Selection Algorithm 与 Median of Medians Algorithm)
- Requirements of pair programming
- Requirements of pair programming
- a pair of
- a pair of
- a pair of
- a pair of
- a pair of
- a pair of
- android中service生命周期
- gstreamer中的rtpjitterbuffer代码分析:推送线程
- hibernate通过参数查询,格式化为map返回结果
- 如果win10 硬盘依然经常100%使用率 务必请安装achi驱动。
- Nginx服务的启停控制
- k pair of min jaccard distance
- Spring的EL表达式
- Ubuntu15.04安装tensorflow详细笔记
- gridview,点击选中一个或多个item,并改变item背景颜色,字体等
- 关于优化页面响应时间
- synchronized和Lock的区别
- 配置Hadoop2.0HDFS的HA以及联邦使用QJM
- java基础-继承
- 基于权因子的图像融合