在这篇文章中,我们将学习如何实现自动编码器来构建稀有事件分类器。 我们将使用来自的真实稀有事件数据集 here.

Background

什么是极端罕见的事件?
在一个罕见的问题中,我们有一个不平衡的数据集。意思是,我们得到的阳性标记样本少于阴性。在典型的罕见事件中,正标记数据约占总数的5-10%。在一个极端罕见的事件问题中,我们的标记数据不到1%。例如,在这里使用的数据集中,它约为0.6%。

这种极端罕见的事件问题在现实世界中非常普遍,例如,在制造,点击或在线行业购买时的纸张断裂和机器故障。

对这些罕见事件进行分类非常具有挑最近,深度学习已被广​​泛用于分类。但是,少量阳性标记样本禁止深度学习应用。无论数据有多大,深度学习的使用都受到正面标记样本数量的限制。

我们为什么还要费心使用深度学习?
这是一个合理的问题。为什么我们不应该考虑使用另一种机器学习方法?

答案是主观的。我们总是可以采用机器学习方法。为了使其工作,我们可以从负面标记的数据中取样,以获得接近平衡的数据集。由于我们有大约0.6%的正标记数据,因此欠采样将导致数据集粗糙,大约是原始数据大小的1%。机器学习方法,例如SVM或随机森林仍然可以处理此大小的数据集。但是,它的准确性会受到限制。我们不会利用剩下的~99%的数据中存在的信息。

如果数据足够,则深度学习方法可能更有能力。它还允许通过使用不同的体系结构灵活地进行模型改进。因此,我们将尝试使用深度学习方法。

在这篇文章中,我们将学习如何使用简单的密集层自动编码器来构建罕见的事件分类器。这篇文章的目的是演示用于极端罕见事件分类的Autoencoder的实现。我们将在用户身上探索Autoencoder的不同架构和配置。如果您发现任何有趣的内容,请分享评论。

自动编码器用于分类
用于分类的自动编码器方法类似于异常检测。在异常检测中,我们学习了正常过程的模式。任何不遵循这种模式的东西都被归类为异常。对于罕见事件的二进制分类,我们可以使用类似的方法使用自动编码器(从此处[2]导出)。

什么是自动编码器?

自动编码器由两个模块组成:编码器和解码器。
编码器学习过程的基本特征。这些特征通常具有减小的尺寸。
解码器可以从这些底层特征重建原始数据。

How to use an Autoencoder rare-event classification?

我们将数据分为两部分:正标记和负标记。
带负标记的数据被视为过程的正常状态。正常状态是指该过程无事件。
我们将忽略带正号的数据,并仅在负标记数据上训练自动编码器。
这个Autoencoder现在已经学习了正常过程的功能。
训练有素的Autoencoder将预测任何来自正常状态的新数据(因为它将具有相同的模式或分布)。
因此,重建误差会很小。
但是,如果我们尝试从稀有事件重建数据,则自动编码器会很困难。
这将使罕见事件期间的重建误差变高。
我们可以捕获如此高的重建误差并将其标记为罕见事件预测。
该过程类似于异常检测方法。
履行

数据和问题

这是来自纸浆和造纸厂的二进制标记数据,用于断纸。纸张断裂是纸张制造中的严重问题。单张纸张会造成数千美元的损失,而且工厂每天至少会看到一次或多次休息。这导致每年数百万美元的损失和工作危险。

由于过程的性质,检测休息事件是具有挑战性的。如[1]中所述,即使断裂减少5%也会给工厂带来显着的好处。

我们的数据包含15天内收集的大约18k行。列y包含二进制标签,1表示分页符。其余列是预测变量。大约有124个阳性标记样本(~0.6%)。

Download data here.

Code

Import the desired libraries.

%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
from pylab import rcParams
import tensorflow as tf
from keras.models import Model, load_model
from keras.layers import Input, Dense
from keras.callbacks import ModelCheckpoint, TensorBoard
from keras import regularizers
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, precision_recall_curve
from sklearn.metrics import recall_score, classification_report, auc, roc_curve
from sklearn.metrics import precision_recall_fscore_support, f1_score
from numpy.random import seed
seed(1)
from tensorflow import set_random_seed
set_random_seed(2)
SEED = 123 #used to help randomly select the data points
DATA_SPLIT_PCT = 0.2
rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]

Note that we are setting the random seeds for reproducibility of the result.

Data preprocessing

Now, we read and prepare the data.

df = pd.read_csv("data/processminer-rare-event-mts - data.csv")

这种罕见事件的目的是在碎片发生之前预测它。 我们将尝试提前4分钟预测休息时间。 要构建此模型,我们将标签向上移动2行(相当于4分钟)。 我们可以这样做df.y = df.y.shift(-2)。 但是,在这个问题中,我们希望将变换视为:如果行n被正面标记,

使行(n-2)和(n-1)等于1.这将有助于分类器学习最多4分钟的预测。
删除行n。 因为我们不希望分类器在发生故障时学习预测中断。
我们将为此曲线移位开发以下UDF。

sign = lambda x: (1, -1)[x < 0]def curve_shift(df, shift_by):'''This function will shift the binary labels in a dataframe.The curve shift will be with respect to the 1s. For example, if shift is -2, the following processwill happen: if row n is labeled as 1, then- Make row (n+shift_by):(n+shift_by-1) = 1.- Remove row n.i.e. the labels will be shifted up to 2 rows up.Inputs:df       A pandas dataframe with a binary labeled column. This labeled column should be named as 'y'.shift_by An integer denoting the number of rows to shift.Outputdf       A dataframe with the binary labels shifted by shift.'''vector = df['y'].copy()for s in range(abs(shift_by)):tmp = vector.shift(sign(shift_by))tmp = tmp.fillna(0)vector += tmplabelcol = 'y'# Add vector to the dfdf.insert(loc=0, column=labelcol+'tmp', value=vector)# Remove the rows with labelcol == 1.df = df.drop(df[df[labelcol] == 1].index)# Drop labelcol and rename the tmp col as labelcoldf = df.drop(labelcol, axis=1)df = df.rename(columns={labelcol+'tmp': labelcol})# Make the labelcol binarydf.loc[df[labelcol] > 0, labelcol] = 1return df

Now, we divide the data into train, valid, and test sets. Then we will take the subset of data with only 0s to train the autoencoder.

df_train, df_test = train_test_split(df, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train, df_valid = train_test_split(df_train, test_size=DATA_SPLIT_PCT, random_state=SEED)
df_train_0 = df_train.loc[df['y'] == 0]
df_train_1 = df_train.loc[df['y'] == 1]
df_train_0_x = df_train_0.drop(['y'], axis=1)
df_train_1_x = df_train_1.drop(['y'], axis=1)
df_valid_0 = df_valid.loc[df['y'] == 0]
df_valid_1 = df_valid.loc[df['y'] == 1]
df_valid_0_x = df_valid_0.drop(['y'], axis=1)
df_valid_1_x = df_valid_1.drop(['y'], axis=1)
df_test_0 = df_test.loc[df['y'] == 0]
df_test_1 = df_test.loc[df['y'] == 1]
df_test_0_x = df_test_0.drop(['y'], axis=1)
df_test_1_x = df_test_1.drop(['y'], axis=1)

Standardization

It is usually better to use a standardized data (transformed to Gaussian, mean 0 and variance 1) for autoencoders.

scaler = StandardScaler().fit(df_train_0_x)
df_train_0_x_rescaled = scaler.transform(df_train_0_x)
df_valid_0_x_rescaled = scaler.transform(df_valid_0_x)
df_valid_x_rescaled = scaler.transform(df_valid.drop(['y'], axis = 1))
df_test_0_x_rescaled = scaler.transform(df_test_0_x)
df_test_x_rescaled = scaler.transform(df_test.drop(['y'], axis = 1))

Autoencoder Classifier

Initialization

First, we will initialize the Autoencoder architecture. We are building a simple autoencoder. More complex architectures and other configurations should be explored.

nb_epoch = 100
batch_size = 128
input_dim = df_train_0_x_rescaled.shape[1] #num of predictor variables,
encoding_dim = 32
hidden_dim = int(encoding_dim / 2)
learning_rate = 1e-3
input_layer = Input(shape=(input_dim, ))
encoder = Dense(encoding_dim, activation="tanh", activity_regularizer=regularizers.l1(learning_rate))(input_layer)
encoder = Dense(hidden_dim, activation="relu")(encoder)
decoder = Dense(hidden_dim, activation='tanh')(encoder)
decoder = Dense(input_dim, activation='relu')(decoder)
autoencoder = Model(inputs=input_layer, outputs=decoder)

Training

We will train the model and save it in a file. Saving a trained model is a good practice for saving time for future analysis.

autoencoder.compile(metrics=['accuracy'],loss='mean_squared_error',optimizer='adam')
cp = ModelCheckpoint(filepath="autoencoder_classifier.h5",save_best_only=True,verbose=0)
tb = TensorBoard(log_dir='./logs',histogram_freq=0,write_graph=True,write_images=True)
history = autoencoder.fit(df_train_0_x_rescaled, df_train_0_x_rescaled,epochs=nb_epoch,batch_size=batch_size,shuffle=True,validation_data=(df_valid_0_x_rescaled, df_valid_0_x_rescaled),verbose=1,callbacks=[cp, tb]).history

Classification

In the following, we show how we can use an Autoencoder reconstruction error for the rare-event classification.

As mentioned before, if the reconstruction error is high, we will classify it as a sheet-break. We will need to determine the threshold for this.

We will use the validation set to identify the threshold.

valid_x_predictions = autoencoder.predict(df_valid_x_rescaled)
mse = np.mean(np.power(df_valid_x_rescaled - valid_x_predictions, 2), axis=1)
error_df = pd.DataFrame({'Reconstruction_error': mse,'True_class': df_valid['y']})
precision_rt, recall_rt, threshold_rt = precision_recall_curve(error_df.True_class, error_df.Reconstruction_error)
plt.plot(threshold_rt, precision_rt[1:], label="Precision",linewidth=5)
plt.plot(threshold_rt, recall_rt[1:], label="Recall",linewidth=5)
plt.title('Precision and recall for different threshold values')
plt.xlabel('Threshold')
plt.ylabel('Precision/Recall')
plt.legend()
plt.show()

Now, we will perform classification on the test data.

We should not estimate the classification threshold from the test data. It will result in overfitting.

test_x_predictions = autoencoder.predict(df_test_x_rescaled)
mse = np.mean(np.power(df_test_x_rescaled - test_x_predictions, 2), axis=1)
error_df_test = pd.DataFrame({'Reconstruction_error': mse,'True_class': df_test['y']})
error_df_test = error_df_test.reset_index()
threshold_fixed = 0.85
groups = error_df_test.groupby('True_class')
fig, ax = plt.subplots()
for name, group in groups:ax.plot(group.index, group.Reconstruction_error, marker='o', ms=3.5, linestyle='',label= "Break" if name == 1 else "Normal")
ax.hlines(threshold_fixed, ax.get_xlim()[0], ax.get_xlim()[1], colors="r", zorder=100, label='Threshold')
ax.legend()
plt.title("Reconstruction error for different classes")
plt.ylabel("Reconstruction error")
plt.xlabel("Data point index")
plt.show();

Figure 4. Using threshold = 0.85 for classification. The orange and blue dots above the threshold line represents the True Positive and False Positive, respectively.

In Figure 4, the orange and blue dot above the threshold line represents the True Positive and False Positive, respectively. As we can see, we have good number of false positives. To have a better look, we can see a confusion matrix.

pred_y = [1 if e > threshold_fixed else 0 for e in error_df.Reconstruction_error.values]
conf_matrix = confusion_matrix(error_df.True_class, pred_y)
plt.figure(figsize=(12, 12))
sns.heatmap(conf_matrix, xticklabels=LABELS, yticklabels=LABELS, annot=True, fmt="d");
plt.title("Confusion matrix")
plt.ylabel('True class')
plt.xlabel('Predicted class')
plt.show()


Figure 5. Confusion Matrix on the test predictions.
我们可以预测32个中断实例中的9个。 请注意,这些实例包括提前2或4分钟的预测。 这大约是28%,这对造纸业来说是一个很好的召回率。 误报率约为6.3%。 这对于工厂来说并不理想,但并不可怕。

尽管如此,这个模型还可以进一步改进,以便以较小的误报率提高召回率。 我们将查看下面的AUC,然后讨论下一个改进方法。

ROC curve and AUC

false_pos_rate, true_pos_rate, thresholds = roc_curve(error_df.True_class, error_df.Reconstruction_error)
roc_auc = auc(false_pos_rate, true_pos_rate,)
plt.plot(false_pos_rate, true_pos_rate, linewidth=5, label='AUC = %0.3f'% roc_auc)
plt.plot([0,1],[0,1], linewidth=5)
plt.xlim([-0.01, 1])
plt.ylim([0, 1.01])
plt.legend(loc='lower right')
plt.title('Receiver operating characteristic curve (ROC)')
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()

The AUC is 0.624.

Github repository

The entire code with comments are present here.

What can be done better here?

This is a (multivariate) time series data. We are not taking into account the temporal information/patterns in the data. In the next post, we will explore if it is possible with an RNN. We will try a LSTM autoencoder.

Conclusion

We worked on an extreme rare event binary labeled data from a paper mill to build an Autoencoder Classifier. We achieved reasonable accuracy. The purpose here was to demonstrate the use of a basic Autoencoder for rare event classification. We will further work on developing other methods, including an LSTM Autoencoder that can extract the temporal features for better accuracy.

The next post on LSTM Autoencoder is here, LSTM Autoencoder for rare event classification.

References

Ranjan, C., Mustonen, M., Paynabar, K., & Pourak, K. (2018). Dataset: Rare Event Classification in Multivariate Time Series. arXiv preprint arXiv:1809.10717.
https://www.datascience.com/blog/fraud-detection-with-tensorflow
Github repo: https://github.com/cran2367/autoencoder_classifier



使用Keras中的Autoencoders进行极端罕见事件分类相关推荐

  1. 用于Keras极端罕见事件分类的LSTM自动编码器

    在这里,我们将学习LSTM模型的数据准备细节,并构建用于稀有事件分类的LSTM Autoencoder. 这篇文章是我之前使用Autoencoders发布极端罕见事件分类的延续.在上一篇文章中,我们讨 ...

  2. NLP(五十三)在Keras中使用英文Roberta模型实现文本分类

      英文Roberta模型是2019年Facebook在论文RoBERTa: A Robustly Optimized BERT Pretraining Approach中新提出的预训练模型,其目的是 ...

  3. keras 中adam_ADAM中的渲染和着色:第3集

    keras 中adam Have you seen ADAM: The Mirror and ADAM: Episode 3 yet? These two short films have capti ...

  4. 气候变化中的极端气候事件对生态系统碳循环的影响

    2012年真是极其艰难的一年!根据玛雅历法所推算的世界末日让全球忧心忡忡,但最后被证实是杞人忧天.但是这一年,全球的日子的确不好过:美国的干旱和热浪,英国.肯尼亚.索马里.日本和澳大利亚非同寻常的降雨 ...

  5. 深度学习布料交换:在Keras中实现条件类比GAN

    2017年10月26日SHAOANLU 条件类比GAN:交换人物形象的时尚文章(链接) 给定三个输入图像:人穿着布A,独立布A和独立布B,条件类比GAN(CAGAN)生成穿着布B的人类图像.参见下图. ...

  6. CNN在Keras中的实践|机器学习你会遇到的“坑”

    2018-12-16 23:43:37 本文作为上一节<卷积之上的新操作>的补充篇,将会关注一些读者关心的问题,和一些已经提到但并未解决的问题: 到底该如何理解padding中的valid ...

  7. 神经网络在Keras中不work!博士小哥证明何恺明的初始化方法堪比“CNN还魂丹”...

    铜灵 发自 凹非寺 量子位 出品 | 公众号 QbitAI 南巴黎电信学院(Télécom SudParis)的在读博士生Nathan Hubens在训练CNN时遇到点难题. 使用在CIFAR10数据 ...

  8. Keras中神经网络可视化模块keras.utils.visualize_util安装配置方法

    Keras中提供了一个神经网络可视化的函数plot,并可以将可视化结果保存在本地.plot使用方法如下: from keras.utils.visualize_util import plot plo ...

  9. Keras之ML~P:基于Keras中建立的回归预测的神经网络模型(根据200个数据样本预测新的5+1个样本)——回归预测

    Keras之ML~P:基于Keras中建立的回归预测的神经网络模型(根据200个数据样本预测新的5+1个样本)--回归预测 目录 输出结果 核心代码 输出结果 核心代码 # -*- coding: u ...

最新文章

  1. weex 阶段总结
  2. SDN控制器构建原理方法—Vecloud
  3. mysql的联合索引_mysql联合索引
  4. 【笔记】mybatis的sqlSession和Mapper详解
  5. Android支持横行滚动的ListView控件
  6. OpenStack云第五天
  7. Spark SQL 中UDF的讲解
  8. Apache Log4j2详解,【高级Java架构师系统学习
  9. WebGoat系列实验Buffer Overflows Code Quality Concurrency
  10. 学术论文的word排版
  11. vgg16 清华镜像_Python models.vgg16方法代码示例
  12. [大话设计模式C++版] 第7章 为别人做嫁衣 —— 代理模式
  13. 全民社会保障月供制度的客观理由
  14. 女生适合做软件开发工作吗?优势在哪里?
  15. ChatGPT版Office(Word/Excel/PPT)来了
  16. Linux中如何切换中文英文
  17. 拉勾网数据分析师职位分析
  18. 网新恒天_点网新角度和点网新React
  19. VisualStudio 调试时会不断刷新 WPF 应用渲染
  20. ps -ef | grep 命令解读

热门文章

  1. 小程序发布之后无法生成海报问题
  2. 高端大气上档次的fullPage.js
  3. 2021-12-02 迈向程序猿的第四十一步
  4. 一个水藻,经过两天的生长后,从第3天开始每天都会分裂出一个新藻,而分裂出的新藻同样经过两天的生长,也会从第3天开始每天分裂出一个新藻,问经过n天后,共有多少个水藻存在。暂时不考虑藻死亡的情况。
  5. 指令集创始人潘爱民博士荣获CSDN“2021年度IT领军人物”
  6. 菜鸟网络业务支撑平台
  7. 开发新闻类APP需要准备什么
  8. 双通道幅频相可调DDS 信号发生器
  9. 氯丁橡胶的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  10. 多单、空单、开仓、平仓、持仓、现货、期货、通货膨胀.......