在Python中识别一维和二维数据中的异常值块
数据:我在一列中有一个数据d,该数据随其他两列中定义的两个变量a和b的函数而变化。我的目标是识别d中的块或异常值。这些离群值块看起来可能不是离群值,但在我的例子中,我想识别那些不属于可以用线性线拟合的数据云的数据 问题:尽管我以前从未做过聚类分析,但这个名字听起来似乎可以实现我的目标。如果我选择进行聚类分析,我想对以下两种情况进行聚类分析:在Python中识别一维和二维数据中的异常值块,python,scikit-learn,cluster-analysis,outliers,chunks,Python,Scikit Learn,Cluster Analysis,Outliers,Chunks,数据:我在一列中有一个数据d,该数据随其他两列中定义的两个变量a和b的函数而变化。我的目标是识别d中的块或异常值。这些离群值块看起来可能不是离群值,但在我的例子中,我想识别那些不属于可以用线性线拟合的数据云的数据 问题:尽管我以前从未做过聚类分析,但这个名字听起来似乎可以实现我的目标。如果我选择进行聚类分析,我想对以下两种情况进行聚类分析: 使用a和d 使用a、b和d 我做了一些搜索并找到了#1,使用KernelDensity模块将更合适,而对于#2,使用MeahShift模块将是一个很好的选择
KernelDensity
模块将更合适,而对于#2,使用MeahShift
模块将是一个很好的选择,无论是在Python中还是在Python中
问题:我以前从未做过聚类分析,因此我无法理解他们文档中给出的
KernelDensity
和MeahShift
的示例(分别是和)。有人能解释一下我如何使用KernelDensity
和MeahShift
来识别案例1和案例2中d中异常值的“块”吗?首先,KernelDensity
用于非参数方法。由于您坚信关系是线性的(即参数化模型),KernelDensity
不是此任务中最合适的选择
下面是识别异常值的示例代码
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import RANSACRegressor
# data: 1000 obs, 100 of them are outliers
# =====================================================
np.random.seed(0)
a = np.random.randn(1000)
b = np.random.randn(1000)
d = 2 * a - b + np.random.randn(1000)
# the last 100 are outliers
d[-100:] = d[-100:] + 10 * np.abs(np.random.randn(100))
fig, axes = plt.subplots(ncols=2, sharey=True)
axes[0].scatter(a, d, c='g')
axes[0].set_xlabel('a')
axes[0].set_ylabel('d')
axes[1].scatter(b, d, c='g')
axes[1].set_xlabel('b')
为您的样本数据
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import RANSACRegressor
df = pd.read_excel('/home/Jian/Downloads/Data.xlsx').dropna()
a = df.a.values.reshape(len(df), 1)
d = df.d.values.reshape(len(df), 1)
fig, axes = plt.subplots(ncols=2, sharey=True)
axes[0].scatter(a, d, c='g')
axes[0].set_xlabel('a')
axes[0].set_ylabel('d')
robust_estimator = RANSACRegressor(random_state=0)
robust_estimator.fit(a, d)
d_pred = robust_estimator.predict(a)
# calculate mse
mse = (d - d_pred) ** 2
index = np.argsort(mse.ravel())
axes[1].scatter(a[index[:-50]], d[index[:-50]], c='b', label='inliers', alpha=0.2)
axes[1].scatter(a[index[-50:]], d[index[-50:]], c='r', label='outliers')
axes[1].set_xlabel('a')
axes[1].legend(loc=2)
我认为您首先需要一个稳健的回归,因为您的数据已经被一些异常值所污染。一旦拟合了稳健回归,则在每个点计算的均方误差可作为到聚类中心(回归线)的距离度量。MSE较大的观测值可能是异常值。sklearn中稳健回归的参考链接@很抱歉,我无法理解参考资料中给出的示例。你能给出一个简单的示例吗?代码似乎适用于你的示例数据文件。我已经在我的帖子中加入了,请看一看。从我对你的代码的理解来看,你是-1)在你已经知道离群值的前提下开始你的代码,2)在所有数据上拟合回归,包括离群值。另外,稳健回归中使用的参数
T
是什么?然而,我的目标是1)首先破译这些离群值块,2)仅在离群值下面的数据云上拟合线性回归。@不,我不假设任何离群值知识。下半部分的所有代码都不假定它知道异常值是最后100个OB。上面的代码演示了如何删除异常值。如果愿意,可以使用剩余的内联线重新调整线性回归。.T
只是转置运算符,请确保每列都是一个特性。为什么要求代码将最大的50毫秒标记为异常值?基本上,我不知道有多少异常值,或者它们是否存在。我希望代码能够识别那些异常值,并在没有异常值的情况下在剩余数据上拟合一行。另外,现在您已经包括了参数a
和b
;如果我只包含一个参数,比如说a
?@pullow 1)d_pred
是基于内联线和离群值的,那么这是否有效?但是由于我们使用稳健回归,回归线对离群值是稳健的。如果您想为另一个标准线性回归重新安装内联线,它将生成非常相似的回归线。2) 据我所知,精确检测数据集中的异常值是非常困难的,如果其mse
比mse
的中值大5倍,则可以将其视为异常值。3) 您可以更改常数并预测新的d_pred
,以便np.percentile(d_pre-d,0.05)
为您提供0.0
@poud您需要解决的问题是a0
使您的函数np.percentile(d_pre-d,0.05)=0
。我认为使用scipy
根查找算法是可行的。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import RANSACRegressor
df = pd.read_excel('/home/Jian/Downloads/Data.xlsx').dropna()
a = df.a.values.reshape(len(df), 1)
d = df.d.values.reshape(len(df), 1)
fig, axes = plt.subplots(ncols=2, sharey=True)
axes[0].scatter(a, d, c='g')
axes[0].set_xlabel('a')
axes[0].set_ylabel('d')
robust_estimator = RANSACRegressor(random_state=0)
robust_estimator.fit(a, d)
d_pred = robust_estimator.predict(a)
# calculate mse
mse = (d - d_pred) ** 2
index = np.argsort(mse.ravel())
axes[1].scatter(a[index[:-50]], d[index[:-50]], c='b', label='inliers', alpha=0.2)
axes[1].scatter(a[index[-50:]], d[index[-50:]], c='r', label='outliers')
axes[1].set_xlabel('a')
axes[1].legend(loc=2)