数据挖掘_unit25

1. 离群点的基本概念

1.1 离群点的概念

  • 在样本空间中,与其他样本点的一般行为或特征不一致的点,我们称为离群点。

1.2 离群点的来源

  • 数据来源不同,如欺诈、入侵、不寻常的实验结果等
  • 数据变量变化引起,如顾客的新的购买模式、基因突变等
  • 数据测量和收集误差

离群点检测的难点

  • 在时间序列样本中发现离群点一般比较困难,因为这些离群点可能会隐藏在趋势、季节性或者其他变化中。
  • 对于维度为非数值型的样本,在检测过程中需要多加考虑、比如对维度进行预处理等。

离群点检测的主要应用领域

离群点分析 数据挖掘 数据挖掘离群点怎么算_聚类

2. 常见的离群点检测方法

2.1 基于统计的离群点检测

离群点的概率定义:离群点是一个对象,关于数据的概率分布模型,离群点具有低概率值。

2.2 基于统计的离群点检测的思路**

  • 设定数据集的分布模型
  • 假设检验验证
  • 发现离群点

2.3 基于统计的离群点检测的实例

  • 例如我们设儿童上学的具体年龄总统服从正态分布,所给的数据集是某地区随机选取的开始上学的20名儿童具体的年龄特征如下:
  • 年龄={6,7,6,8,9,10,8,11,7,9,12,7,11,8,13,7,8,14,9,12}
  • 那么相应的统计参数是:均值=9.1;标准差=2.3
  • 如果选择数据分布的阈值为:阈值=均值±2×标准差
  • 故在[4.5,13.7]区间意外的数据都是潜在的离群点。
  • 将最大值取整为13。所以年龄为14的孩子可能是个例外。而且由均值可知,此地的孩子可能普遍上学较晚。

2.4 基于临近度的检测方法**

  • 通常可以在数据对象之间定义临近性度量,把远离大部分点的对象视为离群点。

2.5 于密度的检测方法**

  • 从基于密度的观点分析,离群点是在低密度区域中的对象。

2.6 基于聚类的检测方法

  • 聚类分析用于发现局部强相关的对象组,而异常检测用来发现不与其他对象强相关的对象。因此,聚类分析非常自然的可以用于利群点检测。
  1. 丢弃远离其他簇的小簇
  2. 基于原型的聚类
    另一种更系统的方法,首先聚类所有对象,然后评估对象属于簇的程度(离群点得分)。在这种方法中,可以用对象到它的簇中心的距离来度量属于簇的程度

2.7 常用离群点检测方法的特点

  • 基于统计模型的离群点检测方法的前提是必须知道数据集服从什么分布;对于高维数据,检验效果可能很差;
  • 基于临近度的检测方法简单,二维或三维的数据可以做散点图观察;大数据集不适用 ;
  • 给出了对象是离群点的定量度量,并且使数据具有不同的区域也能够很好处理;
  • 基于聚类技术来发现离群点可能是高度有效的。

3. 基于距离的检测方法实现

3.1 基于聚类的离群点算法的步骤

  • 1、选择聚类算法进行聚类,找到各簇质心;
  • 2、计算个对象到最近质心的距离;
  • 3、计算各对象到它的最近质心的相对距离;
  • 4、与给定的阈值作比较,选出离群点。

3.2 资源

资源库

numpy  
scikit-learn=0.22.1  
xlrd=1.2.0  
numpy=1.18.0
pandas=0.24.2

数据集
用户交易行为数据

  • R(Recency)——最近一次交易时间间隔。基于最近一次交易日期计算的得分,距离当前日期越近,得分越高。如5分制。反映客户交易活跃度。
  • F(Frequency)——客户在最近一段时间内交易次数。基于交易频率计算的得分,交易频率越高,得分越高。如5分制。反映客户交易活跃度。
  • M(Monetray)——客户最近一段时间内交易金额。基于交易金额计算的得分,交易金额越高,得分越高。如5分制。反映客户价值。
    consumption_data.xls: 交易记录数据

3.3 完整代码

# -*- coding: utf-8 -*-
# 使用K-Means算法聚类消费行为特征数据

import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

k = 3  # 聚类的类别
threshold = 2  # 离散点阈值
iteration = 500  # 聚类最大循环次数


# 数据处理
def get_data(data):
    data_zs = 1.0 * (data - data.mean()) / data.std()  # 数据标准化
    return data_zs


# k-means聚类
def k_means(data_zs):
    model = KMeans(n_clusters=k, n_jobs=4, max_iter=iteration)  # 分为k类,并发数4
    model.fit(data_zs)  # 开始聚类
    return model


def standard(data_zs, model, data):
    # 标准化数据及其类别
    r = pd.concat([data_zs, pd.Series(model.labels_, index=data.index)], axis=1)  # 每个样本对应的类别
    r.columns = list(data.columns) + [u'聚类类别']  # 重命名表头

    norm = []
    for i in range(k):  # 逐一处理
        norm_tmp = r[['R', 'F', 'M']][r[u'聚类类别'] == i] - model.cluster_centers_[i]
        norm_tmp = norm_tmp.apply(np.linalg.norm, axis=1)  # 求出绝对距离
        norm.append(norm_tmp / norm_tmp.median())  # 求相对距离并添加

    norm = pd.concat(norm)  # 合并
    return norm


def mat_plot(norm):
    norm[norm <= threshold].plot(style='go')  # 正常点
    discrete_points = norm[norm > threshold]  # 离群点
    discrete_points.plot(style='ro')

    for i in range(len(discrete_points)):  # 离群点做标记
        id = discrete_points.index[i]
        n = discrete_points.iloc[i]
        plt.annotate('(%s, %0.2f)' % (id, n), xy=(id, n), xytext=(id, n))

    plt.xlabel(u'编号')
    plt.ylabel(u'相对距离')
    plt.show()


def main():
    data = pd.read_excel('consumption_data.xls', index_col='Id')  # 读取数据
    data_zs = get_data(data)  # 标准化数据
    model = k_means(data_zs)  # 聚类

    norm = standard(data_zs, model, data)  # 标准化数据集类别

    mat_plot(norm)


if __name__ == '__main__':
    main()
    model = k_means(data_zs)  # 聚类

    norm = standard(data_zs, model, data)  # 标准化数据集类别

    mat_plot(norm)