【Coursera】Machine Learning Anomaly Detection and Recommender Systems 第八次编程作业

本文深入探讨了异常检测和推荐系统两大主题,详细解析了正态分布模型下的异常检测算法,以及基于协同过滤的推荐系统算法实现。文章涵盖了算法原理、常见问题及解决方案,并提供了具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

本次作业分成两部分,异常检测和推荐系统。工作量真的挺大的。

共有六个函数:Estimate Gaussian Parameters、Select Threshold、Collaborative Filtering Cost、Collaborative Filtering Gradient、Regularized Cost、Regularized Gradient。

二、分析

1、异常检测

异常检测是无监督学习中的一种,给定训练集默认都是正常样本,然后根据概率,在测试集中挑出异常样本。

其假设十分简单,假设样本的所有参数均是正态分布,且各自独立,那么,某个给定样本出现的概率应该为其个参数出现概率的积,若这个积太小,那么就说明这个样本是异常样本。

通过上面说的原理可以看出,这个检测算法十分简单,就是利用训练集中的各参数,分别建模,模型都是正态分布模型,有两个参数:\mu\sigma ^{2},前者就是求参数的平均值,后者则是求方差。注意这里的方差不是样本方差,其除数是m而不是m-1。

对于算法求出概率的阈值\varepsilon,利用交叉验证集进行选择即可。

在这期间,可能会出现以下几个问题,我们来一一说明。

首先,若是参数不符合正态分布,那该怎么办?

当然是对其进行某种运算,使得其分布近似为正态分布即可,比如说对数化或指数化等。

其次,如果某个或某几个特性的取值,对于正常样本和异常样本看起来不明显,那该怎么办?

选择几个不明显的参数,将他们相除、相乘等以设计新的参数代替他们,新的参数要有较好的区分度。这是一种方法。

另外一种就是采用多元正态分布,而不是采用当前的标准正态分布。多元正态分布的优点是可以自己找出参数间的关系,而不是默认它们是独立的。比如说,正常来讲,参数a和b的变化趋势应该是类似的,若是出现a大b小的情况,那么则是异常,然后,对于各自独立的假设,可能a和b的取值都在正常范围内,那么就无法检测出;然而,多元正态则会检测出这一点,从而认为这种概率较小。但是,多元正态分布过于复杂,计算起来较为麻烦。

最后,什么时候用异常检测,什么时候用分类算法呢?

一般来说,当正常样本很多,异常样本很少时用异常检测;如果二者数量五五开那就用分类算法。另外,如果异常样本千奇百怪,那么也优先用异常检测。如果未来出现的异常样本和目前已有的异常样本区别很大,即目前已有的异常样本无法描述全部异常样本空间,那么也优先使用异常检测。

接下来就是具体的算法实现。

estimateGaussian函数用于求出参数的\mu\sigma ^{2},其代码如下:

mu=(sum(X)/m)';
sigma2=var(X,1,1);

注意var的参数,一个是按列求解,一个是说明是方差而不是样本方差。

selectThreshold函数用于选择较好的阈值\varepsilon,代码如下:

for epsilon = min(pval):stepsize:max(pval)
    ytemp=(pval<epsilon);%异常用1表示
    tp=sum((ytemp==yval)&(ytemp==1));%说是异常,实际也是异常
    fp=sum((ytemp~=yval)&(ytemp==1));%说是异常,实际不是异常
    fn=sum((ytemp~=yval)&(ytemp==0));%说不是异常,实际是异常
    prec=tp/(tp+fp);
    rec=tp/(tp+fn);
    F1=2*prec*rec/(prec+rec);
    if F1>bestF1
        bestF1=F1;
        bestEpsilon=epsilon;
    end
end

注意,此处评价算法好坏也是利用F1值,因此,每选择一个阈值,都要计算出它对应的F1值,然后选择最大的作为阈值。这里的tp、fp、fn值很容易弄混,要仔细求解。

这样就完成了一个简单的异常检测算法。

2、推荐系统

推荐系统算法有两个方向,Content-based recommendations和Collaborative filtering。即基于内容的推荐和协同过滤。

前者的主要思想是对推荐的物品抽象出n个特性,对于推荐算法面向的用户,收集他们对于不同特性的喜好,然后拟合不同物品的特性参数。简而言之,该思想是已知“用户的好恶”,去拟合“物品的特性”。

该算法的主要难点在于收集用户的喜好,暂且不谈收集的难度,隐私的侵犯等问题,即使收集到了,也无法确定这是用户的真实喜好,毕竟很多人无法对自己的喜好进行细分的量化。

后者的主要思想是对推荐的物品抽象出n个特性,对每个特性赋值,然后拟合不同用户对于不同特性的喜好。简而言之,该思想是已知“物品的特性”,去拟合“用户的好恶”。

该算法客服了前者的缺点,毕竟,对于某个具体的物品抽象并量化参数,要比对用户进行此类操作简单得多。因为该算法的优越性,主要研究的也是它。

协同过滤算法主要分为以下几步:

①、收集用户的好恶和物品的特性这两类参数。并使用theta描述用户的好恶,使用x描述物品的特性;

②、对theta和x初始化,初始化类似神经网络权值的初始化;

③、利用已有的theta和训练集,求出x的迭代值;

④、利用x的迭代值和训练集,求出theta的迭代值;

⑤、重复③和④,直到误差收敛。

注意,theta和x的更新是分先后的,也就是theta0→x1→theta1→x2→...,实际上,也可以同时更新theta和x。
更新theta的公式如下:

更新x的公式如下:

同时更新它们俩的公式如下:

仔细看会发现,第三个公式就是前两个公式相加的和。要想更新它,就需要同时为theta和x赋初值了。

既然代价函数已经有了,下一步就是求偏导,公式如下:

 

然后利用fmincg等函数迭代求解即可。

注意,存在这样一种情况,某一用户对某一物品一无所知,他也没有打分,这时就需要利用打分矩阵R来标识这种情况。R中元素Rij为1,表示第i个用户对第j个物品有打分,为0表示没有打分。

接下来是具体实现。所有的功能都在函数cofiCostFunc中,其代码如下:

for i=1:size(R,1)%i是第几个用户,j是第几部电影,k是第几个参数,对于X_grad的每个值,等于用户对所有电影的预测误差乘以对应电影的参数的和
    idx=find(R(i,:)==1);
    Thetatemp=Theta(idx,:);
    Ytemp=Y(i,idx);
    X_grad(i,:)=((X(i,:)*Thetatemp'-Ytemp)*Thetatemp)+lambda*X(i,:);
end
for j=1:size(R,2)
    idx=find(R(:,j)==1);
    Ytemp=Y(idx,j);
    Xtemp=X(idx,:);
    Theta_grad(j,:)=((Xtemp*Theta(j,:)'-Ytemp)'*Xtemp)+lambda*(Theta(j,:));
end
Stemp=(X*Theta'-Y).^2;
J=sum(sum(R.*Stemp))/2+sum(sum(Theta.^2))*lambda/2+sum(sum(X.^2))*lambda/2;

debug这玩意花了我好久,关键就是公式看不明白。下面一一解释:

第一个循环用于计算x的偏导数。x是什么?x用于描述物品的特性。先仅考虑x的某一个值xik。xik表示第i个物品的第k个特性参数。那么在公式

中,∑下面的限制就表示,对于某个具体物品的x值的拟合,仅考虑那些对该物品打过分的人的打分。也就是R=1的用户。这些用户打分的预测值减去实际值,乘以用户对物品第k个特性的好恶参数,求和,加上正则化项,就是偏导数。

若是向量化,那就有点难理解。需要把theta和y中,对第i个物品打过分的用户的theta和y都筛出来,得到两个矩阵。然后相乘再相减。强烈推荐在写这个函数时多次利用size函数,否则很容易出现缺少转置或者维数弄错的情况。

第二个循环用于计算theta的偏导数。theta是什么?theta是用来描述用户的好恶的。同样仅考虑theta的某一个值thetajk。thetajk表示第j个用户对第k个物品特性的好恶。那么在公式

中,对于某个具体用户的theta值的拟合,要仅考虑该用户打过分的物品。也就是说R=1的物品。该用户对这些物品打分的预测值减去实际值,乘以物品的特性参数,求和,再加上正则化项,就是偏导数。

若是向量化,注意与上一个循环的区别,上一个循环筛选theta和y,这个循环筛选X和y。

实在是有点难写出来。

这一步完成后,利用fmincg迭代即可。

另外还有几个小问题,比如说,为解决某用户对于所有物品都没有打分的情况,需要将所有打分减去平均值,这被称为Mean
normalization等。

三、总结

本次作业实现了异常检测与推荐系统的简单应用。原理都不复杂,仔细理解之后,耐心一些,还是好写的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值