局部敏感哈希(LSH)相似度(杰卡德距离 计算稀疏矩阵)分析TopN

局部敏感哈希(LSH)相似度(杰卡德)分析TopN

概念

   局部敏感哈希,英文locality-sensetive hashing,常简称为LSH。局部敏感哈希在部分中文
文献中也会被称做位置敏感哈希。LSH是一种哈希算法,最早在1998年由Indyk在[1]上提出。
不同于我们在数据结构教材中对哈希算法的认识,哈希最开始是为了减少冲突方便快速增删改
查,在这里LSH恰恰相反,它利用的正式哈希冲突加速检索,并且效果极其明显。LSH主要运
用到高维海量数据的快速近似查找。近似查找便是比较数据点之间的距离或者是相似度。因
此,很明显,LSH是向量空间模型下的东西。一切数据都是以点或者说以向量的形式表现出来的

思想

   LSH的主要思想是,高维空间的两点若距离很近,那么设计一种哈希函数对这两点进行哈希
值计算,使得他们哈希值有很大的概率是一样的。同时若两点之间的距离较远,他们哈希值相
同的概率会很小。

使用场景

海量数据相似度
海量文本、页面近似检索
海量视频、音频数据近似检索

Spark ml MinHashLSH (scala代码)

  1. 读取到数据(df: DataFrame)
  2. 将数据各维度字段类型转换为double
	//将所有列转换为double类型
    val cols = df.columns.map(f => col(f).cast(DoubleType))
    var newDF = df.select(cols: _*)
  1. 将各维度转换为特征向量(类型:org.apache.spark.ml.linalg.Vector)
	val assembler = new VectorAssembler()
      .setInputCols(featuresArr)
      .setOutputCol("features")
    newDF = assembler.transform(newDF)

在这里插入图片描述

  1. 创建MinHashLSH对象,训练模型
	val mh = new MinHashLSH()
      .setNumHashTables(numHashTables) // 设置最小HashTables 
      .setInputCol("features") // 设置输入特征向量列
      .setOutputCol("hashValues") //设置转换后输出列名
    val mhModel = mh.fit(newDF) //训练模型
  1. 将数据集复制两个dataframe 对标识列重命名
	val dfA = newDF.withColumnRenamed(labelCol, "label1").cache()
    println("dfA ===========")
    dfA.show()
    val dfB = newDF.withColumnRenamed(labelCol, "label2").cache()
    println("dfB ===========")
    dfB.show()
  1. 用模型进行数据预测求两两相似度
	val predictionsDF = mhModel.approxSimilarityJoin(dfA, dfB, 1.0, "JaccardDistance")
    println("predictionsDF ===========" + predictionsDF.count())
    predictionsDF.show()
  1. 从预测结果dataframe中拿出标识列
	predictionsDF.createOrReplaceTempView("predictions")
    val pairs = sparkSession.sql("select datasetA.label1, datasetB.label2, JaccardDistance from predictions where JaccardDistance != 0").cache()
    println("pairs ===========")
    pairs.show()
  1. 对结果进行TopN截取
	val finalDF = pairs.rdd
      .map{row =>
        (row.getAs[String]("label1"),(row.getAs[String]("label2"),row.getAs[Double]("JaccardDistance")))
      }
      .groupBy(_._1)
      .map{ row=>
        val ajbh = row._1
        val top20 = row._2.toArray.sortWith(_._2._2 > _._2._2).take(topN).map{row =>
          row._2
        }
        (row._1,top20.mkString(","))
      }
      .toDF(labelCol, "TOP"+ topN)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值