美文网首页大数据分析
用户画像 - 挖掘标签

用户画像 - 挖掘标签

作者: 架构师老狼 | 来源:发表于2021-06-19 19:19 被阅读0次

    RFM 用户价值模型

    1 需求

    用户画像
    • 假设我是一个市场营销者, 在做一次活动之前, 我可能会思考如下问题
    • 谁是我比较有价值的客户?
    • 谁是比较有潜力成为有价值的客户?
    • 谁快要流失了?
    • 谁能够留下来?
    • 谁会关心这次活动?
    • 其实上面这些思考, 都围绕一个主题 价值
    • RFM 是一个最常见的用来评估价值的和潜在价值的工具

    2 RFM 是什么RFM

    • 通过最后一次消费距今时间, 单位时间内的消费频率, 平均消费金额来评估一个人对公司的价值, 可以理解为 RFM 是一个集成的值, 如下RFM = Rencency(最后一次消费时间), Frequency(消费频率), Monetary(消费金额)
    • RFM 模型可以说明如下事实:
    • 最近一次购买时间越近, 用户对促销越有感
    • 购买频率越高, 对我们满意度就越高
    • 消费金额越大, 越有钱, 越是高消费人群
      RFM模型
      3 RFM的实际应用
      RFM实际应用

    4 高维空间模型

    高维空间模型
    5 通过打分统一量纲
    • R: 1-3天=5分,4-6天=4分,7-9天=3分,10-15天=2分,大于16天=1分
    • F: ≥200=5分,150-199=4分,100-149=3分,50-99=2分,1-49=1分
    • M: ≥20w=5分,10-19w=4分,5-9w=3分,1-4w=2分,<1w=1分
    val rScore: Column = when('r.>=(1).and('r.<=(3)), 5)
      .when('r >= 4 and 'r <= 6, 4)
      .when('r >= 7 and 'r <= 9, 3)
      .when('r >= 10 and 'r <= 15, 2)
      .when('r >= 16, 1)
      .as("r_score")
    
    val fScore: Column = when('f >= 200, 5)
      .when(('f >= 150) && ('f <= 199), 4)
      .when((col("f") >= 100) && (col("f") <= 149), 3)
      .when((col("f") >= 50) && (col("f") <= 99), 2)
      .when((col("f") >= 1) && (col("f") <= 49), 1)
      .as("f_score")
    
    val mScore: Column = when(col("m") >= 200000, 5)
      .when(col("m").between(100000, 199999), 4)
      .when(col("m").between(50000, 99999), 3)
      .when(col("m").between(10000, 49999), 2)
      .when(col("m") <= 9999, 1)
      .as("m_score")
    

    6 模型训练与预测

    • RFMTrainModel 训练模型, 保存模型到 HDFS 中, 调度周期, 一个月执行一次
    • RFMPredictModel 预测模型, 从 HDFS 中读取聚类模型, 对整个数据集进行预测, 每天一次
     def process(source: DataFrame): DataFrame = {
      val assembled = assembleDataFrame(source)
         val regressor = new KMeans()
         .setK(7)
         .setSeed(10)
         .setMaxIter(10)
         .setFeaturesCol("features")
         .setPredictionCol("predict")
    
       regressor.fit(assembled).save(MODEL_PATH)
    
      null
    }
    val assembled = RFMModel.assembleDataFrame(source)
    
    val kmeans = KMeansModel.load(RFMModel.MODEL_PATH)
    val predicted = kmeans.transform(assembled)
    
    // 找到 kmeans 生成的组号和 rule 之间的关系
    val sortedCenters: IndexedSeq[(Int, Double)] = kmeans.clusterCenters.indices // IndexedSeq
      .map(i => (i, kmeans.clusterCenters(i).toArray.sum))
      .sortBy(c => c._2).reverse
    
    val sortedDF = sortedCenters.toDF("index", "totalScore")
    

    RFE 活跃度

    • 类似 RFM, 我们使用 RFE 计算用户的活跃度
    • RFE = R (最近一次访问时间) + F (特定时间内访问频率) + E (活动数量)
    • R = datediff(date_sub(current_timestamp(),60), max('log_time))
    • F = count('loc_url)
    • E = countDistinct('loc_url)
    • R:0-15天=5分,16-30天=4分,31-45天=3分,46-60天=2分,大于61天=1分
    • F:≥400=5分,300-399=4分,200-299=3分,100-199=2分,≤99=1分
    • E:≥250=5分,230-249=4分,210-229=3分,200-209=2分,1=1分

    PSM 价格敏感度模型

    • PSM 用于统计用户的价格敏感度
    • 对于不同级别价格敏感的用户可以实行不同程度的营销

    1 PSM计算公式

    • PSM Score = 优惠订单占比 + (平均优惠金额 / 平均每单应收) + 优惠金额占比
    • 优惠订单占比
    • 优惠订单 / 总单数
    • 优惠订单 = 优惠的订单数量 / 总单数
    • 未优惠订单 = 未优惠的订单数量 / 总单数
    • 平均优惠金额
    • 总优惠金额 / 优惠单数
    • 平均每单应收
    • 总应收 / 总单数
    • 优惠金额占比
    • 总优惠金额 / 总应收金额
    // 应收金额
    val receivableAmount = ('couponCodeValue + 'orderAmount).cast(DoubleType) as "receivableAmount"
    // 优惠金额
    val discountAmount = 'couponCodeValue.cast(DoubleType) as "discountAmount"
    // 实收金额
    val practicalAmount = 'orderAmount.cast(DoubleType) as "practicalAmount"
    // 是否优惠
    val state = when(discountAmount =!= 0.0d, 1) // =!=是column的方法
      .when(discountAmount === 0.0d, 0)
      .as("state")
    
    // 优惠订单数
    val discountCount = sum('state) as "discountCount"
    // 订单总数
    val totalCount = count('state) as "totalCount"
    // 优惠总额
    val totalDiscountAmount = sum('discountAmount) as "totalDiscountAmount"
    // 应收总额
    val totalReceivableAmount = sum('receivableAmount) as "totalReceivableAmount"
    
    // 平均优惠金额
    val avgDiscountAmount = ('totalDiscountAmount / 'discountCount) as "avgDiscountAmount"
    // 平均每单应收
    val avgReceivableAmount = ('totalReceivableAmount / 'totalCount) as "avgReceivableAmount"
    // 优惠订单占比
    val discountPercent = ('discountCount / 'totalCount) as "discountPercent"
    // 平均优惠金额占比
    val avgDiscountPercent = (avgDiscountAmount / avgReceivableAmount) as "avgDiscountPercent"
    // 优惠金额占比
    val discountAmountPercent = ('totalDiscountAmount / 'totalReceivableAmount) as "discountAmountPercent"
    
    // 优惠订单占比 + (平均优惠金额 / 平均每单应收) + 优惠金额占比
    val psmScore = (discountPercent + (avgDiscountPercent / avgReceivableAmount) + discountAmountPercent) as "psm"
    

    2 聚类算法原理

    • 选择 K 个点作为初始中点
    • 计算每个中点到相近点的距离, 将相近的点聚在一类(簇)
    • 欧式距离
    • 重新计算每个簇的中点
    • 重复迭代上面步骤, 直至不再发生变化


      聚类算法原理

    3 确定K - 肘部法则

    • 根据损失函数, 计算每一个 K 的情况下, 总体上的损失
    • 绘制图形, 找到拐点, 就是合适的 K


      肘部法则

    4 模型训练与迭代计算

    val kArray = Array(2, 3, 4, 5, 6, 7, 8)
    val wssseMap = kArray.map(f = k => {
      val kmeans = new KMeans()
        .setK(k)
        .setMaxIter(10)
        .setPredictionCol("prediction")
        .setFeaturesCol("features")
      val model: KMeansModel = kmeans.fit(vectored)
    
      import spark.implicits._
      // mlLib计算损失函数
      val vestors: Array[OldVector] = model.clusterCenters.map(v => OldVectors.fromML(v))
      val libModel: LibKMeansModel = new LibKMeansModel(vestors)
      val features = vectored.rdd.map(row => {
        val ve = row.getAs[Vector]("features")
        val oldVe: OldVector = OldVectors.fromML(ve)
        oldVe
      })
    
      val wssse: Double = libModel.computeCost(features)
      (k, wssse)
    }).toMap
    

    分类模型-预测性别

    • 购物性别模型的意义有两种:
    • 通过用户购物的行为, 预测用户性别
    • 通过用户购物的行为, 判定用户的购物性别偏好

    1 预置标签,量化属性

    |memberId| color|productType|gender|colorIndex|  color|    productType|gender|productTypeIndex|   features|featuresIndex|
    +--------+------+-----------+------+----------+------------------+---------------+------+----------------+-----------+-------------+
    |       4|樱花粉|   智能电视|     1|      14.0|樱花粉|       智能电视|     1|            13.0|[14.0,13.0]|  [14.0,13.0]|
    |       4|樱花粉|   智能电视|     1|      14.0|  蓝色| Haier/海尔冰箱|     0|             1.0| [14.0,1.0]|   [14.0,1.0]|
    val label = when('ogColor.equalTo("樱花粉")
      .or('ogColor.equalTo("白色"))
      .or('ogColor.equalTo("香槟色"))
      .or('ogColor.equalTo("香槟金"))
      .or('productType.equalTo("料理机"))
      .or('productType.equalTo("挂烫机"))
      .or('productType.equalTo("吸尘器/除螨仪")), 1)
      .otherwise(0)
      .alias("gender")
    

    2 决策树算法

    • 决策树是一个监督学习算法, 需要先对数据集人工打上标签, 此处简化整体流程, 通过简单的匹配, 先预置所需要的标签


      决策树算法模型

    3 算法工程与模型评估

    val featureVectorIndexer = new VectorIndexer()
      .setInputCol("features")
      .setOutputCol("featuresIndex")
      .setMaxCategories(3)
    
    val decisionTreeClassifier = new DecisionTreeClassifier()
      .setFeaturesCol("featuresIndex")
      .setLabelCol("gender")
      .setPredictionCol("predict")
      .setMaxDepth(5)
      .setImpurity("gini")
    
    val pipeline = new Pipeline()
      .setStages(Array(colorIndexer, productTypeIndexer, featureAssembler, featureVectorIndexer, decisionTreeClassifier))
    
    val Array(trainData, testData) = source.randomSplit(Array(0.8, 0.2))
    
    val model: PipelineModel = pipeline.fit(trainData)
     val pTrain = model.transform(trainData)
     val tTrain = model.transform(testData)
    
    val accEvaluator = new MulticlassClassificationEvaluator()
      .setPredictionCol("predict")
      .setLabelCol("gender")
      .setMetricName("accuracy")//精准度
    

    相关文章

      网友评论

        本文标题:用户画像 - 挖掘标签

        本文链接:https://www.haomeiwen.com/subject/iysdyltx.html