但是发现在聚类时它总会使模型中的很多0参数都会被聚类成其他数字,请问一下有什么办法可有在聚类时使参数0保存下来吗

我在模型参数聚类使用的是tfmot.clustering.keras.cluster_weights。但是发现在聚类时它总会使模型中的很多0参数都会被聚类成其他数字,请问一下有什么办法可有在聚类时使参数0保存下来吗?

tfmot.clustering.keras.cluster_weights默认的聚类算法是基于K-means,由于每个聚类都由一组高度相关的权重组成,因此很可能将值接近0的参数聚为一类,从而使得一些原本是0的参数被分配到非0的聚类中。 如果需要在聚类时保留0参数,则可以使用硬聚类(Hard Clustering)算法。硬聚类就像是对相似度矩阵应用指示器函数一样,在相似度足够大的前提下才进行聚类划分。因为属于同一个簇的数据点彼此间距离较近,所以不容易将0和非0的数据点分开。与之不同,软聚类(Soft Clustering)会考虑到一组权重(向量)中每个元素的平方和,这可能会导致约束过松,并使得偏向于将某个小特征记为非零。 tfmot.clustering.keras.cluster_weights并不支持直接启用硬聚类,但您可以使用自定义聚类来实现这一点。 您可以利用tf.cluster.KMeans API或其他自定义算法来建立聚类模型,以在训练期间进一步精细化控制具体聚类效果,并根据实际情况重新定义聚类标准。 例如,您可以按以下方式定义一个自定义聚类回调来实现此目的:



import tensorflow as tf
from tensorflow_model_optimization.python.core.clustering.keras import cluster_config
from tensorflow_model_optimization.python.core.clustering.keras import clustering_algorithm


class CustomClusteringAlgorithm(clustering_algorithm.ClusteringAlgorithm):
    def __init__(self, number_of_clusters, percentile=0.1, **kwargs):
        super(CustomClusteringAlgorithm, self).__init__(**kwargs)
        self.number_of_clusters = number_of_clusters
        self.percentile = percentile
        self.cluster_axis = kwargs.get("cluster_axis")

    def get_cluster_centers(self, values):
        # Compute representations for each weight
        similarity_mtx = tf.matmul(values, values, transpose_b=True)

        # Use top Kth percentile to determine whether or not to cluster a given input
        similarity_threshold = tfp.stats.percentile(similarity_mtx, self.percentile)

        # Convert similarity matrix into binary indicators
        mask_nonzeros = tf.greater(similarity_mtx, similarity_threshold) # keep the data points > threshold 相似度之间相差不是太大就类别,否则认为两个点不属于同一类别
        mask_nonzeros = tf.cast(mask_nonzeros, tf.float32)

        # Generate cluster centers by simply taking the mean of every group defined by the above binary mask
        return [
            tf.reduce_mean(tf.boolean_mask(values, tf.transpose(tf.equal(mask_nonzeros, i)), axis=-1), axis=-1)
            for i in range(self.number_of_clusters)]

    @staticmethod
    def configure_params_for_model(input_tensor_shapes, output_tensor_shapes, *args, **kwargs):
        return {"cluster_config": cluster_config.ClusterConfig(
                    number_of_clusters=kwargs["number_of_clusters"],
                    cluster_centroids_init=kwargs.get("cluster_centroids_init", None),
                    # `custom_get_cluster_centers` method will be called.
                    clustering_algorithm=CustomClusteringAlgorithm(kwargs["number_of_clusters"],
                                                                    percentile=kwargs.get("percentile", 0.1),
                                                                    layer_name=kwargs.get("layer_name"),
                                                                    cluster_axis=kwargs.get("cluster_axis"))
            )}

在此自定义算法中,我们使用相似度矩阵的上Kth百分位来判断是继续聚类还是保持原始值不变。如果要继续聚类,则对输入应用K-means聚类。 你可以这样使用上面的自定义回调:

import tensorflow_model_optimization as tfmot

n_clusters = 8
clustering_params = {
    'number_of_clusters': n_clusters,
}

# 开启型聚类
model_for_clustering = tfmot.clustering.keras.cluster_weights(model, **clustering_params)

请根据项目实际情况调整算法细节和参数,并进行适当的调优以实现最佳效果。同时,请注意自定义算法可能会带来更高的时间和计算性能成本,在训练大型模型时可能需要进行优化处理。