- 1.1、模板方法模式
- 1.2、标签基类BasicModel
- 1.3、标签基类(优化)
- 1.3.1、第一、定义Java 中枚举 ModelType ,标签的类型
- 1.3.2、标签基类 AbstractModel
- 1.3.3、测试类(职业标签)
- 1.3.4、标签模型:政治面貌
- 1.3.4.1、新建标签
- 1.3.4.2、新建 属性(5级)标签 :1群众、2党员、3无党派人士,相关字段信息如下:
- 1.3.4.3、标签模型开发
- 1.3.5、标签模型:国籍
- 1.3.5.1、新建标签
- 1.3.5.2、新建 属性(5级)标签 :1中国大陆、2中国香港、3中国澳门、4中国台湾、5其他
- 1.3.5.3、、标签模型开发
- 二、总述:标签数据
- 2.1、标签数据
- 2.2、业务数据
- 2.3、画像标签数据
通过 用户性别标签模型和用户职业标签模型 开发,整个标签模型开发中很多类似的地方,仅仅在如何依据属性标签数据和业务数据计算标签的地方不一样,其他地方完全一样,比如从MySQL数据库读取标签数据、解析标签规则获取业务数据、合并新旧标签数据及保存,所以可以抽象出标签模型开发的基类: BasicModel ,仅仅让每个标签模型实现标签计算代码即可。
1.1、模板方法模式使用设计模式: 模板方法模式(Template Pattern) ,模板模式是一种 类继承模式 ,主要是 通过一个抽象类,把子类一些共有的方法提取出来(称为基本方法),放到抽象类中,并在抽象类中定义一个模板方法,在模板方法中规定基本方法的执行顺序。 将不同的实现细节交给子类去实现。
- 抽象类Abstract Class
- 基本方法 可以有多个,每个方法实现单独功能
- 模板方法 规定基本方法执行顺序
具体说明如下: 模式定义 : 定义一个操作算法中的框架,而将这些步骤延迟加载到子类中。 解决何种问题: 让父类控制子类方法的调用顺序 模式好处: 开发人员在开发时,只需要考虑方法的实现,不需要考虑方法在何种情况下被 调用,实现代码复用。 模式适合场景:
- 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
创建抽象类或者Trait: BasicModel ,将各个步骤公共数据读取处理抽象成方法,如下截图所示:
其中 init 和 close 为 创建SparkSession对象 和 关闭SparkSession会话 资源,其他为模型开发的四个步骤抽象方法, doTag 方法为 标签计算 的地方,需要每个标签模式自己实现,模块如下:
package com.chb.tags.models
import org.apache.spark.internal.Logging
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.apache.spark.storage.StorageLevel
/**
* @Author: chb
* @Date: 2021/4/23 8:44
* @E-Mail:
* @DESC: 标签基类,各个标签模型继承此类,实现其中打标签方法doTag即可
*/
trait BasicModel extends Logging {
// 变量声明
var spark: SparkSession = _
// 1. 初始化:构建SparkSession实例对象
def init(): Unit = {
}
// 2. 准备标签数据:依据标签ID从MySQL数据库表tbl_basic_tag获取标签数据
def getTagData(tagId: Long): DataFrame = {
null
}
// 3. 业务数据:依据业务标签规则rule,从数据源获取业务数据
def getBusinessData(tagDF: DataFrame): DataFrame = {
null
}
// 4. 构建标签:依据业务数据和属性标签数据建立标签
def doTag(businessDF: DataFrame, tagDF: DataFrame): DataFrame
// 5. 5. 保存画像标签数据至HBase表
def saveTag(modelDF: DataFrame): Unit = {
}
// 6. 关闭资源:应用结束,关闭会话实例对象
def close(): Unit = {
}
// 规定标签模型执行流程顺序
def executeModel(tagId: Long): Unit = {
// a. 初始化
init()
try {
// b. 获取标签数据
val tagDF: DataFrame = getTagData(tagId)
//basicTagDF.show()
tagDF.persist(StorageLevel.MEMORY_AND_DISK)
tagDF.count()
// c. 获取业务数据
val businessDF: DataFrame = getBusinessData(tagDF)
//businessDF.show()
// d. 计算标签
val modelDF: DataFrame = doTag(businessDF, tagDF)
//modelDF.show()
// e. 保存标签
saveTag(modelDF)
tagDF.unpersist()
} catch {
case e: Exception => e.printStackTrace()
} finally {
close()
}
}
}
1.3、标签基类(优化)
每个标签模型都有公共属性:标签名称和标签类型,所以定义抽象类 AbstractModel ,所有标签模型类继承此类,实现标签计算方法 doTag
即可。
代码如下:
/**
* 模型类型:规则匹配、统计和挖掘
*/
public enum ModelType {
MATCH, // 规则匹配
ML, // 挖掘
STATISTICS // 统计
}
1.3.2、标签基类 AbstractModel
abstract class AbstractModel (modelName: String, modelType: ModelType) extends Logging {
// ........
// 4. 构建标签:依据业务数据和属性标签数据建立标签
def doTag(businessDF: DataFrame, tagDF: DataFrame): DataFrame
}
1.3.3、测试类(职业标签)
package com.chb.tags.models.rule
import com.chb.tags.ModelType
import com.chb.tags.models.AbstractModel
import com.chb.tags.utils.TagTools
import org.apache.spark.sql.DataFrame
/**
* @Author: chb
* @Date: 2021/4/23 16:12
* @E-Mail:
* @DESC:
*/
class JobTagModel extends AbstractModel("职业标签", ModelType.MATCH) {
/*
321 职业
322 学生 1
323 公务员 2
324 军人 3
325 警察 4
326 职业是教师 5
327 白领 6
*/
/**
* 4. 构建标签:依据业务数据和属性标签数据建立标签
*
* @param businessDF
* @param tagDF
* @return
*/
override def doTag(businessDF: DataFrame, tagDF: DataFrame): DataFrame = {
// 计算标签
val modelDF: DataFrame = TagTools.ruleMatchTag(
businessDF, "job", tagDF
)
// 返回
modelDF
}
}
object JobTagModel {
def main(args: Array[String]): Unit = {
val tagModel = new JobTagModel()
tagModel.executeModel(321L, isHive = true)
}
}
1.3.4、标签模型:政治面貌
在标签管理平台新建对应的标签(业务标签和属性标签),编写标签模型类,继承标签模 型基类 BasicModel
,实现其中标签计算的方法 doTag
。
新建 业务(4级)标签 : 政治面貌 ,相关字段信息如下:
标签名称:政治面貌
标签分类:电商-某商城-人口属性
更新周期:
业务含义:注册用户的政治面貌
标签规则:
inType=hbase
zkHosts=chh1
zkPort=2181
hbaseTable=tbl_tag_users
family=detail
selectFieldNames=id,politicalface
程序入口:
com.chb.tags.models.rule.PoliticalModel
算法名称:
MATCH
算法引擎:
tags-model_2.11.jar
模型参数:
--driver-memory 512m --executor-memory 512m --num-executors 1 --executor-cores 1
1.3.4.2、新建 属性(5级)标签 :1群众、2党员、3无党派人士,相关字段信息如下:
在标签管理平台新建对应的标签(业务标签和属性标签),编写标签模型类,继承标签模型基类AbstractModel
,实现其中标签计算的方法doTag
。
新建 业务(4级)标签 : 国籍 ,相关字段信息如下:
标签名称:国籍
标签分类:电商-某商城-人口属性
更新周期:
业务含义:注册用户所属的国籍:中国大陆、中国香港、中国澳门、中国台湾、其他
标签规则:
inType=hbase
zkHosts=chb1
zkPort=2181
hbaseTable=tbl_tag_users
family=detail
selectFieldNames=id,nationality
程序入口:
com.chb.tags.models.rule.NationalityModel
算法名称:
MATCH
算法引擎:
tags-model_2.11.jar
模型参数:
--driver-memory 512m --executor-memory 512m --num-executors 1 --executor-cores 1
1.3.5.2、新建 属性(5级)标签 :1中国大陆、2中国香港、3中国澳门、4中国台湾、5其他
1.3.5.3、、标签模型开发
继承基类 AbstractModel ,实现标签计算方法 doTag
package com.chb.tags.models.rule
import com.chb.tags.ModelType
import com.chb.tags.models.AbstractModel
import com.chb.tags.utils.TagTools
import org.apache.spark.sql.DataFrame
/**
* @Author: chb
* @Date: 2021/4/23 17:21
* @E-Mail:
* @DESC:
*/
class NationalityTagModel extends AbstractModel("国籍标签", ModelType.MATCH) {
/*
332 国籍
333 中国大陆 1
334 中国香港 2
335 中国澳门 3
336 中国台湾 4
337 其他 5
*/
override def doTag(businessDF: DataFrame, tagDF: DataFrame): DataFrame
= {
// 计算标签
val modelDF: DataFrame = TagTools.ruleMatchTag(
businessDF, "nationality", tagDF
)
//modelDF.printSchema()
//modelDF.show(100, truncate = false)
// 返回
modelDF
}
}
object NationalityTagModel {
def main(args: Array[String]): Unit = {
val tagModel = new NationalityTagModel()
tagModel.executeModel(332L)
}
}
二、总述:标签数据
每个标签模型任务执行流程如下图所示:
用户画像标签系统中每个标签(业务标签,4级标签)的模型开发,涉及到 三种类型的数据 ,如下图示意
具体的数据说明:
2.1、标签数据每个标签模型开发(给每个用户或每个商品打每个标签),必须先在标签管理平台注册【新建标签】 - 业务标签(4级标签)、属性标签(5级标签) - 注册以后,每个标签(业务标签)对应的属性值(属性标签)都有对应标签标识符:tagId - 属性标签ID,标识每个标签,将会打到每个用户或商品上,标识此用户或商品的具体标签 - 每个业务标签对应一个模型,就是一个Spark Application程序 - 运行此应用程序可以给用户或商品打标签 - 在模型表中记录标签对应的模型关系,以及模型运行时参数信息
标签表数据(以【用户性别标签】为例,核心字段)如下: 模型表数据(以【用户性别标签】为例,核心字段)如下:
每个标签(业务标签,4级标签)开发,需要读取对应的业务数据,比如用户性别标签,需要读取【注册会员表】数据(获取用户ID:id和用户性别:gender),进行打标签。 本项目中主要涉及到四类业务数据,给用户和商品打标签,构建画像。
给每个用户或每个商品打上标签以后,存储到HBase表及Elasticsearch索引中,便于查询检索使用 画像标签表名称:tbl_profile, user