我试图从服务器访问日志文件上的IP地址中检测基于地理位置的异常。我使用IP地址和每个请求的时间戳创建了两个特性country和geo_velocity。但是,由于所有请求都来自固定客户端,而且所有客户端都来自日志文件中的一个国家,所以我的数据集最终看起来是这样的。
| Country | geo_velocity|
| ----------- | ----------- |
| USA | 0 |
| USA | 0 |
| USA | 0 |
基本上,如果我把整个数据集绘制成一个零散点,它就会浓缩到一个点上。因此,从字面上讲,这些特性的每一个其他值都应该是此数据集的异常。
我使用隔离森林和GridSearchCV来调优超参数。对于GridSearchCV中的评分参数,我使用了一个定制的评分函数,如下面的代码所示。问题是,这个模型把每件事归类为不稳定因素,尽管它们应该是明显的离群点。
from sklearn.ensemble import IsolationForest
import numpy as np
import pandas as pd
from sklearn.model_selection import GridSearchCV
# this is similar to my dataset after label encoding the "country"
data = np.zeros((5000,2),dtype=int)
dataset = pd.DataFrame(data, columns=['country','geolocation'])
params = {'n_estimators':[70,80,100], 'max_samples':['auto'],
'contamination':[0,0.001,0.010,0.1,0.5], 'max_features':[1,2],
'bootstrap':[True,False],'n_jobs':[-1],
'random_state':[None,1,], 'warm_start':[True]}
def scorer_f(estimator, X):
return np.mean(estimator.score_samples(X))
isolation_forest = GridSearchCV(IsolationForest(), params, scoring=scorer_f)
model = isolation_forest.fit(dataset)
best_model = model.best_estimator_
predictions = best_model.predict([[0,0],[100,100]])
print(predictions)
output : [1,1]
在上述代码中生成的数据集与编码后的数据集类似。尽管第二点显然应该是一个离群点,但该模型将其归类为一个异常值。
这种方法似乎有什么问题?提前感谢!
发布于 2021-02-19 09:03:49
IsolationForest不适用于欧氏距离。因此,0,0几乎和一百,一百一样好
它在数据集上构建随机树,并期望异常值会在树中很早就被挑出来,而Inliers则会深入。有了这个逻辑,它就能找出离群点。
IsolationForest‘通过随机选择一个特征,然后在所选特征的最大值和最小值之间随机选择一个分割值来分离观察。由于递归分区可以用树结构表示,因此分离样本所需的分割数相当于从根节点到终止节点的路径长度。这个路径长度平均在这样的随机树林中,是正规性和我们的决策函数的一种度量。随机分区为异常产生明显较短的路径。科奇-学习博士
你的数据是非常干净和独特的。如果我们在这里观察,我们可以区分0,0和一百,一百在一个单独的分裂。所以节点的深度对于两种情况都是一样的。
您可以尝试一种基于欧氏距离的模型,即LocalOutlierFactor。
from sklearn.neighbors import LocalOutlierFactor
model = LocalOutlierFactor(n_neighbors=10,novelty=True).fit(dataset)
model.predict([[0,0],[100,100]])
输出阵列(1,-1)
Scikit-异类/新颖性学习指南- 链接
https://datascience.stackexchange.com/questions/89563
复制