在上一篇文章我们提到,原始数据集数量很大,导致计算量也特别大,尤其是像(用用户评价过的商店)计算用户相似度,所以我们这里选择了一个用户商店数量最多的城市 Las Vegas 作为分析的对象。该城市涵盖的数据量如下:
关于 Las Vegas 城市数据集过滤过程已经详细记录在 Notebook Filter_Resources_with_City_Las_Vegas 上,请参考。
business 数据集处理
Notebook:Preprocess_Business
business 数据集处理主要分为以下 3 个部分
:
- checkin 数据合并到 business 数据集中
- 对 business 中的 review(评论)数量(review_count)及 checkin(签到)数量(checkin_count)进行归一化
- 根据归一化后的 review_count 及 checkin_count 计算 business 流行度(popularity)
下边针对后两点进行说明。
归一化
这里要对 business 的 review_count 和 checkin_count 进行归一化的原因是后续计算流行度的时候要结合这两者,但这两者统计的角度不一样,所以我们需要将他们各自归一化之后再进行。
具体我们使用的是 sklearn 库中 preprocessing 模块的 MinMaxScaler 进行处理,其归一化公式如下:
流行度计算
对于流行度,我们在 review_count 及 checkin_count 基础上构造一个新的指标 popularity。那 popularity 怎么计算呢?这里考虑到 review(评论)有好有坏,不能认为其数量越高,客户对某一个 business(商店)的满意度就越高;但 checkin(签到)就不一样了,可以认为签到数越多,客户对某一个 business 的满意度越高
,所以,我们在计算流行度的时候简单认为 checkin 的重要性是 review_count 的 2 倍,也即:
$$
popularity = review\_count\_scaled + 2 * checkin\_count\_scaled
$$
review 数据集处理
stars 处理
Notebook:Preprocess_Review_Stars
review 数据集中的每个 review 都有一个时间戳,如下图所示:
但有一个很明显的事实,review 时间戳越靠后(离现在近),它的重要性(参考价值)越大
。例如,去年的评论比前年的参考价值大,比大前年的就更大;而且离现在越近的,参考价值递减程度缓慢,一旦超过某个限度,价值会呈直线式下降;但到达一定极限后,参考价值基本就不变了(没有价值)。
在这里我们选择了一个比较符合我们需求的函数 Sigmoid 作为我们的时间过滤函数,并选定了 2012 年作为该函数中心点,如下图所示:
只要将每个 review 的 stars 乘以该图相应的函数值就可以得到新的 stars 值,详细过程可参考 Notebook Preprocess_Review_Stars。
文本处理
Notebook:Preprocess_Review_Text
为了便于接下来对 review 文本进行分析(如情感分析),我们需要对其进行处理,便于后续使用。处理步骤主要包括分词(Tokenization)、移除停用词(Stop Words)、词形还原(Lemmatization)。这些步骤没有特别需要说明的,具体处理过程可以参考 Notebook Preprocess_Review_Text。
用户相似度计算
Notebook:Calc_User2User_Similarities
用户之间的相似度是通过计算他们之间共同评价过的商店的 stars 值来计算的,计算公式如下:
$$
similarity(A,B)=\frac{A\cdot B}{\left || A \right ||\left || B \right ||} =\frac{\sum_{n}^{i}A_{i}\times B_{i}}{\sqrt{\sum_{n}^{i}A_{i}^{2}}\times \sqrt{\sum_{n}^{i}B_{i}^{2}}}
$$
如用户 A 和 B 共同评价过 Business1、Business2、Business3,而且他们对这三个 business 给出的 stars 分别为 $ \overrightarrow{A}=< 5, 3, 3 > $, $ \overrightarrow{B}=< 4, 2, 3 > $,那他们之间的相似度为:
但这里我们有三个细节需要注意的:
只要用户 A 和 B 只共同评价过一个 business,那他们的相似度就为 1,这显然是不大合常理的,所以这种情况要剔除掉。
当用户 A 和 B 共同评价过某些 business,即使他们给的 stars 都很低,他们之间的相似度可能也会比较高,如 $ \overrightarrow{A}=< 1, 1 > $, $ \overrightarrow{B}=< 1, 1 > $,此时计算出来 A、B 的相似度为 1,这也是不合常理的。
既然用户都不喜欢某一家 business,那他们的相似度不应该高;相似度高的应该是对某些 business 都给过比较高评价的用户。所以在计算用户相似度时,会剔除掉 stars 值低于 3 的评论。
用户 A 和 B 对同一家 business 都给出比较高的评价,但是 A 和 B 对该 business 评价的时间差较大,如 A 在 5 年前给该 business 评了 5 分,B 在今年对它评价了 5 分,直接计算可能会得到较高的相似度。这样得出来的结果也是不大合常理的,因为
时间相隔太久,用户的兴趣可能已经千变万化,所以在计算相似度时还要乘上一个时间衰减函数
,如我们可以定义该函数为:
$$
f(\delta) = \frac {1}{1 + \alpha * \delta}
$$
其中,$\delta$ 表示两个 review 之间时间差;$\alpha$ 表示衰减系数,值越大衰减的越厉害。当 $\alpha = 1$时,可画出其图形为:
综上,可以得到最终的用户相似度公式为:
$$
similarity(A,B)=\frac{A\cdot B \cdot F(\delta)}{\left || A \right ||\left || B \right ||} =\frac{\sum_{n}^{i}A_{i}\times B_{i} \times f(\delta_{i})}{\sqrt{\sum_{n}^{i}A_{i}^{2}}\times \sqrt{\sum_{n}^{i}B_{i}^{2}}}
$$
详细操作过程可以参考 Notebook Calc_User2User_Similarities。