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