嘿!欢迎来到推荐系统的"厨房重地"——特征工程。如果说推荐模型是五星大厨,那特征工程就是把一堆原始食材(数据)变成大厨能用的、处理得干干净净的顶级配料(特征)的过程。配料准备得好不好,直接决定了最后这道"推荐大餐"好不好吃!
1. 什么是特征?——给机器看的"标签"
简单来说,特征就是我们从原始数据里提炼出来的、用来描述人或事物的**"标签",而且这些标签必须是机器能看懂的数字**。
想象一下,我们要向模型描述一个课程,我们不能直接说"这是一个超赞的英语课",模型听不懂。我们得把它翻译成一堆数字标签,比如:
- 学科标签=3 (假设3代表英语)
- 价格标签=2333.0
- 难度标签=2 (假设2代表中等难度)
我们主要会制作以下四种类型的"数字标签":
数值型 (Numerical): 【就是数字本身】
例子:课程价格2333.0元,总共8个课时。这种本身就是数字的,我们直接拿来用就行,顶多做个"缩放"(比如把所有价格都缩放到0-1之间,防止某个天价课程影响过大),简单直接!
类别型 (Categorical): 【给选项编号】
例子:课程的"学科"是一个选择题,选项有"数学"、"英语"、"物理"。我们不能把"英语"这两个汉字给模型,所以我们给它一个编号,比如英语=3。同理,"初一"、"初二"这些年级,也各自有一个独一无二的数字编号。
向量型 (Embedding): 【最神奇的魔法标签】
例子:系统里有100万个学生,每个学生都有一个userId。如果只给每个ID编个号,信息量太少了。所以我们施展一个魔法,给每个学生一个独特的"能力雷达图",这个雷达图由一串数字(比如[0.1, -0.4, 0.8, 0.2]
)表示,这就是Embedding向量。
这个"雷达图"能描述学生的隐藏特性,比如"数学学霸"、"文艺青年"、"拖延症晚期"等。两个学生的"雷达图"越像,说明他们品味越接近。这个神奇的雷达图是模型自己"画"出来的!我们后面会专门讲。
序列型 (Sequence): 【用户的行为日记】
例子:一个用户最近的操作记录:[点击了A课程, 观看了B视频, 购买了C课程]
。这个按时间顺序排列的"行为日记"能告诉我们用户的"心路历程",对于预测他下一步想干嘛至关重要。
2. 案例实战:把你的数据变成"数字大餐"
好了,理论讲完,我们来亲手处理一下您给的JSON数据,看看怎么把它变成模型能吃的"数字大餐"。
"食材"准备:
- 学员U: 一个叫"董云彰"的初一学生,他的userId是"fef93efd..."。
- 商品I: 一个叫"智慧空间暑假G7"的初二英语课,classCode是"GA261008Q1"。
- 场景C: 假设是在一个寂寞的周二晚上8点,系统决定为他推荐点什么。
步骤一:拿出我们的"密码本" (ID映射)
首先,我们需要一本"密码本",把所有中文和代号都翻译成数字ID。
- 年级密码本:
{"初一": 862, "初二": 863}
- 学科密码本:
{"英语": 3}
- 教师密码本:
{"T2024...": 101} (金鑫老师的代号)
- 用户密码本:
{"fef93efd...": 54321} (董云彰同学的代号)
- 班级密码本:
{"GA261008Q1": 98765} (智慧空间课程的代号)
步骤二:开工!逐个"贴标签"
来源 | 原始字段和值 | 特征名 (贴的标签) | 转化后的具体数值 | 特征类型 |
---|---|---|---|---|
学员 (U) | "studentGrade": "初一" | user_grade_id | 862 | 类别ID |
学员 (U) | "classCount": 8 | user_class_count | 8.0 | 数值 |
学员 (U) | "userId": "fef93efd..." | user_id | 54321 | 类别ID |
商品 (I) | "dfee": 2333.0 | item_price | 2333.0 | 数值 |
商品 (I) | "lessonCount": "8" | item_lesson_count | 8.0 | 数值 |
商品 (I) | "currentCount": 29 | item_popularity | 29.0 | 数值 |
商品 (I) | "gradeName": "初二" | item_grade_id | 863 | 类别ID |
商品 (I) | "subjectName": "英语" | item_subject_id | 3 | 类别ID |
商品 (I) | "teachers": [...] | teacher_id | 101 | 类别ID |
商品 (I) | "classCode": "GA261008Q1" | item_id | 98765 | 类别ID |
场景 (C) | 周二晚上8点 | context_day_of_week | 2 | 类别ID |
场景 (C) | 周二晚上8点 | context_hour | 20.0 | 数值 |
特别提醒:像"董云彰"、"134****9198"这种个人隐私,我们必须像对待烫手山芋一样,在第一步就扔掉,绝不能让模型看到!
3. 最终形态:一份给模型的"超级简历"
最后一步,我们要把上面所有零散的"数字标签"整理成一份工整的、长长的"超级简历",也就是特征向量。
最关键的是,那些ID类的标签,比如user_id: 54321,需要通过"Embedding魔法"变成我们说过的"能力雷达图"(向量)。
- user_id: 54321 --> user_embedding =
[0.1, -0.4, 0.8, 0.2]
- item_id: 98765 --> item_embedding =
[-0.5, 0.2, 0.1, -0.7]
- teacher_id: 101 --> teacher_embedding =
[0.9, 0.6, -0.3, 0.0]
现在,我们把所有数字"砖块"拼接起来!
处理流程图:
-
准备好的"砖块"
- 数值型砖块:8.0, 2333.0, ...
- 类别ID砖块:862, 3, 54321, ...
-
模型里的加工厂
- Embedding魔法:将类别ID转换为向量
- 超级拼接机:将所有特征拼接
-
最终输出
- 最终的"超级简历":一个长长的数字向量
这份"超级简历"可能长这样:
[8.0, 2333.0, 8.0, 29.0, 20.0, ..., 0.1, -0.4, 0.8, 0.2, -0.5, 0.2, 0.1, -0.7, ...]
就是这个长长的、由纯数字组成的向量,才是模型 f(U, I, C)
真正需要的输入!