LOF(局部异常因子)算法-异常点/离群点检测

为什么需要LOF

 在数据挖掘方面,经常需要在做特征工程和模型训练之前对数据进行清洗,剔除无效数据和异常数据。异常检测也是数据挖掘的一个方向,用于反作弊、伪基站、金融诈骗等领域。

 异常检测方法,针对不同的数据形式,有不同的实现方法。常用的有基于分布的方法,在上、下α分位点之外的值认为是异常值(例如图1),对于属性值常用此类方法。基于距离的方法,适用于二维或高维坐标体系内异常点的判别,例如二维平面坐标或经纬度空间坐标下异常点识别,可用此类方法。

 这次要介绍一下一种基于距离的异常检测算法,局部异常因子LOF算法(Local Outlier Factor)。

 用视觉直观的感受一下,如图2,对于 C 1 C_1 C1集合的点,整体间距,密度,分散情况较为均匀一致,可以认为是同一簇;对于 C 2 C_2 C2集合的点,同样可认为是一簇。 o 1 o_1 o1 o 2 o_2 o2点相对孤立,可以认为是异常点或离散点。现在的问题是,如何实现算法的通用性,可以满足 C 1 C_1 C1 C 2 C_2 C2这种密度分散情况迥异的集合的异常点识别。LOF可以实现我们的目标。


概念与公式

  1. d(A,B):两点间的距离

  2. k-distance: d i s t a n c e k ( o ) distance_k(o) distancek(o)----- o的第k距离(也就是距离o第k远的点的距离,不包括o)

    看图,当k=3时 d i s t a n c e k ( o ) distance_k(o) distancek(o) = d i s t a n c e ( o , p 3 ) distance(o,p_3) distance(o,p3) 并且满足:

    • 在集合C中至少有不包括o在内的k个点p∈C{p≠o},满足d{o,p}≤d{o, p 3 p_3 p3}
    • 在集合C中至少有不包括o在内的k-1个点p∈C{p≠o},满足d{o,p}<d{o, p 3 p_3 p3}
  3. k-distance neighborhood of p: N k ( o ) N_k(o) Nk(o) ----- o的第k距离邻域

    就是o的第k距离即以内的所有点,包括第k距离

    因此p的第k邻域点的个数 ∣ N k ( p ) ∣ ≥ k |N_k(p)| ≥ k Nk(p)k

  4. distance:可达距离
    d i s t a n c e k ( A , B ) = m a x { d i s t a n c e k ( B ) , d ( A , B ) } distance_{k}(A,B) = max\{distance_k(B),d(A,B)\} distancek(A,B)=max{distancek(B),d(A,B)}

    也就是,点B到点A的第k可达距离,至少是B的第k距离,或者为A、B间的真实距离。

    这也意味着,离点B最近的k个点,B到它们的可达距离被认为相等,且都等于 d i s t a n c e k ( B ) distance_k(B) distancek(B)

  5. local reachability density:局部可达密度
    点A的局部可达密度
    l r d ( A ) = 1 ∑ B ∈ N k ( A ) d i s t a n c e k ( A , B ) ∣ N k ( A ) ∣ lrd(A) = \frac{1}{\frac{\sum_{B∈N_k(A)}distance_k(A,B)}{|N_k(A)|}} lrd(A)=Nk(A)BNk(A)distancek(A,B)1

    这个值的含义可以这样理解,首先这代表一个密度,密度越高,我们认为越可能属于同一簇,密度越低,越可能是离群点

    如果p和周围邻域点是同一簇,那么可达距离越可能为较小的 d k ( o ) d_k(o) dk(o),导致可达距离之和较小,密度值较高;如果p和周围邻居点较远,那么可达距离可能都会取较大值 d(A,B),导致密度较小,越可能是离群点。

    注意:是p的邻域点 N k ( p ) N_k(p) Nk(p)到p的可达距离,不是p到 N k ( p ) N_k(p) Nk(p)的可达距离,一定要弄清楚关系

  6. local outlier factor:局部离群因子
    L O F k ( A ) = ∑ B ∈ N k ( A ) l r d ( B ) l r d ( A ) ∣ N k ( A ) ∣ = ∑ B ∈ N k ( A ) l r d ( B ) ∣ N k ( A ) ∣ l r d ( A ) LOF_k(A) = \frac{\sum_{B∈N_k(A)}\frac{lrd(B)}{lrd(A)}}{|N_k(A)|} = \frac{\frac{\sum_{B∈N_k(A)}lrd(B)}{|N_k(A)|}}{lrd(A)} LOFk(A)=Nk(A)BNk(A)lrd(A)lrd(B)=lrd(A)Nk(A)BNk(A)lrd(B)
     表示点A的邻域点 N k ( A ) N_k(A) Nk(A)的局部可达密度与点A的局部可达密度之比的平均数。又或者说是点A的邻域点 N k ( A ) N_k(A) Nk(A)的局部可达密度的平均数与点A的局部可达密度之比。

     如果这个比值越接近1,说明p的其邻域点密度差不多,A可能和邻域同属一簇;如果这个比值越小于1,说明A的密度高于其邻域点密度,A为密集点;如果这个比值越大于1,说A的密度小于其邻域点密度,A越可能是异常点。
    在这里插入图片描述
    在这个图中,圈越大,LOF越大,代表着越可能是离群点。

现在概念定义已经介绍完了,现在再回过头来看一下lof的思想,主要是通过比较每个点A和其邻域点的密度来判断该点是否为异常点,如果点A的密度越低,越可能被认定是异常点。至于密度,是通过点之间的距离来计算的,点之间距离越远,密度越低,距离越近,密度越高,完全符合我们的理解。而且,因为lof对密度的是通过点的第k邻域来计算,而不是全局计算,因此得名为“局部”异常因子,

算法

  👉 https://github.com/damjankuznar/pylof

  • 2
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: LOF局部异常因子)是一种用于异常检测的算法,它可以用来识别数据集中的离群。该算法的主要思想是通过比较每个数据与其邻居数据之间的密度来判断其异常程度。 以下是一个示例的LOF局部异常因子算法的MATLAB代码: ```matlab function lof = LOF(data, k) n = size(data, 1); % 数据的数量 % 计算每个的k距离 k_dist = zeros(n, 1); for i = 1:n distance = sqrt(sum((data - repmat(data(i, :), n, 1)).^2, 2)); k_dist(i) = sort(distance, 'ascend')(k + 1); % 对距离从小到大排序,取第k+1个值 end % 计算每个局部可达密度(LRD) lrd = zeros(n, 1); for i = 1:n neighbors = find(sqrt(sum((data - repmat(data(i, :), n, 1)).^2, 2)) <= k_dist(i)); sum_density = sum(k_dist(neighbors)); lrd(i) = length(neighbors) / sum_density; end % 计算每个LOFlof = zeros(n, 1); for i = 1:n neighbors = find(sqrt(sum((data - repmat(data(i, :), n, 1)).^2, 2)) <= k_dist(i)); lrd_ratio = sum(lrd(neighbors)) / lrd(i); lof(i) = lrd_ratio / length(neighbors); end end ``` 在这个代码中,输入参数`data`是一个n×d的矩阵,其中n是数据的数量,d是每个数据的维度。`k`是每个数据的邻居数量。 算法首先计算每个的k距离,即与该距离第k近的的距离。然后,通过计算每个的邻居数据的密度之和得到局部可达密度(LRD)。最后,通过将局部可达密度的比率与邻居数量计算得到LOF值。 该代码返回一个n×1的向量`lof`,其中每个元素是相应数据LOF值。LOF值越大,表示该数据异常。 ### 回答2: LOF局部异常因子)是一种用于检测数据集中离群算法。它通过比较每个数据局部密度与其邻居数据局部密度来计算异常因子。该算法的MATLAB代码如下: ```matlab function LOF = local_outlier_factor(data, k) [m,n] = size(data); % 获取数据集的大小 LOF = zeros(m, 1); % 初始化异常因子向量 for i=1:m % 找到数据i的k个最近邻居 neighbors = knnsearch(data, data(i,:), 'K', k+1); % 最近邻的索引(包括自身) neighbors = neighbors(2:end); % 去除自身 % 计算每个邻居的局部可达密度 lrd_i = 0; % 数据i的局部可达密度 for j=1:length(neighbors) lrd_n = local_reachability_density(data, neighbors(j), k); % 邻居的局部可达密度 lrd_i = lrd_i + lrd_n; end lrd_i = lrd_i / k; % 取平均值 % 计算数据i的局部异常因子 lof_i = 0; % 数据i的局部异常因子 for j=1:length(neighbors) lrd_n = local_reachability_density(data, neighbors(j), k); % 邻居的局部可达密度 lof_n = lrd_n / lrd_i; % 邻居的局部异常因子 lof_i = lof_i + lof_n; end lof_i = lof_i / k; % 取平均值 LOF(i) = lof_i; % 存储数据i的局部异常因子 end end function lrd = local_reachability_density(data, idx, k) [m,n] = size(data); % 获取数据集的大小 idx_neighbors = knnsearch(data, data(idx,:), 'K', k+1); % 数据idx的最近邻索引(包括自身) idx_neighbors = idx_neighbors(2:end); % 去除自身 % 计算数据idx的k个最近邻居的可达距离 reach_dist = zeros(1, k); for i=1:k dist = norm(data(idx,:) - data(idx_neighbors(i),:)); reach_dist(i) = max([dist, k_distance(data, idx_neighbors(i), k)]); end % 计算数据idx的局部可达密度 lrd = k / sum(reach_dist); end function k_dist = k_distance(data, idx, k) [m,n] = size(data); % 获取数据集的大小 dist = zeros(m, 1); % 存储数据idx与其他数据的距离 for i=1:m dist(i) = norm(data(idx,:) - data(i,:)); % 计算距离 end % 找到数据idx的第k个最近距离 k_dist = min(nth_element(dist, k+1)); end ``` 该代码首先定义了一个`local_outlier_factor`函数,该函数接受一个数据集以及`k`,计算每个数据局部异常因子,并将结果存储在`LOF`向量中。其次,定义了一个`local_reachability_density`函数和一个`k_distance`函数,分别用于计算局部可达密度和第`k`个最近距离。 使用该代码,可以传入一个数据集和`k`的值来计算每个数据局部异常因子。结果中的值越大,表示对应数据越是异常。 ### 回答3: LOF局部异常因子算法是一种用于异常检测的机器学习算法。该算法通过计算每个样本周围样本的密度来确定其异常程度。 以下是LOF算法的简化版MATLAB代码示例: ```matlab function LOF_scores = LOF(data, k) % data为输入数据,每行代表一个样本 % k为k邻近的数目 [n, m] = size(data); % n为样本数量,m为特征数目 LOF_scores = zeros(n, 1); % 初始化LOF得分数组 for i = 1:n distances = sqrt(sum((repmat(data(i,:), n, 1) - data).^2, 2)); % 计算样本与其他的欧氏距离 [sorted_dist, idx] = sort(distances); % 按距离排序 k_distances = sorted_dist(2:k+1); % 获取k个最近邻距离 k_nearest_points = data(idx(2:k+1), :); % 获取k个最近邻的样本 average_local_reachability = 0; % 平均局部可达密度 for j = 1:k distances_j = sqrt(sum((repmat(k_nearest_points(j,:), k, 1) - k_nearest_points).^2, 2)); % 计算k近邻之间的欧氏距离 reachability_distances = max([distances_j, k_distances], [], 2); % 计算k近邻的可达距离 local_reachability_density = 1 / (sum(reachability_distances) / k); % 计算局部可达密度 average_local_reachability = average_local_reachability + local_reachability_density; % 累加局部可达密度 end average_local_reachability = average_local_reachability / k; % 计算平均局部可达密度 LOF_scores(i) = average_local_reachability / (sum(k_distances) / k); % 计算LOF得分 end LOF_scores = LOF_scores / max(LOF_scores); % 标准化LOF得分 end ``` 以上代码中,首先通过计算样本之间的欧氏距离,找出每个样本的k个最近邻距离和对应的样本。然后,计算每个样本的k近邻之间的欧氏距离,并计算k近邻的可达距离。通过累加所有k近邻的可达距离,计算局部可达密度。最后,将每个样本局部可达密度除以其k个最近邻距离的平均值,得到LOF得分,即该样本异常程度。 需要注意的是,以上代码是一种简化版的LOF算法实现,可能存在一些优化和改进的空间。在实际应用中,可以根据具体的数据和需求进行相应的调整和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值