首先,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')
# processing
# =====================================================
# robust regression
robust_estimator = RANSACRegressor(random_state=0)
robust_estimator.fit(np.vstack([a,b]).T, d)
d_pred = robust_estimator.predict(np.vstack([a,b]).T)
# calculate mse
mse = (d - d_pred.ravel()) ** 2
# get 50 largest mse, 50 is just an arbitrary choice and it doesn't assume that we already know there are 100 outliers
index = argsort(mse)
fig, axes = plt.subplots(ncols=2, sharey=True)
axes[0].scatter(a[index[:-50]], d[index[:-50]], c='b', label='inliers')
axes[0].scatter(a[index[-50:]], d[index[-50:]], c='r', label='outliers')
axes[0].set_xlabel('a')
axes[0].set_ylabel('d')
axes[0].legend(loc='best')
axes[1].scatter(b[index[:-50]], d[index[:-50]], c='b', label='inliers')
axes[1].scatter(b[index[-50:]], d[index[-50:]], c='r', label='outliers')
axes[1].legend(loc='best')
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)