【神经网络】自编码聚类算法--DEC (Deep Embedded Clustering)

1.算法描述

最近在做AutoEncoder的一些探索,看到2016年的一篇论文,虽然不是最新的,但是思路和方法值得学习。论文原文链接 http://proceedings.mlr.press/v48/xieb16.pdf,论文有感于t-SNE算法的t-分布,先假设初始化K个聚类中心,然后数据距离中心的距离满足t-分布,可以用下面的公式表示:

其中 i表示第i样本,j表示第j个聚类中心, z表示原始特征分布经过Encoder之后的表征空间。

$q_{ij}$可以解释为样本i属于聚类j的概率,属于论文上说的"软分配"的概念。那么“硬分配”呢?那就是样本一旦属于一个聚类,其余的聚类都不属于了,也就是其余聚类的概率为0。由于$\alpha$在有label的训练计划中,是在验证集上进行确定的,在该论文中,全部设置成了常数1。

然后神奇的事情发生了,作者发明了一个辅助分布也用来衡量样本属于某个聚类的分布,就是下面的公式了:

,其中$f_{j}=\sum_{i}q_{ij}$

也许你会疑问,上面这个玩意怎么来的?作者的论文中说主要考虑一下三点:

  1. 强化预测。q分布为软分配的概率,那么p如果使用delta分布来表示,显得比较原始。
  2. 置信度越高,属于某个聚类概率越大。
  3. 规范每个质心的损失贡献,以防止大类扭曲隐藏的特征空间。分子中那个$f_{j}$就是做这个的。

假设分布有了,原始的数据分布也有了,剩下衡量两个分布近似的方法,作者使用了KL散度,公式如下:

这个也是DEC聚类的损失函数。有了具体的公式,明确一下每次迭代更新需要Update的参数:

第一个公式是优化AE中的Encoder参数,第二个公式是优化聚类中心。也就是说作者同时优化了聚类和DNN的相关参数。

作者设计的网络概念图如下:

DEC算法由两部分组成,第一部分会预训练一个AE模型;第二部分选取AE模型中的Encoder部分,加入聚类层,使用KL散度进行训练聚类。

2.实验分析

实验部分比较了几种算法,比较的指标是ACC,对比表格如下:

DEC的效果还是比较不错的,另外值得一提的是DEC w/o backprop算法,是将第一部分Encoder的参数固定之后,不再参加训练,只更新聚类中心的算法,从结果上看,并没有两者同时训练效果来的好。

3.源码分析

论文使用的Caffe写的,对于我这种半路出家的和尚有点吃力,网上找了一个keras的实现代码,https://github.com/XifengGuo/DEC-keras/blob/master/DEC.py

首先是DEC的预训练的部分,预训练的模型先保存了起来方便训练聚类使用:

def pretrain(self, x, y=None, optimizer=‘adam‘, epochs=200, batch_size=256, save_dir=‘results/temp‘):
        print(‘...Pretraining...‘)
        self.autoencoder.compile(optimizer=optimizer, loss=‘mse‘)
        self.autoencoder.fit(x, x, batch_size=batch_size, epochs=epochs, callbacks=cb)
        self.autoencoder.save_weights(save_dir + ‘/ae_weights.h5‘)
        self.pretrained = True

在进行训练之前,我们看一下作者构造的一个新的网络层

class ClusteringLayer(Layer):
    .....

    def build(self, input_shape):
        assert len(input_shape) == 2
        input_dim = input_shape[1]
        self.input_spec = InputSpec(dtype=K.floatx(), shape=(None, input_dim))        //在这里定义了需要训练更新的权重,就是说把K个聚类当作了“权重”来进行更新了
        self.clusters = self.add_weight((self.n_clusters, input_dim), initializer=‘glorot_uniform‘, name=‘clusters‘)
        if self.initial_weights is not None:
            self.set_weights(self.initial_weights)
            del self.initial_weights
        self.built = True

    def call(self, inputs, **kwargs):
        """ student t-distribution, as same as used in t-SNE algorithm.
                 q_ij = 1/(1+dist(x_i, u_j)^2), then normalize it.
        Arguments:
            inputs: the variable containing data, shape=(n_samples, n_features)
        Return:
            q: student‘s t-distribution, or soft labels for each sample. shape=(n_samples, n_clusters)
        """
        q = 1.0 / (1.0 + (K.sum(K.square(K.expand_dims(inputs, axis=1) - self.clusters), axis=2) / self.alpha))
        q **= (self.alpha + 1.0) / 2.0
        q = K.transpose(K.transpose(q) / K.sum(q, axis=1))
        return q

    def compute_output_shape(self, input_shape):
        assert input_shape and len(input_shape) == 2
        return input_shape[0], self.n_clusters

    def get_config(self):
        config = {‘n_clusters‘: self.n_clusters}
        base_config = super(ClusteringLayer, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

接下来就是第二部分fit的过程了

def fit(self, x, y=None, maxiter=2e4, batch_size=256, tol=1e-3,
            update_interval=140, save_dir=‘./results/temp‘):

        # Step 1: initialize cluster centers using k-means
        kmeans = KMeans(n_clusters=self.n_clusters, n_init=20)
        y_pred = kmeans.fit_predict(self.encoder.predict(x))
        y_pred_last = np.copy(y_pred)
        self.model.get_layer(name=‘clustering‘).set_weights([kmeans.cluster_centers_])

        # Step 2: deep clustering

        loss = 0
        index = 0
        index_array = np.arange(x.shape[0])
        for ite in range(int(maxiter)):
            if ite % update_interval == 0:
                q = self.model.predict(x, verbose=0)
                p = self.target_distribution(q)  # update the auxiliary target distribution p

                # evaluate the clustering performance
                y_pred = q.argmax(1)
                if y is not None:
                    acc = np.round(metrics.acc(y, y_pred), 5)
                    nmi = np.round(metrics.nmi(y, y_pred), 5)
                    ari = np.round(metrics.ari(y, y_pred), 5)
                    loss = np.round(loss, 5)
                    logdict = dict(iter=ite, acc=acc, nmi=nmi, ari=ari, loss=loss)
                    logwriter.writerow(logdict)
                    print(‘Iter %d: acc = %.5f, nmi = %.5f, ari = %.5f‘ % (ite, acc, nmi, ari), ‘ ; loss=‘, loss)

                # check stop criterion
                delta_label = np.sum(y_pred != y_pred_last).astype(np.float32) / y_pred.shape[0]
                y_pred_last = np.copy(y_pred)
                if ite > 0 and delta_label < tol:
                    print(‘delta_label ‘, delta_label, ‘< tol ‘, tol)
                    print(‘Reached tolerance threshold. Stopping training.‘)
                    logfile.close()
                    break

            # train on batch
            # if index == 0:
            #     np.random.shuffle(index_array)
            idx = index_array[index * batch_size: min((index+1) * batch_size, x.shape[0])]
            loss = self.model.train_on_batch(x=x[idx], y=p[idx])
            index = index + 1 if (index + 1) * batch_size <= x.shape[0] else 0

            # save intermediate model
            if ite % save_interval == 0:
                print(‘saving model to:‘, save_dir + ‘/DEC_model_‘ + str(ite) + ‘.h5‘)
                self.model.save_weights(save_dir + ‘/DEC_model_‘ + str(ite) + ‘.h5‘)

            ite += 1

        return y_pred

文章只是简单分析了一下,具体细节还是看源码来得实在。

想到的一些问题如下:

1.DEC的假设分布从实验效果上看起来不错,是否存在其他的比较牛逼的分布呢?

2.DEC聚类不能产生新的样本,这也是VADE类似的聚类算法的优势,抽空再看看。

3.DEC的使用除了聚类,还有什么呢?个人能想到的一点就是做离散化,相比于AE的那种Encoder的抽象降唯来说,DEC可以产生离散的变量,而不是多维的连续变量。后续可以在工程中尝试一下。

原文地址:https://www.cnblogs.com/wzyj/p/9827584.html

时间: 2024-08-28 06:10:42

【神经网络】自编码聚类算法--DEC (Deep Embedded Clustering)的相关文章

AP聚类算法(Affinity propagation Clustering Algorithm )

AP聚类算法是基于数据点间的"信息传递"的一种聚类算法.与k-均值算法或k中心点算法不同,AP算法不需要在运行算法之前确定聚类的个数.AP算法寻找的"examplars"即聚类中心点是数据集合中实际存在的点,作为每类的代表. 算法描述: 假设$\{ {x_1},{x_2}, \cdots ,{x_n}\} $数据样本集,数据间没有内在结构的假设.令是一个刻画点之间相似度的矩阵,使得$s(i,j) > s(i,k)$当且仅当$x_i$与$x_j$的相似性程度要大

【转载】聚类算法小结

聚类算法总结:---------------------------------------------------------聚类算法的种类: 基于划分聚类算法(partition clustering) k-means: 是一种典型的划分聚类算法,它用一个聚类的中心来代表一个簇,即在迭代过程中选择的聚点不一定是聚类中的一个点,该算法只能处理数值型数据 k-modes: K-Means算法的扩展,采用简单匹配方法来度量分类型数据的相似度 k-prototypes: 结合了K-Means和K-M

【转载】各种聚类算法的比较

聚类的目标是使同一类对象的相似度尽可能地大:不同类对象之间的相似度尽可能地小.目前聚类的方法很多,根据基本思想的不同,大致可以将聚类算法分为五大类:层次聚类算法.分割聚类算法.基于约束的聚类算法.机器学习中的聚类算法和用于高维度的聚类算法.摘自 数据挖掘中的聚类分析研究综述 这篇论文. 1.层次聚类算法 1.1聚合聚类 1.1.1相似度依据距离不同:Single-Link:最近距离.Complete-Link:最远距离.Average-Link:平均距离 1.1.2最具代表性算法 1)CURE算

SPARK在linux中的部署,以及SPARK中聚类算法的使用

目前,SPARK在大数据处理领域十分流行.尤其是对于大规模数据集上的机器学习算法,SPARK更具有优势.一下初步介绍SPARK在linux中的部署与使用,以及其中聚类算法的实现. 在官网http://spark.apache.org/上直接下载编译好的tar安装包可以加快部署速度. spark的运行依赖于scala2.10.4,注意此版本一定要正确,否则spark不能正确运行. 1.scala的安装很简单,在官网http://www.scala-lang.org上下载安装包,解压到任意路径后,在

关于k-means聚类算法的matlab实现

在数据挖掘中聚类和分类的原理被广泛的应用. 聚类即无监督的学习. 分类即有监督的学习. 通俗一点的讲就是:聚类之前是未知样本的分类.而是依据样本本身的相似性进行划分为相似的类簇.     而分类是已知样本分类,则须要将样本特征和分类特征进行匹配,进而将每一个样本归入给出的特定的类. 因为本文是对聚类算法中的k-means算法的实现,所以接下来主要进行一些聚类算法的介绍. 聚类算法包含多种,可按例如以下分配: 1.划分法:基于此种思想的聚类算法包含 k-means,PAM,CLARA,CLARAN

各种聚类算法的比较

各种聚类算法的比较 聚类的目标是使同一类对象的相似度尽可能地大:不同类对象之间的相似度尽可能地小.目前聚类的方法很多,根据基本思想的不同,大致可以将聚类算法分为五大类:层次聚类算法.分割聚类算法.基于约束的聚类算法.机器学习中的聚类算法和用于高维度的聚类算法.摘自 数据挖掘中的聚类分析研究综述 这篇论文. 1.层次聚类算法 1.1聚合聚类 1.1.1相似度依据距离不同:Single-Link:最近距离.Complete-Link:最远距离.Average-Link:平均距离 1.1.2最具代表性

文本聚类算法总结

以下内容为聚类介绍,除了红色的部分,其他来源百度百科,如果已经了解,可以直接忽略跳到下一部分. 聚类概念      聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法,同时也是数据挖掘的一个重要算法.聚类(Cluster)分析是由若干模式(Pattern)组成的,通常,模式是一个度量(Measurement)的向量,或者是多维空间中的一个点.聚类分析以相似性为基础,在一个聚类中的模式之间比不在同一聚类中的模式之间具有更多的相似性. 算法用途      在商业上,聚类可以帮助市场

聚类算法与应用

七月算法4月机器学习算法班课程笔记--No.10 前言 与回归与分类不同,聚类是无监督学习算法,无监督指的是只需要数据,不需要标记结果,试图探索和发现一些模式.比如对用户购买模式的分析.图像颜色分割等.聚类算法的提出比较早,是数据挖掘的一个重要模块,可以对大量数据分类并概括出每一类的特点.目前也有很多种聚类算法,包括划分法.层次法.基于密度的方法.基于网格的方法等.实际生产中,很少有只用聚类算法的系统,因为聚类效果的好坏不容易衡量,有时候会用做监督学习中稀疏特征的预处理. 接下来会重点介绍K-m

机器学习经典算法详解及Python实现--聚类及K均值、二分K-均值聚类算法

摘要 聚类是一种无监督的学习(无监督学习不依赖预先定义的类或带类标记的训练实例),它将相似的对象归到同一个簇中,它是观察式学习,而非示例式的学习,有点像全自动分类.说白了,聚类(clustering)是完全可以按字面意思来理解的--将相同.相似.相近.相关的对象实例聚成一类的过程.机器学习中常见的聚类算法包括 k-Means算法.期望最大化算法(Expectation Maximization,EM,参考"EM算法原理").谱聚类算法(参考机器学习算法复习-谱聚类)以及人工神经网络算法