我们对同样的一些电影,书,音乐进行评分,从这些评分中能看到我们彼此之间的相似度么?说到这里你可能会想到豆瓣,我们有没有方法来模仿豆瓣计算这种相似度呢?本文是《集体智慧编程》介绍相似度算法:欧几里德距离和皮尔逊相关度系数的一次演练。
我们对同样的一些电影,书,音乐进行评分,从这些评分中能看到我们彼此之间的相似度么?说到这里你可能会想到豆瓣,我们有没有方法来模仿豆瓣计算这种相似度呢?本文是《集体智慧编程》介绍相似度算法:欧几里德距离和皮尔逊相关度系数的一次演练。
本文将介绍.
距离是在传统统计学和数据挖掘中衡量接近程度的关键度量。我们如何衡量接近程度或距离呢?在详细介绍不同距离度量方式前,让我们先描述一个便于讨论的问题场景。
故事是这样的:一些人对同样的一些电影做出了评价,我们将在这个基础上进行分析.我们按照IMDB的评分规则,10分为电影的最高评分.首先我们将能够描述这一事实的数据构造出来放入数据库中.我们需要下列的表:
o Moive表 电影信息表
o UserInfo表 用户表(这些人将对电影给出评分)
o Moive_Level表
使用下面的SQL语句就可以完成上面数据表的建表工作.
CREATE TABLES
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Moive]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Moive]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Moive_Level]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Moive_Level]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[UserInfo]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[UserInfo]
GO
CREATE TABLE [dbo].[Moive] (
[Name] [char] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Director] [char] (30) COLLATE Chinese_PRC_CI_AS NULL ,
[Actor] [nvarchar] (200) COLLATE Chinese_PRC_CI_AS NULL ,
[Year] [int] NULL ,
[Region] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
[id] [bigint] IDENTITY (1, 1) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Moive_Level] (
[UserID] [char] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[MoiveID] [char] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Level] [float] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[UserInfo] (
[UserID] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[Age] [int] NULL ,
[ID] [bigint] IDENTITY (1, 1) NOT NULL
) ON [PRIMARY]
GO
首先是Moive电影表,我从一些电影网站中抽取了1330条电影信息,覆盖了爱情电影,动作电影,科幻电影等各种类型的电影.实际上我们坐算法演示的时候只用到其中的10条数据.如下图,这10条数据是比较有代表性的,从类型和发行时间上都有特点..
下列用户将对上面的十部电影进行评价:
用户对电影的评价是如下结构(下图试数据片段):
一个简单常用的距离度量是欧几里德距离。它以人们都评价过的电影为坐标轴,然后将参与评价的人绘制在图上,并考察它们的距离远近,换句话说这幅图就是描述了处于偏好空间中的人们.第一种算法考察方法是:
欧几里德距离
欧几里得度量定义欧几里得空间中点 x = (x1,...,xn) 和 y = (y1,...,yn) 之间的距离为
为了方便将这个算法应用到数据库上,我们创建一个存储过程EuclideanDistance:
EuclideanDistance
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
GO
CREATE PROCEDURE [dbo].[EuclideanDistance]
@UserIDA int,
@UserIDB int
AS
select @UserIDA UserA,@UserIDB UserB,sqrt(sum(result)) Distance
From
(
select m1.*,power(m1.level-m2.level,2) result From moive_level m1,moive_level m2
where m1.userid=@UserIDA and m2.userid=@UserIDB and m1.moiveid=m2.moiveid
)T
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
Code
下面我们计算一下用户Zen和Lily的距离,执行存储过程代码如下:
DECLARE @RC int
DECLARE @UserIDA int
DECLARE @UserIDB int
-- Set parameter values
EXEC @RC = [U-M].[dbo].[EuclideanDistance] 1, 2
我们多看几组距离:
DECLARE @RC int
DECLARE @UserIDA int
DECLARE @UserIDB int
-- Set parameter values
EXEC @RC = [U-M].[dbo].[EuclideanDistance] 1, 2
EXEC @RC = [U-M].[dbo].[EuclideanDistance] 1, 3
EXEC @RC = [U-M].[dbo].[EuclideanDistance] 1, 4
EXEC @RC = [U-M].[dbo].[EuclideanDistance] 1, 5
EXEC @RC = [U-M].[dbo].[EuclideanDistance] 2, 5
执行结果截图如下:
但是当评价结果中,评价者的评价相对于平均水平偏离很大的时候欧几里德距离不能很好的揭示出真实的相似度.还有一种评价方法就是使用皮尔逊相关系数,它可以完成"夸大值纠偏":
皮尔逊相关度系数
两个变量之间的相关系数越高,从一个变量去预测另一个变量的精确度就越高,这是因为相关系数越高,就意味着这两个变量的共变部分越多,所以从其中一个变量的变化就可越多地获知另一个变量的变化。如果两个变量之间的相关系数为1或-1,那么你完全可由变量X去获知变量Y的值。
· 当相关系数为0时,X和Y两变量无关系。
· 当X的值增大,Y也增大,正相关关系,相关系数在0.00与1.00之间
· 当X的值减小,Y也减小,正相关关系,相关系数在0.00与1.00之间
· 当X的值增大,Y减小,负相关关系,相关系数在-1.00与0.00之间
当X的值减小,Y增大,负相关关系,相关系数在-1.00与0.00之间
相关系数的绝对值越大,相关性越强,相关系数越接近于1和-1,相关度越强,相关系数越接近于0,相关度越弱。
PerasonRxy
下面就是把这个算法用在我们的数据上了,我们创建一个存储过程PerasonRxy:
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
GO
CREATE PROCEDURE [dbo].[PerasonRxy]
@userida int,@useridb int
AS
select sum(L1) SumA,sum(L2) SumB,sum(power(L1,2)) SumA2,
sum(power(L2,2)) SumB2,sum(result) Sum_Sqrt,
sum([Cross]) Sum_Corss ,(sum([Cross])-sum(L1)*sum(L2)/10) ,
sqrt((sum(power(L1,2))-power(sum(L1),2)/10)*(sum(power(L2,2))-power(sum(L2),2)/10)),
sum([Cross]) Sum_Corss ,(sum([Cross])-sum(L1)*sum(L2)/10) /sqrt((sum(power(L1,2))-power(sum(L1),2)/10)*(sum(power(L2,2))-power(sum(L2),2)/10))
From
(
select m1.level L1,m2.level L2,power(m1.level-m2.level,2) result,m1.level*m2.level [Cross] From moive_level m1,moive_level m2
where m1.userid=@userida and m2.userid=@useridb and m1.moiveid=m2.moiveid
)T
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
通常情况下:
相关系数0.8-1.0为极强相关
0.6-0.8为强相关
0.4-0.6为中等程度相关
0.2-0.4为弱相关
0.0-0.2为极弱相关或无相关
我们可以看出哪些用户之间的距离比较接近了... ...