Detección de novedades — 10:24 min#

  • 10:24 min | Última modificación: Septiembre 22, 2021 | YouTube

Definición del problema#

Se desea detectar cuando una nueva observación es un outlier. El dataset de entrenamiento no contiene outliers. Esta es una forma de detección de anomalías semi-supervizada.

Las anomalias pueden formar un cluster denso en una región de baja probabilidad del conjunto de entrenamiento.

En las implementaciones, el +1 indica un inlier, y el -1 un outlier.

Proceso:

  • El dataset de entrenamiento contiene n observaciones con p caracaterísticas.

  • Llega una nueva observación desconocida hasta ahora.

  • La nueva observación pertenece a la misma distibución de probabilidades del datset de entrenamiento?

https://scikit-learn.org/stable/auto_examples/svm/plot_oneclass.html

[1]:
import matplotlib.font_manager
import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import OneClassSVM
[2]:
#
# Conjunto de datos de entrenamiento
#
np.random.seed(122)

X = 0.3 * np.random.randn(100, 2)
X_train = np.r_[X + 2, X - 2]

#
# Conjunto de datos de prueba
#
X = 0.3 * np.random.randn(20, 2)
X_test = np.r_[X + 2, X - 2]


#
# Outliers
#
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))

#
# Especificación y entrenamiento del modelo
#
clf = OneClassSVM(
    # -----------------------------------------------------
    # ‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’
    kernel="rbf",
    # -----------------------------------------------------
    # An upper bound on the fraction of training errors and
    # a lower bound of the fraction of support vectors.
    nu=0.1,
    # -----------------------------------------------------
    # Kernel coefficient for ‘rbf’, ‘poly’ and ‘sigmoid’.
    gamma=0.1,
)
clf.fit(X_train)

#
# Pronóstico
#
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)

#
# Número de outliers.
#   n_error_train: puntos en el conjunto de entrenamiento
#     considerados erróneamente como outliers
#   n_error_test: puntos en el conjunto de prueba
#      consieradores erróneamente como outliers
#   n_error_outliers: outliers considerados erróneamente
#      como inliers
#
n_error_train = y_pred_train[y_pred_train == -1].size
n_error_test = y_pred_test[y_pred_test == -1].size
n_error_outliers = y_pred_outliers[y_pred_outliers == 1].size

display(
    "         Errors train: {:d}/200".format(n_error_train),
    " Errors novel regular: {:d}/40".format(n_error_test),
    "Errors novel abnormal: {:d}/40".format(n_error_outliers),
)


X_error_train = X_train[y_pred_train == -1, :]
X_error_test = X_test[y_pred_test == -1, :]
X_error_outliers = X_outliers[y_pred_outliers == 1, :]

#
# Grafica el área con las regiones de probabilidad
# Z es una matriz que contiene la probabilidad de
# la presencia de una nueva observación en ese punto
#
xx, yy = np.meshgrid(
    np.linspace(-5, 5, 500),
    np.linspace(-5, 5, 500),
)
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

#
# Superficie
#
plt.figure(figsize=(10, 10))
plt.contourf(
    xx,
    yy,
    Z,
    levels=np.linspace(Z.min(), 0, 7),
    cmap=plt.cm.Blues,
    alpha=0.2,
)

#
# Frontera de decisión
#
a = plt.contour(
    xx,
    yy,
    Z,
    levels=[0],
    linewidths=2,
    colors="black",
    alpha=1,
    linestyles="--",
)

#
# Area contenida en la frontera de decisión
#
plt.contourf(
    xx,
    yy,
    Z,
    levels=[0, Z.max()],
    colors="white",
    alpha=1.0,
)

#
# Patrones de entrenamiento, prueba y outliers
#
s = 100
b1 = plt.scatter(
    X_train[:, 0], X_train[:, 1], c="tab:blue", s=s, edgecolors="k", alpha=0.4
)
b2 = plt.scatter(
    X_test[:, 0], X_test[:, 1], c="tab:orange", s=s, edgecolors="k", alpha=0.4
)
c = plt.scatter(
    X_outliers[:, 0], X_outliers[:, 1], c="tab:green", s=s, edgecolors="k", alpha=0.4
)

plt.scatter(
    X_error_train[:, 0],
    X_error_train[:, 1],
    c="tab:blue",
    s=s,
    edgecolors="k",
    linewidths=2,
)
plt.scatter(
    X_error_test[:, 0],
    X_error_test[:, 1],
    c="tab:orange",
    s=s,
    edgecolors="k",
    linewidths=2,
)
plt.scatter(
    X_error_outliers[:, 0],
    X_error_outliers[:, 1],
    c="tab:green",
    s=s,
    edgecolors="k",
    linewidths=2,
)

#
# Estetica de la gráfica
#
plt.axis("tight")
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend(
    [a.collections[0], b1, b2, c],
    [
        "learned frontier",
        "training observations",
        "new regular observations",
        "new abnormal observations",
    ],
    loc="upper left",
    prop=matplotlib.font_manager.FontProperties(size=11),
)

plt.show()
'         Errors train: 19/200'
' Errors novel regular: 5/40'
'Errors novel abnormal: 2/40'
../_images/50_deteccion_de_outliers_01_novelty_6_3.png